Skip to content

Commit

Permalink
usrloc: Add generic, contact-level key-value storage
Browse files Browse the repository at this point in the history
Allows various usrloc-dependent modules to easily store data into or to
retrieve data from each usrloc contact.
  • Loading branch information
liviuchircu committed Jan 9, 2018
1 parent 719f620 commit 2ee9407
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 3 deletions.
84 changes: 82 additions & 2 deletions modules/usrloc/ucontact.c
Expand Up @@ -54,6 +54,8 @@

extern event_id_t ei_c_update_id;

void destroy_kv_storage_val(void* _val);

/*
* Determines the IP address of the next hop on the way to given contact based
* on following URIs: path URI -> received URI -> contact URI
Expand Down Expand Up @@ -111,14 +113,19 @@ new_ucontact(str* _dom, str* _aor, str* _contact, ucontact_info_t* _ci)
}
memset(c, 0, sizeof(ucontact_t) + att_data_sz);

c->kv_storage = map_create(AVLMAP_SHARED);
if (!c->kv_storage) {
LM_ERR("oom\n");
goto out_free;
}

if (att_data_sz > 0)
c->attached_data = (void **)(c + 1);

if (parse_uri(_contact->s, _contact->len, &tmp_uri) < 0) {
LM_ERR("contact [%.*s] is not valid! Will not store it!\n",
_contact->len, _contact->s);
shm_free(c);
return NULL;
goto out_free;
}

if (shm_str_dup( &c->c, _contact) < 0) goto mem_error;
Expand Down Expand Up @@ -179,6 +186,7 @@ new_ucontact(str* _dom, str* _aor, str* _contact, ucontact_info_t* _ci)
if (c->c.s) shm_free(c->c.s);
if (c->instance.s) shm_free(c->instance.s);
if (c->attr.s) shm_free(c->attr.s);
if (c->kv_storage) map_destroy(c->kv_storage, destroy_kv_storage_val);
shm_free(c);
return NULL;
}
Expand All @@ -198,6 +206,7 @@ void free_ucontact(ucontact_t* _c)
if (_c->callid.s) shm_free(_c->callid.s);
if (_c->c.s) shm_free(_c->c.s);
if (_c->attr.s) shm_free(_c->attr.s);
map_destroy(_c->kv_storage, destroy_kv_storage_val);
shm_free( _c );
}

Expand Down Expand Up @@ -971,3 +980,74 @@ int update_ucontact(struct urecord* _r, ucontact_t* _c, ucontact_info_t* _ci,
}
return 0;
}

void destroy_kv_storage_val(void* _val)
{
int_str_t *val = (int_str_t *)_val;

if (val->is_str && !ZSTR(val->s))
shm_free(val->s.s);

shm_free(val);
}

int_str_t *get_ucontact_key(ucontact_t* _ct, const str* _key)
{
int_str_t **val;

val = (int_str_t **)map_get(_ct->kv_storage, *_key);
if (!val) {
LM_ERR("oom\n");
return NULL;
}

return *val;
}

int_str_t *put_ucontact_key(ucontact_t* _ct, const str* _key,
const int_str_t* _val)
{
int_str_t **cur, *new_val;

cur = (int_str_t **)map_get(_ct->kv_storage, *_key);
if (!cur) {
LM_ERR("oom\n");
return NULL;
}

if (!*cur) {
*cur = shm_malloc(sizeof **cur);
if (!*cur) {
LM_ERR("oom\n");
return NULL;
}
memset(*cur, 0, sizeof **cur);

}

new_val = *cur;

if (!_val->is_str) {
if (new_val->is_str) {
new_val->is_str = 0;
shm_free(new_val->s.s);
}

new_val->i = _val->i;
} else {
if (!new_val->is_str) {
memset(new_val, 0, sizeof *new_val);
new_val->is_str = 1;
}

if (shm_str_resize(&new_val->s, _val->s.len + 1) != 0) {
LM_ERR("oom\n");
return NULL;
}

memcpy(new_val->s.s, _val->s.s, _val->s.len);
new_val->s.s[_val->s.len] = '\0';
}

return new_val;
}
30 changes: 29 additions & 1 deletion modules/usrloc/ucontact.h
Expand Up @@ -38,6 +38,7 @@

#include <stdio.h>
#include <time.h>
#include "../../map.h"
#include "../../qvalue.h"
#include "../../str.h"
#include "../../proxy.h"
Expand Down Expand Up @@ -96,7 +97,9 @@ typedef struct ucontact {
struct proxy_l next_hop;/*!< SIP-wise determined next hop */
unsigned int label; /*!< label to find the contact in contact list>*/

void **attached_data; /*!< data attached by API subscribers >*/
map_t kv_storage; /*!< data attached by API subscribers >*/

void **attached_data; /*!< TODO del; data attached by API subscribers >*/

struct ucontact* next; /*!< Next contact in the linked list */
struct ucontact* prev; /*!< Previous contact in the linked list */
Expand Down Expand Up @@ -243,4 +246,29 @@ typedef int (*update_ucontact_t)(struct urecord* _r, ucontact_t* _c,
int update_ucontact(struct urecord* _r, ucontact_t* _c, ucontact_info_t* _ci,
char is_replicated);

/*! \brief
* Fetch a key from the contact-level storage
* NOTE: assumes the corresponding udomain lock is properly acquired
*
* Returns: NULL on error/key not found, value pointer otherwise
*/
typedef int_str_t *(*get_ucontact_key_t)(ucontact_t* _ct,
const str* _key);

int_str_t *get_ucontact_key(ucontact_t* _ct, const str* _key);

/*! \brief
* Create or re-assign a key-value pair within contact-level storage.
* ("_key" and "_val" are fully duplicated in shared memory)
*
* NOTE: assumes the corresponding udomain lock is properly acquired
*
* Returns: NULL on error, new value pointer otherwise
*/
typedef int_str_t *(*put_ucontact_key_t)(ucontact_t* _ct,
const str* _key, const int_str_t* _val);

int_str_t *put_ucontact_key(ucontact_t* _ct, const str* _key,
const int_str_t* _val);

#endif /* UCONTACT_H */
2 changes: 2 additions & 0 deletions modules/usrloc/usrloc.c
Expand Up @@ -70,6 +70,8 @@ int bind_usrloc(usrloc_api_t* api)
api->get_ucontact = get_ucontact;
api->get_ucontact_from_id = get_ucontact_from_id;
api->update_ucontact = update_ucontact;
api->get_ucontact_key = get_ucontact_key;
api->put_ucontact_key = put_ucontact_key;
api->register_ulcb = register_ulcb;

api->use_domain = use_domain;
Expand Down
3 changes: 3 additions & 0 deletions modules/usrloc/usrloc.h
Expand Up @@ -71,6 +71,9 @@ typedef struct usrloc_api {
lock_ulslot_t lock_ulslot;
unlock_ulslot_t unlock_ulslot;

get_ucontact_key_t get_ucontact_key;
put_ucontact_key_t put_ucontact_key;

register_ulcb_t register_ulcb;
} usrloc_api_t;

Expand Down
8 changes: 8 additions & 0 deletions ut.h
Expand Up @@ -43,6 +43,14 @@
#include "mem/mem.h"
#include "mem/shm_mem.h"

typedef struct _int_str_t {
union {
int i;
str s;
};
unsigned char is_str;
} int_str_t;

struct sip_msg;

/* zero-string wrapper */
Expand Down

0 comments on commit 2ee9407

Please sign in to comment.