From a71a6ed626266db8265a7a88375be5ef3b2be495 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Wed, 4 Jan 2023 10:18:51 +0100 Subject: [PATCH] core: rpc - support for executing commands with a delta interval limit - RPC_EXEC_DELTA flag has to be set on RPC command export --- src/core/rpc.h | 22 +++++++++- src/core/rpc_lookup.c | 100 ++++++++++++++++++++++++++++++++---------- src/core/rpc_lookup.h | 4 +- 3 files changed, 99 insertions(+), 27 deletions(-) diff --git a/src/core/rpc.h b/src/core/rpc.h index 30f17fb1f31..29162cb2b08 100644 --- a/src/core/rpc.h +++ b/src/core/rpc.h @@ -30,11 +30,18 @@ #ifndef _RPC_H_ #define _RPC_H_ +#include +#include "locking.h" + enum rpc_flags { - RET_ARRAY = (1 << 0), - RET_VALUE = (1 << 1) + RPC_RET_ARRAY = (1 << 0), + RPC_RET_VALUE = (1 << 1), + RPC_EXEC_DELTA = (1 << 2) }; +/* compatibility with old rpc flag name */ +#define RET_ARRAY RPC_RET_ARRAY + typedef enum rpc_capabilities { RPC_DELAYED_REPLY = (1 <<0) /* delayed reply support */ } rpc_capabilities_t; @@ -116,4 +123,15 @@ typedef struct rpc_export { unsigned int flags; /*!< Various flags, reserved for future use */ } rpc_export_t; +typedef struct rpc_xdata { + gen_lock_t elock; + time_t etime; +} rpc_xdata_t; + +typedef struct rpc_exportx { + rpc_export_t r; + rpc_xdata_t *xdata; +} rpc_exportx_t; + + #endif /* _RPC_H_ */ diff --git a/src/core/rpc_lookup.c b/src/core/rpc_lookup.c index f1e6e06617c..208533c6141 100644 --- a/src/core/rpc_lookup.c +++ b/src/core/rpc_lookup.c @@ -25,6 +25,7 @@ #include "str_hash.h" #include "ut.h" #include "dprint.h" +#include "mem/shm.h" #define RPC_HASH_SIZE 32 #define RPC_SARRAY_SIZE 32 /* initial size */ @@ -33,10 +34,12 @@ static struct str_hash_table rpc_hash_table; /* array of pointer to rpc exports, sorted after their name * (used by listMethods) */ -rpc_export_t** rpc_sarray; +rpc_exportx_t** rpc_sarray; int rpc_sarray_crt_size; /* used */ static int rpc_sarray_max_size; /* number of entries alloc'ed */ +int ksr_rpc_exec_delta = 0; + /** init the rpc hash table. * @return 0 on success, -1 on error */ @@ -63,8 +66,14 @@ void destroy_rpcs(void) int r; struct str_hash_entry* e; struct str_hash_entry* bak; + rpc_exportx_t* rx; for (r=0; ru.p; + if(rx->xdata != NULL) { + lock_destroy(&rx->xdata->elock); + shm_free(rx->xdata); + } pkg_free(e); } } @@ -84,11 +93,12 @@ void destroy_rpcs(void) */ static int rpc_hash_add(struct rpc_export* rpc) { - struct str_hash_entry* e; + struct str_hash_entry *e; int name_len; int doc0_len, doc1_len; - struct rpc_export* n_rpc; - struct rpc_export** r; + rpc_exportx_t *n_rpc; + rpc_exportx_t **r; + rpc_xdata_t* xd = NULL; name_len=strlen(rpc->name); doc0_len=rpc->doc_str[0]?strlen(rpc->doc_str[0]):0; @@ -96,7 +106,7 @@ static int rpc_hash_add(struct rpc_export* rpc) /* alloc everything into one block */ e=pkg_malloc(ROUND_POINTER(sizeof(struct str_hash_entry)) - +ROUND_POINTER(sizeof(*rpc))+2*sizeof(char*)+ + +ROUND_POINTER(sizeof(rpc_exportx_t))+2*sizeof(char*)+ +name_len+1+doc0_len+(rpc->doc_str[0]!=0) +doc1_len+(rpc->doc_str[1]!=0) ); @@ -104,31 +114,40 @@ static int rpc_hash_add(struct rpc_export* rpc) PKG_MEM_ERROR; goto error; } - n_rpc=(rpc_export_t*)((char*)e+ + if (rpc->flags & RPC_EXEC_DELTA) { + xd = (rpc_xdata_t*)shm_mallocxz(sizeof(rpc_xdata_t)); + if (xd==NULL) { + pkg_free(e); + goto error; + } + lock_init(&xd->elock); + } + n_rpc=(rpc_exportx_t*)((char*)e+ ROUND_POINTER(sizeof(struct str_hash_entry))); /* copy rpc into n_rpc */ - *n_rpc=*rpc; - n_rpc->doc_str=(const char**)((char*)n_rpc+ROUND_POINTER(sizeof(*rpc))); - n_rpc->name=(char*)n_rpc->doc_str+2*sizeof(char*); - memcpy((char*)n_rpc->name, rpc->name, name_len); - *((char*)&n_rpc->name[name_len])=0; + n_rpc->r=*rpc; + n_rpc->xdata = xd; + n_rpc->r.doc_str=(const char**)((char*)n_rpc+ROUND_POINTER(sizeof(rpc_exportx_t))); + n_rpc->r.name=(char*)n_rpc->r.doc_str+2*sizeof(char*); + memcpy((char*)n_rpc->r.name, rpc->name, name_len); + *((char*)&n_rpc->r.name[name_len])=0; if (rpc->doc_str[0]){ - n_rpc->doc_str[0]=&n_rpc->name[name_len+1]; - memcpy((char*)n_rpc->doc_str[0], rpc->doc_str[0], doc0_len); - *(char*)&(n_rpc->doc_str[0][doc0_len])=0; + n_rpc->r.doc_str[0]=&n_rpc->r.name[name_len+1]; + memcpy((char*)n_rpc->r.doc_str[0], rpc->doc_str[0], doc0_len); + *(char*)&(n_rpc->r.doc_str[0][doc0_len])=0; }else{ - n_rpc->doc_str[0]=0; + n_rpc->r.doc_str[0]=0; } if (rpc->doc_str[1]){ - n_rpc->doc_str[1]=n_rpc->doc_str[0]?&n_rpc->doc_str[0][doc0_len+1]: - &n_rpc->name[name_len+1];; - memcpy((char*)n_rpc->doc_str[1], rpc->doc_str[1], doc1_len); - *(char*)&(n_rpc->doc_str[1][doc1_len])=0; + n_rpc->r.doc_str[1]=n_rpc->r.doc_str[0]?&n_rpc->r.doc_str[0][doc0_len+1]: + &n_rpc->r.name[name_len+1]; + memcpy((char*)n_rpc->r.doc_str[1], rpc->doc_str[1], doc1_len); + *(char*)&(n_rpc->r.doc_str[1][doc1_len])=0; }else{ - n_rpc->doc_str[1]=0; + n_rpc->r.doc_str[1]=0; } - e->key.s=(char*)n_rpc->name; + e->key.s=(char*)n_rpc->r.name; e->key.len=name_len; e->flags=0; e->u.p=n_rpc; @@ -147,7 +166,7 @@ static int rpc_hash_add(struct rpc_export* rpc) }; /* insert into array, sorted */ for (r=rpc_sarray;r<(rpc_sarray+rpc_sarray_crt_size); r++){ - if (strcmp(n_rpc->name, (*r)->name)<0) + if (strcmp(n_rpc->r.name, (*r)->r.name)<0) break; } if (r!=(rpc_sarray+rpc_sarray_crt_size)) @@ -170,10 +189,43 @@ rpc_export_t* rpc_lookup(const char* name, int len) struct str_hash_entry* e; e=str_hash_get(&rpc_hash_table, (char*)name, len); - return e?(rpc_export_t*)e->u.p:0; + return e?&(((rpc_exportx_t*)e->u.p)->r):0; } +/** lookup an extended rpc export after its name. + * @return pointer to rpc export on success, 0 on error + */ +rpc_exportx_t* rpc_lookupx(const char* name, int len, unsigned int *rdata) +{ + rpc_exportx_t *rx; + time_t tnow; + + struct str_hash_entry* e; + + e=str_hash_get(&rpc_hash_table, (char*)name, len); + *rdata = 0; + if(e != NULL) { + rx = (rpc_exportx_t*)e->u.p; + if(ksr_rpc_exec_delta > 0 && rx->xdata != NULL) { + tnow = time(NULL); + lock_get(&rx->xdata->elock); + if(rx->xdata->etime > 0) { + if(rx->xdata->etime > tnow - ksr_rpc_exec_delta) { + *rdata = RPC_EXEC_DELTA; + } else { + rx->xdata->etime = tnow; + } + } else { + rx->xdata->etime = tnow; + } + lock_release(&rx->xdata->elock); + } + return rx; + } + return NULL; +} + /** register a new rpc. * @return 0 on success, -1 on error, 1 on duplicate diff --git a/src/core/rpc_lookup.h b/src/core/rpc_lookup.h index f29aa063fb4..0a9c3188cf3 100644 --- a/src/core/rpc_lookup.h +++ b/src/core/rpc_lookup.h @@ -25,14 +25,16 @@ #define _RPC_LOOKUP_H_ #include "rpc.h" + /* must be exported for listing the rpcs */ -extern rpc_export_t** rpc_sarray; +extern rpc_exportx_t** rpc_sarray; extern int rpc_sarray_crt_size; int init_rpcs(void); void destroy_rpcs(void); rpc_export_t* rpc_lookup(const char* name, int len); +rpc_exportx_t* rpc_lookupx(const char* name, int len, unsigned int *rdata); int rpc_register(rpc_export_t* rpc); int rpc_register_array(rpc_export_t* rpc_array);