Revert "Remove TPCS and TWPServer features" 21/52121/1 tizen
authorKyungwook Tak <k.tak@samsung.com>
Thu, 19 Nov 2015 07:48:05 +0000 (16:48 +0900)
committerKyungwook Tak <k.tak@samsung.com>
Thu, 19 Nov 2015 07:48:11 +0000 (16:48 +0900)
This reverts commit 05eca95adfd234279596bfb329e1e9e718573f2b.

Change-Id: I89ed847733b6cda2484e02a821fb7a89434cba08

34 files changed:
README
framework/IpcClient.c [new file with mode: 0644]
framework/IpcClient.h [new file with mode: 0644]
framework/IpcForkDaemon.c [new file with mode: 0644]
framework/IpcForkDaemon.h [new file with mode: 0644]
framework/IpcMacros.h [new file with mode: 0644]
framework/IpcServer.c [new file with mode: 0644]
framework/IpcServer.h [new file with mode: 0644]
framework/IpcServerError.c [new file with mode: 0644]
framework/IpcServerError.h [new file with mode: 0644]
framework/IpcServerHdr.h [new file with mode: 0644]
framework/IpcStructs.c [new file with mode: 0644]
framework/IpcStructs.h [new file with mode: 0644]
framework/IpcThrdPool.c [new file with mode: 0644]
framework/IpcThrdPool.h [new file with mode: 0644]
framework/IpcTypes.h [new file with mode: 0644]
framework/Makefile_TPCSSerDaemon [new file with mode: 0644]
framework/Makefile_TWPSerDaemon [new file with mode: 0644]
framework/Makefile_channel_client [new file with mode: 0644]
framework/Makefile_channel_server [new file with mode: 0644]
framework/TPCSSerDaemon.c [new file with mode: 0644]
framework/TPCSSerDaemon.h [new file with mode: 0644]
framework/TSCErrorCodes.h [new file with mode: 0644]
framework/TWPSerDaemon.c [new file with mode: 0644]
framework/TWPSerDaemon.h [new file with mode: 0644]
packaging/com.tsc.ipc.server.plugin.conf [new file with mode: 0644]
packaging/com.tsc.ipc.server.wp.conf [new file with mode: 0644]
packaging/csf-framework.spec
packaging/tpcsserdaemon.service [new file with mode: 0644]
packaging/twpserdaemon.service [new file with mode: 0644]
test/scripts/MfeTPCSSerDaemonToEmul.sh [new file with mode: 0755]
test/scripts/MfeTWPSerDaemonToEmul.sh [new file with mode: 0755]
test/scripts/TPCSSerDaemonTest.sh [new file with mode: 0755]
test/scripts/TWPSerDaemonTest.sh [new file with mode: 0755]

diff --git a/README b/README
index 6f9b017..29d69e2 100644 (file)
--- a/README
+++ b/README
 Install following packages to the rootstrap
 and setup the build environment
 *************************
+dbus (Version 1.6.4)
+dbus-glib (Version 0.100)
+glib (Version 2.32.3)
+gobject (Version 2.32.3)
 dlog (Version 1.0)
 
 Compiling for multiple architectures
@@ -83,3 +87,48 @@ EMULATOR(x86) - use test/scripts/PrepareForEmul.sh
   - make
   - The library can be found at 'lib/libsecfw.so'
 
