#ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include "config.h" #include "timed_out_string.h" typedef struct { unsigned long int key; /* it is a key used by the calling functions to scan */ /* only part of the tos_array. For instance, all entries */ /* registered by /CSRCH use the key 'CSRC' */ time_t time_out_time; /* when the given time is reached, this entry is automatically deleted */ GByteArray *ba[2]; /* 2 byte arrays can be stored and retrieved */ } TOS_ENTRY; /**********************/ /* array of TOS_ENTRY */ /**********************/ static GArray *tos_array=NULL; G_LOCK_DEFINE_STATIC(tos_array); /****************************************************/ /* add a new timed_out entry to the timed_out array */ /********************************************************************************/ /* input: key= it is a non uniq value used to create group of timed_out entries */ /* duration= number of seconds before the expiration of the entry. */ /* ptr1= pointer on an array of bytes to store. */ /* len1= number of bytes inside ptr1 */ /* ptr2, len2= same as ptr1,len1 */ /* ptr1 and/or ptr2 can be NULL. */ /********************************************************************************/ void add_tos_entry(const unsigned long key, const time_t duration, const char *ptr1, const int len1, const char *ptr2, const int len2) { TOS_ENTRY nw; nw.key=key; nw.time_out_time=time(NULL)+duration; if(ptr1==NULL) { nw.ba[0]=NULL; } else { nw.ba[0]=g_byte_array_new(); nw.ba[0]=g_byte_array_append(nw.ba[0],ptr1,len1); } if(ptr2==NULL) { nw.ba[1]=NULL; } else { nw.ba[1]=g_byte_array_new(); nw.ba[1]=g_byte_array_append(nw.ba[1],ptr2,len2); } G_LOCK(tos_array); if(tos_array==NULL) { tos_array=g_array_new(FALSE,FALSE,sizeof(TOS_ENTRY)); } tos_array=g_array_append_val(tos_array,nw); G_UNLOCK(tos_array); } /**************************************************************************************/ /* remove the given entry. WARNING: this function doesn't and must not lock tos_array */ /**************************************************************************************/ static inline void delete_tos_entry(int num) { TOS_ENTRY *te; te=&(g_array_index(tos_array,TOS_ENTRY,num)); if(te->ba[0]) g_byte_array_free(te->ba[0],TRUE); if(te->ba[1]) g_byte_array_free(te->ba[1],TRUE); tos_array=g_array_remove_index_fast(tos_array,num); } /******************************************************************/ /* search and remove a tos having the same value as the given one */ /******************************************************************/ /* input: key= key to find */ /* ptr= array to find */ /* len= ptr array length */ /* each entry of the tos is a triplet (key,ptr1,ptr2) */ /* if side==0, this function destroys the first tos matching*/ /* (key,ptr,x). If side==1, it is for (key,x,ptr) */ /************************************************************/ /* NOTE: this function MUST be called when the tos_array */ /* is locked. */ /*********************************************************/ static void delete_same_key(const unsigned long key, const char *ptr, const int len, int side) { if(tos_array!=NULL) { int i; for(i=0;ilen;i++) { TOS_ENTRY *te; te=&(g_array_index(tos_array,TOS_ENTRY,i)); /* same key */ if(te->key!=key) continue; if((te->ba[side]==NULL)|| /* no array on the side ? */ (te->ba[side]->len!=len)|| /* array with a != length ? */ (memcmp(te->ba[side]->data,ptr,len)) /* different array ? */ ) continue; delete_tos_entry(i); break; } } } /*****************************************************************************************/ /* add a new timed_out entry to the timed_out array, 1st value will be uniq in the array */ /*****************************************************************************************/ /* input: key= it is a non uniq value used to create group of timed_out entries */ /* duration= number of seconds before the expiration of the entry. */ /* ptr1= pointer on an array of bytes to store. */ /* len1= number of bytes inside ptr1 */ /* ptr2, len2= same as ptr1,len1 */ /* ptr1 and/or ptr2 can be NULL. */ /********************************************************************************/ void add_tos_entry_v1_uniq(const unsigned long key, const time_t duration, const char *ptr1, const int len1, const char *ptr2, const int len2) { TOS_ENTRY nw; nw.key=key; nw.time_out_time=time(NULL)+duration; if(ptr1==NULL) { nw.ba[0]=NULL; } else { nw.ba[0]=g_byte_array_new(); nw.ba[0]=g_byte_array_append(nw.ba[0],ptr1,len1); } if(ptr2==NULL) { nw.ba[1]=NULL; } else { nw.ba[1]=g_byte_array_new(); nw.ba[1]=g_byte_array_append(nw.ba[1],ptr2,len2); } G_LOCK(tos_array); if(tos_array==NULL) { tos_array=g_array_new(FALSE,FALSE,sizeof(TOS_ENTRY)); } else { delete_same_key(key,ptr1,len1,0); } tos_array=g_array_append_val(tos_array,nw); G_UNLOCK(tos_array); } /************************/ /* get the wanted entry */ /************************************************************/ /* input: key= key to find */ /* ptr= array to find */ /* len= ptr array length */ /* *out_ptr, *out_len= copy of the returned address. */ /* content of out_ptr must be freed using free() */ /* each entry of the tos is a triplet (key,ptr1,ptr2) */ /* if side==0, this function returns in *out_ptr the first x*/ /* matching (key,ptr,x). If side==1, it is for (key,x,ptr) */ /************************************************************/ /* output: ==0 not found, ==1, ok */ /* on success, *out_ptr and *out_len are filled */ /**************************************************/ int get_tos_entry(const unsigned long key, const char *ptr, const int len, int side, char **out_ptr, int *out_len) { int ret=0; G_LOCK(tos_array); if(tos_array!=NULL) { int i; for(i=0;ilen;i++) { TOS_ENTRY *te; te=&(g_array_index(tos_array,TOS_ENTRY,i)); /* same key */ if(te->key!=key) continue; if((te->ba[side]==NULL)|| /* no array on the side ? */ (te->ba[side]->len!=len)|| /* array with a != length ? */ (memcmp(te->ba[side]->data,ptr,len)) /* different array ? */ ) continue; /* ok, so it is the good entry */ if(te->ba[side^1]==NULL) { if(out_len) *out_len=0; *out_ptr=NULL; } else { if(out_len) *out_len=te->ba[side^1]->len; *out_ptr=malloc(te->ba[side^1]->len); if(*out_ptr!=NULL) { memcpy(*out_ptr,te->ba[side^1]->data,te->ba[side^1]->len); } } ret=1; break; } } G_UNLOCK(tos_array); return ret; } /***************************/ /* delete the wanted entry */ /************************************************************/ /* input: key= key to find */ /* ptr= array to find */ /* len= ptr array length */ /* each entry of the tos is a triplet (key,ptr1,ptr2) */ /* if side==0, this function returns in *out_ptr the first x*/ /* matching (key,ptr,x). If side==1, it is for (key,x,ptr) */ /************************************************************/ void delete_this_tos_entry(const unsigned long key, const char *ptr, const int len, int side) { G_LOCK(tos_array); delete_same_key(key, ptr, len, side); G_UNLOCK(tos_array); } /******************************************/ /* scan tos array to find expired entries */ /******************************************/ void timeout_tos(void) { time_t now; G_LOCK(tos_array); now=time(NULL); if(tos_array!=NULL) { int i; for(i=tos_array->len-1;i>=0;i--) { TOS_ENTRY *te; te=&(g_array_index(tos_array,TOS_ENTRY,i)); if(te->time_out_time<=now) { delete_tos_entry(i); } } } G_UNLOCK(tos_array); }