#ifndef FCALL_H_ #define FCALL_H_ /* Cesar project {{{ * * Copyright (C) 2007 Spidcom * * <<>> * * }}} */ /** * \file fcall.h * \brief The remote function call layer for fulminata. * \ingroup host * * This file descibe the content of fcall structures used by fulminata sci layer * * \todo */ #include #include "maximus/common/types/functioncall_types.h" #ifndef UNIT_TEST #include "lib/swap.h" #else /* UNIT_TEST */ #include #endif /* UNIT_TEST */ #include "host/config.h" #include "host/fwd.h" #include "host/sci.h" #include "host/station.h" #define PROBE_ID_MAX_SIZE FUNCTION_CALL_ID_MAX_SIZE #define PROBE_VAR_MAX_NB FUNCTION_CALL_FUNCTION_MAX_NB struct station_ctx; struct sci_msg; /** type of fcall message; used by fcall msg header */ typedef enum Function_Call_Type fcall_type_t; struct fcall_param_elt { /** parameter id in string format */ char *id; /** parameter data length in network format (big endian)*/ unsigned short *length; /** parameter data */ unsigned char *data; }; struct fcall_param { /** function id in string format */ char id[FUNCTION_CALL_ID_MAX_SIZE]; /** identifier for asynchronous function call return */ unsigned short msg_id; /** true if rteurn from function call is asynchronous */ int is_async; /** function parameters table */ struct fcall_param_elt param_table[FUNCTION_CALL_PARAM_MAX_NB]; /** number of parameter */ int param_nb; }; typedef struct fcall_param fcall_param_t; /** fcall registring list */ struct fcall_function { /** function id in string format */ char id[FUNCTION_CALL_ID_MAX_SIZE]; /** callback function to use */ int (* function)(fcall_ctx_t *fcall, fcall_param_t **param, sci_msg_t **msg, void *data); /* pointer to private data called by function */ void *data; }; /** fcall context definition */ struct fcall_ctx { /** current sci context */ struct sci_ctx *sci; /** table of registered functions */ struct fcall_function function_table[FUNCTION_CALL_FUNCTION_MAX_NB]; /** number of registered functions */ int function_nb; }; /** variable register structure */ struct probe_var { /** var id in string format */ char id[PROBE_ID_MAX_SIZE]; unsigned short length; /** memory address of var */ void *addr; }; typedef struct probe_var probe_var_t; /** probe context definition */ struct probe_ctx { struct fcall_ctx *fcall; struct probe_var var_table[PROBE_VAR_MAX_NB]; int var_nb; }; //BEGIN_DECLS /** * create a new fcall_param context, to manage fcall parameter list * \param function_id function id as string * \return the new fcall_param context, NULL if failed with errno= * - EINVAL if function_id is NULL */ fcall_param_t *fcall_param_new(char *function_id); /** * fcall_param context destruction with memory freeing. * \param param pointer to fcall_param context to destroy */ void fcall_param_free(fcall_param_t *param); /** * 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); /** * 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); /** * set if fucntion call return is asynchronous * \param param pointer to param context to set * \param async boolean to set if return is asynchronous */ static inline void fcall_param_set_async(fcall_param_t *param, int async) { param->is_async = async; return; } /** * get function id * \param param pointer to fcall_param structure * \return current function id of param */ static inline char *fcall_param_get_id(fcall_param_t *param) { return param->id; } /** * get message id * \param param pointer to fcall_param structure * \return current message id of param */ static inline unsigned short fcall_param_get_msg_id(fcall_param_t *param) { return param->msg_id; } static inline void* fcall_param_copy(fcall_param_t *copy, fcall_param_t *source) { return memcpy(copy, source, sizeof(fcall_param_t)); } /** * 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); /** * 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); /** * helper function to bind a long integer into a user variable; * value is converted from BIG-ENDIAN format (network) to CPU format * \param param pointer to param context * \param msg sci message containing the parameters * \param id identifier of wanted parameter as string format * \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 */ static inline int fcall_param_bind_long( fcall_param_t *param, sci_msg_t *msg, char *id, void *data) { int result; result = fcall_param_bind(param, msg, id, sizeof(long), data); *((long *)data) = ntohl(*((long *)data)); return result; } /** * helper function to bind a short integer into a user variable; * value is converted from BIG-ENDIAN format (network) to CPU format * \param param pointer to param context * \param msg sci message containing the parameters * \param id identifier of wanted parameter as string format * \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 */ static inline int fcall_param_bind_short( fcall_param_t *param, sci_msg_t *msg, char *id, void *data) { int result; result = fcall_param_bind(param, msg, id, sizeof(short), data); *((short *)data) = ntohs(*((short *)data)); return result; } /** * 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); /** * helper to add a new long parameter element into the parameter context; * long value is set into BIG-ENDIAN format (network) * \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 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 */ static inline int fcall_param_add_long(fcall_param_t *param, sci_msg_t *msg, char *id, void *data) { long tmp; tmp = htonl(*((long *)data)); return fcall_param_add(param, msg, id, sizeof(long), &tmp); } /** * helper to add a new short parameter element into the parameter context; * long value is set into BIG-ENDIAN format (network) * \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 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 */ static inline int fcall_param_add_short(fcall_param_t *param, sci_msg_t *msg, char *id, void *data) { short tmp; tmp = htons(*((short *)data)); return fcall_param_add(param, msg, id, sizeof(short), &tmp); } /** * create a new fcall context. * \param station current station context * \return the new fcall context, NULL if failed with errno= * - EINVAL if sstation == NULL */ fcall_ctx_t *fcall_new(station_ctx_t *station); /** * fcall context destruction with memory freeing. * \param fcall pointer to fcall context to destroy */ void fcall_free(fcall_ctx_t *fcall); /** * initialize a static fcall context, called during station context creation. * \param fcall fcall context to initialize * \param sci sci which uses the fcall context * \return 0 if ok, -1 if failed with errno= * - EINVAL if fcall or station is NULL */ int fcall_init(fcall_ctx_t *fcall, sci_ctx_t *sci); /** * fcall callback function registering * \param fcall pointer to current fcall context * \param id function string id * \param function pointer to callback function * \param data pointer to private function data * \return 0 if ok, -1 if fail with errno= * - EINVAL if fcall or id is NULL * - ENAMETOOLONG if id length is >= FUNCTION_CALL_ID_MAX_SIZE * - ENOSPC if max number of registred function is reached * - EEXIST if function is already registered */ int fcall_register(fcall_ctx_t *fcall, char *id, int (* function)(fcall_ctx_t *fcall, fcall_param_t **param, sci_msg_t **msg, void *data), void *data); /** * fill a blank fcall header with needed parameter number * \param fcall current fcall context * \param msg pointer to sci message to fill header * \param param pointer to parameter structure to fill into msg * \param flags flags of message * \return 0 if ok, -1 if failed with errno: * - EINVAL if param or msg are NULL */ int fcall_fill_hdr( fcall_ctx_t *fcall, sci_msg_t *msg, fcall_param_t *param, int flags); /** * send the return parameter list of asynchronous function call * \param fcall pointer to the current fcall context * \param pointer to returned parameter structure * \param msg pointer to returned parameter message buffer * \return 0 if ok, -1 if failed with errno: * - EINVAL if fcall, param or msg is NULL * - errno set by sci_send() */ int fcall_return(fcall_ctx_t *fcall, fcall_param_t *param, sci_msg_t *msg); /** * fill fcall body with all function parameters * sci_msg_push() is called each time a parameter is added * \param fcall current fcall context * \param msg sci message to fill body * \param param current fcall param context * \return 0 if ok, -1 if failed with errno: * - EINVAL if param or msg are NULL * - ENOSPC if body overwhelm msg storage capacity */ //int fcall_fill_body( // fcall_ctx_t *fcall, // sci_msg_t *msg, // fcall_param_t *param); /** * fill fcall full content: header + body inside a message * \param fcall current fcall context * \param msg sci message to fill * \param flags flags of message * \return 0 if ok, -1 if failed with errno: * - EINVAL if param or msg are NULL * - ENOSPC if body = header overwhelm msg storage capacity */ //int fcall_fill_msg( // fcall_ctx_t *fcall, // sci_msg_t *msg, // int flags); /** * fcall message processing fucntion; called by sci_recv() * must be registred to sci layer with SCI_MSG_TYPE_FUNCTION_CALL type * \param msg pointer to received message with sci pre-processing * \param fcall pointer to current fcall context * \return 0 if ok, -1 if failed with errno= * - EINVAL if fcall or msg is NULL * - EPROTOTYPE if fcall type != FUNCTION_CALL_TYPE_REQ */ int fcall_recv(sci_msg_t *msg, void *fcall); void fcall_param_dump(fcall_param_t *param, int fd, char *buffer, int size); void fcall_hdr_dump(struct fcall_msg_hdr *hdr, int fd, char *buffer, int size); /** * 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); /** * probe var registering * \param probe pointer to current probe context * \param id variable string id * \param length variable length * \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); /** * 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 0 if ok, -1 if failed with errno= * - EINVAL if fcall, param or msg is NULL */ int probe_recv(fcall_ctx_t *fcall, fcall_param_t **param, sci_msg_t **msg, void *data); //END_DECLS #endif /*FCALL_H_*/