summaryrefslogtreecommitdiff
path: root/cesar/host/src/probe.c
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/host/src/probe.c')
-rw-r--r--cesar/host/src/probe.c275
1 files changed, 275 insertions, 0 deletions
diff --git a/cesar/host/src/probe.c b/cesar/host/src/probe.c
new file mode 100644
index 0000000000..ddbb1dda06
--- /dev/null
+++ b/cesar/host/src/probe.c
@@ -0,0 +1,275 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+
+/**
+ * \file probe.c
+ * \brief The 'probe' context management functions
+ * \ingroup host
+ *
+ * This file provides 'probe' function context 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 <arpa/inet.h>
+#endif /* UNIT_TEST */
+
+/**
+ * initialize a static probe context, called during station context creation.
+ * \param probe probe context to initialize
+ * \param fcall fcall which process the probe function
+ * \return 0 if ok, -1 if failed with errno=
+ * - EINVAL if probe or fcall is NULL
+ */
+int probe_init(probe_ctx_t *probe, fcall_ctx_t *fcall)
+{
+ DBG_ASSERT(probe);
+ DBG_ASSERT(fcall);
+ if((probe == NULL)
+ || (fcall == NULL))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ memset(probe, '\0', sizeof(probe_ctx_t));
+ probe->fcall = fcall;
+ fcall_register(fcall, PROBE_ID, probe_recv, probe);
+ return 0;
+}
+
+/**
+ * probe var registering
+ * \param probe pointer to current probe context
+ * \param id variable string id
+ * \param addr pointer to variable
+ * \return 0 if ok, -1 if fail with errno=
+ * - EINVAL if probe or id is NULL
+ * - ENAMETOOLONG if id length is >= PROBE_ID_MAX_SIZE
+ * - ENOSPC if max number of registred variable is reached
+ * - EEXIST if variable is already registered
+ */
+int probe_register(probe_ctx_t *probe, char *id, int length, void *addr)
+{
+ int index;
+
+ DBG_ASSERT(probe);
+ DBG_ASSERT(id);
+ DBG_ASSERT(length > 0);
+ DBG_ASSERT(length < FUNCTION_CALL_PARAM_MAX_SIZE);
+ DBG_ASSERT(addr);
+ if((probe == NULL)
+ || (id == NULL)
+ || (length <= 0)
+ || (length >= FUNCTION_CALL_PARAM_MAX_SIZE)
+ || (addr == NULL))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* check id length */
+ DBG_ASSERT(strlen(id) < PROBE_ID_MAX_SIZE);
+ if(strlen(id) >= PROBE_ID_MAX_SIZE)
+ {
+ errno = ENAMETOOLONG;
+ station_log(probe->fcall->sci->station, STATION_LOG_ERROR, STATION_LOGTYPE_PROBE,
+ "%s: errno = %d because id length is invalid", __FUNCTION__, errno);
+ return -1;
+ }
+
+ /* check if there is free place */
+ DBG_ASSERT(probe->var_nb < PROBE_VAR_MAX_NB);
+ if(probe->var_nb >= PROBE_VAR_MAX_NB)
+ {
+ errno = ENOSPC;
+ station_log(probe->fcall->sci->station, STATION_LOG_ERROR, STATION_LOGTYPE_PROBE,
+ "%s: errno = %d because there is no free place", __FUNCTION__, errno);
+ return -1;
+ }
+
+ /* check if variable is already registered */
+ for(index = 0; index < probe->var_nb; index++)
+ {
+ DBG_ASSERT(strcmp(probe->var_table[index].id, id));
+ if(!strcmp(probe->var_table[index].id, id))
+ {
+ errno = EEXIST;
+ station_log(probe->fcall->sci->station, STATION_LOG_ERROR, STATION_LOGTYPE_PROBE,
+ "%s: errno = %d because variable is already registered", __FUNCTION__, errno);
+ return -1;
+ }
+ }
+
+ /* register the function */
+ strcpy(probe->var_table[probe->var_nb].id, id);
+ probe->var_table[probe->var_nb].length = length;
+ probe->var_table[probe->var_nb].addr = addr;
+
+ /* increment the number of function */
+ probe->var_nb++;
+
+ return 0;
+}
+
+/**
+ * probe message processing function; called by fcall_recv()
+ * must be registred to fcall layer as "probe" function id
+ * \param fcall pointer to the current fcall context
+ * \param param pointer to param
+ * \param msg pointer to received message with fcall pre-processing
+ * \return number of param if ok, -1 if failed with errno=
+ * - EINVAL if param or msg is NULL
+ */
+int probe_recv(fcall_ctx_t *fcall, fcall_param_t **param, sci_msg_t **msg, void *data)
+{
+ int index_param, index_var;
+ probe_ctx_t *probe;
+ static fcall_param_t param_result;
+ static sci_msg_t msg_result;
+ static unsigned char buffer[FUNCTION_CALL_PARAM_MAX_SIZE];
+
+ probe = (probe_ctx_t *)data;
+
+ DBG_ASSERT(fcall);
+ DBG_ASSERT(param);
+ DBG_ASSERT(*param);
+ DBG_ASSERT(msg);
+ DBG_ASSERT(*msg);
+ DBG_ASSERT(probe);
+ if((fcall == NULL)
+ || (param == NULL)
+ || (*param == NULL)
+ || (msg == NULL)
+ || (*msg == NULL)
+ || (probe == NULL))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* init result structures */
+ fcall_param_init(&param_result, (*param)->id, (*param)->msg_id);
+ if(sci_msg_init(&msg_result, buffer, sizeof(buffer)) < 0)
+ {
+ station_log(fcall->sci->station, STATION_LOG_ERROR, STATION_LOGTYPE_PROBE,
+ "%s: errno = %d because cannot init result structures", __FUNCTION__, errno);
+ return -1;
+ }
+
+ if((*param)->param_nb == 0)
+ {
+ /* we want all the var list */
+ for(index_var = 0; index_var < probe->var_nb; index_var++)
+ {
+ if(strlen(probe->var_table[index_var].id) > 0)
+ {
+ fcall_param_add(
+ &param_result,
+ &msg_result,
+ probe->var_table[index_var].id,
+ probe->var_table[index_var].length,
+ probe->var_table[index_var].addr
+ );
+ }
+ }
+ }
+
+ else
+ {
+ /* normal get or set request */
+ /* get all param for processing */
+ for(index_param = 0; index_param < (*param)->param_nb; index_param++)
+ {
+ /* find the asked id */
+ for(index_var = 0; index_var < probe->var_nb; index_var++)
+ {
+ if(!strcmp((*param)->param_table[index_param].id, probe->var_table[index_var].id))
+ {
+ /* found !*/
+ if(*(*param)->param_table[index_param].length == 0)
+ {
+ /* this is a get request */
+ station_log(fcall->sci->station, STATION_LOG_INFO, STATION_LOGTYPE_PROBE,
+ "%s get '%s' (%d bytes @ %p)",
+ __FUNCTION__,
+ probe->var_table[index_var].id,
+ probe->var_table[index_var].length,
+ probe->var_table[index_var].addr
+ );
+ fcall_param_add(
+ &param_result,
+ &msg_result,
+ probe->var_table[index_var].id,
+ probe->var_table[index_var].length,
+ probe->var_table[index_var].addr
+ );
+ station_log(fcall->sci->station, STATION_LOG_DEBUG, STATION_LOGTYPE_PROBE,
+ "content: %02x-%02x-%02x-%02x",
+ *((unsigned char *)probe->var_table[index_var].addr),
+ *((unsigned char *)probe->var_table[index_var].addr + 1),
+ *((unsigned char *)probe->var_table[index_var].addr + 2),
+ *((unsigned char *)probe->var_table[index_var].addr + 3)
+ );
+ }
+ else if(ntohs(*(*param)->param_table[index_param].length) <= probe->var_table[index_var].length)
+ {
+ /* this is a set request with a correct length */
+ memcpy(
+ probe->var_table[index_var].addr,
+ (*param)->param_table[index_param].data,
+ ntohs(*(*param)->param_table[index_param].length)
+ );
+ station_log(fcall->sci->station, STATION_LOG_INFO, STATION_LOGTYPE_PROBE,
+ "%s set '%s' (%d bytes @ %p)",
+ __FUNCTION__,
+ probe->var_table[index_var].id,
+ ntohs(*(*param)->param_table[index_param].length),
+ probe->var_table[index_var].addr
+ );
+ fcall_param_add(
+ &param_result,
+ &msg_result,
+ probe->var_table[index_var].id,
+ 0,
+ NULL
+ );
+ }
+ /* do nothing else */
+ break;
+ }
+ }
+ if(index_var >= probe->var_nb)
+ {
+ /* variable not registered */
+ msg_result.hdr.fcall->param_nb = 0;
+ msg_result.hdr.fcall->flags |= FUNCTION_CALL_FLAG_FAILED;
+ station_log(fcall->sci->station, STATION_LOG_NOTICE, STATION_LOGTYPE_PROBE,
+ "%s var '%s' not registered",
+ __FUNCTION__,
+ (*param)->param_table[index_param].id
+ );
+ }
+ }
+ }
+
+ /* switch param and msg for result */
+ *param = &param_result;
+ *msg = &msg_result;
+
+ return param_result.param_nb;
+}