Browse code

registrar - add xavp to reg_fetch_contacts

modparams("usrloc", "xavp_contact", "ulattrs");

reg_fetch_contacts("location", "$fu", "caller");
xlog("L_INFO", "$fu xavp = $ulc(caller=>received)");
xlog("L_INFO", "$fu xavp = $ulc(caller=>ulattrs=>account_id)");

Luis Azedo authored on 17/02/2015 19:47:51
Showing 1 changed files
... ...
@@ -55,6 +55,7 @@ typedef struct _regpv_profile {
55 55
 typedef struct _regpv_name {
56 56
 	regpv_profile_t *rp;
57 57
 	int attr;
58
+	pv_xavp_name_t* xname;
58 59
 } regpv_name_t;
59 60
 
60 61
 static regpv_profile_t *_regpv_profile_list = NULL;
... ...
@@ -112,6 +113,9 @@ static void regpv_free_profile(regpv_profile_t *rpp)
112 113
 	ptr = rpp->contacts;
113 114
 	while(ptr)
114 115
 	{
116
+		if(ptr->xavp) {
117
+			xavp_destroy_list(&ptr->xavp);
118
+		}
115 119
 		ptr0 = ptr;
116 120
 		ptr = ptr->next;
117 121
 		pkg_free(ptr0);
... ...
@@ -153,6 +157,285 @@ void regpv_free_profiles(void)
153 157
 	_regpv_profile_list = 0;
154 158
 }
155 159
 
160
+char* regpv_xavp_fill_ni(str *in, pv_xavp_name_t *xname)
161
+{
162
+	char *p;
163
+	str idx;
164
+	int n;
165
+
166
+	if(in->s==NULL || in->len<=0 || xname==NULL)
167
+		return NULL;
168
+	p = in->s;
169
+
170
+	/* eat ws */
171
+	while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
172
+		p++;
173
+	if(p>in->s+in->len || *p=='\0')
174
+		goto error;
175
+	xname->name.s = p;
176
+	while(p < in->s + in->len)
177
+	{
178
+		if(*p=='=' || *p==' ' || *p=='\t' || *p=='\n' || *p=='\r' || *p=='[')
179
+			break;
180
+		p++;
181
+	}
182
+	xname->name.len = p - xname->name.s;
183
+	if(p>in->s+in->len || *p=='\0')
184
+		return p;
185
+	/* eat ws */
186
+	while(p<in->s+in->len && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r'))
187
+		p++;
188
+	if(p>in->s+in->len || *p=='\0')
189
+		return p;
190
+
191
+	if(*p!='[')
192
+		return p;
193
+	/* there is index */
194
+	p++;
195
+	idx.s = p;
196
+	n = 0;
197
+	while(p<in->s+in->len && *p!='\0')
198
+	{
199
+		if(*p==']')
200
+		{
201
+			if(n==0)
202
+				break;
203
+			n--;
204
+		}
205
+		if(*p == '[')
206
+			n++;
207
+		p++;
208
+	}
209
+	if(p>in->s+in->len || *p=='\0')
210
+		goto error;
211
+
212
+	if(p==idx.s)
213
+	{
214
+		LM_ERR("xavp [\"%.*s\"] does not get empty index param\n",
215
+				in->len, in->s);
216
+		goto error;
217
+	}
218
+	idx.len = p - idx.s;
219
+	if(pv_parse_index(&xname->index, &idx)!=0)
220
+	{
221
+		LM_ERR("idx \"%.*s\" has an invalid index param [%.*s]\n",
222
+					in->len, in->s, idx.len, idx.s);
223
+		goto error;
224
+	}
225
+	xname->index.type = PVT_EXTRA;
226
+	p++;
227
+	return p;
228
+error:
229
+	return NULL;
230
+}
231
+
232
+int regpv_parse_xavp_name(pv_spec_p sp, str *in)
233
+{
234
+	pv_xavp_name_t *xname=NULL;
235
+	char *p;
236
+	str s;
237
+
238
+	if(in->s==NULL || in->len<=0)
239
+		return -1;
240
+
241
+	xname = (pv_xavp_name_t*)shm_malloc(sizeof(pv_xavp_name_t));
242
+	if(xname==NULL)
243
+		return -1;
244
+
245
+	memset(xname, 0, sizeof(pv_xavp_name_t));
246
+
247
+	s = *in;
248
+
249
+	p = regpv_xavp_fill_ni(&s, xname);
250
+	if(p==NULL) {
251
+		goto error;
252
+	}
253
+
254
+	if(*p!='=') {
255
+		goto done;
256
+	}
257
+	p++;
258
+	if(*p!='>') {
259
+		goto error;
260
+	}
261
+	p++;
262
+
263
+	s.len = in->len - (int)(p - in->s);
264
+	s.s = p;
265
+	LM_INFO("xavp sublist [%.*s] - key [%.*s]\n", xname->name.len,
266
+			xname->name.s, s.len, s.s);
267
+
268
+	xname->next = (pv_xavp_name_t*)pkg_malloc(sizeof(pv_xavp_name_t));
269
+	if(xname->next==NULL) {
270
+		goto error;
271
+	}
272
+
273
+	memset(xname->next, 0, sizeof(pv_xavp_name_t));
274
+
275
+	p = regpv_xavp_fill_ni(&s, xname->next);
276
+	if(p==NULL) {
277
+		goto error;
278
+	}
279
+
280
+done:
281
+	sp->pvp.pvn.u.dname = (void*)xname;
282
+	sp->pvp.pvn.type = PV_NAME_PVAR;
283
+	return 0;
284
+
285
+error:
286
+	if(xname!=NULL) {
287
+		pkg_free(xname);
288
+	}
289
+	return -1;
290
+}
291
+
292
+int regpv_xavp_get_value(struct sip_msg *msg, pv_param_t *param,
293
+		pv_value_t *res, sr_xavp_t *avp)
294
+{
295
+	static char _pv_xavp_buf[128];
296
+	str s;
297
+
298
+	switch(avp->val.type) {
299
+		case SR_XTYPE_NULL:
300
+			return pv_get_null(msg, param, res);
301
+		break;
302
+		case SR_XTYPE_INT:
303
+			return pv_get_sintval(msg, param, res, avp->val.v.i);
304
+		break;
305
+		case SR_XTYPE_STR:
306
+			return pv_get_strval(msg, param, res, &avp->val.v.s);
307
+		break;
308
+		case SR_XTYPE_TIME:
309
+			if(snprintf(_pv_xavp_buf, 128, "%lu", (long unsigned)avp->val.v.t)<0)
310
+				return pv_get_null(msg, param, res);
311
+		break;
312
+		case SR_XTYPE_LONG:
313
+			if(snprintf(_pv_xavp_buf, 128, "%ld", (long unsigned)avp->val.v.l)<0)
314
+				return pv_get_null(msg, param, res);
315
+		break;
316
+		case SR_XTYPE_LLONG:
317
+			if(snprintf(_pv_xavp_buf, 128, "%lld", avp->val.v.ll)<0)
318
+				return pv_get_null(msg, param, res);
319
+		break;
320
+		case SR_XTYPE_XAVP:
321
+			if(snprintf(_pv_xavp_buf, 128, "<<xavp:%p>>", avp->val.v.xavp)<0)
322
+				return pv_get_null(msg, param, res);
323
+		break;
324
+		case SR_XTYPE_DATA:
325
+			if(snprintf(_pv_xavp_buf, 128, "<<data:%p>>", avp->val.v.data)<0)
326
+				return pv_get_null(msg, param, res);
327
+		break;
328
+		default:
329
+			return pv_get_null(msg, param, res);
330
+	}
331
+	s.s = _pv_xavp_buf;
332
+	s.len = strlen(_pv_xavp_buf);
333
+	return pv_get_strval(msg, param, res, &s);
334
+}
335
+
336
+int regpv_get_xavp_from_start(struct sip_msg *msg, pv_param_t *param,
337
+		pv_value_t *res, sr_xavp_t **start)
338
+{
339
+	pv_xavp_name_t *xname=NULL;
340
+	sr_xavp_t *avp=NULL;
341
+	int idxf = 0;
342
+	int idx = 0;
343
+	int count;
344
+	char *p, *p_ini;
345
+	int p_size;
346
+
347
+	if(param==NULL)
348
+	{
349
+		LM_ERR("bad parameters\n");
350
+		return -1;
351
+	}
352
+	xname = ((regpv_name_t*)param->pvn.u.dname)->xname;
353
+
354
+	if(xname->index.type==PVT_EXTRA)
355
+	{
356
+		/* get the index */
357
+		if(pv_get_spec_index(msg, &xname->index.pvp, &idx, &idxf)!=0)
358
+		{
359
+			LM_ERR("invalid index\n");
360
+			return -1;
361
+		}
362
+	}
363
+	/* fix the index */
364
+	if(idx<0)
365
+	{
366
+		count = xavp_count(&xname->name, start);
367
+		idx = count + idx;
368
+	}
369
+	avp = xavp_get_by_index(&xname->name, idx, start);
370
+	if(avp==NULL) {
371
+		LM_DBG("GET XAVP AVP = NULL\n");
372
+		return pv_get_null(msg, param, res);
373
+	}
374
+	if(xname->next==NULL) {
375
+		LM_DBG("GET XAVP XNAME NEXT = NULL\n");
376
+		return regpv_xavp_get_value(msg, param, res, avp);
377
+	}
378
+
379
+	idx = 0;
380
+	idxf = 0;
381
+	if(xname->next->index.type==PVT_EXTRA)
382
+	{
383
+		/* get the index */
384
+		if(pv_get_spec_index(msg, &xname->next->index.pvp, &idx, &idxf)!=0)
385
+		{
386
+			LM_ERR("invalid index\n");
387
+			return -1;
388
+		}
389
+	}
390
+	/* fix the index */
391
+	if(idx<0)
392
+	{
393
+		count = xavp_count(&xname->next->name, &avp->val.v.xavp);
394
+		idx = count + idx;
395
+	}
396
+	avp = xavp_get_by_index(&xname->next->name, idx, &avp->val.v.xavp);
397
+	if(avp==NULL) {
398
+		LM_DBG("GET XAVP AVP BY INDEX = NULL\n");
399
+		return pv_get_null(msg, param, res);
400
+	}
401
+	/* get all values of second key */
402
+	if(idxf==PV_IDX_ALL)
403
+	{
404
+		p_ini = pv_get_buffer();
405
+		p = p_ini;
406
+		p_size = pv_get_buffer_size();
407
+		do {
408
+			if(p!=p_ini)
409
+			{
410
+				if(p-p_ini+REGPV_FIELD_DELIM_LEN+1>p_size)
411
+				{
412
+					LM_ERR("local buffer length exceeded\n");
413
+					return pv_get_null(msg, param, res);
414
+				}
415
+				memcpy(p, REGPV_FIELD_DELIM, REGPV_FIELD_DELIM_LEN);
416
+				p += REGPV_FIELD_DELIM_LEN;
417
+			}
418
+			if(regpv_xavp_get_value(msg, param, res, avp)<0)
419
+			{
420
+				LM_ERR("can get value\n");
421
+				return pv_get_null(msg, param, res);
422
+			}
423
+			if(p-p_ini+res->rs.len+1>p_size)
424
+			{
425
+				LM_ERR("local buffer length exceeded!\n");
426
+				return pv_get_null(msg, param, res);
427
+			}
428
+			memcpy(p, res->rs.s, res->rs.len);
429
+			p += res->rs.len;
430
+		} while ((avp=xavp_get_next(avp))!=0);
431
+		res->rs.s = p_ini;
432
+		res->rs.len = p - p_ini;
433
+		return 0;
434
+	}
435
+	return regpv_xavp_get_value(msg, param, res, avp);
436
+}
437
+
438
+
156 439
 int pv_get_ulc(struct sip_msg *msg,  pv_param_t *param,
157 440
 		pv_value_t *res)
158 441
 {
... ...
@@ -194,7 +477,7 @@ int pv_get_ulc(struct sip_msg *msg,  pv_param_t *param,
194 477
 	/* get contact */
195 478
 	i = 0;
196 479
 	c = rpp->contacts;
197
-	while(rpp)
480
+	while(c)
198 481
 	{
199 482
 		if(i == idx)
200 483
 			break;
... ...
@@ -271,6 +554,10 @@ int pv_get_ulc(struct sip_msg *msg,  pv_param_t *param,
271 554
 			if(c->instance.len>0)
272 555
 				return  pv_get_strval(msg, param, res, &c->instance);
273 556
 		break;
557
+		case 21: /* xavp */
558
+			if(c->xavp)
559
+				return regpv_get_xavp_from_start(msg, param, res, &c->xavp);
560
+		break;
274 561
 	}
275 562
 
276 563
 	return pv_get_null(msg, param, res);
... ...
@@ -335,6 +622,15 @@ int pv_parse_ulc_name(pv_spec_p sp, str *in)
335 622
 	memset(rp, 0, sizeof(regpv_name_t));
336 623
 	rp->rp = rpp;
337 624
 
625
+	if(strstr(pa.s, "=>")) {
626
+		regpv_parse_xavp_name(sp, &pa);
627
+		pv_xavp_name_t* xname = (pv_xavp_name_t*)sp->pvp.pvn.u.dname;
628
+		LM_DBG("ulc parse xavp name [%.*s] \n", xname->name.len, xname->name.s);
629
+		rp->xname = xname;
630
+		rp->attr = 21;
631
+		goto done;
632
+	}
633
+
338 634
 	switch(pa.len)
339 635
 	{
340 636
 		case 1: 
... ...
@@ -404,6 +700,7 @@ int pv_parse_ulc_name(pv_spec_p sp, str *in)
404 700
 		default:
405 701
 			goto error;
406 702
 	}
703
+done:
407 704
 	sp->pvp.pvn.u.dname = (void*)rp;
408 705
 	sp->pvp.pvn.type = PV_NAME_PVAR;
409 706
 
... ...
@@ -540,6 +837,10 @@ int pv_fetch_contacts(struct sip_msg* msg, char* table, char* uri,
540 837
 			c0->instance.len = ptr->instance.len;
541 838
 			p += c0->instance.len;
542 839
 		}
840
+		if(ptr->xavp != NULL)
841
+		{
842
+			c0->xavp = xavp_clone_level_nodata(ptr->xavp);
843
+		}		
543 844
 
544 845
 		if(ptr0==NULL)
545 846
 		{
... ...
@@ -681,6 +982,10 @@ void reg_ul_expired_contact(ucontact_t* ptr, int type, void* param)
681 982
 		c0->instance.len = ptr->instance.len;
682 983
 		p += c0->instance.len;
683 984
 	}
985
+	if(ptr->xavp != NULL)
986
+	{
987
+		c0->xavp = xavp_clone_level_nodata(ptr->xavp);
988
+	}		
684 989
 
685 990
 	rpp->contacts = c0;
686 991
 	rpp->nrc = 1;