Table of Contents

eXtended Attribute Value Pairs - XAVP

Proposal and prototype implementation by:
   Daniel-Constantin Mierla <miconda [at] gmail (dot) com>

CODE IN GIT REPOSITORY BRANCH: daniel/xavp

Purpose

It is not a replacement for current AVP implementation, but a new feature (a new data structure available in code and config, similar to pseudo-variable like: sahred variable $shv(…), hash table variable $sht(…), private variable $var(…)). Developers and script writers can decide which one to use: AVP or XAVP.

Primary goals:

Internal design

Data types definition

struct _sr_xavp;
 
typedef enum {
	SR_XTYPE_NULL=0,
	SR_XTYPE_INT,
	SR_XTYPE_STR,
	SR_XTYPE_TIME,
	SR_XTYPE_LONG,
	SR_XTYPE_LLONG,
	SR_XTYPE_XAVP,
	SR_XTYPE_DATA
} sr_xtype_t;
 
typedef void (*sr_xavp_sfree_f)(void *d);
typedef void (*sr_data_free_f)(void *d, sr_xavp_sfree_f sfree);
 
typedef struct _sr_data {
	void *p;
	sr_data_free_f pfree;
} sr_data_t;
 
typedef struct _sr_xval {
	sr_xtype_t type;
	union {
		int i;
		str s;                 /* replicated */
		time_t t;
		long l;
		long long ll;
		struct _sr_xavp *xavp; /* must be given in shm */
		sr_data_t *data;       /* must be given in shm */
	} v;
} sr_xval_t;
 
typedef struct _sr_xavp {
	unsigned int id;
	str name;
	sr_xval_t val;
	struct _sr_xavp *next;
} sr_xavp_t;

Generic data value

It allows to store any type of data built in shared memory. A structure of sr_data_t has to be allocated in shared memory and filled with two fields:

Example of usage (c-like pseudo-code):

#include <xavp.h>
 
struct _test {
  int a;
  char *s;
} *d;
 
sr_data_t *xdata;
sr_xval_t xval;
str xname = {"my-xavp", 7};
 
void test_free(void *d, sr_xavp_sfree_f sfree)
{
  sfree(d->s);
  sfree(d);
}
 
data = shm_malloc(sizeof(sr_data_t));
 
d = shm_malloc(sizeof(struct _test));
d->s = shm_malloc(5);
 
d->a = 10;
strcpy(d->s, "test");
 
xdata->p = (void*)d;
xdata->pfree = test_free;
 
xval.type = SR_XTYPE_DATA;
xval.v.data = xdata;
xavp_add(&xname, &xval, NULL);

NOTE: this avp printed to xlog will return a string: «data:value of the pointer to data» (e.g., «data:0x973937393»), good for debug purposes.

This type of value is intended for internal usage, one of the modules that needs it immediately being dialog.

XAVP data value

This allow to store within an xavp another xavp or list of xavps.

Example of usage (c-like pseudo-code):

#include <xavp.h>
 
sr_avp_t *list;
sr_xval_t xval;
str xname;
 
// build the list of xavp
list = NULL;
xval.type = SR_XTYPE_INT;
xval.v.i = 10;
xname.s = "avp1"; xname.len = 4;
xavp_add(&xname, &xval, &list);
xval.type = SR_XTYPE_INT;
xval.v.i = 20;
xname.s = "avp2"; xname.len = 4;
xavp_add(&xname, &xval, &list);
 
// add to default list the xavp having the value the above list
xval.type = SR_XTYPE_XAVP;
xval.v.xavp = list;
xname.s = "avp3"; xname.len = 4;
xavp_add(&xname, &xval, NULL);
 
// add to default list another xavp
xval.type = SR_XTYPE_INT;
xval.v.i = 40;
xname.s = "avp4"; xname.len = 4;
xavp_add(&xname, &xval, NULL);

The content of xavp default list is now:

(avp4, 40), (avp3, ((avp2, 20), (avp1, 10)))

These types of xavp can be used directly in configuration file, via PV module, as long as inner xavp has integer or string value. To address them, the format is:

$xavp(avp3=>avp1)=10; # add new xavp 'avp3' with value being xavp 'avp1' with value 10
$xavp(avp3[0]=>avp2)=20; # add to first xavp 'avp3' a new xavp 'avp2' with value 20

IMPORTANT: in assignments, if index is missing, then a new xavp is added. If index is provided, like above [0], then an inner xavp is added to the xavp at respective position.

When getting the value, no index or [0] point to same xavp - first one with respective name.

Benefits

$xavp(sf=>uri)="sip:10.10.10.10";
$xavp(sf[0]=>fr_timer)=10;
$xavp(sf[0]=>fr_inv_timer)=15;
$xavp(sf[0]=>headers)="X-CustomerID: 1234\r\n";
 
$xavp(sf=>uri)="sip:10.10.10.11";
$xavp(sf[0]=>fr_timer)=20;
$xavp(sf[0]=>fr_inv_timer)=35;
 
$xavp(sf=>uri)="sip:10.10.10.12";
$xavp(sf[0]=>fr_timer)=10;
$xavp(sf[0]=>fr_inv_timer)=15;
$xavp(sf[0]=>headers)="X-CustomerID: pw45\r\n";

For second destination, there is no extra header to be added. With current avp model, a dummy value must be set, otherwise the value from third destination will be used.

Use cases

Couple of use cases I have in mind now:

Observations