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
- 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
--- /dev/null
+/*
+ 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;
+ }
+ }
+}
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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);
+}
--- /dev/null
+/*
+ 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();
--- /dev/null
+/*
+ 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 */
+
--- /dev/null
+/*
+ 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;
+}
+
--- /dev/null
+/*
+ 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 */
+
--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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
+
--- /dev/null
+/*
+ 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"
--- /dev/null
+/*
+ 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 */
+
--- /dev/null
+/*
+ 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;
+}
+
--- /dev/null
+/*
+ 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
+
--- /dev/null
+/*
+ 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 */
+
--- /dev/null
+#
+# 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
--- /dev/null
+#
+# 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
--- /dev/null
+#
+# 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
--- /dev/null
+#
+# 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
--- /dev/null
+/**
+ * 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;
+
+}
--- /dev/null
+#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"
+
--- /dev/null
+/*
+ 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 */
--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+/*
+ 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 */
--- /dev/null
+<!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>
--- /dev/null
+<!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>
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.
%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
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
--- /dev/null
+[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
--- /dev/null
+[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
--- /dev/null
+#!/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"
--- /dev/null
+#!/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
--- /dev/null
+#!/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
+
--- /dev/null
+#!/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
+