+  2.2 Building IPC Client library
+  ======================
+  - make -f Makefile_channel_client clean
+  - make -f Makefile_channel_client
+  - The library can be found at 'lib/libscclient.so'
+
+  2.3 Building IPC Server library
+  ======================
+  - make -f Makefile_channel_server clean;
+  - make -f Makefile_channel_server
+  - The library can be found at 'lib/libscserver.so'
+
+  2.4 Building Plugin control service
+  ======================
+  - make -f Makefile_TPCSSerDaemon clean;
+  - make -f Makefile_TPCSSerDaemon
+  - The binary can be found at 'bin/TPCSSerDaemon'
+
+  2.5 Building Web protection control service
+  ======================
+  - make -f Makefile_TWPSerDaemon clean
+  - make -f Makefile_TWPSerDaemon
+  - The binary can be found at 'bin/TWPSerDaemon'
+
+  2.6 Testing Plugin control service
+  ======================
+  -cd test (change your folder to test)
+  -Start the emulator
+  -chmod +x ./scripts/MfeTPCSSerDaemonToEmul.sh
+  -sdb -e shell (make sure you have enough privilege to write or read all folders under /opt/, /usr/bin/ and /tmp)
+  -cd /usr/bin
+  -chmod +x ./Test.sh
+  - ./Test.sh
+  - ./tpcsserdaemontest
+
+  2.7 Testing Web protection control service
+  ======================
+  -cd test (change your folder to test)
+  -Start the emulator
+  -chmod +x ./scripts/MfeTWPSerDaemonToEmul.sh
+  -sdb -e shell (make sure you have enough privilege to write or read all folders under /opt/, /tmp)
+  -cd /usr/bin
+  -chmod +x ./Test.sh
+  - ./Test.sh
+  - ./twpserdaemontest
\ No newline at end of file
diff --git a/framework/IpcClient.c b/framework/IpcClient.c
new file mode 100644 (file)
index 0000000..935b29c
--- /dev/null
@@ -0,0 +1,785 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+    
+    All rights reserved.
+    
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+    
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+    
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+    
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+    
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * \file IpcClient.c
+ * \brief Ipc Client Source File
+ *  
+ * This file implements the IPC Client API functions used by Security framework.
+ */
+
+#include <dbus/dbus.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "Debug.h"
+#include "IpcClient.h"
+#include "IpcStructs.h"
+#include "TSCErrorCodes.h"
+
+static DBusHandlerResult _IpcClientMsgFilter(DBusConnection *dbconn, DBusMessage *dbmsg, void *data);
+static bool _IpcClientInit(IpcClientInfo *pInfo);
+static void _IpcClientDeInit(IpcClientInfo *pInfo);
+static void _IpcHandleAsyncReply(DBusPendingCall *pPendingCall, void *pThreadData);
+static void _free_str_array(char*** arr, int size);
+
+/**
+ * Initializes and returns handle to client side IPC.
+ */
+TSC_IPC_HANDLE IpcClientOpen(void)
+{
+    IpcClientInfo *pInfo = NULL;
+    pInfo = calloc(1, sizeof(IpcClientInfo));
+    if (pInfo == NULL)
+        return NULL;
+
+    snprintf(pInfo->pid, TSC_REQ_STR_LEN, "%d", getpid());
+    snprintf(pInfo->req_name, TSC_REQ_STR_LEN, "%s%d", TSC_DBUS_CLIENT, getpid());
+
+    // Init Dbus Client
+    if (!_IpcClientInit(pInfo))
+        goto err_conn;
+
+    return (TSC_IPC_HANDLE)pInfo;
+
+err_conn:
+    if (pInfo)
+        free(pInfo);
+
+    return INVALID_IPC_HANDLE;
+}
+
+/**
+ * Close the client-side IPC and release the resources.
+ */
+void IpcClientClose(TSC_IPC_HANDLE hIpc)
+{
+    if (hIpc == INVALID_IPC_HANDLE)
+        return;
+
+    IpcClientInfo *pInfo = (IpcClientInfo *)hIpc;
+    _IpcClientDeInit(pInfo);
+    free(pInfo);
+}
+
+/**
+ * Gives the prefix for the unique id of message sent.
+ */
+char *_GetMsgIdPrefix(void)
+{
+    char szIdPrefix[MSGHANDLE_LEN] = {0};
+    if (snprintf(szIdPrefix, MSGHANDLE_LEN, TSC_MID_PREFIX_FORMAT, getpid(), pthread_self()) >= 0)
+        return strdup(szIdPrefix);
+
+    return NULL;
+}
+
+/**
+ * Requests the Security framework's IPC server and returns back the reply.
+ */
+int TSCSendMessageN(TSC_IPC_HANDLE hIpc, const char *service_name, const char *szMethod, int argc,
+                    char **argv, int *argc_reply, char ***argv_reply, int timeout_milliseconds)
+{
+    IpcClientInfo *pInfo = (IpcClientInfo *)hIpc;
+    DBusMessage *dbmsg = NULL;
+    DBusMessage *reply_msg = NULL;
+    DBusMessageIter dbiter;
+    DBusError dberr;
+    char *pArgItem = NULL;
+    char *pBuf = NULL;
+    int i = 0;
+    int j = 0;
+    int iErr = TSC_ERROR_MODULE_GENERIC;
+    int iSize = TSC_REPLY_MSG_COUNT_AVERAGE;
+
+    *argc_reply = 0;
+
+    // TODO: Avoid multiple exits.
+    if (pInfo == NULL)
+        return TSC_ERROR_INVALID_HANDLE;
+
+    if (pInfo->dbconn == NULL)
+        return TSC_ERROR_INVALID_HANDLE;
+
+    if (argc < 0 || !szMethod)
+        return TSC_ERROR_INVALID_PARAM;
+
+    *argv_reply = malloc(iSize * sizeof(char *));
+    if (!*argv_reply)
+    {
+        iErr = TSC_ERROR_INSUFFICIENT_RES;
+        goto err_send;
+    }
+
+    dbus_error_init(&dberr);
+
+    dbmsg = dbus_message_new_method_call(service_name, TSC_DBUS_PATH, TSC_DBUS_INTERFACE, szMethod);
+    if (dbmsg == NULL)
+    {
+        iErr = TSC_ERROR_INSUFFICIENT_RES;
+        goto err_send;
+    }
+    dbus_message_iter_init_append(dbmsg, &dbiter);
+
+    // Add the message unique id as first element (the prefix).
+    char *szIdPrefix = _GetMsgIdPrefix();
+    if (!szIdPrefix || !dbus_message_iter_append_basic(&dbiter, DBUS_TYPE_STRING, &szIdPrefix))
+    {
+        DDBG("client_lib: Failed to append id prefix for %s.\n", szMethod);
+        free(szIdPrefix);
+        goto err_send;
+    }
+    free(szIdPrefix);
+    for (i = 0; i < argc; i++)
+    {
+        if (!dbus_validate_utf8(argv[i], &dberr))
+        {
+            DDBG("%s", "client_lib: Not valid utf8 string\n");
+            goto err_send;
+        }
+        if (!dbus_message_iter_append_basic(&dbiter, DBUS_TYPE_STRING, &argv[i]))
+        {
+            DDBG("client_lib: %s failed to append arguments\n", pInfo->pid);
+            goto err_send;
+        }
+    }
+
+    if (timeout_milliseconds == 0)
+        timeout_milliseconds = DBUS_TIMEOUT_INFINITE;
+
+    reply_msg = dbus_connection_send_with_reply_and_block(pInfo->dbconn, dbmsg, 
+                                                          timeout_milliseconds,
+                                                          &dberr);
+
+    if (reply_msg == NULL && dbus_error_is_set(&dberr))
+    {
+        DDBG("client_lib: Failed to end %s\n", dberr.message);
+        goto err_send;
+    }
+
+    if (reply_msg == NULL)
+    {
+        DDBG("%s\n", "client_lib: reply message is NULL");
+        goto err_send;
+    }
+
+    j = 0;
+    if (!dbus_message_iter_init(reply_msg, &dbiter))
+    {
+        DDBG("%s\n", "client_lib: Message has no arguments.");
+        goto zero_args;
+    }
+
+    do
+    {
+        if (dbus_message_iter_get_arg_type(&dbiter) != DBUS_TYPE_STRING)
+        {
+            DDBG("client_lib: %s argument is not string\n", pInfo->pid);
+            goto err_send;
+        }
+
+        dbus_message_iter_get_basic(&dbiter, &pArgItem);
+        if (!pArgItem)
+        {
+            DDBG("client_lib: %s arg is NULL\n", pInfo->pid);
+            goto err_send;
+        }
+
+        if (!(pBuf = strdup((const char*)pArgItem)))
+        {
+            goto err_send;
+        }
+        (*argv_reply)[j++] = pBuf;
+
+        if (j >= iSize)
+        {
+            iSize += TSC_REPLY_MSG_COUNT_AVERAGE;
+            *argv_reply = realloc(*argv_reply, sizeof(char*) * iSize);
+            if (!*argv_reply)
+            {
+                goto err_send;
+            }
+        }
+    } while (dbus_message_iter_has_next(&dbiter) && dbus_message_iter_next(&dbiter));
+
+zero_args:
+    *argc_reply = j;
+    return 0;
+
+err_send:
+    if (*argv_reply)
+    {
+        while (j)
+            free((*argv_reply)[--j]);
+
+        free(*argv_reply);
+        *argv_reply = NULL;
+    }
+    if (dbmsg)
+        dbus_message_unref(dbmsg);
+    if(reply_msg)
+        dbus_message_unref(reply_msg);
+
+    return -1;
+}
+
+/**
+ * Block current thread till message is sent and structure is updated in child thread.
+ */
+void BlockTillSent(SharedData *pSharedData)
+{
+    pthread_mutex_lock(&pSharedData->lock);
+    while (pSharedData->iSent == 0)
+        pthread_cond_wait(&pSharedData->cond, &pSharedData->lock);
+    pthread_mutex_unlock(&pSharedData->lock);
+}
+
+/**
+ * Unblock parent thread as the message structures have been updated.
+ * Unblocks only 1 thread associated with the condition variable.
+ * Broadcast avoided as only waiting thread is expected.
+ */
+void UnblockOnSent(SharedData *pSharedData)
+{
+    pthread_mutex_lock(&pSharedData->lock);
+    pSharedData->iSent = 1;
+    pthread_cond_signal(&pSharedData->cond);
+    pthread_mutex_unlock(&pSharedData->lock);
+}
+
+/**
+ * Creates a thread for asynchronous task.
+ * TODO: Merge with TCS module.
+ */
+int _RunDetachedThread(void *pfWorkerFunc, void *pThreadData)
+{
+    pthread_t thread;
+    pthread_attr_t attr;
+
+    int rc = -1;
+    do
+    {
+        if (pthread_attr_init(&attr) != 0)
+            break;
+
+        if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
+            break;
+
+        if (pthread_create(&thread, &attr, pfWorkerFunc, pThreadData) != 0)
+            break;
+
+        if (pthread_attr_destroy(&attr) != 0)
+        {
+            // As the thread is already running, return different error code.
+            rc = -2;
+            break;
+        }
+
+        rc = 0;
+    }
+    while (0);
+
+    return rc;
+}
+
+void *_SendMessageWorker(void *pData)
+{
+    dbus_bool_t result;
+    DBusPendingCall *pPendingCall = NULL;
+    ThreadData *pThreadData = (ThreadData *) pData;
+    ThreadData *pPendingData = NULL;
+    int iSentFailed = 1;
+
+    do
+    {
+        if (pThreadData == NULL)
+        {
+            DDBG("%s\n", "Nothing to send from thread. Deadlock!!");
+            break;
+        }
+
+        // Duplicate the User data to create the pending User data.
+        pPendingData = _AllocThreadData(NULL, DEF_TIMEOUT, NULL, pThreadData->pCallBack,
+                                        pThreadData->pPrivate);
+        if (pPendingData == NULL)
+        {
+            DDBG("%s\n", "Duplicating user data in thread failed. Deadlock!!");
+            break;
+        }
+
+        // Ownership of pThreadData remains with 'parent' thread.
+        result = dbus_connection_send_with_reply(pThreadData->pConn, pThreadData->pSharedData->pMsg,
+                                                 &pPendingCall, pThreadData->timeout_milliseconds);
+        if (!result || !pPendingCall)
+        {
+            DDBG("%s\n", "client_lib: SendAsync failed.");
+            break;
+        }
+
+        if (!pPendingData->pCallBack)
+            dbus_pending_call_cancel(pPendingCall);
+        else
+            dbus_pending_call_set_notify(pPendingCall, _IpcHandleAsyncReply, pPendingData,
+                                         _FreeThreadData);
+
+        // Set the values for parent thread to allow cancellation or further async action if needed.
+        if (_CreateClientCallHandle(&pThreadData->pSharedData->pCallHandle,
+                                    pThreadData->pSharedData->szCallHandlePrefix,
+                                    dbus_message_get_serial(pThreadData->pSharedData->pMsg),
+                                    pPendingCall) != 0)
+        {
+            dbus_pending_call_cancel(pPendingCall);
+            break;
+        }
+
+        UnblockOnSent(pThreadData->pSharedData);
+        // WARNING: Do not use pThreadData beyond this point, as parent thread may destroy it.
+
+        dbus_pending_call_block(pPendingCall);
+
+        iSentFailed = 0;
+    }
+    while(0);
+
+    if (iSentFailed && pThreadData)
+    {
+        DDBG("%s\n", "Error in send messsage worker. Unblocking..");
+        UnblockOnSent(pThreadData->pSharedData);
+    }
+
+    DDBG("%s\n", "Finished send message worker.");
+    return NULL;
+}
+
+
+/**
+ * Requests the Security framework's IPC server asynchronously.
+ */
+int TSCSendMessageAsync(TSC_IPC_HANDLE hIpc, const char *service_name, const char *szMethod,
+                        int argc, char **argv, TSC_CALL_HANDLE *phCallHandle, TSCCallback pCallback,
+                        void *pPrivate, int timeout_milliseconds)
+{
+    DDBG("%s %s\n", "sendmessage async ", service_name);
+    IpcClientInfo *pInfo = (IpcClientInfo *)hIpc;
+    DBusMessage *pMsg = NULL;
+    DBusMessageIter dbiter;
+    DBusError dberr;
+    ThreadData *pThreadData = NULL;
+    int i = 0;
+    int iErr = TSC_ERROR_MODULE_GENERIC;
+
+    // TODO: Avoid multiple exits.
+    if (pInfo == NULL)
+        return TSC_ERROR_INVALID_HANDLE;
+
+    if (pInfo->dbconn == NULL)
+        return TSC_ERROR_INVALID_HANDLE;
+
+    if (argc < 0 || !szMethod)
+        return TSC_ERROR_INVALID_PARAM;
+
+    dbus_error_init(&dberr);
+    pMsg = dbus_message_new_method_call(service_name, TSC_DBUS_PATH, TSC_DBUS_INTERFACE, szMethod);
+
+    if (pMsg == NULL)
+    {
+        iErr = TSC_ERROR_INSUFFICIENT_RES;
+        goto err_send;
+    }
+
+    dbus_message_iter_init_append(pMsg, &dbiter);
+
+    // Add the message unique id as first element (the prefix).
+    char *szIdPrefix = _GetMsgIdPrefix();
+    if (!szIdPrefix || !dbus_message_iter_append_basic(&dbiter, DBUS_TYPE_STRING, &szIdPrefix))
+    {
+        DDBG("client_lib: Failed to append id prefix for %s.\n", szMethod);
+        free(szIdPrefix);
+        goto err_send;
+    }
+
+    for (i = 0; i < argc; i++)
+    {
+        if (!dbus_validate_utf8(argv[i], &dberr))
+        {
+            DDBG("%s", "client_lib: Not valid utf8 string\n");
+            goto err_send;
+        }
+        if (!dbus_message_iter_append_basic(&dbiter, DBUS_TYPE_STRING, &argv[i]))
+        {
+            DDBG("client_lib: %s failed to append arguments\n", pInfo->pid);
+            goto err_send;
+        }
+    }
+
+    // Reply is discarded and not sent back to client, if no callback available.
+    if (!pCallback)
+        dbus_message_set_no_reply(pMsg, TRUE);
+
+    SharedData *pSharedData = _CreateSharedData(szIdPrefix, pMsg);
+    free(szIdPrefix);
+
+    if (!pSharedData)
+    {
+        iErr = TSC_ERROR_INSUFFICIENT_RES;
+        goto err_send;
+    }
+
+    if (timeout_milliseconds == 0)
+        timeout_milliseconds = DBUS_TIMEOUT_INFINITE;
+
+    pThreadData = _AllocThreadData(pInfo->dbconn, timeout_milliseconds, pSharedData, pCallback,
+                                   pPrivate);
+    if (!pThreadData)
+    {
+        _FreeSharedData(pSharedData);
+        iErr = TSC_ERROR_INSUFFICIENT_RES;
+        goto err_send;
+    }
+
+    // Assert that the message is ready to be used.
+    if (pThreadData->pSharedData->iSent)
+    {
+        DDBG("%s\n", "client_lib: Sent flag already set!!");
+        goto err_send;
+    }
+
+    DDBG("Before sending: %d\n", dbus_message_get_serial(pMsg));
+    if (_RunDetachedThread(_SendMessageWorker, pThreadData) == -1)
+    {
+        DDBG("%s\n", "client_lib: Running thread failed!!");
+        goto err_send;
+    }
+
+    BlockTillSent(pThreadData->pSharedData);
+    DDBG("After sending: %d\n", dbus_message_get_serial(pMsg));
+
+    if (phCallHandle)
+    {
+        *phCallHandle = (TSC_CALL_HANDLE)pThreadData->pSharedData->pCallHandle;
+        //TODO: should add here
+        DDBG("method unique  id :%s\n", ((ClientCallHandle*) phCallHandle)->idUnique);
+        strncpy(pThreadData->pSharedData->pCallHandle->service_name, service_name, TSC_SERVER_NAME_LEN);
+    }
+    else
+    {
+        // The caller does not want to call special methods (cancel, get progress) later.
+        _FreeClientCallHandle(pThreadData->pSharedData->pCallHandle);
+        pThreadData->pSharedData->pCallHandle = NULL;
+    }
+
+    iErr = 0;
+
+err_send:
+    if (pMsg)
+        dbus_message_unref(pMsg);
+
+    if (pThreadData)
+        _FreeThreadData(pThreadData);
+
+    return iErr;
+}
+
+/**
+ * Releases the asynchronous call handle.
+ */
+void TSCFreeSentMessageHandle(TSC_CALL_HANDLE hCallHandle)
+{
+    _FreeClientCallHandle((ClientCallHandle *)hCallHandle);
+}
+
+/**
+ * Callback when reply is received from IPC server for asynchronous method call.
+ */
+static void _IpcHandleAsyncReply(DBusPendingCall *pPendingCall, void *pThreadData)
+{
+    int i = 0;
+    int argc = 0;
+    char **argv = NULL;
+    char *pBuf = NULL;
+    char *pArgItem = NULL;
+    DBusError dberr;
+    DBusMessageIter dbiter;
+    DBusMessage *pMsg = NULL;
+    int iErr = TSC_ERROR_MODULE_GENERIC;
+    int iSize = TSC_REPLY_MSG_COUNT_AVERAGE;
+    ThreadData *pData = (ThreadData *)pThreadData;
+
+    argv = malloc(iSize * sizeof(char *));
+    if (!argv)
+    {
+        iErr = TSC_ERROR_INSUFFICIENT_RES;
+        goto reply_err;
+    }
+
+    dbus_error_init(&dberr);
+
+    pMsg = dbus_pending_call_steal_reply(pPendingCall);
+    if (pMsg == NULL)
+    {
+        DDBG("%s\n", "client_lib: reply message is NULL");
+        goto reply_err;
+    }
+
+    i = 0;
+    if (!dbus_message_iter_init(pMsg, &dbiter))
+    {
+        DDBG("%s\n", "client_lib: Async reply has no arguments");
+        goto reply_err;
+    }
+
+    do
+    {
+        if (dbus_message_iter_get_arg_type(&dbiter) != DBUS_TYPE_STRING)
+        {
+            DDBG("%s\n", "client_lib: Reply argument is not string");
+            goto reply_err;
+        }
+
+        dbus_message_iter_get_basic(&dbiter, &pArgItem);
+        if (!pArgItem)
+        {
+            DDBG("%s\n", "client_lib: Failed getting string arg from reply");
+            goto reply_err;
+        }
+
+        if (!(pBuf = strdup((const char*)pArgItem)))
+        {
+            goto reply_err;
+        }
+        argv[i++] = pBuf;
+
+        if (i >= iSize)
+        {
+            iSize += TSC_REPLY_MSG_COUNT_AVERAGE;
+            argv = realloc(argv, sizeof(char*) * iSize);
+            if (!argv)
+            {
+                goto reply_err;
+            }
+        }
+    } while (dbus_message_iter_has_next(&dbiter) && dbus_message_iter_next(&dbiter));
+
+    argc = i;
+    // Continue passing the returned values to callback.
+    goto forward_reply;
+
+reply_err:
+    // Reset values being returned.
+    _free_str_array(&argv, i);
+
+forward_reply:
+    if(pMsg)
+        dbus_message_unref(pMsg);
+    if (pPendingCall)
+        dbus_pending_call_unref(pPendingCall);
+
+    if (pData && pData->pCallBack)
+        (*(pData->pCallBack))(pData->pPrivate, argc, (const char**)argv);
+
+    _free_str_array(&argv, i);
+
+    DDBG("%s\n", "client_lib: Async Reply Completed.");
+}
+
+
+/**
+ * Cancels an asynchronous request previously made to the Security framework's IPC server.
+ * On success, releases the handle of the previously called asynchronous method.
+ */
+int TSCCancelMessage(TSC_IPC_HANDLE hIpc, TSC_CALL_HANDLE hCallHandle)
+{
+    IpcClientInfo *pInfo = (IpcClientInfo *)hIpc;
+    ClientCallHandle *pCallHandle = (ClientCallHandle *)hCallHandle;
+    char *argv_req[1];
+    int iResult = -1;
+
+    do
+    {
+        DDBG("%s\n", "client_lib: CANCELing.");
+        if (!pInfo || !pCallHandle)
+            break;
+
+        DDBG("%s\n", "prepare cancel");
+        // Cancel the message call locally.
+        dbus_pending_call_cancel(pCallHandle->pPendingCall);
+
+        // Now request the server to abort the running of the method.
+        argv_req[0] = pCallHandle->idUnique;
+        DDBG("cancel method unique id:%s\n", argv_req[0]);
+        //TODO: need change here for cancel message
+
+        TSC_CALL_HANDLE handle = NULL;
+        iResult = TSCSendMessageAsync((TSC_IPC_HANDLE)pInfo, pCallHandle->service_name,
+                                      TSC_FN_CANCELMETHOD, 1, argv_req, &handle, NULL, NULL,
+                                      DEF_TIMEOUT);
+        DDBG("%s\n", "client_lib: Sent Cancel to server.");
+
+        if (iResult == 0)
+        {
+            _FreeClientCallHandle(pCallHandle);
+        }
+
+    } while (0);
+
+    return iResult;
+}
+
+static DBusHandlerResult _IpcClientMsgFilter(DBusConnection *dbconn, DBusMessage *dbmsg, void *data)
+{
+    IpcClientInfo *info = (IpcClientInfo*) data;
+    if (dbus_message_is_signal(dbmsg, DBUS_INTERFACE_LOCAL, "Disconnected"))
+    {
+       DDBG("client_lib: %s disconnected by signal\n", info->pid);
+        info->dbconn = NULL;
+        return DBUS_HANDLER_RESULT_HANDLED;
+    }
+
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static bool _IpcClientInit(IpcClientInfo *pInfo)
+{
+    if (!pInfo)
+        return false;
+
+    DBusError dberr;
+    int ret;
+
+    if (!dbus_threads_init_default())
+    {
+        DDBG("failed dbus_threads_init_default %s\n", "");
+        goto err;
+    }
+
+    dbus_error_init(&dberr);
+
+
+    if (pInfo->dbconn != NULL)
+        return false;
+
+    pInfo->dbconn = dbus_bus_get(DBUS_BUS_SYSTEM, &dberr);
+
+    if (pInfo->dbconn == NULL && dbus_error_is_set(&dberr))
+    {
+       DDBG("client_lib: %s error in get connection %s\n", pInfo->pid, dberr.message);
+        goto err_get;
+    }
+
+    if (!pInfo->dbconn)
+    {
+       DDBG("client_lib: %s get connection is NULL\n", pInfo->pid);
+        goto err_get;
+    }
+
+    dbus_connection_set_exit_on_disconnect(pInfo->dbconn, false);
+
+    if (!dbus_connection_add_filter(pInfo->dbconn, _IpcClientMsgFilter, pInfo, NULL))
+    {
+       DDBG("client_lib: %s failed to add filter %s\n", pInfo->pid, dberr.message);
+        goto err_get;
+    }
+
+    ret = dbus_bus_request_name(pInfo->dbconn, pInfo->req_name, DBUS_NAME_FLAG_REPLACE_EXISTING, &dberr);
+
+    if (ret == -1 && dbus_error_is_set(&dberr))
+    {
+       DDBG("client_lib: %s failed to request name %s\n", pInfo->pid, dberr.message);
+        goto err_get;
+    }
+
+    if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+    {
+       DDBG("client_lib: %s failed, it is not primary owner %d\n", pInfo->req_name, ret);
+        goto err_get;
+    }
+
+    dbus_error_free(&dberr);
+    return  true;
+
+err_get:
+    if (pInfo->dbconn)
+    {
+        dbus_connection_unref(pInfo->dbconn);
+        pInfo->dbconn = NULL;
+    }
+    dbus_error_free(&dberr);
+
+err:
+    return false;
+}
+
+static void _IpcClientDeInit(IpcClientInfo *pInfo)
+{
+    if (!pInfo)
+        return;
+
+    DBusError dberr;
+    int ret;
+
+    if (!pInfo->dbconn)
+        return;
+
+    dbus_error_init(&dberr);
+    ret = dbus_bus_release_name(pInfo->dbconn, pInfo->req_name, &dberr);
+
+    if (ret == -1 && dbus_error_is_set(&dberr))
+       DDBG("client_lib: %s failed to release name %s\n", pInfo->pid, dberr.message);
+
+    dbus_error_free(&dberr);
+
+    dbus_connection_remove_filter(pInfo->dbconn, _IpcClientMsgFilter, pInfo);
+    dbus_connection_unref(pInfo->dbconn);
+    pInfo->dbconn = NULL;
+}
+
+/**
+ * Release all the elements of the array and assign it to NULL.
+ */
+static void _free_str_array(char*** arr, int size)
+{
+    if (arr)
+    {
+        char **sArr = *arr;
+        if (sArr && *sArr)
+        {
+            while (size)
+                free(sArr[--size]);
+
+            free(sArr);
+            *arr = NULL;
+        }
+    }
+}
diff --git a/framework/IpcClient.h b/framework/IpcClient.h
new file mode 100644 (file)
index 0000000..42681c4
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+    
+    All rights reserved.
+    
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+    
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+    
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+    
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+    
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef IPCCLIENT_H
+#define IPCCLIENT_H
+
+#ifdef __cplusplus 
+extern "C" {
+#endif
+
+/**
+ * \file IpcClient.h
+ * \brief Ipc Client Header File
+ *  
+ * This file provides the IPC Client API functions used by Security framework.
+ */
+
+#include "IpcTypes.h"
+
+/*==================================================================================================
+                                 CONSTANTS & ENUMS
+==================================================================================================*/
+#define DEF_TIMEOUT -1
+
+
+/*==================================================================================================
+                                     FUNCTION PROTOTYPES
+==================================================================================================*/
+
+/**
+ * \brief Initializes client side IPC and returns its handle.
+ *
+ * Opens and initialises the handle to client side IPC using the security 
+ * framework defaults.
+ *
+ * This is a synchronous API.
+ *
+ * \return Return Type (TSC_IPC_HANDLE) \n
+ * Client IPC handle - on success. \n
+ * NULL - on failure. \n
+ */
+TSC_IPC_HANDLE IpcClientOpen(void);
+
+/**
+ * \brief Requests the Security framework's IPC server and returns back the reply.
+ *
+ * This is a synchronous API.
+ *
+ * \param[in] hIpc IPC handle returned by IpcClientOpen().
+ *
+ * \return Return Type (void) \n
+ */
+void IpcClientClose(TSC_IPC_HANDLE hIpc);
+
+/**
+ * \brief Requests the Security framework's IPC server and returns back the reply.
+ *
+ * This is a synchronous API.
+ *
+ * \param[in] hIpc Client side IPC handle.
+ * \param[in] szMethod Name of the method called.
+ * \param[in] argc Number of parameters passed in argv.
+ * \param[in] argv Array of strings representing parameters for method called.
+ * \param[out] reply_len Length of the string in reply_argv.
+ * \param[out] reply_argv Array of strings representing result value from method called.
+ * \param[in] timeout_milliseconds Timeout in milliseconds. -1 for default or 0 for no timeout.
+ *
+ * \return Return Type (int) \n
+ * 0 - on send success. \n
+ * -1 - on send failure. \n
+ */
+int TSCSendMessageN(TSC_IPC_HANDLE hIpc, const char *service_name, const char *szMethod, int argc,
+                    char **argv, int *argc_reply, char ***argv_reply, int timeout_milliseconds);
+
+/**
+ * \brief Requests the Security framework's IPC server asynchronously.
+ *
+ * This is an asynchronous API.
+ *
+ * \param[in] hIpc Client side IPC handle.
+ * \param[in] szMethod Name of the method called.
+ * \param[in] argc Number of parameters passed in argv.
+ * \param[in] argv Array of strings representing parameters for method called.
+ * \param[out] phCallHandle Pointer to handle of the asynchronous message sent.
+ * \param[in] pCallback Callback function for the asynchronous reply.
+ * \param[in] pPrivate API caller's context information, to be supplied with callback.
+ * \param[in] timeout_milliseconds Timeout in milliseconds. -1 for default or 0 for no timeout.
+ *
+ * \return Return Type (int) \n
+ * 0 - on send success. \n
+ * Error code - on send failure. \n
+ */
+int TSCSendMessageAsync(TSC_IPC_HANDLE hIpc, const char *service_name, const char *szMethod, int argc, char **argv,
+                        TSC_CALL_HANDLE *phCallHandle, TSCCallback pCallback, void *pPrivate,
+                        int timeout_milliseconds);
+
+/**
+ * \brief Releases the asynchronous call handle.
+ *
+ * \param[in] hCallHandle Handle of the asynchronous message sent earlier.
+ */
+void TSCFreeSentMessageHandle(TSC_CALL_HANDLE hCallHandle);
+
+/**
+ * \brief Cancels an asynchronous request previously made to the Security framework's IPC server.
+ * On success, releases the handle of the previously called asynchronous method.
+ *
+ * This is an asynchronous API.
+ *
+ * \param[in] hIpc Client side IPC handle.
+ * \param[in] hCallHandle Handle of the asynchronous message sent earlier.
+ *
+ * \return Return Type (int) \n
+ * 0 - on send success. \n
+ * Error code - on failure. \n
+ */
+int TSCCancelMessage(TSC_IPC_HANDLE hIpc, TSC_CALL_HANDLE hCallHandle);
+
+#ifdef __cplusplus
+}
+#endif 
+
+#endif  /* IPCCLIENT_H */
diff --git a/framework/IpcForkDaemon.c b/framework/IpcForkDaemon.c
new file mode 100644 (file)
index 0000000..5ee1f3c
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * \file IpcForkDaemon.c
+ * \brief Ipc Fork Daemon source file.
+ *
+ * This file implements the Ipc Fork Daemon function used by Security framework.
+ */
+
+#include "Debug.h"
+#include "IpcForkDaemon.h"
+#include <signal.h>
+
+void
+fork_daemon()
+{
+    pid_t pid;
+
+    // Fork off the parent process.
+    pid = fork();
+
+    // An error occurred.
+    if (pid < 0)
+    {
+        DERR("%s\n", "unable to start the TWPSerDaemon");
+        exit(EXIT_FAILURE);
+    }
+
+    // Success: Let the parent terminate.
+    if (pid > 0)
+    {
+        DERR("%s\n", "Successfully forked the child process");
+        exit(EXIT_SUCCESS);
+    }
+
+    // On success: The child process becomes session leader.
+    if (setsid() < 0)
+    {
+        DERR("%s\n", "unable to start the TWPSerDaemon");
+        exit(EXIT_FAILURE);
+    }
+
+    signal(SIGCHLD, SIG_IGN);
+    signal(SIGHUP, SIG_IGN);
+
+    // Fork off for the second time to ensure session leading process ends.
+    pid = fork();
+
+    // An error occurred.
+    if (pid < 0)
+    {
+        DERR("%s\n", "unable to start the TWPSerDaemon");
+        exit(EXIT_FAILURE);
+    }
+
+    // Success: Let the session leading process end.
+    if (pid > 0)
+    {
+        DERR("%s\n", "Successfully forked the TWPSerDaemon process in the new session");
+        exit(EXIT_SUCCESS);
+    }
+
+    //close the file descriptors of terminal associated with the process
+    close(STDIN_FILENO);
+    close(STDOUT_FILENO);
+    close(STDERR_FILENO);
+}
diff --git a/framework/IpcForkDaemon.h b/framework/IpcForkDaemon.h
new file mode 100644 (file)
index 0000000..da186ac
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * \file IpcForkDaemon.h
+ * \brief TWP Server Daemon Header file.
+ *
+ * This file has the function prototypes.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/**
+ * \brief this method forks the daemon
+ * This is a synchronized API.
+ *
+ * \param[in] none.
+ * \param[out] none.
+ * \return Return Type (void) \n
+ *
+ */
+void fork_daemon();
diff --git a/framework/IpcMacros.h b/framework/IpcMacros.h
new file mode 100644 (file)
index 0000000..4c91412
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+    
+    All rights reserved.
+    
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+    
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+    
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+    
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+    
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef IPCMACROS_H
+#define IPCMACROS_H
+
+/**
+ * \file IpcMacros.h
+ * \brief Common constants and macros Header File
+ *  
+ * This file provides the constants and macros for IPC used by Security framework.
+ */
+
+#define TSC_DBUS_SERVER_GENERIC_STUB "com.tsc.ipc.server.generic"
+#define TSC_DBUS_SERVER_WP_CHANNEL "com.tsc.ipc.server.wp"
+#define TSC_DBUS_SERVER_PLUGIN_CHANNEL "com.tsc.ipc.server.plugin"
+#define TSC_DBUS_SERVER_INTEGRITY_TEST_STUB "com.tsc.ipc.server.integrity"
+
+#define TSC_DBUS_SERVER        "com.tsc.ipc.server"
+#define TSC_DBUS_INTERFACE     "org.tsc.ipc.interface"
+#define TSC_DBUS_PATH          "/org/tsc/ipc/path"
+#define TSC_DBUS_CLIENT        "com.tsc.ipc.client"
+#define TSC_FN_FETCHLIST       "FetchList"
+#define TSC_FN_CANCELMETHOD    "_Cancel_"
+#define TSC_FN_PROGRESSMETHOD  "_Progress_"
+#define TSC_FN_SHUTDOWN "IpcShutdown"
+
+#define TSC_MID_PREFIX_FORMAT  "%u_%lu_"
+#define TSC_MID_FORMAT         TSC_MID_PREFIX_FORMAT"%u"
+#define TSC_MID_SVR_FORMAT     "%s%u"
+
+#define TSC_READ_WRITE_DISPATCH_SLEEP_SECONDS  1
+#define TSC_SEND_MESSAGE_REPLY_TIME    5000
+
+#define TSC_THREAD_POOL_NUMBERS 3
+
+#define TSC_REQ_STR_LEN                128
+#define TSC_INFO_RULE_LEN      128
+#define TSC_SERVER_NAME_LEN 128
+#define TSC_METHOD_NAME_LEN 128
+
+#define TSC_REPLY_MSG_COUNT_AVERAGE 4
+
+
+// Client side call handle length.
+// TODO: Reduce size by avoiding string type handle.
+#define MSGHANDLE_LEN   25
+
+typedef enum
+{
+    TSC_CANCEL = -1,
+    TSC_PROGRESS = 0
+} TSC_METHOD_REASON_CODE;
+
+#define TSC_IS_CANCEL   0
+#define TSC_NON_CANCEL   1;
+
+#endif  /* IPCMACROS_H */
+
diff --git a/framework/IpcServer.c b/framework/IpcServer.c
new file mode 100644 (file)
index 0000000..3d85e85
--- /dev/null
@@ -0,0 +1,1239 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * \file IpcServer.c
+ * \brief Ipc Server Source File
+ *
+ * This file implements the IPC Server API functions used by Security framework.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <signal.h>
+
+#include "Debug.h"
+#include "IpcMacros.h"
+#include "IpcServerError.h"
+#include "IpcServerHdr.h"
+#include "TSCErrorCodes.h"
+
+
+#ifdef DEBUG
+#define DBUS_D_LOG(_dbusErr_, _fmt_, _param_...)    \
+    { \
+        DDBG("%s:%s; " _fmt_, _dbusErr_.name, _dbusErr_.message, _param_); \
+    }
+#else
+#define DBUS_D_LOG(_dbusErr_, _fmt_, _param_...)
+#endif
+
+static void IterateList(IpcMethodHandle* pHandle)
+{
+    IpcMethodHandle *ph;
+    int count = 0;
+    for(ph = pHandle; ph != NULL; ph = ph->pNext)
+    {
+        count++;
+    }
+    DDBG(".....total count: %d\n", count);
+}
+
+inline DBusHandlerResult _IpcSendMessageAndUnref(DBusConnection *pConn, DBusMessage *pMsg)
+{
+    if (pMsg) {
+        dbus_connection_send(pConn, pMsg, NULL);
+        dbus_message_unref(pMsg);
+    }
+    return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+void _FreeHandleMethods(IpcServerInfo *pInfo)
+{
+    if (!pInfo)
+        return;
+
+    // Free MethodList
+    IpcServerMethodList *pCurr = pInfo->pMethodList;
+    IpcServerMethodList *pPrev = NULL;
+
+    pthread_mutex_lock(&(pInfo->Lock));
+    while (pCurr)
+    {
+        pPrev = pCurr;
+        pCurr = pCurr->pNext;
+
+        if (pPrev->pMethod)
+        {
+            /* TODO: Explain why its not leak for non-cancel methods.  */
+            //if (pPrev->pMethod->method == (METHODFUNC)IpcCancelMethod || pPrev->pMethod->method == (METHODFUNC)IpcGetProgressMethod)
+            free(pPrev->pMethod);
+
+            pPrev->pMethod = NULL;
+        }
+        free(pPrev);
+    }
+    pInfo->pMethodList = NULL;
+    pInfo->pRunningMethods = NULL;
+    pthread_mutex_unlock(&(pInfo->Lock));
+
+}
+
+void _FreeHandlePool(IpcServerInfo *pInfo)
+{
+    if (!pInfo)
+        return;
+
+    while(IpcThrPoolIdleCount(pInfo->pHandlePool) != TSC_THREAD_POOL_NUMBERS && IpcThrPoolIdleCount(pInfo->pHandlePool) != -1)  //wait till no detachable thread is running
+    {
+        // TODO: Use condition instead of infinite loop
+        sleep(1);
+    }
+    pthread_mutex_lock(&(pInfo->Lock));
+
+    if (pInfo->pHandlePool)
+    {
+        IpcThrPoolFree(&pInfo->pHandlePool);
+    }
+
+    pthread_mutex_unlock(&(pInfo->Lock));
+}
+
+void _FreeHandleTable(IpcServerInfo *pInfo)
+{
+    if (!pInfo)
+        return;
+
+    pthread_mutex_lock(&(pInfo->Lock));
+    if (pInfo->pTable)
+    {
+        free(pInfo->pTable);
+        pInfo->pTable = NULL;
+    }
+    pthread_mutex_unlock(&(pInfo->Lock));
+}
+
+void _FreeHandleConn(IpcServerInfo *pInfo)
+{
+    if (!pInfo)
+        return;
+
+    pthread_mutex_lock(&(pInfo->Lock));
+    if (pInfo->pConn)
+    {
+        dbus_connection_remove_filter(pInfo->pConn, _IpcServerMsgFilter, pInfo);
+           pInfo->pConn = NULL;
+    }
+    pthread_mutex_unlock(&(pInfo->Lock));
+
+}
+
+void _WaitForListenThreadClose(IpcServerInfo *pInfo)
+{
+    if (pInfo && pInfo->lDbus_listen_thread)
+    {
+        pthread_mutex_lock(&(pInfo->Lock));
+        pInfo->start_server_flag = false;
+        pthread_mutex_unlock(&(pInfo->Lock));
+
+        if (pInfo->lDbus_listen_thread)
+            pthread_join(pInfo->lDbus_listen_thread, NULL);
+    }
+}
+
+int IpcServerAddMethod(TSC_SERVER_HANDLE hServer, IpcServerMethod *pMethod)
+{
+    IpcServerInfo *pInfo = NULL;
+    IpcServerMethodList *pList = NULL;
+    int r = TSC_ERROR_ADD_METHOD_FAILED;
+
+    if (INVALID_TSC_SERVER_HANDLE == hServer)
+        return r;
+
+       pList = calloc(1, sizeof(IpcServerMethodList));
+       if (!pList)
+           return r;
+
+       IpcServerMethod* tpMethod = calloc(1, sizeof(IpcServerMethod));
+       if (tpMethod == NULL)
+       {
+               free(pList);
+               pList = NULL;
+           return r;
+       }
+       // Copy method
+
+       tpMethod->method = pMethod->method;
+       strncpy(tpMethod->szMethod, pMethod->szMethod, TSC_METHOD_NAME_LEN-1);
+       tpMethod->pData = pMethod->pData;
+
+    pInfo = (IpcServerInfo *) hServer;
+
+    pthread_mutex_lock(&(pInfo->Lock));
+    pList->pNext = pInfo->pMethodList;
+
+    //pList->pMethod = pMethod;
+    pList->pMethod = tpMethod;
+
+    pInfo->pMethodList = pList;
+    pthread_mutex_unlock(&(pInfo->Lock));
+
+    r = 0;
+    return r;
+}
+
+int IpcServerRemoveMethod(TSC_SERVER_HANDLE hServer, METHODFUNC method)
+{
+    IpcServerInfo *pInfo = NULL;
+    IpcServerMethodList **pPrev = NULL;
+    IpcServerMethodList *pCurr = NULL;
+    int r = TSC_ERROR_REMOVE_METHOD_NOT_FOUND;
+
+    DDBG("%s\n", "IpcServerRemoveMethod");
+    if (INVALID_TSC_SERVER_HANDLE == hServer)
+        return r;
+
+    pInfo = (IpcServerInfo *) hServer;
+
+    // Change the head to next node, if deleted.
+    pthread_mutex_lock(&(pInfo->Lock));
+       for (pPrev = &pInfo->pMethodList; *pPrev; pPrev = &(*pPrev)->pNext)
+       {
+               DDBG("REMOVE method list name :%s\n", (*pPrev)->pMethod->szMethod);
+               if ((*pPrev)->pMethod->method == method)
+               {
+                       DDBG("==== FIND REVMOE MOETHOD %s\n", " ");
+                       pCurr = *pPrev;
+                       *pPrev = (*pPrev)->pNext;
+            r = 0;
+            break;
+               }
+       }
+    pthread_mutex_unlock(&(pInfo->Lock));
+
+    // Release the found method now.
+    if (r == 0 && pCurr->pMethod)
+    {
+        free(pCurr->pMethod);
+        pCurr->pMethod = NULL;
+    }
+    free(pCurr);
+
+    return r;
+}
+
+TSC_SERVER_HANDLE IpcServerOpen(char *service_name)
+{
+    DDBG("IpcServerOpen: %s\n", service_name);
+       DBusError dberr;
+
+    if (!dbus_threads_init_default())
+    {
+        DDBG("failed dbus_threads_init_default %s\n", "");
+        goto err_ret;
+    }
+
+       dbus_error_init(&dberr);
+
+    if (!dbus_validate_bus_name(service_name, &dberr) && dbus_error_is_set(&dberr))
+    {
+        DDBG("it is invalid request name %s\n", "");
+        goto err;
+    }
+
+       IpcServerInfo *pInfo;
+       if ((pInfo = (IpcServerInfo *) calloc(1, sizeof(IpcServerInfo))) == NULL)
+           goto err;
+
+       pInfo->pMethodList = NULL;
+       pInfo->count = 0;
+       if ((pInfo->pTable = (DBusObjectPathVTable *) calloc(1, sizeof(DBusObjectPathVTable))) == NULL)
+           goto free_info;
+
+       pInfo->lDbus_listen_thread = 0;
+       strncpy(pInfo->name, service_name, TSC_SERVER_NAME_LEN - 1);
+
+       if (_IpcServerInit(pInfo, service_name))
+       {
+           DDBG("IpcServerInit failed: %s\n", service_name);
+           goto free_table;
+       }
+
+    //DDBG("IpcServerOpen  success conn:%s\n", pInfo->name);
+    dbus_error_free(&dberr);
+    return (TSC_SERVER_HANDLE) pInfo;
+
+free_table:
+    SAFE_FREE(pInfo->pTable);
+
+free_info:
+    DDBG("IpcServerOpen free_info, conn:%s\n", pInfo->name);
+    FREE(pInfo);
+
+err:
+    dbus_error_free(&dberr);
+
+err_ret:
+    return INVALID_TSC_SERVER_HANDLE;
+}
+
+int IpcServerMainLoop(TSC_SERVER_HANDLE hServer)
+{
+    IpcServerInfo *pInfo = (IpcServerInfo*) hServer;
+    if (pInfo)
+    {
+        if (pInfo->lDbus_listen_thread)
+        {
+            pthread_join(pInfo->lDbus_listen_thread, NULL);
+            DDBG("finsihed main loop:%s\n", "==========");
+        }
+
+    }
+    return 0;
+}
+void IpcServerClose(TSC_SERVER_HANDLE *hServer)
+{
+       IpcServerInfo *pInfo = (IpcServerInfo *) *hServer;
+       if (pInfo != (IpcServerInfo*)INVALID_TSC_SERVER_HANDLE)
+       {
+           DDBG("IpcServerClose:%s\n", pInfo->name);
+           _WaitForListenThreadClose(pInfo);
+
+           // Wait till no detachable thread is running
+        while (IpcThrPoolIdleCount(pInfo->pHandlePool) != TSC_THREAD_POOL_NUMBERS && IpcThrPoolIdleCount(pInfo->pHandlePool) != -1)
+        {
+            // TODO: Use conditional mutex.
+            sleep(1);
+        }
+
+        _FreeHandleTable(pInfo);
+        _FreeHandleMethods(pInfo);
+        _FreeHandlePool(pInfo);
+        _FreeHandleConn(pInfo);
+        pthread_mutex_destroy(&(pInfo->Lock));
+
+        free(pInfo);
+        *hServer = INVALID_TSC_SERVER_HANDLE;
+       }
+}
+
+
+int _IpcServerInit(IpcServerInfo *pInfo, char *szServiceName)
+{
+    IpcServerMethod *pMethodCancel = NULL;
+    DBusError dberr;
+    int ret;
+
+    if (!pInfo)
+        goto err;
+
+    pInfo->pMethodList = NULL;
+    pInfo->pRunningMethods = NULL;
+    pInfo->start_server_flag = false;
+
+    dbus_error_init(&dberr);
+
+    pInfo->pConn = dbus_bus_get(DBUS_BUS_SYSTEM, &dberr);
+    if (pInfo->pConn == NULL && dbus_error_is_set(&dberr))
+    {
+        DBUS_D_LOG(dberr, "%s\n", "Server failed: connection NULL.");
+        goto free_err;
+    }
+
+    ret = dbus_bus_request_name(pInfo->pConn, szServiceName, DBUS_NAME_FLAG_REPLACE_EXISTING, &dberr);
+    if (ret == -1 && dbus_error_is_set(&dberr))
+    {
+        DBUS_D_LOG(dberr, "%s\n", "server failed: request name.");
+        goto free_conn;
+    }
+
+    // TODO: Why not allow DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER also?
+    if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+    {
+       DDBG("server failed: Not primary owner :%d\n", ret);
+        goto free_conn;
+    }
+
+    if (0 > snprintf(pInfo->rule, sizeof(pInfo->rule), "type='method_call', interface='%s'",
+                     TSC_DBUS_INTERFACE))
+    {
+        DDBG("%s\n", "server failed: Unable to write rule");
+        goto free_conn;
+    }
+
+    dbus_bus_add_match(pInfo->pConn, pInfo->rule, &dberr);
+    if (dbus_error_is_set(&dberr))
+    {
+        DBUS_D_LOG(dberr, "%s\n", "Match add failed.");
+        goto free_conn;
+    }
+
+    if (!dbus_connection_try_register_object_path(pInfo->pConn, TSC_DBUS_PATH, pInfo->pTable,
+                                                   pInfo, &dberr)
+               && dbus_error_is_set(&dberr))
+    {
+        DBUS_D_LOG(dberr, "%s\n", "server failed: register object path");
+        goto free_match;
+    }
+
+    dbus_connection_set_exit_on_disconnect(pInfo->pConn, false);
+
+    if (!dbus_connection_add_filter(pInfo->pConn, _IpcServerMsgFilter, pInfo, NULL))
+    {
+       DDBG("%s\n", "server failed: add filter.");
+        goto free_register;
+    }
+
+    if (!dbus_connection_get_unix_fd(pInfo->pConn, &pInfo->fd) || pInfo->fd < 0)
+    {
+       DDBG("%s\n", "server failed: get fd.");
+        goto free_filter;
+    }
+
+    pInfo->pHandlePool = calloc(1, sizeof(IpcHandlePool));
+    if (pInfo->pHandlePool == NULL)
+    {
+        DDBG("%s\n", "Thread pool alloc failed.");
+        goto free_filter;
+    }
+
+    ret = IpcThrPoolInit(pInfo->pHandlePool, TSC_THREAD_POOL_NUMBERS);
+    if (ret)
+    {
+        DDBG("%s\n", "*****Failed in IpcThrPoolInit");
+        goto free_handle;
+    }
+
+    ret = pthread_mutex_init(&(pInfo->Lock), NULL);
+    if (ret)
+    {
+        DDBG("Failed to init IpcServerInfo lock %d\n", ret);
+        goto free_pool;
+    }
+
+    // Add default two methods: Cancel and GetStatus
+    pMethodCancel = calloc(1, sizeof(IpcServerMethod));
+    if (pMethodCancel == NULL)
+    {
+        DDBG("%s\n", "Cancel alloc failed.");
+        goto free_mutex;
+    }
+
+    ret = snprintf(pMethodCancel->szMethod, sizeof(pMethodCancel->szMethod), "%s", TSC_FN_CANCELMETHOD);
+    if (ret < 0)
+    {
+        DDBG("%s\n", "Cancel create failed.");
+        goto free_method_cancel;
+    }
+
+    pMethodCancel->method = (METHODFUNC) IpcCancelMethod;
+    pMethodCancel->pData = NULL;
+    ret = IpcServerAddMethod((TSC_SERVER_HANDLE) pInfo,  pMethodCancel);
+    if (ret)
+    {
+        DDBG("%s\n", "Cancel add failed.");
+        goto free_method_cancel;
+    }
+
+    IpcServerMethod *pMethodProgress = calloc(1, sizeof(IpcServerMethod));
+    if (pMethodProgress == NULL)
+    {
+        DDBG("%s\n", "Progress alloc failed.");
+        goto free_method_cancel;
+    }
+
+    ret = snprintf(pMethodProgress->szMethod, sizeof(pMethodProgress->szMethod), "%s", TSC_FN_PROGRESSMETHOD);
+    if (ret < 0)
+    {
+        DDBG("%s\n", "Progress create failed.");
+        goto free_method_progress;
+    }
+
+    pMethodProgress->method = (METHODFUNC) IpcGetProgressMethod;
+    pMethodProgress->pData = NULL;
+
+    ret = IpcServerAddMethod((TSC_SERVER_HANDLE) pInfo, pMethodProgress);
+    if (ret)
+    {
+        DDBG("%s\n", "Progress add failed.");
+        goto free_method_progress;
+    }
+
+    IpcServerMethod *pMethodShutdown = calloc(1, sizeof(IpcServerMethod));
+    if (pMethodShutdown == NULL)
+    {
+        DDBG("%s\n", "shutdown alloc failed.");
+        goto free_method_progress;
+    }
+
+    ret = snprintf(pMethodShutdown->szMethod, sizeof(pMethodShutdown->szMethod), "%s", TSC_FN_SHUTDOWN);
+    if (ret < 0)
+    {
+        DDBG("%s\n", "Shutdown create failed.");
+        goto free_method_shutdown;
+    }
+
+    pMethodShutdown->method = (METHODFUNC) IpcShutdown;
+    pMethodShutdown->pData = NULL;
+
+    ret = IpcServerAddMethod((TSC_SERVER_HANDLE) pInfo, pMethodShutdown);
+    if (ret)
+    {
+        DDBG("%s\n", "Shutdown add failed.");
+        goto free_method_shutdown;
+    }
+    SAFE_FREE(pMethodShutdown);
+    SAFE_FREE(pMethodProgress);
+    SAFE_FREE(pMethodCancel);
+
+    pthread_mutex_lock(&(pInfo->Lock));
+
+    ret = pthread_create(&(pInfo->lDbus_listen_thread), NULL, _IpcPopMessage, (void *)pInfo);
+    DDBG("Creating thrd for Server: %s\n", pInfo->name);
+
+    if (ret)
+    {
+        DDBG("%s(%d)\n", "** FAILED to launch thread", ret);
+        pInfo->start_server_flag = false;
+        pthread_mutex_unlock(&(pInfo->Lock));
+        goto free_mutex;
+    }
+    pInfo->start_server_flag = true;
+
+    pthread_mutex_unlock(&(pInfo->Lock));
+
+    return 0;
+free_method_shutdown:
+    SAFE_FREE(pMethodShutdown);
+free_method_progress:
+    SAFE_FREE(pMethodProgress);
+free_method_cancel:
+    SAFE_FREE(pMethodCancel);
+free_mutex:
+    pthread_mutex_destroy(&(pInfo->Lock));
+free_pool:
+free_handle:
+    if (pInfo->pHandlePool)
+        IpcThrPoolFree(&pInfo->pHandlePool);
+free_filter:
+    //dbus_connection_remove_filter(pInfo->pConn, _IpcServerMsgFilter, pInfo);
+free_register:
+    //dbus_connection_unregister_object_path(pInfo->pConn, TSC_DBUS_PATH);
+free_match:
+    //dbus_bus_remove_match(pInfo->pConn, pInfo->rule, &dberr);
+free_conn:
+    //dbus_connection_close(pInfo->pConn); TODO: Why not????
+free_err:
+    dbus_error_free(&dberr);
+    DDBG("%s", "_IpcServerInit free_err before return -1\n");
+err:
+    return -1;
+}
+
+void _IpcServerDeInit(TSC_SERVER_HANDLE hServer)
+{
+    DDBG("%s\n", "IpcServerDeInit========");
+       IpcServerInfo *pInfo = (IpcServerInfo *) hServer;
+    if (pInfo)
+    {
+        if (pInfo->lDbus_listen_thread)
+        {
+            pthread_join(pInfo->lDbus_listen_thread, NULL);
+        }
+        FreeIpcServerHandle((TSC_SERVER_HANDLE) pInfo);
+    }
+    //dbus_shutdown(); // for valgrind only
+    DDBG("%s\n", "*_*_*_*_*_*_* Server is disconnected *_*_*_*_*_*_*_*_*");
+}
+
+
+DBusHandlerResult _IpcServerReplyMessage(DBusConnection *pConn, DBusMessage *pMsg,
+                                                char **pReply, int size)
+{
+    DDBG("%s %d\n", "ReplyMessage size: ", size);
+    DBusMessage *pReplyMsg = NULL;
+    DBusMessageIter    iter;
+    int i;
+
+    if (pConn == NULL)
+        return DBUS_HANDLER_RESULT_HANDLED;
+
+    pReplyMsg = dbus_message_new_method_return(pMsg);
+
+    if (pReplyMsg == NULL)
+        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+    dbus_message_iter_init_append(pReplyMsg, &iter);
+
+    for (i = 0; i < size; i++)
+    {
+        if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &(pReply[i])))
+        {
+            DDBG("----- Replied string :%s\n", pReply[i]);
+            dbus_message_unref(pReplyMsg);
+            return DBUS_HANDLER_RESULT_NEED_MEMORY;
+        }
+    }
+
+    return _IpcSendMessageAndUnref(pConn, pReplyMsg);
+}
+
+DBusHandlerResult _IpcServerReplyError(DBusConnection *pConn, DBusMessage *pMsg,
+                                              int iErrCode)
+{
+    DDBG("%s\n", "IpcServerReplyError");
+    DBusMessage *pErrMsg = NULL;
+
+    if (!pConn || !pMsg)
+        return DBUS_HANDLER_RESULT_HANDLED;
+
+    pErrMsg = dbus_message_new_error(pMsg, GetErrorName(iErrCode), GetErrorDescription(iErrCode));
+    if (!pErrMsg)
+        return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+    return _IpcSendMessageAndUnref(pConn, pErrMsg);
+}
+
+
+DBusHandlerResult _IpcServerMsgFilter(DBusConnection *pConn, DBusMessage *pMsg, void *pData)
+{
+    DDBG("%s\n", "IpcServerMsgFilter");
+    IpcServerInfo *pInfo = (IpcServerInfo*) pData;
+    if (!pInfo)
+    {
+       DDBG("%s\n", "not handled the server info");
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+    else if (dbus_message_is_signal(pMsg, DBUS_INTERFACE_LOCAL, "Disconnected"))
+    {
+       DDBG("%s\n", "server is disconnected by signal");
+        IpcServerClose((TSC_SERVER_HANDLE*) pInfo);
+        //return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+        return DBUS_HANDLER_RESULT_HANDLED;
+    }
+
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
+DBusHandlerResult _IpcServerMsgHandler(void *user_data)
+{
+    DBusHandlerResult ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    IpcAsyncInfo *pAsync = user_data;
+
+    if (pAsync)
+    {
+        DBusMessage *pMsg = pAsync->pMsg;
+        IpcServerInfo *pInfo = pAsync->pInfo;
+
+        bool handle_flag = false;
+        if (pInfo)
+        {
+            DDBG("==IpcServerMsgHandler:%s\n", pInfo->name);
+            IpcServerMethodList **pPrev;
+            pthread_mutex_lock(&(pInfo->Lock));
+            for (pPrev = &pInfo->pMethodList; *pPrev; pPrev = &(*pPrev)->pNext)
+            {
+                if ((*pPrev) && (*pPrev)->pMethod)
+                {
+                    if (dbus_message_is_method_call(pMsg, TSC_DBUS_INTERFACE, (*pPrev)->pMethod->szMethod)){
+                        DDBG("FOUND method: %s\n", (*pPrev)->pMethod->szMethod);
+                        handle_flag = true;
+                        pAsync->pMethod = (*pPrev)->pMethod;
+                        break;
+                    }
+                }
+            }
+            pthread_mutex_unlock(&(pInfo->Lock));
+            if (handle_flag)
+            {
+                return _IpcServerProcessMessage(pAsync);
+            }
+        }
+        if (ret == DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
+        {
+            if (pAsync->pInfo->pHandlePool)
+            {
+                IpcThrPoolPut(pAsync->pInfo->pHandlePool, pAsync->pHandle);
+            }
+            CleanupAsync(pAsync);
+        }
+
+    }
+
+    return ret;
+}
+
+int _ParseDBusMessage(DBusMessage *pMsg, int *pargc, char ***argv)
+{
+    DBusBasicValue temp = {{0}};
+    int argc = 0;
+    int iSize = TSC_REPLY_MSG_COUNT_AVERAGE;
+    DBusMessageIter iter;
+    int iRet = TSC_ERROR_NOT_IMPLEMENTED;   // Return as result of method requested by client.
+
+    if (dbus_message_iter_init(pMsg, &iter))
+    {
+        do
+        {
+            if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+            {
+                DDBG("%s\n", "wrong type");
+                if (argc == 0)
+                    iSize = 0;
+                iRet = TSC_ERROR_NOT_IMPLEMENTED;
+                goto clean_up;
+            }
+            dbus_message_iter_get_basic(&iter, &temp);
+            if (!temp.str)
+            {
+                DDBG("%s\n", "no string");
+                iRet = TSC_ERROR_INTERNAL;
+                goto clean_up;
+            }
+
+            if (argc >= iSize)
+            {
+                iSize += TSC_REPLY_MSG_COUNT_AVERAGE;
+                (*argv) = realloc((*argv), sizeof(char*) * iSize);
+
+                if (!(*argv))
+                {
+                    DDBG("PARSE message, insufficient: 7-1, argc:%d iSize:%d\n",  argc, iSize);
+                    iRet = TSC_ERROR_INSUFFICIENT_RES;
+                    iSize = iSize - TSC_REPLY_MSG_COUNT_AVERAGE;
+                    goto clean_up;
+                }
+            }
+            else if (argc == 0)
+            {
+                (*argv) = calloc(1, iSize * sizeof(char *));
+                if (!(*argv))
+                {
+                    iRet = TSC_ERROR_INSUFFICIENT_RES;
+                    iSize = 0;  //reset iSize, used to free the memory
+                    goto clean_up;
+                }
+            }
+
+            (*argv)[argc] = strdup((const char*)temp.str);
+
+            if (!(*argv)[argc])
+            {
+                DDBG("not engough memory: %s\n", "4");
+                iRet = TSC_ERROR_INSUFFICIENT_RES;
+                goto clean_up;
+            }
+            argc++;
+        } while (dbus_message_iter_next(&iter));
+
+        iRet = 0;   // TODO: Is this the right place & code?
+    }
+    else
+    {
+        DDBG("%s\n", "Request message has no arguments");
+        *pargc = argc;
+        return iRet;
+    }
+
+clean_up:
+
+    if (iRet)
+    {
+        //Error code here
+       int i = 0;
+       if (*argv)
+       {
+               for (i = 0; i < iSize; i++)
+               {
+                       if ((*argv)[i])
+                               free((*argv)[i]);
+                       (*argv)[i] = NULL;
+               }
+                   free(*argv);
+                   *argv = NULL;
+       }
+    }
+    else
+    {
+        // Everything went well till now...
+        *pargc = argc;
+    }
+
+    return iRet;
+}
+
+
+DBusHandlerResult _IpcServerProcessMessage(void *user_data)
+{
+    DDBG("%s\n", "IpcServerProcessMessage");
+    IpcAsyncInfo *pAsync = user_data;
+    DBusError dberr;
+    char **reply = NULL;
+    int iFreeMtdHandle = 0;
+    int len = 0;
+//    int iErr = DBUS_HANDLER_RESULT_HANDLED; // Return the result to caller of this function.
+    int iRet = TSC_ERROR_MODULE_GENERIC;   // Return as result of method requested by client.
+    IpcMethodHandle *pMtdHandle = NULL;
+
+    dbus_error_init(&dberr);
+    if (pAsync->pConn == NULL)
+    {
+        goto clean_up;
+    }
+    // Here when calling method, pass the callback function
+    pMtdHandle = calloc(1, sizeof(IpcMethodHandle));
+
+    if (pMtdHandle == NULL)
+    {
+        goto clean_up;
+    }
+
+    pMtdHandle->pMethod = pAsync->pMethod;
+    iRet = pthread_mutex_init(&(pMtdHandle->Lock), NULL);
+    if (iRet)
+    {
+        if (pMtdHandle)
+            free(pMtdHandle);
+        pMtdHandle = NULL;
+        goto clean_up;
+    }
+
+    if ((pAsync->pMethod)->method)
+    {
+        // insert to RunningMethods
+        if (pAsync->argv[0] == NULL)
+        {
+            goto clean_up;
+        }
+
+        strncpy(pMtdHandle->unique_id, pAsync->async_unique_id, MSGHANDLE_LEN);
+        (pMtdHandle->unique_id)[MSGHANDLE_LEN] = '\0';
+
+        pthread_mutex_lock(&pAsync->pInfo->Lock);
+        (pAsync->pInfo->count)++;
+        pMtdHandle->pNext = pAsync->pInfo->pRunningMethods;
+        pAsync->pInfo->pRunningMethods = pMtdHandle;
+/*
+        DDBG("============== after adding running method:%s\n", "------");
+        IterateList(pMtdHandle);
+*/
+        pthread_mutex_unlock(&pAsync->pInfo->Lock);
+
+        pMtdHandle->pInfo = pAsync->pInfo;
+        pMtdHandle->cStatus = "1";
+        pMtdHandle->iCancel = TSC_NON_CANCEL;
+
+        // Skip the first params which is for unique_id
+        DDBG("method to run:%s, argv[0]:%s\n", pAsync->pMethod->szMethod, pAsync->argv[0]);
+
+        iRet = (pAsync->pMethod)->method((pAsync->pMethod)->pData, pAsync->argc - 1,
+                                         &(pAsync->argv[1]), &reply, &len,
+                                         (CALLBACKFUNC) IpcServerCallbackMethod, pMtdHandle);
+        iRet = 0; //till here, able to run the method, it is success
+    }
+
+clean_up:
+
+    if (iRet)
+        _IpcServerReplyError(pAsync->pConn, pAsync->pMsg, TSC_ERROR_INTERNAL);
+    else
+    {
+        // Everything went well till now...
+        _IpcServerReplyMessage(pAsync->pConn, pAsync->pMsg, reply, len);
+    }
+
+    dbus_connection_flush(pAsync->pConn);
+    CleanupArray(&reply, len);
+
+    // Method finished, remove it from pInfo, running methods list
+    IpcMethodHandle **pmpPrev;
+    pthread_mutex_lock(&(pAsync->pInfo->Lock));
+    for (pmpPrev = &(pAsync->pInfo->pRunningMethods); *pmpPrev; pmpPrev = &((*pmpPrev)->pNext))
+    {
+        if (strncmp((*pmpPrev)->unique_id, pAsync->async_unique_id,  MSGHANDLE_LEN) == 0)
+        {
+            *pmpPrev = (*pmpPrev)->pNext;
+            iFreeMtdHandle = 1;
+            DDBG("FOUND method, and remove from running one, method:%s, uniquid:%s\n",
+                      pAsync->pMethod->szMethod, pAsync->async_unique_id);
+            IterateList(pAsync->pInfo->pRunningMethods);
+            break;
+        }
+    }
+    pthread_mutex_unlock(&(pAsync->pInfo->Lock));
+
+    IpcThrPoolPut(pAsync->pInfo->pHandlePool, pAsync->pHandle);
+    CleanupAsync(pAsync);
+    dbus_error_free(&dberr);
+
+    if (pMtdHandle && iFreeMtdHandle)
+    {
+        free(pMtdHandle);
+        pMtdHandle = NULL;
+    }
+
+    return iRet;
+}
+
+void *_IpcPopMessage(void *hServer)
+{
+    IpcServerInfo *pInfo = (IpcServerInfo *) hServer;
+    DDBG("=IpcPopMessage:%s\n", pInfo->name);
+    int iRet = 0;
+
+    while (pInfo != NULL && pInfo->pConn != NULL && pInfo->start_server_flag) {
+
+        // non blocking read of the next available message
+        dbus_connection_read_write(pInfo->pConn, 0);
+        DBusMessage *pMsg = dbus_connection_pop_message(pInfo->pConn);
+
+        if (NULL == pMsg) {
+            sleep(TSC_READ_WRITE_DISPATCH_SLEEP_SECONDS);
+            continue;
+        }
+        else
+        {
+            // TODO: Strangely, first message needs to be processed, for the next N pending msgs
+            // to be picked up for asynchronous processing.
+            IpcHandles *pIpcHandle = IpcThrPoolGet(pInfo->pHandlePool);
+               IpcAsyncInfo *pAsync = calloc(1, sizeof(IpcAsyncInfo));
+               if (pAsync != NULL)
+               {
+                pAsync->pConn = pInfo->pConn;
+                pAsync->pInfo = pInfo;
+                pAsync->pMsg = pMsg;
+                pAsync->argc = 0;
+                pAsync->argv = NULL;
+                pAsync->pHandle = pIpcHandle;
+
+                iRet = _ParseDBusMessage(pMsg, &(pAsync->argc), &(pAsync->argv));
+
+                if (iRet == 0)
+                {
+                    iRet = snprintf(pAsync->async_unique_id, MSGHANDLE_LEN, TSC_MID_SVR_FORMAT, pAsync->argv[0],
+                                                       dbus_message_get_serial(pAsync->pMsg));
+                    //DDBG("ASYNC_UNQIEU-DI: %s\n", pAsync->async_unique_id);
+                    if (iRet < 0)
+                        break;
+
+                    iRet = _RunDetachedThread(_IpcServerMsgHandler, pAsync);
+                    DDBG("====RunDetachedThread ret:%d\n", iRet);
+                }
+
+                if (iRet)
+                {
+                    IpcThrPoolPut(pInfo->pHandlePool, pIpcHandle);
+                    CleanupAsync(pAsync);
+                }
+
+               }
+        }
+    }
+    DDBG("popmessage ended :%s\n", "============");
+
+    return NULL;
+}
+
+
+void CleanupArray(char*** pArr, int len)
+{
+    if (pArr) {
+        while (len > 0)
+        {
+            len--;
+            free ((*pArr)[len]);
+            (*pArr)[len] = NULL;
+        }
+        free(*pArr);
+        *pArr = NULL;
+    }
+}
+
+void CleanupAsync(IpcAsyncInfo *pAsync)
+{
+    if (pAsync)
+    {
+        CleanupArray(&(pAsync->argv), pAsync->argc);
+        if (pAsync->pMsg)
+            dbus_message_unref(pAsync->pMsg);
+
+        if (pAsync)
+            free(pAsync);
+        pAsync = NULL;
+
+    }
+}
+
+/***
+ * reason_params is cleaned up within this method
+ */
+int IpcServerCallbackMethod(TSC_METHOD_HANDLE *pMHandle, TSC_METHOD_REASON_CODE iReason, void *reason_params)
+{
+    IpcMethodHandle  *p_MHandle = (IpcMethodHandle *) pMHandle;
+    char *data = reason_params;
+    int iRet = -1;
+
+    if (iReason == TSC_CANCEL)
+    {
+        pthread_mutex_lock(&(p_MHandle->Lock));
+        if (p_MHandle->iCancel == TSC_IS_CANCEL)
+        {
+            iRet = 0;
+            DDBG("%s", "callback check, it is cancel true\n");
+        }
+        pthread_mutex_unlock(&(p_MHandle->Lock));
+    }
+    else if (iReason == TSC_PROGRESS)
+    {
+        pthread_mutex_lock(&(p_MHandle->Lock));
+        p_MHandle->cStatus = strdup(data);  // TODO: any better way to update data?
+        iRet = 0;
+        pthread_mutex_unlock(&(p_MHandle->Lock));
+
+        if (data)
+            free(data);
+        data = NULL;
+    }
+    return iRet;
+}
+
+/*void IpcCancelMethod(TSC_SERVER_HANDLE hServer, char  *method_unique_id)*/
+int IpcCancelMethod(void *pData, int argc, char **argv, char ***szReply, int *len, CALLBACKFUNC callback, TSC_METHOD_HANDLE *handle)
+{
+
+    int ret = 0;
+    if (argc > 0)
+    {
+        DDBG("IpcCancelMethod unique_id %s\n", argv[0]);
+    }
+    else
+    {
+        DDBG("%s\n", "Error params in cancel method");
+    }
+
+    //TODO :error checking
+    IpcMethodHandle *pMHandle = (IpcMethodHandle*) handle;
+    IpcServerInfo *pInfo = (IpcServerInfo*) pMHandle->pInfo;
+    // Get the running method by the method_unique_id, then set its cancel flag
+    IpcMethodHandle **pmpPrev;
+
+    if (argc != 1)
+    {
+        //the argc should be 2, the second param is unique id of to cancel method
+        ret = -1;
+    }
+    pthread_mutex_lock(&(pInfo->Lock));
+
+    for (pmpPrev = &(pInfo->pRunningMethods); *pmpPrev; pmpPrev = &((*pmpPrev)->pNext))
+    {
+        DDBG("Method to cancel: %s, list method:%s\n", argv[0], (*pmpPrev)->unique_id);
+        if (strcmp((*pmpPrev)->unique_id, argv[0]) == 0)
+        {
+            DDBG("%s\n", "found the running method to cancel");
+            pthread_mutex_lock(&(pMHandle->Lock));
+            (*pmpPrev)->iCancel = TSC_IS_CANCEL;
+            DDBG("%s %s\n", "set is cancel to true for this method: ", (*pmpPrev)->unique_id);
+            //TODO: should we return something?
+            *len = 1;
+            *szReply = calloc(1, sizeof(char*) *(*len));
+            (*szReply)[0] = strdup("0");
+            pthread_mutex_unlock(&(pMHandle->Lock));
+            break;
+        }
+    }
+    pthread_mutex_unlock(&(pInfo->Lock));
+
+    DDBG("%s\n", "END OF cancel method");
+    return ret;
+}
+
+
+
+int
+IpcGetProgressMethod(void *pData, int argc, char **argv, char ***szReply, int *len, CALLBACKFUNC callback, TSC_METHOD_HANDLE *handle)
+{
+    DDBG("%s\n", "IpcGetProgressMethod");
+    IpcMethodHandle *pMHandle = (IpcMethodHandle*) handle;
+    IpcServerInfo *pInfo = (IpcServerInfo*) pMHandle->pInfo;
+
+    //TODO: Error handling, check argv argc
+    //Here the running method finished, either end or cancelled.
+    IpcMethodHandle **pmpPrev;
+    for (pmpPrev = &(pInfo->pRunningMethods); *pmpPrev; pmpPrev = &((*pmpPrev)->pNext))
+    {
+        DDBG("running methods unique id :%s,  passing id :%s \n", (*pmpPrev)->unique_id, argv[0]);
+
+        if (!strcmp((*pmpPrev)->unique_id, argv[0]))
+        {
+            DDBG("=== found running method to get progress %s\n", argv[0]);
+            // get the running method, update its status
+            *len = 1;
+            *szReply = calloc(1, sizeof(char*) * 10);
+            DDBG("-- status to reply :%s\n",(*pmpPrev)->cStatus);
+            (*szReply)[0] = strdup((*pmpPrev)->cStatus);
+            break;
+        }
+    }
+    return 0;
+}
+
+int
+IpcShutdown(void *pData, int argc, char **argv, char ***szReply, int *len, CALLBACKFUNC callback, TSC_METHOD_HANDLE *handle)
+{
+    DDBG("==============%s\n", "IpcShutdownMethod");
+    IpcMethodHandle *pMHandle = (IpcMethodHandle*) handle;
+    IpcServerInfo *pInfo = (IpcServerInfo*) pMHandle->pInfo;
+
+    pthread_mutex_lock(&(pInfo->Lock));
+    pInfo->start_server_flag = false;
+    pthread_mutex_unlock(&(pInfo->Lock));
+    DDBG("end of shutdown:%s\n", "===================");
+    return 0;
+}
+
+
+void FreeIpcServerHandle(TSC_SERVER_HANDLE hServer)
+{
+    DDBG("%s\n", "FreeIpcServerHandle");
+    IpcServerInfo *pInfo = (IpcServerInfo*) hServer;
+
+    if (pInfo)
+    {
+        pthread_mutex_lock(&(pInfo->Lock));
+        // Free MethodList
+        IpcServerMethodList *pCurr = pInfo->pMethodList;
+        IpcServerMethodList *pPrev;
+
+        while (pCurr)
+        {
+            pPrev = pCurr;
+            pCurr = pCurr->pNext;
+            DDBG("*****pPrev method is 0 :%s\n", pPrev->pMethod->szMethod);
+
+            if (pPrev)
+            {
+                if (pPrev->pMethod)
+                {
+                    if (pPrev->pMethod->method == (METHODFUNC) IpcCancelMethod
+                            || pPrev->pMethod->method == (METHODFUNC) IpcGetProgressMethod
+                            || pPrev->pMethod->method == (METHODFUNC) IpcShutdown)
+                    {
+                       free(pPrev->pMethod);
+                    }
+                    pPrev->pMethod = NULL;
+                }
+                if (pPrev->pNext)
+                {
+                       pPrev->pNext = NULL;
+                }
+
+                free(pPrev);
+                pPrev = NULL;
+            }
+        }
+
+        pInfo->pMethodList = NULL;
+        pInfo->pRunningMethods = NULL;
+
+        if (pInfo->pHandlePool)
+            IpcThrPoolFree(&pInfo->pHandlePool);
+
+        pthread_mutex_unlock(&(pInfo->Lock));
+
+        pthread_mutex_destroy(&(pInfo->Lock));
+
+        if (pInfo->pTable)
+            free(pInfo->pTable);
+        pInfo->pTable = NULL;
+
+        if (pInfo->pConn)
+        {
+            DBusError dberr;
+            dbus_error_init(&dberr);
+
+            dbus_connection_remove_filter(pInfo->pConn, _IpcServerMsgFilter, pInfo);
+            dbus_connection_unregister_object_path(pInfo->pConn, TSC_DBUS_PATH);
+            dbus_bus_remove_match(pInfo->pConn, pInfo->rule, &dberr);
+
+            dbus_bus_release_name(pInfo->pConn, TSC_DBUS_SERVER, &dberr);
+
+            dbus_connection_unref(pInfo->pConn);
+            dbus_error_free(&dberr);
+        }
+        pInfo->pConn = NULL;
+
+        free(pInfo);
+        pInfo = NULL;
+    }
+}
+
+
+
+/**
+ * Creates a thread for asynchronous task.
+ * TODO: Merge with TCS module.
+ */
+int _RunDetachedThread(void *pfWorkerFunc, void *pThreadData)
+{
+    pthread_t thread;
+    pthread_attr_t attr;
+
+    int rc = -1;
+    do
+    {
+        if (pthread_attr_init(&attr) != 0)
+            break;
+
+        if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
+            break;
+
+
+        if (pthread_create(&thread, &attr, pfWorkerFunc, pThreadData) != 0)
+            break;
+
+        if (pthread_attr_destroy(&attr) != 0)
+        {
+            // As the thread is already running, return different error code.
+            rc = -2;
+            break;
+        }
+
+        rc = 0;
+    }
+    while (0);
+    return rc;
+}
+
diff --git a/framework/IpcServer.h b/framework/IpcServer.h
new file mode 100644 (file)
index 0000000..d187700
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+    
+    All rights reserved.
+    
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+    
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+    
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+    
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+    
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef IPCSERVER_H
+#define IPCSERVER_H
+
+#ifdef __cplusplus 
+extern "C" {
+#endif
+
+/**
+ * \file IpcServer.h
+ * \brief Ipc Server Header File
+ *  
+ * This file provides the IPC Server API functions used by Security framework.
+ */
+
+#include <dbus/dbus.h>
+#include <stdbool.h>
+#include "IpcMacros.h"
+
+
+/*==================================================================================================
+                                 STRUCTURES AND OTHER TYPEDEFS
+==================================================================================================*/
+
+/**
+ * Pointer to method requested by client module.
+ */
+/*typedef int (*CALLBACKFUNC) (void *pHandle, TSC_METHOD_REASON_CODE iReason, void *user_data);*/
+typedef int (*CALLBACKFUNC) (void *pHandle, int iReason, void *reason_params);
+
+typedef int (*METHODFUNC) (void *pData, int argc, char **argv, char ***szReply, int *len, CALLBACKFUNC callback, void *pHandle);
+
+/**
+ * Server side method to handle request from client module. All the requests 
+ * are managed in a list.
+ */
+typedef struct _IpcServerMethod
+{
+    char       szMethod[TSC_METHOD_NAME_LEN];
+    METHODFUNC method;
+    void       *pData; //when execute the method, the pData besides the data passed from client, also has methodHandle for this method
+} IpcServerMethod;
+
+#define TSC_NULL ((void *) 0)
+
+#define TSCSERVERHANDLE(n) struct n##_struct {int iDummy;}; typedef struct n##_struct *n
+TSCSERVERHANDLE(TSC_SERVER_HANDLE);
+
+#define TSCMETHODHANDLE(n) struct n##_struct {int iDummy;}; typedef struct n##_struct *n
+TSCMETHODHANDLE(TSC_METHOD_HANDLE);
+
+#define INVALID_TSC_METHOD_HANDLE ((TSC_METHOD_HANDLE) TSC_NULL)
+
+#define INVALID_TSC_SERVER_HANDLE ((TSC_SERVER_HANDLE) TSC_NULL)
+
+/*==================================================================================================
+                                     FUNCTION PROTOTYPES
+==================================================================================================*/
+
+/**
+ * \brief Adds a handler method to the list of methods at server, to process 
+ * request from the client.
+ *
+ * During initialisation, the server builds a list of handlers to process
+ * request coming from client-side IPC. Later the client side IPC sends request
+ * along with the name of the handler to use. The handlers are implemented
+ * in the module hosting the server-side IPC.
+ *
+ * This is a synchronous API.
+ *
+ * \param[in] pMethod Details of the handler method to be added at server-side.
+ *
+ * \return Return Type (void) \n
+ *
+ */
+int IpcServerAddMethod(TSC_SERVER_HANDLE hServer, IpcServerMethod *pMethod);
+
+/**
+ * \brief Removes a handler method from the list of methods at server.
+ *
+ * During initialisation, the server builds a list of handlers to process
+ * request coming from client-side IPC. Later the client side IPC sends request
+ * along with the name of the handler to use. The handlers are implemented
+ * in the module hosting the server-side IPC. As part of un-initialisation
+ * the handler should be removed from the list.
+ *
+ * This is a synchronous API.
+ *
+ * \param[in] pMethod Pointer to handler method to be removed.
+ *
+ * \return Return Type (void) \n
+ *
+ */
+int IpcServerRemoveMethod(TSC_SERVER_HANDLE hServer, METHODFUNC pMethod);
+
+
+/*
+void IpcCancelMethod(TSC_SERVER_HANDLE hServer, char *method_unique_id);
+char *IpcGetProgressMethod(TSC_SERVER_HANDLE hServer, char *method_unique_id);
+*/
+/**
+ * \brief Initialises the server-side IPC to make it ready for request from
+ * client side IPC.
+ *
+ * The IPC has two parts - client and server. The server-side IPC processes the
+ * request sent from the client-side IPC. The server-side uses handlers provided
+ * by the hosting module. When server comes up, the IPC needs to be initialised
+ * and be ready for the requests.
+ *
+ * This is a synchronous API.
+ *
+ * \return Return Type (int) \n
+ * 0 - on send success. \n
+ * -1 - on send failure. \n
+ */
+TSC_SERVER_HANDLE IpcServerOpen(char *servie_name);
+
+/**
+ * \brief Close the server-side IPC and release the resources.
+ *
+ * This is a synchronous API.
+ *
+ * \return Return Type (void) \n
+ */
+void IpcServerClose(TSC_SERVER_HANDLE*);
+
+int IpcServerMainLoop(TSC_SERVER_HANDLE hServer);
+
+/**
+ * Callback function for Server Stub in cancel the method, update method progress
+ */
+
+
+
+#ifdef __cplusplus
+}
+#endif 
+
+#endif  /* IPCSERVER_H */
+
diff --git a/framework/IpcServerError.c b/framework/IpcServerError.c
new file mode 100644 (file)
index 0000000..cdcb069
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+    
+    All rights reserved.
+    
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+    
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+    
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+    
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+    
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * \file IpcServerError.c
+ * \brief Ipc server-side error handling File
+ *  
+ * This file contains the server-side exception handling, used by Security framework.
+ */
+
+#include "IpcMacros.h"
+#include "IpcServerError.h"
+#include "TSCErrorCodes.h"
+
+const char *GetErrorName(const int iErrCode)
+{
+    switch (iErrCode)
+    {
+    case TSC_ERROR_CANCELLED:
+        return TSC_DBUS_INTERFACE ERR_NAME_CANCELLED;
+    case TSC_ERROR_DATA_ACCESS:
+        return TSC_DBUS_INTERFACE ERR_NAME_DATA_ACCESS;
+    case TSC_ERROR_INVALID_PARAM:
+        return TSC_DBUS_INTERFACE ERR_NAME_INVALID_PARAM;
+    case TSC_ERROR_INSUFFICIENT_RES:
+        return TSC_DBUS_INTERFACE ERR_NAME_INSUFFICIENT_RES;
+    case TSC_ERROR_INTERNAL:
+        return TSC_DBUS_INTERFACE ERR_NAME_INTERNAL;
+    case TSC_ERROR_INVALID_HANDLE:
+        return TSC_DBUS_INTERFACE ERR_NAME_INVALID_HANDLE;
+    case TSC_ERROR_NOT_IMPLEMENTED:
+        return TSC_DBUS_INTERFACE ERR_NAME_NOT_IMPLEMENTED;
+    }
+
+    /* default: TSC_ERROR_MODULE_GENERIC */
+    return TSC_DBUS_INTERFACE ERR_NAME_MODULE_GENERIC;
+}
+
+const char *GetErrorDescription(const int iErrCode)
+{
+    switch (iErrCode)
+    {
+    case TSC_ERROR_CANCELLED:
+        return ERR_DESC_CANCELLED;
+    case TSC_ERROR_DATA_ACCESS:
+        return ERR_DESC_DATA_ACCESS;
+    case TSC_ERROR_INVALID_PARAM:
+        return ERR_DESC_INVALID_PARAM;
+    case TSC_ERROR_INSUFFICIENT_RES:
+        return ERR_DESC_INSUFFICIENT_RES;
+    case TSC_ERROR_INTERNAL:
+        return ERR_DESC_INTERNAL;
+    case TSC_ERROR_INVALID_HANDLE:
+        return ERR_DESC_INVALID_HANDLE;
+    case TSC_ERROR_NOT_IMPLEMENTED:
+        return ERR_DESC_NOT_IMPLEMENTED;
+    }
+
+    /* default: TSC_ERROR_MODULE_GENERIC */
+    return ERR_DESC_MODULE_GENERIC;
+}
diff --git a/framework/IpcServerError.h b/framework/IpcServerError.h
new file mode 100644 (file)
index 0000000..e45a450
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+    
+    All rights reserved.
+    
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+    
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+    
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+    
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+    
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef IPCSERVERERROR_H
+#define IPCSERVERERROR_H
+
+#ifdef __cplusplus 
+extern "C" {
+#endif
+
+/**
+ * \file IpcServerError.h
+ * \brief Ipc server-side error Header File
+ *  
+ * This file contains the server-side error code details, used by Security framework.
+ */
+
+const char *GetErrorName(const int iErrCode);
+const char *GetErrorDescription(const int iErrCode);
+
+#ifdef __cplusplus
+}
+#endif 
+
+#endif  /* IPCSERVERERROR_H */
diff --git a/framework/IpcServerHdr.h b/framework/IpcServerHdr.h
new file mode 100644 (file)
index 0000000..d48d4d2
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef IPCSERVERHDR_H
+#define IPCSERVERHDR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "IpcServer.h"
+#include "IpcThrdPool.h"
+
+#define SAFE_FREE(x)    if (x) {free(x); x = NULL;}
+#define FREE(x)         if (x) {free(x);}
+
+/**
+ * Forward Declarations.
+ */
+/*struct IpcServerInfo;*/
+typedef struct _IpcServerInfo IpcServerInfo;
+
+/**
+ * Keep registered methods list
+ */
+typedef struct _IpcServerMethodList
+{
+    IpcServerMethod *pMethod;
+    struct _IpcServerMethodList *pNext;
+} IpcServerMethodList;
+
+/**
+ * Keep the context for callback passed to stub method
+ */
+typedef struct _IpcMethodHandle
+{
+    IpcServerMethod *pMethod;
+    void *pData;
+    IpcServerInfo *pInfo;
+    char unique_id[MSGHANDLE_LEN + 1]; //uniquely identify the running method
+    int iCancel;  // 1 is cancel, 0 not cancel
+    char *cStatus;    // any status
+    pthread_mutex_t Lock;
+
+    struct _IpcMethodHandle *pNext;
+} IpcMethodHandle;
+
+/**
+ *  Single context per server connection.
+ */
+struct _IpcServerInfo
+{
+    char name[TSC_SERVER_NAME_LEN + 1];
+    DBusConnection *pConn;
+    IpcServerMethodList *pMethodList;   // available methods list
+    char rule[TSC_INFO_RULE_LEN];
+    int fd;
+    bool start_server_flag;
+    DBusObjectPathVTable *pTable; //TODO: it is core dump if new thread the running method through pTable registered list
+    pthread_t lDbus_listen_thread; //listen thread on the socket for reading message
+    IpcHandlePool *pHandlePool; // thread pool for the running methods
+    int count;
+    IpcMethodHandle *pRunningMethods;  // current running methods
+    pthread_mutex_t Lock;   // mutex to manage methods - iteration, add, remove.
+};
+
+
+/**
+ * Copy the data from the message read from the listening/reading socket thread, and pass it to the reply thread, where executing the method
+ */
+typedef struct _IpcAsyncInfo
+{
+    DBusConnection *pConn;
+    IpcServerInfo *pInfo;
+    DBusMessage *pMsg;
+    int argc;
+    char **argv;
+    IpcServerMethod *pMethod;
+    IpcHandles *pHandle;
+    char async_unique_id[MSGHANDLE_LEN + 1]; //uniquely identify the running method
+} IpcAsyncInfo;
+
+int _IpcServerInit(IpcServerInfo *pServerInfo, char *szServiceName);
+void _IpcServerDeInit(TSC_SERVER_HANDLE hServer);
+DBusHandlerResult _IpcServerReplyMessage(DBusConnection *pConn, DBusMessage *pMsg,
+                                         char **pReply, int size);
+DBusHandlerResult _IpcServerMsgFilter(DBusConnection *pConn, DBusMessage *pMsg, void *pData);
+int _ParseDBusMessage(DBusMessage *pMsg, int *argc, char ***argv);
+DBusHandlerResult _IpcServerMsgHandler(void *data);
+DBusHandlerResult _IpcServerProcessMessage(void *data);
+void *_IpcPopMessage(void *hServer);
+void CleanupArray(char*** pArr, int len);
+void CleanupAsync(IpcAsyncInfo *pAsync);
+void FreeIpcServerHandle(TSC_SERVER_HANDLE hServer);
+DBusHandlerResult _IpcServerReplyError(DBusConnection *pConn, DBusMessage *pMsg,
+                                       int iErrCode);
+int IpcCancelMethod(void *pData, int argc, char **argv, char ***szReply, int *len, CALLBACKFUNC callback, TSC_METHOD_HANDLE *handle);
+int IpcGetProgressMethod(void *pData, int argc, char **argv, char ***szReply, int *len, CALLBACKFUNC callback, TSC_METHOD_HANDLE *handle);
+int IpcShutdown(void *pData, int argc, char **argv, char ***szReply, int *len, CALLBACKFUNC callback, TSC_METHOD_HANDLE *handle);
+int IpcServerCallbackMethod(TSC_METHOD_HANDLE *pMHandle, TSC_METHOD_REASON_CODE iReason, void *reason_params);
+int _RunDetachedThread(void *pfWorkerFunc, void *pThreadData);
+
+
+void _FreeHandleMethods(IpcServerInfo *pServerInfo);
+void _FreeHandlePool(IpcServerInfo *pServerInfo);
+void _FreeHandleTable(IpcServerInfo *pServerInfo);
+void _FreeHandleConn(IpcServerInfo *pServerInfo);
+void _WaitForListenThreadClose(IpcServerInfo *pServerInfo);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/framework/IpcStructs.c b/framework/IpcStructs.c
new file mode 100644 (file)
index 0000000..1d73751
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+    
+    All rights reserved.
+    
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+    
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+    
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+    
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+    
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * \file IpcStructs.c
+ * \brief Source File for structures needed by Ipc.
+ *  
+ * This file implements the structures needed by IPC Client, used by Security framework.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "IpcStructs.h"
+
+/**
+ * Assign new fields to existing call handle.
+ * A NULL pPendingCall will not replace the existing one.
+ */
+int _AssignToClientCallHandle(ClientCallHandle *pHandle, const char *szPrefix, dbus_uint32_t serial,
+                              DBusPendingCall *pPendingCall)
+{
+    int iRet = 1;
+
+    do
+    {
+        if (!pHandle)
+            break;
+
+        if (0 > (iRet = snprintf(pHandle->idUnique, MSGHANDLE_LEN, TSC_MID_SVR_FORMAT, szPrefix,
+                                 serial)))
+            break;
+
+        if (pPendingCall)
+            pHandle->pPendingCall = pPendingCall;
+
+        iRet = 0;
+
+    } while(0);
+
+    return iRet;
+}
+
+int _CreateClientCallHandle(ClientCallHandle **ppHandle, const char *szPrefix, dbus_uint32_t serial,
+                            DBusPendingCall *pPendingCall)
+{
+    int iRet = 1;
+    ClientCallHandle *pHandle = NULL;
+
+    do
+    {
+        if (!ppHandle)
+            break;
+
+        pHandle = (ClientCallHandle *) malloc(sizeof(ClientCallHandle));
+        if (!pHandle)
+            break;
+
+        if ((iRet = _AssignToClientCallHandle(pHandle, szPrefix, serial, pPendingCall)))
+            break;
+
+        *ppHandle = pHandle;
+        iRet = 0;
+
+    } while(0);
+
+    if (iRet && pHandle)
+    {
+        free(pHandle);
+        pHandle = NULL;
+    }
+
+    return iRet;
+}
+
+void _FreeClientCallHandle(ClientCallHandle *pHandle)
+{
+    free(pHandle);
+}
+
+void _FreeSharedData(SharedData *pSharedData)
+{
+    if (pSharedData)
+    {
+        pthread_mutex_destroy(&pSharedData->lock);
+        pthread_cond_destroy(&pSharedData->cond);
+        free(pSharedData);
+    }
+}
+
+// Create the handle to monitor send completion and receive sent message details.
+// Maintains only reference of DBusMessage; Ownership is not changed.
+SharedData *_CreateSharedData(const char *szCallHandlePrefix, DBusMessage *pMsg)
+{
+    int iDone = 0;
+    SharedData *pSharedData = NULL;
+
+    do
+    {
+        if (!pMsg)
+            break;
+
+        if ((pSharedData = (SharedData *)calloc(1, sizeof(SharedData))) == NULL)
+            break;
+
+        if (0 > snprintf(pSharedData->szCallHandlePrefix, MSGHANDLE_LEN, "%s", szCallHandlePrefix))
+            break;
+
+        pSharedData->pMsg = pMsg;
+        pSharedData->pCallHandle = NULL;
+        pSharedData->iSent = 0;
+
+        if (pthread_mutex_init(&(pSharedData->lock), NULL))
+            break;
+
+        if (pthread_cond_init(&(pSharedData->cond), NULL))
+            break;
+
+        iDone = 1;
+    } while(0);
+
+    if (!iDone)
+    {
+        _FreeSharedData(pSharedData);
+        return NULL;
+    }
+    return pSharedData;
+}
+
+ThreadData *_AllocThreadData(DBusConnection *pConn, int timeout_milliseconds,
+                             SharedData *pSharedData, TSCCallback pCallback, void *pPrivate)
+{
+    ThreadData *pThreadData = (ThreadData *)dbus_malloc(sizeof(ThreadData));
+    if (!pThreadData)
+        return NULL;
+
+    pThreadData->pConn = pConn;
+    pThreadData->timeout_milliseconds = timeout_milliseconds;
+    pThreadData->pSharedData = pSharedData;
+    pThreadData->pCallBack = pCallback;
+    pThreadData->pPrivate = pPrivate;
+
+    return pThreadData;
+}
+
+void _FreeThreadData(void *pThreadData)
+{
+    if (pThreadData)
+    {
+        _FreeSharedData(((ThreadData*)pThreadData)->pSharedData);
+    }
+    dbus_free(pThreadData);
+}
+
+
+#include "IpcStructs.h"
diff --git a/framework/IpcStructs.h b/framework/IpcStructs.h
new file mode 100644 (file)
index 0000000..d312a24
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef IPCSTRUCTS_H
+#define IPCSTRUCTS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \file IpcStructs.h
+ * \brief Header File for structures by Ipc.
+ *
+ * This file implements the structures needed by IPC Client, used by Security framework.
+ */
+
+#include <dbus/dbus.h>
+#include <pthread.h>
+
+#include "IpcMacros.h"
+#include "IpcTypes.h"
+
+/*==================================================================================================
+                                 STRUCTURES AND OTHER TYPEDEFS
+==================================================================================================*/
+
+/**
+ * Handle for message sent, to be used for future reference.
+ */
+typedef struct _ClientCallHandle
+{
+    char idUnique[MSGHANDLE_LEN];
+    DBusPendingCall *pPendingCall;
+    char service_name[TSC_SERVER_NAME_LEN + 1];
+} ClientCallHandle;
+
+/**
+ * IPC client connection info.
+ */
+typedef struct _IpcClientInfo
+{
+    DBusConnection *dbconn;
+    char req_name[TSC_REQ_STR_LEN];
+    char pid[TSC_REQ_STR_LEN];
+} IpcClientInfo;
+
+/**
+ * Data shared between the synchronized thread. It wraps the asynchronous call handle.
+ */
+typedef struct _SharedData
+{
+    int iSent;
+    ClientCallHandle *pCallHandle;
+    char szCallHandlePrefix[MSGHANDLE_LEN];
+    DBusMessage *pMsg;
+    pthread_mutex_t lock;
+    pthread_cond_t cond;
+} SharedData;
+
+/**
+ * Data passed to threads sending messages asynchronously.
+ * Owns only SharedData, rest are owned by 'parent thread'.
+ */
+typedef struct _ThreadData
+{
+    DBusConnection *pConn;
+    int timeout_milliseconds;
+    SharedData *pSharedData;
+    TSCCallback pCallBack;
+    void *pPrivate;
+} ThreadData;
+
+/*==================================================================================================
+                                     FUNCTION PROTOTYPES
+==================================================================================================*/
+
+/**
+ * _ClientCallHandle related.
+ */
+int _AssignToClientCallHandle(ClientCallHandle *pHandle, const char *szPrefix, dbus_uint32_t serial,
+                              DBusPendingCall *pPendingCall);
+
+int _CreateClientCallHandle(ClientCallHandle **ppHandle, const char *szPrefix, dbus_uint32_t serial,
+                            DBusPendingCall *pPendingCall);
+
+void _FreeClientCallHandle(ClientCallHandle *pHandle);
+
+/**
+ * SharedData related.
+ */
+void _FreeSharedData(SharedData *pSharedData);
+
+// Create the handle to monitor send completion and receive sent message details.
+// Maintains only reference of DBusMessage; Ownership is not changed.
+SharedData *_CreateSharedData(const char *szCallHandlePrefix, DBusMessage *pMsg);
+
+/**
+ * ThreadData related.
+ */
+ThreadData *_AllocThreadData(DBusConnection *pConn, int timeout_milliseconds,
+                             SharedData *pSharedData, TSCCallback pCallback, void *pPrivate);
+
+void _FreeThreadData(void *pThreadData);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* IPCSTRUCTS_H */
+
diff --git a/framework/IpcThrdPool.c b/framework/IpcThrdPool.c
new file mode 100644 (file)
index 0000000..253b638
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * \file IpcThrdPool.c
+ * \brief Ipc Thread pool Ipc Source File
+ *
+ * This file implements the thread pool used by IPC Server in Security framework.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+#include "Debug.h"
+#include "IpcThrdPool.h"
+
+static void IpcThrPoolReset(IpcHandlePool *pHPool)
+{
+    IpcHandles *pHandle;
+
+    if (!pHPool)
+        return;
+
+    while ((pHandle = pHPool->pHList) != NULL)
+    {
+        pHPool->pHList = pHPool->pHList->pNext;
+        free(pHandle);
+    }
+
+    pthread_cond_destroy(&pHPool->Cond);
+    pthread_mutex_destroy(&pHPool->Lock);
+    pHPool->iIdleCount = 0;
+}
+
+/**
+ * Frees the resources and nullifies the thread pool object.
+ */
+void IpcThrPoolFree(IpcHandlePool **pHPool)
+{
+    IpcThrPoolReset(*pHPool);
+    free(*pHPool);
+    *pHPool = NULL;
+}
+
+/**
+ * Creates a new handle and makes it head of the pool list.
+ * Return 0 on success and -1 on failure.
+ */
+static int AddHandleToThrPool(IpcHandlePool *pHPool)
+{
+    IpcHandles *pHandle = NULL;
+    if ((pHandle = (IpcHandles *) calloc(1, sizeof(IpcHandles))) == NULL)
+    {
+        DDBG("%s\n", "calloc IpcHandles");
+        return -1;
+    }
+
+
+    pHandle->pNext = pHPool->pHList;
+    pHPool->pHList = pHandle;
+    return 0;
+}
+
+/**
+ * Initializes thread pool. Returns 0 on success and -1 on failure.
+ */
+int IpcThrPoolInit(IpcHandlePool *pHPool, int iNumHandles)
+{
+    int i;
+    int result = 0;
+
+    if (!pHPool)
+        return -1;
+
+    if (pthread_mutex_init(&pHPool->Lock, NULL))
+    {
+        DDBG("%s\n", "mutex init");
+        return -1;
+    }
+
+
+    if (pthread_cond_init(&pHPool->Cond, NULL))
+    {
+        pthread_mutex_destroy(&pHPool->Lock);
+        DDBG("%s\n", "cond_init");
+        return -1;
+    }
+
+    pHPool->iIdleCount = iNumHandles;
+    pHPool->pHList = NULL;
+
+    for (i = 0; i < iNumHandles; i++)
+    {
+        if (0 != AddHandleToThrPool(pHPool))
+        {
+            DDBG("%s\n", "add to thrpool");
+            result = -1;
+            break;
+        }
+    }
+
+    return result;
+}
+
+/**
+ * Synchronized method to returns a thread handle from the pool. The method is blocked till a
+ * handle is available.
+ */
+IpcHandles *IpcThrPoolGet(IpcHandlePool *pHPool)
+{
+    IpcHandles *pHandle;
+    pthread_mutex_lock(&pHPool->Lock);
+    while ((pHandle = pHPool->pHList) == NULL)
+    {
+        pthread_cond_wait(&pHPool->Cond, &pHPool->Lock);
+    }
+    pHPool->pHList = pHandle->pNext;
+    (pHPool->iIdleCount)--;
+    pthread_mutex_unlock(&pHPool->Lock);
+
+    return pHandle;
+}
+
+void IpcThrPoolPut(IpcHandlePool *pHPool, IpcHandles *pHandle)
+{
+    pthread_mutex_lock(&pHPool->Lock);
+    pHandle->pNext = pHPool->pHList;
+    pHPool->pHList = pHandle;
+    (pHPool->iIdleCount)++;
+
+    pthread_cond_broadcast(&pHPool->Cond);
+    pthread_mutex_unlock(&pHPool->Lock);
+}
+
+/**
+ * Returns number of handles available in thread pool.
+ * Returns -1 when pool is invalid.
+ */
+int IpcThrPoolIdleCount(IpcHandlePool *pHPool)
+{
+
+    return pHPool? pHPool->iIdleCount : -1;
+}
+
diff --git a/framework/IpcThrdPool.h b/framework/IpcThrdPool.h
new file mode 100644 (file)
index 0000000..2e98f2c
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _IPCTHRDPOOL_H
+#define _IPCTHRDPOOL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "IpcServer.h"
+
+/**
+ *
+ */
+typedef struct IpcHandles_struct
+{
+    struct IpcHandles_struct *pNext;
+    void *pMethodHandle;
+    void *pData;
+} IpcHandles;
+
+/**
+ *
+ */
+typedef struct IpcHandlePool_struct
+{
+    IpcHandles *pHList;
+    pthread_mutex_t Lock;
+    pthread_cond_t Cond;
+    int iIdleCount;
+} IpcHandlePool;
+
+/**
+ * Initializes thread pool. Returns 0 on success and -1 on failure.
+ */
+int IpcThrPoolInit(IpcHandlePool *pHPool, int iNumHandles);
+
+/**
+ * Frees the resources and nullifies the thread pool object.
+ */
+void IpcThrPoolFree(IpcHandlePool **pHPool);
+
+/**
+ * Synchronized method to returns a thread handle from the pool. The method is blocked till a
+ * handle is available.
+ */
+IpcHandles *IpcThrPoolGet(IpcHandlePool *pHPool);
+
+/**
+ *
+ */
+void IpcThrPoolPut(IpcHandlePool *pHPool, IpcHandles *pHandle);
+
+/**
+ * Returns number of handles available in thread pool.
+ * Returns -1 when pool is invalid.
+ */
+int IpcThrPoolIdleCount(IpcHandlePool *pHPool);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/framework/IpcTypes.h b/framework/IpcTypes.h
new file mode 100644 (file)
index 0000000..296c03b
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef IPCTYPES_H
+#define IPCTYPES_H
+
+/**
+ * \file IpcTypes.h
+ * \brief Data types and structs for Security framework IPC clients.
+ *
+ * This file provides the data types and structs needed by clients of Security framework IPC.
+ */
+
+/*==================================================================================================
+                                 STRUCTURES AND OTHER TYPEDEFS
+==================================================================================================*/
+
+/**
+ * \brief CallBack Function type for Async method supported by the IPC.
+ *
+ * \param[in] pPrivate API caller's context information, supplied with TSCSendMessageAsync earlier.
+ * \param[in] argc Length of the string in argv.
+ * \param[in] argv Array of strings representing result value of asynchronous reply.
+ */
+typedef void (*TSCCallback)(void *pPrivate, int argc, const char **argv);
+
+/**
+ * Client side IPC handles.
+ */
+#define TSCHANDLE(n) struct n##_struct { int iDummy; }; typedef struct n##_struct *n
+
+/**
+ * IPC client handle.
+ */
+TSCHANDLE(TSC_IPC_HANDLE);
+#define INVALID_IPC_HANDLE ((TSC_IPC_HANDLE) NULL)
+
+/**
+ * Asynchronous call handle.
+ */
+TSCHANDLE(TSC_CALL_HANDLE);
+
+#endif  /* IPCTYPES_H */
+
diff --git a/framework/Makefile_TPCSSerDaemon b/framework/Makefile_TPCSSerDaemon
new file mode 100644 (file)
index 0000000..47614bf
--- /dev/null
@@ -0,0 +1,103 @@
+#
+#  Copyright (c) 2014, McAfee, Inc.
+#  
+#  All rights reserved.
+#  
+#  Redistribution and use in source and binary forms, with or without modification,
+#  are permitted provided that the following conditions are met:
+#  
+#  Redistributions of source code must retain the above copyright notice, this list
+#  of conditions and the following disclaimer.
+#  
+#  Redistributions in binary form must reproduce the above copyright notice, this
+#  list of conditions and the following disclaimer in the documentation and/or other
+#  materials provided with the distribution.
+#  
+#  Neither the name of McAfee, Inc. nor the names of its contributors may be used
+#  to endorse or promote products derived from this software without specific prior
+#  written permission.
+#  
+#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+#  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+#  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+#  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+#  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+#  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+#  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+#  OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+OUTDIR = bin
+TARGET = $(OUTDIR)/TPCSSerDaemon
+SRCDIR = .
+LD_FLAGS := $(LD_FLAGS) -ldl $(shell pkg-config --libs libtzplatform-config)
+
+ifeq ($(TCS_CC), )
+       CC = gcc
+else
+       CC = $(TCS_CC)
+endif
+ifeq ($(TCS_LD), )
+       LD = ld
+else
+       LD = $(TCS_LD)
+endif
+ifeq ($(TCS_AR), )
+       AR = ar
+else
+       AR = $(TCS_AR)
+endif
+ifeq ($(TCS_STRIP), )
+       STRIP = strip
+else
+       STRIP = $(TCS_STRIP)
+endif
+
+ifeq ($(TCS_CFG), release)
+       CFLAGS := -O3 -fPIE -DUNIX $(CFLAGS)
+else
+       CFLAGS := -g -fPIE -DUNIX -DDEBUG $(CFLAGS)
+endif
+
+# Define a list of pkg-config packages we want to use
+pkg_packages = dbus-glib-1 dlog
+
+PKG_CFLAGS  = $(shell pkg-config --cflags $(pkg_packages))
+PKG_LDFLAGS = $(shell pkg-config --libs $(pkg_packages))
+
+# Combine user supplied, additional, and pkg-config flags
+LD_FLAGS += $(PKG_LDFLAGS) -lscserver -L./lib -lxml2
+
+GBS_CFLAGS = -I${SYSROOT}/usr/include/dbus-1.0 -I${SYSROOT}/usr/lib/dbus-1.0/include -I${SYSROOT}/usr/include/libxml2
+CFLAGS += -I$(SRCDIR) $(PKCL_CFLAGS) $(GBS_CFLAGS) $(PKG_CFLAGS)
+
+SOURCES = $(SRCDIR)/TPCSSerDaemon.c \
+               $(SRCDIR)/IpcForkDaemon.c
+
+OBJECTS = $(OUTDIR)/TPCSSerDaemon.o \
+               $(OUTDIR)/IpcForkDaemon.o
+
+$(OUTDIR)/%.o: $(SRCDIR)/%.c
+       $(CC) $(CFLAGS) -o $(OUTDIR)/$*.o -c $(SRCDIR)/$*.c
+
+all: $(OUTDIR) $(TARGET)
+
+$(TARGET): $(OBJECTS)
+       $(CC) -Wl,-zdefs -o $(TARGET) $(OBJECTS) $(LD_FLAGS) $(PKG_LDFLAGS)
+
+$(OUTDIR):
+       @mkdir $(OUTDIR)
+
+install: all
+       mkdir -p ${DESTDIR}/bin
+       cp ${TARGET} ${DESTDIR}/bin/
+
+distclean: clean
+       @rm -rf $(OUTDIR)
+
+clean:
+       @rm -f $(TARGET)
+       @rm -f $(OBJECTS) *~
+       @rm -f *.bb *.bbg *.da *.gcov
diff --git a/framework/Makefile_TWPSerDaemon b/framework/Makefile_TWPSerDaemon
new file mode 100644 (file)
index 0000000..14e36de
--- /dev/null
@@ -0,0 +1,106 @@
+#
+#  Copyright (c) 2014, McAfee, Inc.
+#  
+#  All rights reserved.
+#  
+#  Redistribution and use in source and binary forms, with or without modification,
+#  are permitted provided that the following conditions are met:
+#  
+#  Redistributions of source code must retain the above copyright notice, this list
+#  of conditions and the following disclaimer.
+#  
+#  Redistributions in binary form must reproduce the above copyright notice, this
+#  list of conditions and the following disclaimer in the documentation and/or other
+#  materials provided with the distribution.
+#  
+#  Neither the name of McAfee, Inc. nor the names of its contributors may be used
+#  to endorse or promote products derived from this software without specific prior
+#  written permission.
+#  
+#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+#  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+#  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+#  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+#  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+#  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+#  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+#  OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+OUTDIR = bin
+TARGET = $(OUTDIR)/TWPSerDaemon
+SRCDIR = .
+INCLUDE = -I. $(TCS_INC) -I../plugin
+LD_FLAGS := $(LD_FLAGS) -ldl -lpthread -lsecfw -lscserver -lm -Llib $(shell pkg-config --libs libtzplatform-config)
+
+ifeq ($(TCS_CC), )
+       CC = gcc
+else
+       CC = $(TCS_CC)
+endif
+ifeq ($(TCS_LD), )
+       LD = ld
+else
+       LD = $(TCS_LD)
+endif
+ifeq ($(TCS_AR), )
+       AR = ar
+else
+       AR = $(TCS_AR)
+endif
+ifeq ($(TCS_STRIP), )
+       STRIP = strip
+else
+       STRIP = $(TCS_STRIP)
+endif
+
+ifeq ($(TCS_CFG), release)
+       CFLAGS := -O3 -fPIC $(INCLUDE) -DUNIX $(CFLAGS)
+else
+       CFLAGS := -g -fPIC $(INCLUDE) -DUNIX -DDEBUG $(CFLAGS)
+endif
+
+CFLAGS := $(CFLAGS) $(PKCL_CFLAGS) $(TCS_CFLAGS)
+
+SOURCES = $(SRCDIR)/TWPSerDaemon.c \
+               $(SRCDIR)/IpcForkDaemon.c 
+
+OBJECTS = $(OUTDIR)/TWPSerDaemon.o \
+               $(OUTDIR)/IpcForkDaemon.o
+
+# Define a list of pkg-config packages we want to use
+ifeq ($(TCS_CFG), release)
+       pkg_packages = dbus-glib-1
+else
+       pkg_packages = dbus-glib-1 dlog
+endif
+
+PKG_CFLAGS  = $(shell pkg-config --cflags $(pkg_packages))
+PKG_LDFLAGS = $(shell pkg-config --libs $(pkg_packages))
+
+# Combine user supplied, additional, and pkg-config flags
+PKGLD_FLAGS += $(PKG_LDFLAGS) -lscserver -L./lib
+
+GBS_CFLAGS = -I${SYSROOT}/usr/include/dbus-1.0 -I${SYSROOT}/usr/lib/dbus-1.0/include
+PKGCFLAGS += -I$(SRCDIR) $(PKCL_CFLAGS) $(GBS_CFLAGS) $(PKG_CFLAGS)
+
+$(OUTDIR)/%.o: $(SRCDIR)/%.c
+       $(CC) $(CFLAGS) $(PKGCFLAGS) -I. -o $(OUTDIR)/$*.o -c $(SRCDIR)/$*.c
+
+all: $(OUTDIR) $(TARGET)
+
+$(TARGET): $(OBJECTS)
+       $(CC) -Wl,-zdefs -o $(TARGET) $(OBJECTS) $(LD_FLAGS) $(PKGLD_FLAGS)
+
+$(OUTDIR):
+       @mkdir $(OUTDIR)
+
+distclean: clean
+       @rm -rf $(OUTDIR)
+
+clean:
+       @rm -f $(TARGET)
+       @rm -f $(OBJECTS) *~
+       @rm -f *.bb *.bbg *.da *.gcov
diff --git a/framework/Makefile_channel_client b/framework/Makefile_channel_client
new file mode 100644 (file)
index 0000000..a1ce28e
--- /dev/null
@@ -0,0 +1,108 @@
+#
+#  Copyright (c) 2014, McAfee, Inc.
+#  
+#  All rights reserved.
+#  
+#  Redistribution and use in source and binary forms, with or without modification,
+#  are permitted provided that the following conditions are met:
+#  
+#  Redistributions of source code must retain the above copyright notice, this list
+#  of conditions and the following disclaimer.
+#  
+#  Redistributions in binary form must reproduce the above copyright notice, this
+#  list of conditions and the following disclaimer in the documentation and/or other
+#  materials provided with the distribution.
+#  
+#  Neither the name of McAfee, Inc. nor the names of its contributors may be used
+#  to endorse or promote products derived from this software without specific prior
+#  written permission.
+#  
+#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+#  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+#  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+#  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+#  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+#  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+#  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+#  OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+OUTDIR = lib
+TARGET = $(OUTDIR)/libscclient.so
+SRCDIR = .
+LD_FLAGS := $(LD_FLAGS) -ldl -lpthread $(shell pkg-config --libs libtzplatform-config)
+
+ifeq ($(TCS_CC), )
+       CC = gcc
+else
+       CC = $(TCS_CC)
+endif
+ifeq ($(TCS_LD), )
+       LD = ld
+else
+       LD = $(TCS_LD)
+endif
+ifeq ($(TCS_AR), )
+       AR = ar
+else
+       AR = $(TCS_AR)
+endif
+ifeq ($(TCS_STRIP), )
+       STRIP = strip
+else
+       STRIP = $(TCS_STRIP)
+endif
+
+ifeq ($(TCS_CFG), release)
+       CFLAGS := -O3 -fPIC -DUNIX $(CFLAGS)
+else
+       CFLAGS := -g -fPIC -DUNIX -DDEBUG $(CFLAGS)
+endif
+
+# Define a list of pkg-config packages we want to use
+
+ifeq ($(TCS_CFG), release)
+       pkg_packages = dbus-glib-1
+else
+       pkg_packages =  dbus-glib-1 dlog
+endif
+
+PKG_CFLAGS  = $(shell pkg-config --cflags $(pkg_packages))
+PKG_LDFLAGS = $(shell pkg-config --libs $(pkg_packages))
+
+# Combine user supplied, additional, and pkg-config flags
+LD_FLAGS += $(PKG_LDFLAGS)
+
+GBS_CFLAGS = -I${SYSROOT}/usr/include/dbus-1.0 -I${SYSROOT}/usr/lib/dbus-1.0/include
+CFLAGS   += $(PKCL_CFLAGS) $(TCS_CFLAGS) $(GBS_CFLAGS) $(PKG_CFLAGS)
+
+SOURCES = $(SRCDIR)/IpcClient.c        \
+               $(SRCDIR)/IpcStructs.c
+
+OBJECTS = $(OUTDIR)/IpcClient.o        \
+               $(OUTDIR)/IpcStructs.o
+
+$(OUTDIR)/%.o: $(SRCDIR)/%.c
+       $(CC) $(CFLAGS) -o $(OUTDIR)/$*.o -c $(SRCDIR)/$*.c
+
+all: $(OUTDIR) $(TARGET)
+
+$(TARGET): $(OBJECTS)
+       $(CC) -shared -Wl,-zdefs -o $(TARGET) $(OBJECTS) $(LD_FLAGS)
+
+$(OUTDIR):
+       @mkdir $(OUTDIR)
+
+install: all
+       mkdir -p ${DESTDIR}/bin
+       cp ${TARGET} ${DESTDIR}/bin/
+
+distclean: clean
+       @rm -rf $(OUTDIR)
+
+clean:
+       @rm -f $(TARGET)
+       @rm -f $(OBJECTS) *~
+       @rm -f *.bb *.bbg *.da *.gcov
diff --git a/framework/Makefile_channel_server b/framework/Makefile_channel_server
new file mode 100644 (file)
index 0000000..e5b94c1
--- /dev/null
@@ -0,0 +1,109 @@
+#
+#  Copyright (c) 2014, McAfee, Inc.
+#  
+#  All rights reserved.
+#  
+#  Redistribution and use in source and binary forms, with or without modification,
+#  are permitted provided that the following conditions are met:
+#  
+#  Redistributions of source code must retain the above copyright notice, this list
+#  of conditions and the following disclaimer.
+#  
+#  Redistributions in binary form must reproduce the above copyright notice, this
+#  list of conditions and the following disclaimer in the documentation and/or other
+#  materials provided with the distribution.
+#  
+#  Neither the name of McAfee, Inc. nor the names of its contributors may be used
+#  to endorse or promote products derived from this software without specific prior
+#  written permission.
+#  
+#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+#  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+#  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+#  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+#  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+#  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+#  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+#  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+#  OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+OUTDIR = lib
+TARGET = $(OUTDIR)/libscserver.so
+SRCDIR = .
+LD_FLAGS := $(LD_FLAGS) -ldl -lpthread $(shell pkg-config --libs libtzplatform-config)
+
+ifeq ($(TCS_CC), )
+       CC = gcc
+else
+       CC = $(TCS_CC)
+endif
+ifeq ($(TCS_LD), )
+       LD = ld
+else
+       LD = $(TCS_LD)
+endif
+ifeq ($(TCS_AR), )
+       AR = ar
+else
+       AR = $(TCS_AR)
+endif
+ifeq ($(TCS_STRIP), )
+       STRIP = strip
+else
+       STRIP = $(TCS_STRIP)
+endif
+
+ifeq ($(TCS_CFG), release)
+       CFLAGS := -O3 -fPIC -DUNIX $(CFLAGS)
+else
+       CFLAGS := -g -fPIC -DUNIX -DDEBUG $(CFLAGS)
+endif
+
+# Define a list of pkg-config packages we want to use
+ifeq ($(TCS_CFG), release)
+       pkg_packages = dbus-glib-1
+else
+       pkg_packages = dbus-glib-1 dlog
+endif
+
+PKG_CFLAGS  = $(shell pkg-config --cflags $(pkg_packages))
+PKG_LDFLAGS = $(shell pkg-config --libs $(pkg_packages))
+
+# Combine user supplied, additional, and pkg-config flags
+LD_FLAGS += $(PKG_LDFLAGS)
+
+GBS_CFLAGS = -I${SYSROOT}/usr/include/dbus-1.0 -I${SYSROOT}/usr/lib/dbus-1.0/include
+CFLAGS   += $(PKCL_CFLAGS) $(TCS_CFLAGS) $(GBS_CFLAGS) $(PKG_CFLAGS)
+
+SOURCES = $(SRCDIR)/IpcServer.c \
+               $(SRCDIR)/IpcServerError.c \
+                       $(SRCDIR)/IpcThrdPool.c
+
+OBJECTS = $(OUTDIR)/IpcServer.o \
+               $(OUTDIR)/IpcServerError.o \
+                       $(OUTDIR)/IpcThrdPool.o
+
+$(OUTDIR)/%.o: $(SRCDIR)/%.c
+       $(CC) $(CFLAGS) -o $(OUTDIR)/$*.o -c $(SRCDIR)/$*.c
+
+all: $(OUTDIR) $(TARGET)
+
+$(TARGET): $(OBJECTS)
+       $(CC) -shared -Wl,-zdefs -o $(TARGET) $(OBJECTS) $(LD_FLAGS)
+
+$(OUTDIR):
+       @mkdir $(OUTDIR)
+
+install: all
+       mkdir -p ${DESTDIR}/bin
+       cp ${TARGET} ${DESTDIR}/bin/
+
+distclean: clean
+       @rm -rf $(OUTDIR)
+
+clean:
+       @rm -f $(TARGET)
+       @rm -f $(OBJECTS) *~
+       @rm -f *.bb *.bbg *.da *.gcov
diff --git a/framework/TPCSSerDaemon.c b/framework/TPCSSerDaemon.c
new file mode 100644 (file)
index 0000000..fcb2687
--- /dev/null
@@ -0,0 +1,1399 @@
+/**
+ * Methods supported in TPCS (Tizen Plugin Control Service)
+ */
+
+#include <dirent.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <ftw.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlreader.h>
+#include <libxml/xmlwriter.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "Debug.h"
+#include "IpcServer.h"
+#include "IpcForkDaemon.h"
+#include "TPCSSerDaemon.h"
+
+/**
+ * This daemon provides four services to manage plugins.
+ * InstallPlugin, UninstallPlugin, SetActivePlugin, GetInfoPlugin
+ *
+ * It maintains config.xml that has the plugin info.
+ * It will recover the config.xml if it is corrupted.
+ *
+ * During the services, the update config.xml and set up the symbolic link of the library is an
+ * atomic action.
+ * Daemon will store the config.xml in the buffer. When running each method, the buffer config.xml
+ * is copied to pData and being update inside the method.
+ * Except the GetInfoPlugin(), all other methods serializing when updating the config.xml.
+ */
+
+/**
+ * Common Utils, TODO: move to Utils.c
+ *
+ */
+
+typedef struct _ConfigBuf
+{
+    xmlDoc *pConfigBuffer;
+    pthread_mutex_t configLock;
+} ConfigBuf;
+
+static void GetNSURI(xmlDoc *pXmlDoc, xmlChar **pns, xmlChar **uri);
+static void GetConfigElements(xmlDoc **pXmlDoc, xmlChar *pXPath, int *size, char ***content);
+static int WriteXmlToFile(xmlDoc *pXmlDoc, const char* filename);
+static int UpdatePluglibList(const char *appPath, xmlDoc **pXmlDoc, const char *appId);
+static int ActivePlugin(ConfigBuf *pBuf, xmlDoc **pXmlCp, const xmlChar *appId);
+static void SetSuccessReturn(int *argc, char ***argv);
+static void SetFailureReturn(int *argc, char ***argv);
+static void CleanupArray(char*** pArr, int len);
+static int EndsWith(char const *hay, char const *needle);
+
+/**
+ * Local functions declaration.
+ */
+static int HasTag(const char *pTag, const char *pFileName, const char *xpath);
+int UpdateNode(const xmlChar* content, xmlDoc **pDoc, const xmlChar *xpathNodeParent,
+               const char* appID);
+
+static void SetReturn(int *res_argc, char ***res_argv, char *val)
+{
+    if (val)
+    {
+        *res_argv = calloc(1, sizeof(char*));
+        if (*res_argv)
+        {
+            (*res_argv)[0] = strdup((const char*) val);
+            if ((*res_argv)[0])
+            {
+                *res_argc = 1;
+                return;
+            }
+        }
+
+        free(*res_argv);
+        *res_argc = 0;
+    }
+}
+
+static void SetSuccessReturn(int *res_argc, char ***res_argv)
+{
+    SetReturn(res_argc, res_argv, RETURN_SUCCESS);
+}
+
+static void SetFailureReturn(int *res_argc, char ***res_argv)
+{
+    SetReturn(res_argc, res_argv, RETURN_FAILURE);
+}
+
+int SearchNodeN(const xmlChar *xpath, xmlDoc *pXmlDoc, xmlXPathObject **pXPathObj)
+{
+    DDBG("searchNode :%s\n", xpath);
+    int result = -1;
+    xmlXPathContextPtr pXPathCtx;
+
+    pXPathCtx = xmlXPathNewContext(pXmlDoc);
+    if (pXPathCtx == NULL)
+        return result;
+
+    xmlChar *pns = NULL;
+    xmlChar *puri = NULL;
+    GetNSURI(pXmlDoc, &pns, &puri);
+
+    if (pns != NULL && puri != NULL)
+    {
+        if (xmlXPathRegisterNs(pXPathCtx, pns, puri) != 0)
+            return result;
+    }
+
+    //Evaluate xpath expression
+    *pXPathObj = xmlXPathEvalExpression(xpath, pXPathCtx);
+    DDBG("============== XPATHobj address:%p\n", *pXPathObj);
+
+    if (*pXPathObj == NULL)
+    {
+        DDBG("Cannot find node:%s\n", xpath);
+        free(pns);
+        free(puri);
+        return result;
+    }
+
+    result = 0;
+
+    free(pns);
+    free(puri);
+
+    xmlXPathFreeContext(pXPathCtx);
+    return result;
+
+}
+
+// Dynamically load the library, get the product name, vendor name and version number, then
+// update the xml file.
+int InsertNode(xmlDoc **pDoc, const xmlChar *xpathNodeParent, const char *content)
+{
+    DDBG("insert node :%s\n", "==============");
+    int result = -1;
+    xmlXPathContext *pXPathCtx;
+    xmlXPathObject *pXPathObj;
+
+    pXPathCtx = xmlXPathNewContext(*pDoc);
+    if (pXPathCtx != NULL)
+    {
+        xmlChar *pns = NULL;
+        xmlChar *puri = NULL;
+        GetNSURI(*pDoc, &pns, &puri);
+        if (pns != NULL && puri != NULL)
+        {
+            if (xmlXPathRegisterNs(pXPathCtx, pns, puri) != 0)
+            {
+                DDBG("Cannot register xpath :%s\n", "");
+                return result;
+            }
+        }
+
+        // Evaluate xpath expression
+        pXPathObj = xmlXPathEvalExpression(xpathNodeParent, pXPathCtx);
+        if (pXPathObj != NULL)
+        {
+            xmlNodeSet *pNodeSet = pXPathObj->nodesetval;
+            int size;
+            size = pNodeSet ? pNodeSet->nodeNr : 0;
+            if (size == 1) // Should find only one node
+            {
+                // Get xmlnode
+                xmlDoc *pPlugDoc = xmlReadMemory(content, strlen(content), NULL, NULL, 0);
+                DDBG("plugdoc :%s\n", content);
+
+                if (pPlugDoc != NULL)
+                {
+                    xmlNode *newnode = xmlDocCopyNode(xmlDocGetRootElement(pPlugDoc),
+                                                      pNodeSet->nodeTab[0]->doc,1);
+                    DDBG("=========== pplugdoc address:%p\n", pPlugDoc);
+
+                    xmlFreeDoc(pPlugDoc);
+                    //xmlNode *addNode = xmlAddChildList(pNodeSet->nodeTab[0], newnode->children);
+                    xmlNode *addNode = xmlAddChildList(pNodeSet->nodeTab[0], newnode->children);
+                    DDBG("=========== new node addr:%p\n", newnode);
+
+                    if (addNode != NULL)
+                    {
+                        result = 0;
+                        DDBG("FREE new node:%p\n", newnode);
+                        newnode->children = NULL;
+                        xmlFreeNode(newnode);
+                    }
+                }
+            }
+        }
+        free(pns);
+        free(puri);
+        pns = NULL;
+        puri = NULL;
+
+        xmlXPathFreeObject(pXPathObj);
+        xmlXPathFreeContext(pXPathCtx);
+    }
+
+    return result;
+}
+
+int RemoveNodeParent(xmlDoc **pDoc, const xmlChar *path, const char* value)
+{
+    int result = -1;
+    if (*pDoc != NULL)
+    {
+        xmlXPathContext *pXPathCtx;
+        xmlXPathObject *pXPathObj;
+
+        pXPathCtx = xmlXPathNewContext(*pDoc);
+
+        if (pXPathCtx != NULL)
+        {
+            xmlChar *pns = NULL;
+            xmlChar *puri = NULL;
+            GetNSURI(*pDoc, &pns, &puri);
+            if (pns != NULL && puri != NULL)
+            {
+                if (xmlXPathRegisterNs(pXPathCtx, pns, puri) != 0)
+                {
+                    return result;
+                }
+            }
+            pXPathObj = xmlXPathEvalExpression(path, pXPathCtx);
+            if (pXPathObj != NULL)
+            {
+                xmlNodeSet *pNodeSet = pXPathObj->nodesetval;
+
+                int size;
+                size = pNodeSet ? pNodeSet->nodeNr : 0;
+                int i = 0;
+                xmlNode *cur;
+                xmlNode *parent;
+                for (; i < size; i++)
+                {
+                    cur = pNodeSet->nodeTab[i]->children;
+                    if (strcmp((const char*)cur->content, value) == 0)
+                    {
+                        parent = cur->parent->parent;
+                        xmlUnlinkNode(parent);
+                        break;
+                    }
+                    else
+                        DDBG("THEY ARE NOT EQUAL:%s\n", value);
+
+                }
+                result = 0;
+                xmlXPathFreeObject(pXPathObj);
+            }
+            free(pns);
+            free(puri);
+            pns = NULL;
+            puri = NULL;
+            xmlXPathFreeContext(pXPathCtx);
+        }
+    }
+    return result;
+}
+
+int PrintXmlDoc(xmlDocPtr pDoc)
+{
+#ifdef DEBUG
+    int result = 0;
+    int xmlSize;
+    xmlChar *xmlMem;
+    xmlDocDumpFormatMemory(pDoc, &xmlMem, &xmlSize, 0);
+    DDBG("pdoc content:%s\n", xmlMem);
+    free(xmlMem);
+    return result;
+#else
+    return 0;
+#endif
+}
+
+int UpdateConfigFile(ConfigBuf **pData, xmlDoc **pXmlCp)
+{
+    int result = -1;
+
+    if (pData && *pData)
+    {
+        pthread_mutex_lock(&((*pData)->configLock));
+        if (pXmlCp && *pXmlCp)
+        {
+            result = WriteXmlToFile(*pXmlCp, CONFIG_FILE_NEW_W_PATH);
+            if (result == 0)
+            {
+                DDBG("==============update config file%s\n", " ");
+                PrintXmlDoc(*pXmlCp);
+                result = WriteXmlToFile(*pXmlCp, CONFIG_FILE_W_PATH);
+                if (result == 0)
+                {
+                    //delete config new file
+                    DDBG("REMOVE file:%s\n", CONFIG_FILE_NEW_W_PATH);
+                    result = remove(CONFIG_FILE_NEW_W_PATH);
+
+                     if ((*pData)->pConfigBuffer != NULL)
+                         xmlFreeDoc((*pData)->pConfigBuffer);
+
+                    (*pData)->pConfigBuffer = xmlCopyDoc(*pXmlCp, DO_RECURSIVE_COPY);
+                }
+            }
+        }
+        pthread_mutex_unlock(&((*pData)->configLock));
+    }
+    return result;
+}
+
+static int UpdatePlugin(const char *libname, xmlDoc **pXmlDoc, const char* appId)
+{
+    DDBG("~~~~~ UPDATE plugin: libname:%s, appID:%s\n", libname, appId);
+    int result = -1;
+    void *pHandle = NULL;
+
+    pHandle = dlopen(libname, RTLD_LAZY);
+    if (pHandle == NULL)
+    {
+        char *error;
+        if ((error = dlerror()) != NULL)
+            DDBG("failed to open lib: %s, error:%s\n", libname, error);
+    }
+    else
+    {
+        char *pInfo = NULL;
+        char* (*getInfo)(void);
+
+        DDBG("open library:%s\n", libname);
+        getInfo = dlsym(pHandle, "TCSGetInfo");
+
+        if (getInfo == NULL)
+        {
+            char *error;
+            if ((error = dlerror()) != NULL)
+                DDBG("SOMETHID :%s\n", error);
+        }
+        else
+        {
+            pInfo = strdup(getInfo());
+            if (pInfo != NULL)
+            {
+                // Update node tree
+                result = UpdateNode((const xmlChar*) pInfo, pXmlDoc, (const xmlChar*) XPATH_PLUGINS,
+                                    appId);
+                free(pInfo);
+                pInfo = NULL;
+            }
+        }
+
+        dlclose(pHandle);
+    }
+    return result;
+}
+
+/**
+ * Get plugins node, should only have one node. After that, Check if has the node with appId, if so,
+ * remove this node. otherwise, add the new node.
+ */
+int UpdateNode(const xmlChar* content, xmlDoc **pDoc, const xmlChar *xpathNodeParent,
+               const char* appId)
+{
+    int result = -1;
+
+    // Remove the plugin first if its appId same
+    char appidpath[GENERIC_STRING_SIZE];
+    strncpy(appidpath, (const char*) XPATH_PLUGINS_PLUG, sizeof(appidpath));
+    result = RemoveNodeParent(pDoc, (const xmlChar *)appidpath, appId);
+
+    result = InsertNode(pDoc, xpathNodeParent, (const char*)content);
+    return result;
+}
+
+static int ActivePlugin(ConfigBuf *pBuf, xmlDoc **pXmlCp, const xmlChar *appId)
+{
+    int result = -1;
+
+    xmlXPathObject *pObj = NULL;
+    result = SearchNodeN((const xmlChar *)XPATH_ACTIVE_PLUGIN, *pXmlCp, &pObj);
+
+    PrintXmlDoc(*pXmlCp);
+
+    if (result == -1)
+        return result;
+
+    result = -1;
+    xmlNodeSet *pNodeSet = NULL;
+    if (pObj)
+    {
+       pNodeSet = pObj->nodesetval;
+    }
+
+    // If appId is empty, disable the active plugin, update activePlugin Node to None
+    if (strcmp((const char*)appId, APP_ID_NULL) == 0)
+    {
+        pthread_mutex_lock(&(pBuf->configLock));
+        result = unlink(SYSLINK_PLUG_PATH);
+        pthread_mutex_unlock(&(pBuf->configLock));
+
+               if (pNodeSet)
+               {
+                       if (pNodeSet->nodeTab[0])
+                       {
+                               xmlNode *cur = pNodeSet->nodeTab[0];
+                               xmlNodeSetContent(cur, (xmlChar*)ACTIVE_NONE);
+                               DDBG("GET node content :%s\n", cur->content);
+                       }
+               }
+               result = 0;
+    }
+    else
+    {
+        // Get the plugin path from the appPath, set symbolic link for the plugin, update the xmlDoc
+        int count;
+        char **paths = NULL;
+        GetConfigElements(pXmlCp, (xmlChar *) XPATH_APP_PATHS, &count, &paths);
+        int i = 0;
+        for (; i < count; i++)
+        {
+            char appPath[FILE_NAME_MAX_SIZE];
+            snprintf(appPath, FILE_NAME_MAX_SIZE, "%s%s%s%s", paths[i], "/", appId,
+                     PLUGIN_DEFAULT_DIR_NAME);
+
+            //Found the app path
+            struct stat info;
+            if (stat(appPath, &info) != 0)
+                continue;
+
+            pthread_mutex_lock(&(pBuf->configLock));
+            unlink(SYSLINK_PLUG_PATH);
+            result = symlink(appPath, SYSLINK_PLUG_PATH);
+            pthread_mutex_unlock(&(pBuf->configLock));
+
+            DDBG("set symbolic link result:from :%s to %s result:%d\n", appPath, SYSLINK_PLUG_PATH, result);
+            if (result == 0 && pNodeSet)
+            {
+                //update active Id node
+                xmlNode *cur = pNodeSet->nodeTab[0];
+                xmlNodeSetContent(cur, appId);
+                DDBG("GET NOde conten :%s\n", cur->content);
+
+                //xmlFreeNode(cur);
+                DDBG("RETURn from active plu g  0000:%d\n", result);
+                PrintXmlDoc(*pXmlCp);
+
+            }
+            DDBG("RETURn from active plu g  0000  000000:%d\n", result);
+            //xmlXPathFreeNodeSet(pNodeSet);
+            break;
+        }
+        DDBG("RETURn from active plu g  0000  0111 :%d\n", result);
+        CleanupArray(&paths, count);
+        xmlXPathFreeObject(pObj);
+
+    }
+
+    DDBG("RETURn from active plug :%d\n", result);
+    return result;
+}
+
+/**
+ * @appPath: /opt/usr/app/appId
+ */
+static int UpdatePluglibList(const char *appPath, xmlDoc **pXmlDoc, const char* appId)
+{
+    DDBG("=========================update plugin lib path:%s\n", appPath);
+
+    int result = -1;
+    char plugPath[FILE_NAME_MAX_SIZE];
+
+    sprintf(plugPath, "%s%s", appPath, PLUGIN_DEFAULT_DIR_NAME);
+    DIR *pDir;
+    struct dirent *pDirEnt;
+
+    pDir = opendir(plugPath);
+    DDBG("OPEN DIR:%s\n", plugPath);
+    if (pDir)
+    {
+        //open directories
+        while ((pDirEnt = readdir(pDir)) != NULL)
+        {
+            if (strcmp(pDirEnt->d_name, ".") == 0 || strcmp(pDirEnt->d_name, "..") == 0)
+                continue;
+
+            if (pDirEnt->d_type == DT_REG)
+            {
+                // load the library, update xml node
+                char libPath[FILE_NAME_MAX_SIZE];
+                sprintf(libPath, "%s%s%s", plugPath, "/", pDirEnt->d_name);
+                result = UpdatePlugin(libPath, pXmlDoc, appId);
+                break;
+            }
+            else
+            {
+                DDBG("IT IS NO regular file:%s\n", pDirEnt->d_name);
+                continue;
+            }
+        }
+        closedir(pDir);
+
+    }
+    DDBG("RESTURN  from update pluglib list :%d\n", result);
+    return result;
+}
+
+/**
+ *
+ */
+int GetInfoPlugin(void *pData, int req_argc, char **req_argv, char ***res_argv, int *res_argc,
+                  CALLBACKFUNC callback, TSC_METHOD_HANDLE *handle)
+{
+    // check data pass is valid xml
+    xmlDoc *pXml = (xmlDoc*) *((xmlDoc**) pData);
+    *res_argc = FN_GET_INFO_RTN_COUNT;
+    *res_argv = calloc(1, sizeof(char*) * FN_GET_INFO_RTN_COUNT);
+    if (*res_argv == NULL)
+        goto no_memory;
+
+    (*res_argv)[0] = strdup((const char*) RETURN_SUCCESS);
+    if ((*res_argv)[0] != NULL)
+    {
+        xmlChar *xmlMem;
+        int xmlSize;
+        xmlDocDumpFormatMemory(pXml, &xmlMem, &xmlSize, 0);
+        if (xmlMem != NULL)
+        {
+            DDBG("size is: %d, xmlmem is ** :%s\n", xmlSize, xmlMem);
+            (*res_argv)[1] = strdup((const char*) xmlMem);
+            if ((*res_argv)[1] == NULL)
+            {
+                DDBG("Not enough memory in :%s\n", "set xmlmem in return");
+                free((*res_argv)[0]);
+                (*res_argv)[0] = NULL;
+                goto invalid_xml;
+            }
+            xmlFree(xmlMem);
+            xmlMem = NULL;
+        }
+        else
+            goto invalid_xml;
+    }
+    else
+    {
+        DDBG("failed to copy return_successS:%s\n", "");
+        goto no_memory;
+    }
+    DDBG("successfully finished:%s\n", "GetInfoPlugin");
+    return 0;
+
+    invalid_xml:
+    // get recoverred config.xml and return
+    no_memory:
+    *res_argc = 0;
+    return 0;
+}
+
+/**
+ * pData is the buffer of config.xml,
+ * ** apply lock
+ *   if copy pData to pData.cp success,
+ *     if update pData.cp with the newly installed info
+ *       if successfully update the symbolic link,
+ *         if write pData.cp to config.xml.new
+ *           if switch config.xml.new to config.xml
+ *           else do nothing, wait for next time update
+ *         else do nothing, wait for next time udpate
+ *         copy pData.cp to pData, free pData.cp
+ *       else return failure update
+ *     ** unlock
+ *
+ *     @req_argc: 1
+ *     @req_argv: app installation path, i.e. /opt/usr/apps/appID
+ */
+int InstallPlugin(void *pData, int req_argc, char **req_argv, char ***res_argv, int *res_argc,
+                  CALLBACKFUNC callback, TSC_METHOD_HANDLE *handle)
+{
+    DDBG("InstallPlugin for serverstub:%s\n", req_argv[0]);
+    int result = -1;
+    ConfigBuf *pBuf = *((ConfigBuf **) pData);
+    pthread_mutex_lock(&(pBuf->configLock));
+    xmlDoc *pXml = (*((ConfigBuf **) pData))->pConfigBuffer;
+    xmlDoc *pXmlCp = xmlCopyDoc(pXml, DO_RECURSIVE_COPY);
+    pthread_mutex_unlock(&(pBuf->configLock));
+
+    if (pXmlCp != NULL)
+    {
+        if (req_argc == 1 && req_argv != NULL)
+        {
+            // Get apppath list
+            int count;
+            char **paths = NULL;
+            GetConfigElements(&pXmlCp, (xmlChar *) XPATH_APP_PATHS, &count, &paths);
+            int i = 0;
+            for (; i < count; i++)
+            {
+                char appPath[FILE_NAME_MAX_SIZE];
+                sprintf(appPath, "%s%s%s", paths[i], "/", req_argv[0]);
+
+                PrintXmlDoc(pXmlCp);
+                if (UpdatePluglibList(appPath, &pXmlCp, req_argv[0]) == 0)
+                {
+                    if (ActivePlugin(*((ConfigBuf**) pData), &pXmlCp, (const xmlChar *)req_argv[0]) == 0)
+                    {
+                        // Write to new file
+                        DDBG("Success cpy xml 2:%s\n", appPath);
+
+                        *res_argc = FN_INSTALL_PLUG_RTN_COUNT;
+                        *res_argv = calloc(1, sizeof(char*) * FN_INSTALL_PLUG_RTN_COUNT);
+                        if (*res_argv == NULL)
+                            goto no_memory;
+
+                        (*res_argv)[0] = strdup((const char*) RETURN_SUCCESS);
+                        if ((*res_argv)[0] == NULL)
+                            goto no_memory;
+
+                        xmlChar *xmlMem = NULL;
+                        int xmlSize;
+
+                        xmlDocDumpFormatMemory(pXmlCp, &xmlMem, &xmlSize, 0);
+                        DDBG("XMLmEM address: %p\n", xmlMem);
+                        if (xmlMem != NULL)
+                        {
+                            (*res_argv)[1] = strdup((const char*) xmlMem);
+                            DDBG("return from install plug:%s\n", (*res_argv)[1]);
+                            free(xmlMem);
+                            xmlMem = NULL;
+
+                            if ((*res_argv)[1] != NULL)
+                            {
+                                result = UpdateConfigFile(pData, &pXmlCp);
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+            CleanupArray(&paths, count);
+        }
+    }
+    xmlFreeDoc(pXmlCp);
+
+    if (result == -1)
+        goto failure;
+    else
+    {
+        return result;
+    }
+
+no_memory:
+    xmlFreeDoc(pXmlCp);
+
+failure:
+    *res_argc = 1;
+    *res_argv = calloc(1, sizeof(char*));
+    (*res_argv)[0] = strdup((const char*) RETURN_FAILURE);
+    return result;
+}
+
+/**
+ * If it is active plugin, unlink the syslink, and update active element with AppId to None.
+ * If the request plugin is not active one, remove it from the plugin list
+ */
+int UninstallPlugin(void *pData, int req_argc, char **req_argv, char ***res_argv, int *res_argc,
+                    CALLBACKFUNC callback, TSC_METHOD_HANDLE *handle)
+{
+    int result = -1;
+    xmlDoc *pXml = NULL;
+    xmlDoc *pXmlCp = NULL;
+    ConfigBuf *pBuf = NULL;
+    xmlXPathObject *pObj = NULL;
+
+    if (req_argc != 1 || req_argv == NULL)
+        goto failure;
+
+    pBuf = *((ConfigBuf **) pData);
+
+    pthread_mutex_lock(&(pBuf->configLock));
+    pXml = pBuf->pConfigBuffer;
+    pXmlCp = xmlCopyDoc(pXml, DO_RECURSIVE_COPY);
+    pthread_mutex_unlock(&(pBuf->configLock));
+
+    if (pXmlCp == NULL)
+        goto failure;
+
+    result = SearchNodeN((const xmlChar *)XPATH_ACTIVE_PLUGIN, pXmlCp, &pObj);
+    if (result != 0)
+        goto failure;
+
+    xmlNodeSet *pNodeSet = pObj->nodesetval;
+    xmlNode *pNode = pNodeSet->nodeTab[0];
+    if (pNode == NULL)
+    {
+        DDBG("not such node %s\n", XPATH_ACTIVE_PLUGIN);
+        goto failure;
+    }
+
+    if (pNode->type != XML_ELEMENT_NODE)
+        goto failure;
+
+    // Search for plugin. If found, unlink the plugin. Otherwise, the plugin was already
+    // unlinked and updated in the config file.
+    DDBG("node name:%s, activenode value: %s\n", pNode->name, pNode->children->content);
+    if (strcmp((const char *)pNode->children->content, req_argv[0]) == 0)
+    {
+        pthread_mutex_lock(&(pBuf->configLock));
+        result = unlink(SYSLINK_PLUG_PATH);
+        pthread_mutex_unlock(&(pBuf->configLock));
+
+        if (result != 0 && result != ENOENT)
+            goto failure;
+
+        xmlNodeSetContent(pNode, (const xmlChar *)ACTIVE_NONE);
+    }
+
+    // Remove the plugin node if it is in the plugin list
+    result = RemoveNodeParent(&pXmlCp, (const xmlChar *)XPATH_PLUGINS_PLUG, req_argv[0]);
+    result = UpdateConfigFile((ConfigBuf**) pData, &pXmlCp);
+    if (result != 0)
+    {
+        DDBG("Unable to update config file with uninstall info\n");
+        goto failure;
+    }
+    SetSuccessReturn(res_argc, res_argv);
+    goto cleanup;
+
+failure:
+    SetFailureReturn(res_argc, res_argv);
+
+cleanup:
+    if (pObj)
+        xmlXPathFreeObject(pObj);
+    if (pXmlCp)
+        xmlFreeDoc(pXmlCp);
+
+    return result;
+}
+
+/**
+ * Copy the xmlDoc
+ * Update the symbolic link if it is not the active plug
+ * Update xmlDoc, save to the tpcs_config.xml
+ */
+int SetActivePlugin(void *pData, int req_argc, char **req_argv, char ***res_argv, int *res_argc,
+                    CALLBACKFUNC callback, TSC_METHOD_HANDLE *handle)
+{
+    DDBG("SetActivePlugin :%s\n", req_argv[0]);
+
+    ConfigBuf *pBuf = NULL;
+    xmlDoc *pXml = NULL;
+    xmlDoc *pXmlCp = NULL;
+    int result = -1;
+
+    if (req_argc != 1 || req_argv == NULL)
+        return result;
+
+    pBuf = *((ConfigBuf **) pData);
+
+    pthread_mutex_lock(&(pBuf->configLock));
+    pXml = pBuf->pConfigBuffer;
+    pXmlCp = xmlCopyDoc(pXml, DO_RECURSIVE_COPY);
+    pthread_mutex_unlock(&(pBuf->configLock));
+
+    if (pXmlCp == NULL)
+        return result;
+
+    PrintXmlDoc(pXmlCp);
+    if ((ActivePlugin(pBuf, &pXmlCp, (const xmlChar *)req_argv[0]) == 0)
+            && UpdateConfigFile((ConfigBuf**) pData, &pXmlCp) == 0)
+    {
+        SetSuccessReturn(res_argc, res_argv);
+        DDBG("==== FINd tha ppid %s\n", req_argv[0]);
+    }
+    else
+    {
+        DDBG("==== **** FINd tha ppid %s\n", req_argv[0]);
+        SetFailureReturn(res_argc, res_argv);
+    }
+
+    xmlFreeDoc(pXmlCp);
+    return result;
+}
+
+static int WriteXmlToFile(xmlDoc *pXmlDoc, const char* filename)
+{
+
+    DDBG("Write xml to file: %s\n", filename);
+    int result = -1;
+    FILE *pfConfig = fopen(filename, "w");
+    if (pfConfig != NULL)
+    {
+        xmlDocDump(pfConfig, pXmlDoc);
+        fclose(pfConfig);
+        result = 0;
+    }
+    return result;
+}
+
+static int InitConfigFile(xmlDoc **pXmlDoc)
+{
+    int result = -1;
+    DDBG("Size of xml doc in memory :%d\n", sizeof(CONFIG_DEFAULT_STRING));
+
+    *pXmlDoc = xmlReadMemory(CONFIG_DEFAULT_STRING, sizeof(CONFIG_DEFAULT_STRING) + 1,
+                             CONFIG_FILE_NAME,
+                             NULL, 0);
+
+    if (*pXmlDoc != NULL)
+    {
+        result = 0;
+    }
+
+    return result;
+}
+
+static bool IsValidTPCSConfig(const char *pFileName, xmlDoc **ppXmlDoc)
+{
+    // Create a parse context
+    bool ret = FALSE;
+    xmlParserCtxt *pParserCtxt = xmlNewParserCtxt();
+    xmlDoc *pXmlDoc;
+    if (pParserCtxt == NULL)
+    {
+        DDBG("%s\n", "======Failed to allocate parser context");
+        return ret;
+    }
+    else
+    {
+        // valid this config file
+            // Parse the file, activating the DTD validation option */
+               DDBG("------------------ IS VALID config file :%s\n", "---------------------");
+               pXmlDoc = xmlCtxtReadFile(pParserCtxt, pFileName, NULL, XML_PARSE_DTDVALID);
+               DDBG("--- 1 pxmldoc address: %p\n", pXmlDoc);
+               DDBG("file to read:%s\n", pFileName);
+               PrintXmlDoc(pXmlDoc);
+               if (pXmlDoc != NULL)
+               {
+                       // Check if validation succeeded
+                       if (pParserCtxt->valid)
+                       {
+                               *ppXmlDoc = pXmlDoc;
+                               DDBG("address of ppxmldoc: %p\n", *ppXmlDoc);
+                               ret = TRUE;
+                       }
+               }
+               else
+               {
+                       DDBG("NOT VALID file: %s\n", pFileName);
+               }
+
+        xmlFreeParserCtxt(pParserCtxt);
+        return ret;
+    }
+}
+
+/**
+ * Return directory list that has the specified directory within
+ */
+static void GetDirsHasPath(const char *dir, const char *search_path, int *pCount,
+                           char ***name_w_path, char ***appId)
+{
+    DIR *pDir = NULL;
+    struct dirent *pDirEnt = NULL;
+
+    if (!dir || !search_path || !pCount || !appId || !name_w_path)
+        return;
+
+    pDir = opendir(dir);
+    *pCount = 0;
+    if (pDir)
+    {
+        char plugPath[FILE_NAME_MAX_SIZE];
+        char appPath[FILE_NAME_MAX_SIZE];
+
+        struct stat info;
+        while ((pDirEnt = readdir(pDir)) != NULL)
+        {
+            if (strcmp(pDirEnt->d_name, ".") == 0 || strcmp(pDirEnt->d_name, "..") == 0)
+            {
+                continue;
+            }
+            if (pDirEnt->d_type == DT_DIR)
+            {
+                sprintf(appPath, "%s%s%s", dir, "/", pDirEnt->d_name);
+
+                sprintf(plugPath, "%s%s", appPath, PLUGIN_DEFAULT_DIR_NAME);
+
+                if (stat(plugPath, &info) == 0)
+                {
+                    if (*pCount == 0)
+                    {
+                        *name_w_path = calloc(1, sizeof(char*));
+
+                        if (*name_w_path)
+                        {
+                            (*pCount)++;
+                            (*name_w_path)[0] = strdup((const char*) appPath);
+
+                            if ((*name_w_path)[0] == NULL)
+                                goto clean_up;
+                        }
+                        else
+                            goto clean_up;
+
+                        *appId = calloc(1, sizeof(char*));
+                        if (*appId)
+                        {
+                            (*appId)[0] = strdup((const char*) pDirEnt->d_name);
+                            DDBG("COUNT 0, name: %s\n", pDirEnt->d_name);
+                            if ((*appId)[0] == NULL)
+                                goto clean_up;
+                        }
+                    }
+                    else
+                    {
+                        //TODO: all the realloc * size, use chunk
+                        *name_w_path = realloc(*name_w_path, sizeof(char*) * (*pCount + 1));
+                        if (*name_w_path)
+                        {
+                            (*pCount)++;
+                            (*name_w_path)[(*pCount) - 1] = strdup((const char*) appPath);
+                            if ((*name_w_path)[(*pCount) - 1] == NULL)
+                                goto clean_up;
+
+                            *appId = realloc(*appId, sizeof(char*) * (*pCount + 1));
+                            if (*appId)
+                            {
+                                (*appId)[*pCount - 1] = strdup((const char*) pDirEnt->d_name);
+                                if (((*appId)[*pCount - 1]) == NULL)
+                                {
+                                    goto clean_up;
+                                }
+                            }
+                            else
+                            {
+                                goto clean_up;
+                            }
+                        }
+                        else
+                        {
+                            goto clean_up;
+                        }
+                    }
+                }
+            }
+        }
+
+        goto success;
+    }
+
+clean_up:
+    CleanupArray(name_w_path, *pCount);
+
+success:
+    DDBG("CLOSE dir: %s\n", " " );
+    if (pDir)
+        closedir(pDir);
+
+    return;
+}
+
+/**
+ *
+ */
+static void CleanupArray(char*** pArr, int len)
+{
+    if (pArr)
+    {
+        while (len > 0)
+        {
+            len--;
+            if ((*pArr)[len])
+            {
+                free((*pArr)[len]);
+                (*pArr)[len] = NULL;
+            }
+        }
+
+        if (*pArr)
+        {
+            free(*pArr);
+            *pArr = NULL;
+        }
+    }
+}
+
+/*
+ * int ftw(const char *dir, int (*fn)(const char *file, const struct stat *sb, int flag), int nopenfd);
+ */
+int FileTreeCallback(const char *pFile, const struct stat *pStat, int flag)
+{
+    int result = 0;
+    if (pStat->st_mode & S_IFREG)
+    {
+        //DDBG(">>>>>file tree walk :%s, such substring:%s\n", pFile, MANIFEST_FILE_NAME);
+        if (EndsWith(pFile, MANIFEST_FILE_NAME) == 0)
+        {
+            DDBG("FOUNd the file: %s\n", pFile);
+            // check if it has the plugin tag
+            if (HasTag(PLUGIN_ANTI_VIRUS_TAG, pFile, XPATH_PLUGIN_CATEGORY) == 0)
+            {
+                // found the library
+                DDBG("this app is plugin app:%s\n", pFile);
+                result = 1;
+            }
+        }
+    }
+    return result;
+}
+
+/**
+ * Checks if str ends with needle. Return zero on success otherwise non-zero.
+ */
+static int EndsWith(const char *hay, const char *needle)
+{
+    size_t haylen, needlelen;
+
+    if (!hay || !needle)
+        return -1;
+
+    needlelen = strlen(needle);
+    haylen = strlen(hay);
+
+    if (needlelen > haylen)
+        return -1;
+
+    return strncmp(hay + haylen - needlelen, needle, needlelen);
+}
+
+static void GetNSURI(xmlDoc *pXmlDoc, xmlChar **pns, xmlChar **uri)
+{
+    xmlNode *root_node = xmlDocGetRootElement(pXmlDoc);
+
+    if (root_node)
+    {
+        xmlNs *pXmlNS = root_node->ns;
+        xmlNs *pXmlNSDef = root_node->nsDef;
+
+        if (pXmlNS != NULL)
+        {
+            if (pXmlNS->prefix != NULL)
+            {
+                *pns = (xmlChar*) strdup((const char*) pXmlNS->prefix);
+            }
+            else
+            {
+                DDBG("root node name:%s\n", root_node->name);
+                *pns = (xmlChar*) strdup((const char*) root_node->name);
+            }
+        }
+
+        if (pXmlNSDef != NULL)
+        {
+            if (pXmlNSDef->href != NULL)
+            {
+                DDBG("nsdef :%s\n", pXmlNSDef->href);
+                *uri = (xmlChar*) strdup((const char*) pXmlNSDef->href);
+            }
+        }
+    }
+    return;
+}
+
+/**
+ * Get elements from xmlDoc, and output to the count and content
+ */
+static void GetConfigElements(xmlDoc **pXmlDoc, xmlChar *pXPath, int *size, char ***content)
+{
+    DDBG("GetConfigElements in xpath: %s\n", (char*)pXPath);
+    // Scan all the directories that has av category, update its plugin element in config.xml
+    xmlXPathContext *pXPathCtx;
+    xmlXPathObject *pXPathObj;
+
+    pXPathCtx = xmlXPathNewContext(*pXmlDoc);
+    if (pXPathCtx != NULL)
+    {
+        xmlChar *pns = NULL;
+        xmlChar *puri = NULL;
+        GetNSURI(*pXmlDoc, &pns, &puri);
+        if (pns != NULL && puri != NULL)
+        {
+            if (xmlXPathRegisterNs(pXPathCtx, pns, puri) != 0)
+            {
+                DDBG("Cannot register xpath :%s\n", "");
+                return;
+            }
+        }
+        // Evaluate xpath expression
+        pXPathObj = xmlXPathEvalExpression(pXPath, pXPathCtx);
+        if (pXPathObj != NULL)
+        {
+            xmlNode *cur;
+            xmlNodeSet *pNodeSet = pXPathObj->nodesetval;
+
+            *size = pNodeSet ? pNodeSet->nodeNr : 0;
+            if (*size > 0)
+            {
+                int i = 0;
+                *content = calloc(1, sizeof(char*) * (*size));
+                DDBG("XAPTH OBJCT FOUND:%s, size:%d\n", "", *size);
+                if (*content)
+                {
+                    for (; i < *size; i++)
+                    {
+                        if (pNodeSet->nodeTab[i]->type == XML_ELEMENT_NODE)
+                        {
+                            cur = pNodeSet->nodeTab[i];
+
+                            if (*content)
+                            {
+                                DDBG("content; %s\n", cur->children->content);
+                                (*content)[i] = strdup((const char*) cur->children->content);
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    DDBG("CANNOT FOUND content:%s\n", "");
+                }
+
+            }
+            xmlXPathFreeObject(pXPathObj);
+        }
+        if (pns)
+        {
+            free(pns);
+            pns = NULL;
+        }
+
+        if (puri)
+        {
+            free(puri);
+            puri = NULL;
+        }
+
+        xmlXPathFreeContext(pXPathCtx);
+    }
+}
+
+static int HasTag(const char *pTag, const char *pFileName, const char *xpath)
+{
+    int result = 1;
+    xmlDoc *pConfigXml = NULL;
+
+    if (!pTag)
+        return result;
+
+    pConfigXml = xmlReadFile(pFileName, NULL, 0);
+    if (pConfigXml != NULL)
+    {
+        int size;
+        char **pCategory = NULL;
+        GetConfigElements(&pConfigXml, (xmlChar*) xpath, &size, &pCategory);
+        if (size > 0)
+        {
+            DDBG("size is: %d, category:%s\n", size, pCategory[0]);
+            int i = 0;
+            for (; i < size; i++)
+            {
+                if (strcmp(pCategory[i], pTag) == 0)
+                {
+                    result = 0;
+                    break;
+                }
+            }
+        }
+        CleanupArray(&pCategory, size);
+    }
+    xmlFreeDoc(pConfigXml);
+    return result;
+}
+
+/*
+ * config.xml validation
+ * If config.xml.new exists, and it is valid,
+ *  if it is consistent with symbolic link, switch this to config.xml
+ *  else if there is config.xml, and
+ *   if it is valid
+ *    if it is consistent with symbolic link, buffer the config.xml
+ *    else based on the symbolic link, update config.xml, then buffer the config.xml
+ *   else
+ *    recover the config.xml by scan all the applications, checking symbolic link, create the
+ *    config.xml, buffer it.
+ * Pass the data address to the pData
+ */
+int main(int argc, char **argv)
+{
+    //TODO: make it a daemon
+
+#ifndef DEBUG
+    fork_daemon();
+#endif
+
+    //Add methods
+    //Start TPCS daemon
+    TSC_SERVER_HANDLE hServer = NULL;
+    int ret = -1;
+
+
+    fprintf(stderr, "TPCS Service Daemon Started%s\n", "");
+    //TODO: rename TSC_DBUS_SERVER_PLUGIN_CHANNEL to TSC_DBUS_SERVER_PLUGIN_CHANNEL
+    if ((hServer = IpcServerOpen(TSC_DBUS_SERVER_PLUGIN_CHANNEL)) != NULL)
+    {
+        DDBG("%s", "**** successfully opened server ****\n");
+        // Write out the DTD validation file
+        FILE *pDTD = fopen(CONFIG_DTD_FILE_W_PATH, "r");
+        if (pDTD == NULL)
+        {
+            pDTD = fopen(CONFIG_DTD_FILE_W_PATH, "w");
+            if (pDTD)
+            {
+                fwrite(CONFIG_DEFAULT_DTD_STRING, strlen(CONFIG_DEFAULT_DTD_STRING), 1, pDTD);
+                fclose(pDTD);
+            }
+            else
+            {
+                goto done;
+            }
+        }
+        else
+        {
+            //TODO: close the file, check if the file exists lstat, signature of the file
+        }
+
+        ConfigBuf *pConfigBuf = calloc(1, sizeof(ConfigBuf));
+        if (pConfigBuf == NULL)
+            return ret;
+        ret = pthread_mutex_init(&(pConfigBuf->configLock), NULL);
+        if (ret == -1)
+        {
+            //TODO: memory clean up
+            free(pConfigBuf);
+            pConfigBuf = NULL;
+            return ret;
+        }
+
+        if (IsValidTPCSConfig(CONFIG_FILE_NEW_W_PATH, &(pConfigBuf->pConfigBuffer)))
+        {
+            // switch to config.xml
+            if (rename(CONFIG_FILE_NEW_W_PATH, CONFIG_FILE_W_PATH) == 0)
+            {
+                DDBG("%s has been renamed to :%s\n", CONFIG_FILE_NEW_W_PATH, CONFIG_FILE_W_PATH);
+            }
+            //TODO: if failed, it will exist,
+        }
+        else
+        {
+            DDBG("=== check config.xml not valid config file: %s\n", CONFIG_FILE_NEW_W_PATH);
+
+
+            // Buffer config.xml
+            if (!IsValidTPCSConfig(CONFIG_FILE_W_PATH, &(pConfigBuf->pConfigBuffer)))
+            {
+                //Recover config.xml from memory
+                InitConfigFile(&(pConfigBuf->pConfigBuffer));
+                DDBG("***************** initconfigfile: %p\n", pConfigBuf->pConfigBuffer);
+
+                DDBG("Failed to parse file : %s\n", CONFIG_FILE_W_PATH);
+
+                // Add plugins by scanning appPath directory
+                int count;
+                char **paths = NULL;
+                GetConfigElements(&(pConfigBuf->pConfigBuffer), (xmlChar*) XPATH_APP_PATHS, &count,
+                                  &paths);
+
+                int i;
+                int dirCount = 0;
+                char **app_path = NULL;
+                char **appId = NULL;
+                for (i = 0; i < count; i++)
+                {
+                    // Get list of directories under the app path, if it has $appPath/lib/plugin/,
+                    // search its manifest.xml for av tag, then recompose config.xml
+
+                    //TODO: if better way to get list of directory
+                    GetDirsHasPath(paths[i], PLUGIN_DEFAULT_DIR_NAME, &dirCount, &app_path, &appId);
+                    DDBG("fater get dirshas path:%s\n", PLUGIN_DEFAULT_DIR_NAME);
+                    if (dirCount > 0)
+                    {
+                        // search manifest.xml within the app_path, if found, copy the appid to plugin element
+                        int j;
+                        for (j = 0; j < dirCount; j++)
+                        {
+                            //ftw return 0: tree exhausted, -1: error, others whatever the FileTreeCallback return
+                            int result = ftw(app_path[j], FileTreeCallback, 12);
+                            if (result == 1)
+                            {
+                                DDBG("it found the plugin app dir:%s, appID:%s\n", app_path[j], appId[j]);
+                                //Update plugin element node
+                                UpdatePluglibList(app_path[j], &(pConfigBuf->pConfigBuffer),
+                                                  appId[j]);
+                            }
+                        }
+                    }
+                    CleanupArray(&appId, dirCount);
+                    CleanupArray(&app_path, dirCount);
+                }
+
+                CleanupArray(&paths, count);
+
+                // Recover config.xml from memory
+                WriteXmlToFile(pConfigBuf->pConfigBuffer, CONFIG_FILE_W_PATH);
+                DDBG("before clean up:%s, dircoutn:%d, pathCount:%d, \n", CONFIG_FILE_W_PATH, dirCount, count);
+
+            }
+            else
+            {
+                DDBG("Success in paring file: %s\n", CONFIG_FILE_W_PATH);
+            }
+        }
+
+        // Register methods for GetInfoPlugin
+        IpcServerMethod method_getPlugin;
+        snprintf(method_getPlugin.szMethod, sizeof(method_getPlugin.szMethod), "%s",
+                 "TPCSGetInfoPlugin");
+        method_getPlugin.method = (METHODFUNC) GetInfoPlugin;
+        method_getPlugin.pData = &(pConfigBuf->pConfigBuffer);
+
+        if (IpcServerAddMethod(hServer, &method_getPlugin) != 0)
+        {
+            DDBG("%s", "unable to add method GetInfoPlugin\n");
+            goto close_server;
+        }
+
+        // Register methods for InstallPlugin
+        IpcServerMethod method_installPlugin;
+        snprintf(method_installPlugin.szMethod, sizeof(method_installPlugin.szMethod), "%s",
+                 "TPCSInstallPlugin");
+        method_installPlugin.method = (METHODFUNC) InstallPlugin;
+        method_installPlugin.pData = &pConfigBuf;
+
+        if (IpcServerAddMethod(hServer, &method_installPlugin) != 0)
+        {
+            DDBG("%s", "unable to add method InstallPlugin\n");
+            goto close_server;
+        }
+
+        // Register methods for SetActivePlugin
+        IpcServerMethod method_setActivePlugin;
+        snprintf(method_setActivePlugin.szMethod, sizeof(method_setActivePlugin.szMethod), "%s",
+                 "TPCSSetActivePlugin");
+        method_setActivePlugin.method = (METHODFUNC) SetActivePlugin;
+        method_setActivePlugin.pData = &pConfigBuf;
+
+        if (IpcServerAddMethod(hServer, &method_setActivePlugin) != 0)
+        {
+            DDBG("%s", "unable to add method SetActivePlugin\n");
+            goto close_server;
+        }
+
+        // Register methods for UnInstallPlugin
+        IpcServerMethod method_uninstallPlugin;
+        snprintf(method_uninstallPlugin.szMethod, sizeof(method_uninstallPlugin.szMethod), "%s",
+                 "TPCSUninstallPlugin");
+        method_uninstallPlugin.method = (METHODFUNC) UninstallPlugin;
+        method_uninstallPlugin.pData = &pConfigBuf;
+
+        if (IpcServerAddMethod(hServer, &method_uninstallPlugin) != 0)
+        {
+            DDBG("%s", "unable to add method UninstallPlugin\n");
+            goto close_server;
+        }
+
+        DDBG("----------------- START method loop----------%s", "\n");
+
+        // Daemon waits here for request from clients.
+        IpcServerMainLoop(hServer);
+        DDBG("----------------- END method loop----------%s", "\n");
+        // Clean up
+        DDBG("======================= free xmldoc for isvalidConfig %s\n", "==============");
+        DDBG("pconfigbuf address:%p\n", pConfigBuf->pConfigBuffer);
+        xmlFreeDoc(pConfigBuf->pConfigBuffer);
+        free(pConfigBuf);
+
+        IpcServerClose(&hServer);
+    }
+    else
+    {
+        DDBG("%s", "unable to open server connection \n");
+        ret = -1;
+        goto done;
+    }
+    xmlCleanupParser(); // clean up library for xml library for valgrind
+    close_server:
+    IpcServerClose(&hServer);
+
+    done:
+    DDBG("%s", "Unable to start the Daemon \n");
+
+    return ret;
+
+}
diff --git a/framework/TPCSSerDaemon.h b/framework/TPCSSerDaemon.h
new file mode 100644 (file)
index 0000000..7dd3e2c
--- /dev/null
@@ -0,0 +1,59 @@
+#define ERROR_GENERIC -1
+#define RETURN_SUCCESS "0"
+#define RETURN_FAILURE "1"
+
+#define FN_GET_INFO_RTN_COUNT 2
+#define FN_INSTALL_PLUG_RTN_COUNT 2
+#define DO_RECURSIVE_COPY 1
+#define FILE_NAME_MAX_SIZE  128
+#define GENERIC_STRING_SIZE 128
+#define FN_GET_INFO "getInfo"
+#define TAG_VERSION "Version"
+#define TAG_VENDOR_NAME "VendorName"
+#define TAG_PRODUCT_NAME "ProductName"
+#define TAG_APP_ID "AppId"
+#define TAG_PLUG_NODE "Plug"
+#define MANIFEST_FILE_NAME "manifest.xml"
+#define XPATH_PLUGIN_CATEGORY "//Manifest:Manifest/Manifest:Apps/Manifest:UiApp/Manifest:Categories/Manifest:Category"
+#define PLUGIN_ANTI_VIRUS_TAG "http://tizen.org/category/antivirus"
+#define PLUGIN_SYSTEM_PATH "/usr/bin"
+#define PLUGIN_DEFAULT_DIR_NAME "/lib/plugin"
+#define XPATH_PLUGINS "//TPCSConfig/Plugins"
+#define XPATH_PLUGINS_PLUG "//TPCSConfig/Plugins/Plug/AppId"
+#define XPATH_ACTIVE_PLUGIN "//TPCSConfig/Active/AppId"
+#define XPATH_ACTIVE "//TPCSConfig/Active"
+#define XPATH_APP_PATHS "//TPCSConfig/AppPaths/Path"
+#define CONFIG_ENCODING "UTF-8"
+#define CONFIG_DTD_FILE_W_PATH "/usr/bin/tpcs_config.dtd"
+#define CONFIG_FILE_W_PATH "/usr/bin/tpcs_config.xml"
+#define CONFIG_FILE_NEW_W_PATH "/usr/bin/tpcs_config_new.xml"
+#define SYSLINK_PLUG_PATH "/lib/plugin"
+#define ACTIVE_NONE "None"
+#define APP_ID_NULL ""
+#define CONFIG_DEFAULT_STRING "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+    <!DOCTYPE TPCSConfig SYSTEM \"tpcs_config.dtd\">\n\
+    <TPCSConfig>\n\
+    <AppPaths>\n\
+    <Path>/opt/usr/apps</Path>\n\
+    <Path>/sdcard</Path>\n \
+    </AppPaths>\n\
+    <Active>\n\
+        <AppId>None</AppId>\n\
+    </Active>\n\
+    <Plugins>\n\
+    </Plugins>\n\
+</TPCSConfig>"
+
+
+#define CONFIG_DEFAULT_DTD_STRING "<!ELEMENT TPCSConfig (AppPaths, Active, Plugins)>\n\
+<!ELEMENT AppPaths (Path+)>\n\
+<!ELEMENT Active (AppId)>\n\
+<!ELEMENT Plugins (Plug*)>\n\
+<!ELEMENT Plug (Version|VendorName|ProductName|AppId)*>\n\
+<!ELEMENT Path (#PCDATA)>\n\
+<!ELEMENT Version (#PCDATA)>\n\
+<!ELEMENT VendorName (#PCDATA)>\n\
+<!ELEMENT ProductName (#PCDATA)>\n\
+<!ELEMENT AppId (#PCDATA)>"
+#define CONFIG_FILE_NAME "tpcs_config.xml"
+
diff --git a/framework/TSCErrorCodes.h b/framework/TSCErrorCodes.h
new file mode 100644 (file)
index 0000000..e345971
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+    
+    All rights reserved.
+    
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+    
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+    
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+    
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+    
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef TSCERRORCODES_H
+#define TSCERRORCODES_H
+
+#ifdef __cplusplus 
+extern "C" {
+#endif
+/**
+ * \file TSCErrorCodes.h
+ * \brief TSC Error Code Header File
+ *  
+ * This file provides the TSC error code definition.
+ */
+
+#define TSC_ERROR_MODULE_GENERIC 1 /* A generic error code. */
+#define ERR_NAME_MODULE_GENERIC "Generic"
+#define ERR_DESC_MODULE_GENERIC "A generic error."
+
+#define TSC_ERROR_CANCELLED 1 /* Operation cancelled. */
+#define ERR_NAME_CANCELLED "Cancelled"
+#define ERR_DESC_CANCELLED "Operation cancelled."
+
+#define TSC_ERROR_DATA_ACCESS 2 /* Unable to access data. */
+#define ERR_NAME_DATA_ACCESS "DataAccess"
+#define ERR_DESC_DATA_ACCESS "Unable to access data."
+
+#define TSC_ERROR_INVALID_PARAM 3 /* Invalid parameter. */
+#define ERR_NAME_INVALID_PARAM "InvalidParam"
+#define ERR_DESC_INVALID_PARAM "Invalid parameter."
+
+#define TSC_ERROR_INSUFFICIENT_RES 4 /* Insufficient resource. */
+#define ERR_NAME_INSUFFICIENT_RES "InsufficientRes"
+#define ERR_DESC_INSUFFICIENT_RES "Insufficient resource."
+
+#define TSC_ERROR_INTERNAL 5 /* Unexpected internal error. */
+#define ERR_NAME_INTERNAL "Internal"
+#define ERR_DESC_INTERNAL "Unexpected internal error."
+
+#define TSC_ERROR_INVALID_HANDLE 6 /* Invalid handle. */
+#define ERR_NAME_INVALID_HANDLE "InvalidHandle"
+#define ERR_DESC_INVALID_HANDLE "Invalid handle."
+
+#define TSC_ERROR_NOT_IMPLEMENTED 7 /* Specified method is not implemented by the Channel server. */
+#define ERR_NAME_NOT_IMPLEMENTED "NotImplemented"
+#define ERR_DESC_NOT_IMPLEMENTED "Specified method is not implemented."
+
+#define TSC_ERROR_REMOVE_METHOD_NOT_FOUND -1
+#define TSC_ERROR_ADD_METHOD_FAILED -1
+
+#ifdef __cplusplus
+}
+#endif 
+
+#endif /* TSCERRORCODES_H */
diff --git a/framework/TWPSerDaemon.c b/framework/TWPSerDaemon.c
new file mode 100644 (file)
index 0000000..bc01242
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/**
+ * \file TWPSerDaemon.c
+ * \brief TWP Service Daemon source file.
+ *
+ * This file implements the TWP Service Daemon functions used by Security framework.
+ */
+
+#include <malloc.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "Debug.h"
+#include "IpcForkDaemon.h"
+#include "TWPImpl.h"
+#include "TWPSerDaemon.h"
+
+#define RISK_LEVEL_LEN 2
+#define RETURN_STATUS_STR_LEN 4
+
+int
+TWPSerGetVersion(void *pData, int req_argc, char **req_argv, char ***rep_argv, int *rep_argc,
+                   CALLBACKFUNC callback, TSC_METHOD_HANDLE *handle)
+{
+    // Opens TWP Framework library.
+    TWPAPIInit Init;
+    TWPLIB_HANDLE hLib;
+
+    Init.api_version = TWPAPI_VERSION;
+    Init.memallocfunc = (TWPFnMemAlloc) malloc;
+    Init.memfreefunc = free;
+    hLib = TWPInitLibrary(&Init);
+
+    *rep_argc = 1;
+    *rep_argv = NULL;
+
+    TWP_RESULT iRes;
+    char *szRes = NULL;
+
+    if (hLib == INVALID_TWPLIB_HANDLE)
+    {
+        iRes = TWP_INVALID_HANDLE;
+        goto close_library;
+    }
+
+    // Get the Version Information of TWP Framework.
+    TWPVerInfo VerInfo;
+    iRes = TWPGetVersion(hLib, &VerInfo);
+
+    // Check if TWPGetVersion call returned TWP_SUCCESS.
+    if (iRes != TWP_SUCCESS)
+    {
+        DERR("%s", "TWPGetVersion did not return TWP_SUCCESS\n");
+    }
+    else
+    {
+        DINFO("TWPGetVersion returns = %s %s\n", VerInfo.szFrameworkVer, VerInfo.szPluginVer);
+
+        char *szRepArgv1 = strdup(VerInfo.szFrameworkVer);
+        char *szRepArgv2 = strdup(VerInfo.szPluginVer);
+        char *szRepArgv3 = strdup(TWP_DAEMON_VERSION);
+
+        if (szRepArgv1 == NULL || szRepArgv2 == NULL || szRepArgv3 == NULL)
+        {
+            DERR("%s", "strdup fails to allocate mem for version info");
+
+            free(szRepArgv1);
+            free(szRepArgv2);
+            free(szRepArgv3);
+            iRes = TWP_NOMEM;
+            goto close_library;
+        }
+
+        *rep_argc = 4;
+        *rep_argv = (char **) malloc(sizeof(char*) * (*rep_argc));
+
+        if (*rep_argv == NULL)
+        {
+            DERR("%s", "malloc returns Error for reply pointer array\n");
+
+            free(szRepArgv1);
+            free(szRepArgv2);
+            free(szRepArgv3);
+            *rep_argc = 1;
+            iRes = TWP_NOMEM;
+            goto close_library;
+        }
+
+        (*rep_argv)[1] = szRepArgv1;
+        (*rep_argv)[2] = szRepArgv2;
+        (*rep_argv)[3] = szRepArgv3;
+    }
+
+close_library:
+    // Compose the return value.
+    // Convert iRes to String.
+    szRes = (char *) malloc(sizeof(char) * RETURN_STATUS_STR_LEN);
+    if (szRes == NULL)
+    {
+        DERR("%s", "malloc returns error\n");
+        goto err;
+    }
+    snprintf(szRes, RETURN_STATUS_STR_LEN, "%d", iRes);
+
+    if (*rep_argc == 1)
+    {
+        *rep_argv = (char **) malloc (sizeof(char*) * 1);
+        if (*rep_argv == NULL)
+            goto err;
+    }
+
+    //Assign result code.
+    (*rep_argv)[0] = szRes;
+
+    TWPUninitLibrary(hLib);
+    return 0;
+
+err:
+    if (*rep_argv != NULL)
+    {
+        free((*rep_argv)[1]);
+        free((*rep_argv)[2]);
+        free((*rep_argv)[3]);
+    }
+    *rep_argc = 0;
+    free(*rep_argv);
+    *rep_argv = NULL;
+    rep_argv = NULL;
+    free(szRes);
+    TWPUninitLibrary(hLib);
+
+    return -1;
+}
+
+int
+TWPSerGetURLReputation(void *pData, int req_argc, char **req_argv, char ***rep_argv, int *rep_argc,
+                   CALLBACKFUNC callback, TSC_METHOD_HANDLE *handle)
+{
+    // open TWP framework library
+    TWPAPIInit Init;
+    TWPLIB_HANDLE hLib;
+
+    Init.api_version = TWPAPI_VERSION;
+    Init.memallocfunc = (TWPFnMemAlloc) malloc;
+    Init.memfreefunc = free;
+    hLib = TWPInitLibrary(&Init);
+
+    *rep_argc = 1;
+    *rep_argv = NULL;
+
+    TWP_RESULT iRes;
+    char *szRes = NULL;
+
+    if (hLib == INVALID_TWPLIB_HANDLE)
+    {
+        iRes = TWP_INVALID_HANDLE;
+        goto close_library;
+    }
+
+    // Get Risk Level.
+    int iRiskLevel;
+    unsigned int uBlkUrlLen;
+    char *pBlkUrl = NULL;
+
+    // Check for Risk Level of URL.
+    iRes = TWPCheckURL(hLib, req_argv[0], &pBlkUrl, &uBlkUrlLen, &iRiskLevel);
+
+    // Check if TWPCheckURL call returned TWP_SUCCESS.
+    if (iRes != TWP_SUCCESS)
+    {
+        DERR("%s : %s\n", "TWPCheckURL returned Error", req_argv[0]);
+    }
+    else
+    {
+        DINFO("TWPCheckURL returns risk level = %d\n", iRiskLevel);
+
+        // convert RiskLevel integer to string
+        char *szRiskLevel;
+        szRiskLevel = (char *) malloc(sizeof(char) * RISK_LEVEL_LEN);
+        if (szRiskLevel == NULL)
+        {
+            DINFO("%s", "malloc returns error\n");
+            iRes = TWP_NOMEM;
+            goto close_library;
+        }
+        snprintf(szRiskLevel, RISK_LEVEL_LEN, "%d", iRiskLevel);
+
+        *rep_argc = 2;
+        *rep_argv = (char **) malloc(sizeof(char*) * (*rep_argc));
+        if (*rep_argv == NULL)
+        {
+            DINFO("%s", "realloc returns Error for reply pointer array\n");
+            free(szRiskLevel);
+            *rep_argc = 1;
+            iRes = TWP_NOMEM;
+            goto close_library;
+        }
+
+        //Assign Risk Level
+        (*rep_argv)[1] = szRiskLevel;
+
+        // Assign redirect url if RiskLevel is greater than or equal to TWP_Medium
+        if (iRiskLevel >= TWP_Medium)
+        {
+            *rep_argc = 3;
+            *rep_argv = (char **) realloc(*rep_argv, sizeof(char*) * (*rep_argc));
+            if (*rep_argv == NULL)
+            {
+                DINFO("%s", "realloc returns Error for reply pointer array\n");
+                free(szRiskLevel);
+                *rep_argc = 1;
+                iRes = TWP_NOMEM;
+                goto close_library;
+            }
+            (*rep_argv)[2] = pBlkUrl;
+        }
+    }
+
+close_library:
+    // Compose the return value.
+    // Convert iRes to String.
+    szRes = (char *) malloc(sizeof(char) * RETURN_STATUS_STR_LEN);
+    if (szRes == NULL)
+    {
+        DERR("%s", "malloc returns error\n");
+        goto err;
+    }
+    snprintf(szRes, RETURN_STATUS_STR_LEN, "%d", iRes);
+
+    if (*rep_argc == 1)
+    {
+        *rep_argv = (char **) malloc (sizeof(char*) * 1);
+        if (*rep_argv == NULL)
+            goto err;
+    }
+    //Assign Result code
+    (*rep_argv)[0] = szRes;
+
+    TWPUninitLibrary(hLib);
+    return 0;
+
+err:
+    if (*rep_argv != NULL)
+    {
+        free((*rep_argv)[1]);
+        free((*rep_argv)[2]);
+    }
+    *rep_argc = 0;
+    free(*rep_argv);
+    *rep_argv = NULL;  
+    rep_argv = NULL;
+    free(szRes);
+    TWPUninitLibrary(hLib);
+    return -1;
+}
+
+int
+main(int argc, char **argv)
+{
+#ifndef DEBUG
+    fork_daemon();
+#endif
+
+    TSC_SERVER_HANDLE hServer;
+
+    if ((hServer = IpcServerOpen(TSC_DBUS_SERVER_WP_CHANNEL)) != NULL)
+    {
+        DINFO("%s", "successfully opened server \n");
+
+        // Register methods for get url reputation
+        IpcServerMethod method_1;
+        snprintf(method_1.szMethod, sizeof(method_1.szMethod), "%s", "TWPSerGetURLReputation");
+        method_1.method = (METHODFUNC) TWPSerGetURLReputation;
+        method_1.pData = NULL;
+
+        if (IpcServerAddMethod(hServer, &method_1) != 0)
+        {
+            DERR("%s", "unable to add method TWPSerGetURLReputation\n");
+            goto close_server;
+        }
+
+        // Register methods for getversion
+        IpcServerMethod method_2;
+        snprintf(method_2.szMethod, sizeof(method_2.szMethod), "%s", "TWPSerGetVersion");
+        method_2.method = (METHODFUNC) TWPSerGetVersion;
+        method_2.pData = NULL;
+
+        if (IpcServerAddMethod(hServer, &method_2) != 0)
+        {
+            DERR("%s", "unable to add method TWPSerGetVersion\n");
+            goto close_server;
+        }
+
+        // Daemon waits here for request from clients.
+        IpcServerMainLoop(hServer);
+
+        IpcServerClose(&hServer);
+    }
+    else
+    {
+        DFATAL("%s", "unable to open server connection \n");
+        goto err;
+    }
+
+    return 0;
+
+close_server:
+    IpcServerClose(&hServer);
+
+err:
+    DFATAL("%s", "Unable to start the Daemon \n");
+    return -1;
+}
diff --git a/framework/TWPSerDaemon.h b/framework/TWPSerDaemon.h
new file mode 100644 (file)
index 0000000..9211ce0
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+    Copyright (c) 2014, McAfee, Inc.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without modification,
+    are permitted provided that the following conditions are met:
+
+    Redistributions of source code must retain the above copyright notice, this list
+    of conditions and the following disclaimer.
+
+    Redistributions in binary form must reproduce the above copyright notice, this
+    list of conditions and the following disclaimer in the documentation and/or other
+    materials provided with the distribution.
+
+    Neither the name of McAfee, Inc. nor the names of its contributors may be used
+    to endorse or promote products derived from this software without specific prior
+    written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+    IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+    OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+    OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef TWPSERDAEMON_H
+#define TWPSERDAEMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \file TWPSerDaemon.h
+ * \brief TWP Server Daemon Header file.
+ *
+ * This file has the function prototypes.
+ * These functions should not be called directly but instead through IpcClient.h APIs
+ */
+
+#include "IpcServer.h"
+
+#define TWP_DAEMON_VERSION "1.0.0"
+
+/*==================================================================================================
+                                     FUNCTION PROTOTYPES
+==================================================================================================*/
+/**
+ * \brief handler method to get the version information.
+ * This will be called by IpcServer library with the following input/output params.
+ * This can be both synchronous and asynchronous API.
+ *
+ * \param[in] pData - contextual data.
+ * \param[in] req_argc - set to 0.
+ * \param[in] req_argv - set to null.
+ * \param[out] rep_argc - set to 0, 1 or 4.
+ * \param[out] rep_argv - contains  0, 1 or 4 strings for result code, framework version, plugin version, daemon version.
+ * \param[in] callback - method callback.
+ * \param[in] handle - handler.
+ * \return Return Type (int) \n
+ */
+int TWPSerGetVersion(void *pData, int req_argc, char **req_argv, char ***rep_argv, int *rep_argc,
+                        CALLBACKFUNC callback, TSC_METHOD_HANDLE *handle);
+
+/**
+ * \brief handler method to get the URL Reputation.
+ * This will be called by IpcServer library with the following input/output params.
+ * This can be both synchronous and asynchronous API.
+ *
+ * \param[in] pData - contextual data.
+ * \param[in] req_argc - set to 1.
+ * \param[in] req_argv - set to the URL required to check reputation.
+ *
+ * \param[out] rep_argc - set to 0, 1, 2 or 3.
+ * \param[out] rep_argv - contains 0, 1, 2  or 3 strings, first is the result code, second is the risklevel, third is the redirect URL.
+ *                        redirect URL is returned only if risk level is greater than or equal to TWP_Medium.
+ * \param[in] callback - method callback.
+ * \param[in] handle - handler.
+ * \return Return Type (int) \n
+ */
+int TWPSerGetURLReputation(void *pData, int req_argc, char **req_argv, char ***rep_argv, int *rep_argc,
+                               CALLBACKFUNC callback, TSC_METHOD_HANDLE *handle);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* TWPSERDAEMON_H */
diff --git a/packaging/com.tsc.ipc.server.plugin.conf b/packaging/com.tsc.ipc.server.plugin.conf
new file mode 100644 (file)
index 0000000..0be2c8d
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+    <policy user="root">
+        <allow own="com.tsc.ipc.server.plugin"/>
+    </policy>
+    <policy at_console="true">
+        <allow send_destination="com.tsc.ipc.server.plugin"/>
+    </policy>
+    <policy context="default">
+        <deny send_destination="com.tsc.ipc.server.plugin"/>
+    </policy>
+</busconfig>
diff --git a/packaging/com.tsc.ipc.server.wp.conf b/packaging/com.tsc.ipc.server.wp.conf
new file mode 100644 (file)
index 0000000..a97c7d6
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+    <policy user="root">
+        <allow own="com.tsc.ipc.server.wp"/>
+    </policy>
+    <policy at_console="true">
+        <allow send_destination="com.tsc.ipc.server.wp"/>
+    </policy>
+    <policy context="default">
+        <deny send_destination="com.tsc.ipc.server.wp"/>
+    </policy>
+</busconfig>
index dc42cc3..df1e688 100644 (file)
@@ -7,8 +7,14 @@ Group:         Security/Libraries
 URL:           http://tizen.org
 Source:        %{name}-%{version}.tar.gz
 Source1001:    csf-framework.manifest
+Source1002:    com.tsc.ipc.server.plugin.conf
+Source1003:    com.tsc.ipc.server.wp.conf
+Source1004:    tpcsserdaemon.service
+Source1005:    twpserdaemon.service
 BuildRequires: pkgconfig(libtzplatform-config)
+BuildRequires: pkgconfig(dbus-glib-1)
 BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(libxml-2.0)
 
 %description
 A general purpose content screening and reputation solution.
@@ -24,12 +30,43 @@ Development files
 %prep
 %setup -q
 cp %{SOURCE1001} .
+cp %{SOURCE1002} .
+cp %{SOURCE1003} .
+cp %{SOURCE1004} .
+cp %{SOURCE1005} .
 
 %build
+
+# Build Framework Library
 make -C framework -f Makefile all VERSION=%version PREFIX=%_prefix
 
+# Build IPC Client Library
+make -C framework -f Makefile_channel_client all
+
+# Build IPC Server Library
+make -C framework -f Makefile_channel_server all
+
+# Build Plugin Control Service
+make -C framework -f Makefile_TPCSSerDaemon all
+
+# Build Web Protection Control Service
+make -C framework -f Makefile_TWPSerDaemon all
+
 %install
 rm -rf %{buildroot}
+mkdir -p %{buildroot}%{_bindir}
+mkdir -p %{buildroot}%{_libdir}
+mkdir -p %{buildroot}%{_unitdir}
+mkdir -p %{buildroot}/%{_sysconfdir}/dbus-1/system.d
+install -D framework/lib/libscclient.so %{buildroot}%{_libdir}/
+install -D framework/lib/libscserver.so %{buildroot}%{_libdir}/
+install -D framework/bin/TPCSSerDaemon %{buildroot}%{_bindir}/
+install -D framework/bin/TWPSerDaemon %{buildroot}%{_bindir}/
+install -m0644 %{SOURCE1002} %{buildroot}%{_sysconfdir}/dbus-1/system.d/
+install -m0644 %{SOURCE1003} %{buildroot}%{_sysconfdir}/dbus-1/system.d/
+install -m0644 %{SOURCE1004} %{buildroot}%{_unitdir}
+install -m0644 %{SOURCE1005} %{buildroot}%{_unitdir}
+
 mkdir -p %buildroot%_includedir/csf
 mkdir -p %buildroot%_libdir/pkgconfig
 
@@ -38,14 +75,47 @@ make install -C framework \
              HEADER_DESTDIR=%buildroot%_includedir/csf \
              VERSION=%version
 
-%post -p /sbin/ldconfig
+%post
+/sbin/ldconfig
+systemctl daemon-reload
+if [ $1 = 1 ]; then
+    systemctl restart tpcsserdaemon.service
+    systemctl restart twpserdaemon.service
+    systemctl enable tpcsserdaemon.service -q
+    systemctl enable twpserdaemon.service -q
+fi
+
+%preun
+if [ $1 = 0 ]; then
+    systemctl stop tpcsserdaemon.service
+    systemctl stop twpserdaemon.service
+    systemctl disable tpcsserdaemon.service -q
+    systemctl disable twpserdaemon.service -q
+fi
 
-%postun -p /sbin/ldconfig
+%postun
+/sbin/ldconfig
+if [ $1 = 0 ]; then
+    systemctl daemon-reload
+fi
+rm -fr /usr/bin/tpcs_config.dtd
+rm -fr /usr/bin/tpcs_config.xml
 
 %files
 %manifest %{name}.manifest
 %license LICENSE
+%defattr(-,root,root,-)
 %{_libdir}/libsecfw.so.*
+%{_libdir}/libscclient.so
+%{_libdir}/libscserver.so
+%defattr(0755,root,root)
+%{_bindir}/TPCSSerDaemon
+%{_bindir}/TWPSerDaemon
+%defattr(0644,root,root)
+%config %{_sysconfdir}/dbus-1/system.d/com.tsc.ipc.server.plugin.conf
+%config %{_sysconfdir}/dbus-1/system.d/com.tsc.ipc.server.wp.conf
+%{_unitdir}/tpcsserdaemon.service
+%{_unitdir}/twpserdaemon.service
 
 %files devel
 %_includedir/csf/TCSErrorCodes.h
diff --git a/packaging/tpcsserdaemon.service b/packaging/tpcsserdaemon.service
new file mode 100644 (file)
index 0000000..db91ec1
--- /dev/null
@@ -0,0 +1,11 @@
+[Unit]
+Description=CSF Tizen Plugin Control Service Daemon (TPCSSerDaemon)
+
+[Service]
+Type=dbus
+ExecStart=/usr/bin/TPCSSerDaemon
+BusName=com.tsc.ipc.server.plugin
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
diff --git a/packaging/twpserdaemon.service b/packaging/twpserdaemon.service
new file mode 100644 (file)
index 0000000..815da09
--- /dev/null
@@ -0,0 +1,11 @@
+[Unit]
+Description=CSF Tizen Web Protection Service Daemon (TWPSerDaemon)
+
+[Service]
+Type=dbus
+ExecStart=/usr/bin/TWPSerDaemon
+BusName=com.tsc.ipc.server.wp
+Restart=always
+
+[Install]
+WantedBy=multi-user.target
diff --git a/test/scripts/MfeTPCSSerDaemonToEmul.sh b/test/scripts/MfeTPCSSerDaemonToEmul.sh
new file mode 100755 (executable)
index 0000000..6d047a2
--- /dev/null
@@ -0,0 +1,49 @@
+#!/bin/bash
+
+. ./scripts/PrepareForEmul.sh
+#export TCS_CFG="debug"
+
+echo -e "\nbuilding security channel CLIENT..."
+pushd ../framework
+make -f Makefile_channel_client clean 
+make -f Makefile_channel_client
+
+echo -e "\nbuilding security channel SERVER..."
+make -f Makefile_channel_server clean
+make -f Makefile_channel_server
+
+echo -e "\nbuilding TPCS Ser Daemon..."
+make -f Makefile_TPCSSerDaemon clean
+make -f Makefile_TPCSSerDaemon
+popd
+
+echo -e "\nbuilding test cases..."
+pushd test_cases/tpcsserdaemon
+make clean
+make
+popd
+
+echo -e "\ncleanup test files on device ..."
+sdb -e root on
+sdb -e shell rm -rf /tmp/tsc_test
+
+echo -e "\ncopying test files to device ..."
+mkdir -p tsc_test/
+cp ../framework/lib/libscclient.so tsc_test/
+cp ../framework/lib/libscserver.so tsc_test/
+cp scripts/TPCSSerDaemonTest.sh tsc_test/Test.sh
+cp test_cases/tpcsserdaemon/bin/tpcsserdaemontest tsc_test/
+cp ../framework/bin/TPCSSerDaemon tsc_test/TPCSSerDaemon
+
+sdb -e push tsc_test /tmp/tsc_test
+sdb -e push test_cases/q7097a278m /opt/usr/apps/q7097a278m
+sdb -e push test_cases/u7097a278m /opt/usr/apps/u7097a278m
+sdb -e push test_cases/n7097a278m /opt/usr/apps/n7097a278m
+sdb -e push tsc_test/Test.sh /usr/bin/Test.sh
+
+echo -e "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@"
+echo "preparation is done, please login to your device and perform following instructions"
+echo "sdb -e shell"
+echo "cd /usr/bin"
+echo "chmod +x Test.sh (optional)"
+echo "./Test.sh"
diff --git a/test/scripts/MfeTWPSerDaemonToEmul.sh b/test/scripts/MfeTWPSerDaemonToEmul.sh
new file mode 100755 (executable)
index 0000000..78ee2bb
--- /dev/null
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+. ./scripts/PrepareForEmul.sh
+#export TCS_CFG="debug"
+
+echo -e "\nbuilding libsecfw.so..."
+pushd ../framework
+make clean;
+make
+
+echo -e "\nbuilding security channel CLIENT..."
+make -f Makefile_channel_client clean 
+make -f Makefile_channel_client
+
+echo -e "\nbuilding security channel SERVER..."
+make -f Makefile_channel_server clean
+make -f Makefile_channel_server
+
+echo -e "\nbuilding TWPSerDaemon..."
+make -f Makefile_TWPSerDaemon clean
+make -f Makefile_TWPSerDaemon
+popd
+
+echo -e "\nbuilding libwpengine.so..."
+pushd ../plugin
+make clean
+make
+popd
+
+echo -e "\nbuilding test cases ..."
+pushd test_cases/twpserdaemon
+make clean
+make
+popd
+
+echo -e "\ncleanup test files on emulator ..."
+sdb -e root on
+sdb -e shell rm -rf /tmp/twpserdaemon_test
+
+echo -e "\ncopying test files to emulator ..."
+mkdir -p twpserdaemon_test/
+cp ../framework/lib/libscclient.so twpserdaemon_test/
+cp ../framework/lib/libscserver.so twpserdaemon_test/
+cp ../framework/lib/libsecfw.so twpserdaemon_test/
+cp scripts/TWPSerDaemonTest.sh twpserdaemon_test/Test.sh
+cp ../framework/bin/TWPSerDaemon twpserdaemon_test/
+cp test_cases/twpserdaemon/bin/twpserdaemontest twpserdaemon_test/
+cp test_cases/mfe-testcontents/.tcs.cfg twpserdaemon_test/
+
+cp ../plugin/plugin_i386_release/libwpengine.so twpserdaemon_test/
+
+sdb -e push twpserdaemon_test /tmp/twpserdaemon_test
+
+# push Test.sh to /usr/bin
+sdb -e push scripts/TWPSerDaemonTest.sh /usr/bin/Test.sh
+
+echo -e "\n@@@@@@@@@@@@@@@@@@@@@@@@@@@"
+echo "preparation is done, please login to the emulator and perform following instructions"
+echo "sdb -e shell"
+echo "cd /usr/bin/"
+echo "chmod +x Test.sh (optional)"
+echo "./Test.sh"
\ No newline at end of file
diff --git a/test/scripts/TPCSSerDaemonTest.sh b/test/scripts/TPCSSerDaemonTest.sh
new file mode 100755 (executable)
index 0000000..d54fb43
--- /dev/null
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+#echo EmbkcJFK7q > /proc/$$/attr/current
+killall TPCSSerDaemon
+killall tpcsserdaemontest
+killall TWPSerDaemon
+killall twpserdaemontest
+
+echo "copying test plug-in ..."
+#export LD_LIBRARY_PATH=$PWD
+cp -f /tmp/tsc_test/libscclient.so /usr/lib/
+cp -f /tmp/tsc_test/libscserver.so /usr/lib/
+cp -f /tmp/tsc_test/TPCSSerDaemon /usr/bin/
+cp -f /tmp/tsc_test/tpcsserdaemontest /usr/bin/
+
+echo "setup environment ..."
+#mkdir testcontents-1
+#export TWP_CONTENT_PATH=testcontents-1
+
+echo "Do following to run the test cases ..."
+echo "cd /usr/bin/"
+echo "./tpcsserdaemontest"
+
+
+#echo "cleanup test contents ..."
+#rm -rf testcontents-1
+
diff --git a/test/scripts/TWPSerDaemonTest.sh b/test/scripts/TWPSerDaemonTest.sh
new file mode 100755 (executable)
index 0000000..88f5860
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+#echo EmbkcJFK7q > /proc/$$/attr/current
+
+killall TWPSerDaemon
+killall twpserdaemontest
+killall TPCSSerDaemon
+killall tpcsserdaemontest
+
+echo "copying test plug-in ..."
+#export LD_LIBRARY_PATH=$PWD
+cp -f /tmp/twpserdaemon_test/libscclient.so /usr/lib/
+cp -f /tmp/twpserdaemon_test/libscserver.so /usr/lib/
+cp -f /tmp/twpserdaemon_test/libsecfw.so /usr/lib/
+cp -f /tmp/twpserdaemon_test/TWPSerDaemon /usr/bin/
+cp -f /tmp/twpserdaemon_test/twpserdaemontest /usr/bin/
+
+mkdir -p /opt/usr/share/sec_plugin
+cp -f /tmp/twpserdaemon_test/libwpengine.so /opt/usr/share/sec_plugin/
+mkdir -p /opt/usr/apps/EmbkcJFK7q/data/database
+cp -f /tmp/twpserdaemon_test/.tcs.cfg /opt/usr/apps/EmbkcJFK7q/data/
+echo "setup environment ..."
+#mkdir testcontents-1
+#export TWP_CONTENT_PATH=testcontents-1
+
+echo "Do following to run the test cases ..."
+echo "cd /usr/bin/"
+echo "./twpserdaemontest"
+#echo "end of test cases ..."
+
+#echo "cleanup test contents ..."
+#rm -rf testcontents-1
+