summaryrefslogtreecommitdiff
path: root/cesar/host/src/fcall_param.c
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/host/src/fcall_param.c')
-rw-r--r--cesar/host/src/fcall_param.c316
1 files changed, 316 insertions, 0 deletions
diff --git a/cesar/host/src/fcall_param.c b/cesar/host/src/fcall_param.c
new file mode 100644
index 0000000000..cf87edffe5
--- /dev/null
+++ b/cesar/host/src/fcall_param.c
@@ -0,0 +1,316 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+
+/**
+ * \file fcall_param.c
+ * \brief The 'function call' parameters management functions
+ * \ingroup host
+ *
+ * This file provides 'function call' parameters management functions
+ *
+ * \todo
+ */
+
+#include "common/std.h"
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include "host/fcall.h"
+#ifndef UNIT_TEST
+#include "lib/swap.h"
+#include "host/syscall.h"
+#else /* UNIT_TEST */
+#include <unistd.h>
+#include <arpa/inet.h>
+#endif /* UNIT_TEST */
+
+/**
+ * init the parameter table to add new paramters inside the message
+ * \param param pointer to param context
+ * \param id string id of parameters' function
+ * \param msg_id id of fcall message to process asynchronous calls
+ * \return 0 if ok, -1 if failed with errno=
+ * - EINVAL if fcall or id is NULL
+ * - ENAMETOOLONG if id length >= FUNCTION_CALL_ID_MAX_SIZE
+ */
+int fcall_param_init(fcall_param_t *param, char *id, unsigned short msg_id)
+{
+
+ DBG_ASSERT(param);
+ DBG_ASSERT(id);
+ if((param == NULL)
+ || (id == NULL))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(param, '\0', sizeof(fcall_param_t));
+ /* check id length */
+ if(id != NULL)
+ {
+ DBG_ASSERT(strlen(id) < FUNCTION_CALL_ID_MAX_SIZE);
+ if(strlen(id) >= FUNCTION_CALL_ID_MAX_SIZE)
+ {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ /* get the function id */
+ strcpy(param->id, id);
+ }
+
+ param->msg_id = msg_id;
+
+ return 0;
+}
+
+/**
+ * reset the parameter table and buffer to add new paramters inside the message
+ * function id, msg id and is_async stay unmodified
+ * \param param pointer to param context
+ * \return 0 if ok, -1 if failed with errno=
+ * - EINVAL if fcall is NULL
+ */
+int fcall_param_reset(fcall_param_t *param)
+{
+ int i;
+
+ DBG_ASSERT(param);
+ if(param == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ param->param_nb = 0;
+ for(i = 0; i < FUNCTION_CALL_PARAM_MAX_NB; i++)
+ {
+ param->param_table[i].id = NULL;
+ }
+ return 0;
+}
+
+/**
+ * find if a parameter, according to its id, is contained into an sci message
+ * \param param pointer to param context
+ * \param msg sci message containing the parameters
+ * \param id identifier of wanted parameter as string format
+ * \return true if parameter was found, false otherwise or if failed with errno=
+ * - EINVAL if param, msg or id is NULL
+ * - ENOENT if param->param_nb is invalid
+ */
+bool fcall_is_param(fcall_param_t *param, sci_msg_t *msg, char *id)
+{
+ bool is_param = false;
+ int index = 0;
+
+ DBG_ASSERT(param);
+ DBG_ASSERT(msg);
+ DBG_ASSERT(id);
+
+ if((param == NULL)
+ || (msg == NULL)
+ || (id == NULL))
+ {
+ errno = EINVAL;
+ return false;
+ }
+
+ /* check param_nb validity */
+ DBG_ASSERT((param->param_nb <= FUNCTION_CALL_PARAM_MAX_NB) && (param->param_nb >= 0));
+ if(param->param_nb > FUNCTION_CALL_PARAM_MAX_NB)
+ param->param_nb = FUNCTION_CALL_PARAM_MAX_NB;
+ else if(param->param_nb <= 0)
+ {
+ errno = ENOENT;
+ return false;
+ }
+
+ /* get the wanted index */
+ for(index = 0; index < param->param_nb; index++)
+ {
+ if(!strcmp(param->param_table[index].id, id))
+ {
+ /* found id */
+ is_param = true;
+ }
+ }
+
+ return is_param;
+}
+
+/**
+ * find a parameter according to its id and bind it into a user variable
+ * \param param pointer to param context
+ * \param msg sci message containing the parameters
+ * \param id identifier of wanted parameter as string format
+ * \param max_length maximum length of receiving data area
+ * \param data pointer to data area where to put the found parameter
+ * \return actual length of binded data if ok, -1 if failed with errno=
+ * - EINVAL if param, id or data is NULL
+ * - ENOENT if id has not been found into parameter context
+ */
+int fcall_param_bind(fcall_param_t *param, sci_msg_t *msg, char *id, unsigned int max_length, void *data)
+{
+ int index;
+ unsigned int length;
+
+ DBG_ASSERT(param);
+ DBG_ASSERT(msg);
+ DBG_ASSERT(id);
+ DBG_ASSERT(data);
+
+ if((param == NULL)
+ || (msg == NULL)
+ || (id == NULL)
+ || (data == NULL))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ DBG_ASSERT(max_length != 0);
+ if(max_length == 0)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* check param_nb validity */
+ DBG_ASSERT((param->param_nb <= FUNCTION_CALL_PARAM_MAX_NB) && (param->param_nb >= 0));
+ if(param->param_nb > FUNCTION_CALL_PARAM_MAX_NB)
+ param->param_nb = FUNCTION_CALL_PARAM_MAX_NB;
+ else if(param->param_nb <= 0)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ /* get the wanted index */
+ for(index = 0; index < param->param_nb; index++)
+ {
+ if(!strcmp(param->param_table[index].id, id))
+ {
+ /* found id */
+ /* get length */
+ length = ntohs(*param->param_table[index].length);
+ /* check the maximum available length */
+ if(length > max_length)
+ length = max_length;
+ /* copy data into user buffer */
+ if(length > 0)
+ memcpy(data, param->param_table[index].data, length);
+ break;
+ }
+ }
+
+ DBG_ASSERT(index < param->param_nb);
+ if(index >= param->param_nb)
+ {
+ /* not found */
+ errno = ENOENT;
+ return -1;
+ }
+
+ return length;
+}
+
+/**
+ * add a new parameter element into the parameter context
+ * \param param pointer to param context where to add new parameter
+ * \param msg pointer to sci message to add the paramter
+ * \param id id of new parameter
+ * \param length length of new parameter
+ * \param data pointer to data of new added parameter
+ * \return 0 if ok, -1 if failed with errno=
+ * - EINVAL if param, id of data is NULL, or if length < 0 or > FUNCTION_CALL_PARAM_MAX_SIZE
+ * - ENAMETOOLONG if id length >= FUNCTION_CALL_ID_MAX_SIZE
+ * - ENOSPC if parameter nb is already FUNCTION_CALL_PARAM_MAX_NB
+ */
+int fcall_param_add(fcall_param_t *param, sci_msg_t *msg, char *id, int length, void *data)
+{
+ int total_len;
+
+ DBG_ASSERT(param);
+ DBG_ASSERT(msg);
+ DBG_ASSERT(id);
+ DBG_ASSERT(strlen(id));
+ DBG_ASSERT(length >= 0);
+ DBG_ASSERT(length <= FUNCTION_CALL_PARAM_MAX_SIZE);
+ DBG_ASSERT((length <= 0) || (data != NULL));
+ if((param == NULL)
+ || (msg == NULL)
+ || (id == NULL)
+ || (strlen(id) == 0)
+ || (length < 0)
+ || (length > FUNCTION_CALL_PARAM_MAX_SIZE)
+ || ((length > 0)
+ && (data == NULL)))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* check id length */
+ DBG_ASSERT(strlen(id) < FUNCTION_CALL_ID_MAX_SIZE);
+ if(strlen(id) >= FUNCTION_CALL_ID_MAX_SIZE)
+ {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ /* check available free param */
+ DBG_ASSERT(param->param_nb < FUNCTION_CALL_PARAM_MAX_NB);
+ if(param->param_nb >= FUNCTION_CALL_PARAM_MAX_NB)
+ {
+ errno = ENOSPC;
+ return -1;
+ }
+
+ /* compute total data length to reserve */
+ total_len = strlen(id) + 1 + sizeof(uint16_t) + length;
+ if(sci_msg_push(msg, total_len) < total_len)
+ {
+ errno = ENOSPC;
+ return -1;
+ }
+
+ /* copy id, length and data into msg and match the param structure */
+ param->param_table[param->param_nb].id = (char *)(msg->data_begin);
+ strcpy(param->param_table[param->param_nb].id, id);
+ param->param_table[param->param_nb].length = (unsigned short *)(param->param_table[param->param_nb].id + strlen(id) + 1);
+ *param->param_table[param->param_nb].length = htons(length);
+ param->param_table[param->param_nb].data = (unsigned char *)param->param_table[param->param_nb].length + sizeof(unsigned short);
+ memcpy(param->param_table[param->param_nb].data, data, length);
+
+ /* increment the parameter number */
+ param->param_nb++;
+
+ return 0;
+}
+
+void fcall_param_dump(fcall_param_t *param, int fd, char *buffer, int size)
+{
+ int i, j;
+ buffer[size - 1] = '\0';
+ snprintf(buffer, size - 1, "fcall_param: id='%s', nb=%d\n", param->id, param->param_nb);
+ write(fd, buffer, strlen(buffer));
+ for(i = 0; i < param->param_nb; i++)
+ {
+ snprintf(buffer, size - 1, " id=%s, length=%d, data=", param->param_table[i].id, ntohs(*param->param_table[i].length));
+ write(fd, buffer, strlen(buffer));
+ for(j = 0; j < ntohs(*param->param_table[i].length); j++)
+ {
+ snprintf(buffer, size - 1, "%02x-", param->param_table[i].data[j]);
+ write(fd, buffer, 3);
+ }
+ write(fd, "\n", 1);
+ }
+}
+