Browse code

Merge be3df480dfe2f2094e716cc332002091dd2382bf into 42bc79b3b617632b6f83e1352b5cb8266706d7c0

sergey-safarov authored on 06/05/2021 06:03:11 • GitHub committed on 06/05/2021 06:03:11
Showing 3 changed files
... ...
@@ -43,6 +43,7 @@
43 43
 #include "../../core/script_cb.h"
44 44
 
45 45
 #include "functions.h"
46
+#include "lost_select.h"
46 47
 
47 48
 MODULE_VERSION
48 49
 
... ...
@@ -161,6 +162,8 @@ static int mod_init(void)
161 162
 
162 163
 	LM_DBG("**** init lost: held response time: %d \n", held_resp_time);
163 164
 
165
+	register_select_table(lost_sel);
166
+
164 167
 	LM_DBG("**** init lost module done.\n");
165 168
 
166 169
 	return 0;
167 170
new file mode 100644
... ...
@@ -0,0 +1,877 @@
1
+/*
2
+ * lost module - select interface
3
+ *
4
+ * Copyright (C) 2021 Eugene Sukhanov
5
+ * NGA911
6
+ *
7
+ * This file is part of Kamailio, a free SIP server.
8
+ *
9
+ * Kamailio is free software; you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation; either version 2 of the License, or
12
+ * (at your option) any later version
13
+ *
14
+ * Kamailio is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with this program; if not, write to the Free Software
21
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22
+ *
23
+ */
24
+
25
+/*!
26
+ * \file
27
+ * \brief Kamailio lost :: Select interface.
28
+ * \ingroup lost
29
+ * Module: \ref lost
30
+ */
31
+
32
+#include "../../core/select.h"
33
+#include "../../core/select_buf.h"
34
+#include "../../core/parser/msg_parser.h"
35
+#include "../../core/parser/hf.h"
36
+#include "../../core/parser/parse_content.h"
37
+#include "../../core/parser/parse_param.h"
38
+#include "../../core/parser/parse_uri.h"
39
+#include "../../core/parser/parse_body.h"
40
+#include "../../core/strutils.h"
41
+#include "../../core/trim.h"
42
+#include "../../core/msg_translator.h"
43
+
44
+
45
+/*
46
+@lost.nena - all Call-Info headers with “purpose” param “nena-CallId” or “nena-IncidentId”;
47
+@lost.nena.call_id - the value of the first Call-Info header with purpose param of “nena-CallId”;
48
+@lost.nena.incident_id - the value of the first Call-Info header with purpose param of “nena-IncidentId”;
49
+
50
+@lost.emergency_call_data - all Call-Info headers with “purpose=EmergencyCallData”;
51
+
52
+@lost.emergency_call_data.provider_info - all Call-Info headers with “purpose=EmergencyCallData.ProviderInfo”;
53
+@lost.emergency_call_data.provider_info.counter - counter of present Call-Info headers with relevant emergency call data type;
54
+@lost.emergency_call_data.provider_info[%i].uri_type - one of `http`, `https`, `cid` or `sip`;
55
+@lost.emergency_call_data.provider_info[%i].uri - content of header inside “<>”;
56
+@lost.emergency_call_data.provider_info[%i].raw - see details below;
57
+@lost.emergency_call_data.provider_info[%i].body - if call-info header contains `cid` value (emergency call data passed BY_VALUE),
58
+	then contains `body` of relevant multipart part;
59
+@lost.emergency_call_data.provider_info[%i].header.%s[%i] - if call-info header contains `cid` value (emergency call data passed BY_VALUE),
60
+	then provide access to multipart part headers like `Content-Type`, `Content-Disposition`;
61
+@lost.emergency_call_data.provider_info[%i].header.%s - the short form of @lost.emergency_call_data.provider_info[%i].header.%s[1];
62
+
63
+@lost.emergency_call_data.service_info - all Call-Info headers with “purpose=EmergencyCallData.ServiceInfo”;
64
+@lost.emergency_call_data.service_info.counter - same as provider_info;
65
+@lost.emergency_call_data.service_info[%i].uri_type - same as provider_info
66
+@lost.emergency_call_data.service_info[%i].uri - content of header inside “<>”;
67
+@lost.emergency_call_data.service_info[%i].raw - same as provider_info
68
+@lost.emergency_call_data.service_info[%i].body - same as provider_info
69
+@lost.emergency_call_data.service_info[%i].header.%s[%i] - if call-info header contains `cid` value (emergency call data passed BY_VALUE), then provide access to multipart part headers like `Content-Type`, `Content-Disposition`;
70
+@lost.emergency_call_data.service_info[%i].header.%s - the short form of @lost.emergency_call_data.service_info[%i].header.%s[1];
71
+
72
+@lost.emergency_call_data.device_info - all Call-Info headers with “purpose=EmergencyCallData.DeviceInfo”;
73
+@lost.emergency_call_data.device_info.counter - same as provider_info;
74
+@lost.emergency_call_data.device_info[%i].uri_type - same as provider_info
75
+@lost.emergency_call_data.device_info[%i].uri - content of header inside “<>”;
76
+@lost.emergency_call_data.device_info[%i].raw - same as provider_info
77
+@lost.emergency_call_data.device_info[%i].body - same as provider_info
78
+@lost.emergency_call_data.device_info[%i].header.%s[%i] - if call-info header contains `cid` value (emergency call data passed BY_VALUE), then provide access to multipart part headers like `Content-Type`, `Content-Disposition`;
79
+@lost.emergency_call_data.device_info[%i].header.%s - the short form of @lost.emergency_call_data.device_info[%i].header.%s[1];
80
+
81
+@lost.emergency_call_data.subscriber_info - all Call-Info headers with “purpose=EmergencyCallData.SubscriberInfo”;
82
+@lost.emergency_call_data.subscriber_info.counter - same as provider_info;
83
+@lost.emergency_call_data.subscriber_info[%i].uri_type - same as provider_info
84
+@lost.emergency_call_data.subscriber_info[%i].uri - content of header inside “<>”;
85
+@lost.emergency_call_data.subscriber_info[%i].raw - same as provider_info
86
+@lost.emergency_call_data.subscriber_info[%i].body - same as provider_info
87
+@lost.emergency_call_data.subscriber_info[%i].header.%s[%i] - if call-info header contains `cid` value (emergency call data passed BY_VALUE), then provide access to multipart part headers like `Content-Type`, `Content-Disposition`;
88
+@lost.emergency_call_data.subscriber_info[%i].header.%s - the short form of @lost.emergency_call_data.subscriber_info[%i].header.%s[1];
89
+
90
+@lost.emergency_call_data.comment - all Call-Info headers with “purpose=EmergencyCallData.Comment”;
91
+@lost.emergency_call_data.comment.counter - same as provider_info;
92
+@lost.emergency_call_data.comment[%i].uri_type - same as provider_info
93
+@lost.emergency_call_data.comment[%i].uri - content of header inside “<>”;
94
+@lost.emergency_call_data.comment[%i].raw - same as provider_info
95
+@lost.emergency_call_data.comment[%i].body - same as provider_info
96
+@lost.emergency_call_data.comment[%i].header.%s[%i] - if call-info header contains `cid` value (emergency call data passed BY_VALUE), then provide access to multipart part headers like `Content-Type`, `Content-Disposition`;
97
+@lost.emergency_call_data.comment[%i].header.%s - the short form of @lost.emergency_call_data.comment[%i].header.%s[1];
98
+ */
99
+
100
+static char* strstrin(char* string, int len, char* substring, int n)
101
+{
102
+    const char *a, *b;
103
+    int l;
104
+    b = substring;
105
+    if ((*b == 0) || (n <= 0)) return string;
106
+    for(l = 0; (string[l] != 0) && (l < len); l++)
107
+    {
108
+        if (tolower(string[l]) != tolower(*b)) continue;
109
+        a = string + l;
110
+        while(1)
111
+        {
112
+            if((b - substring) >= n) return string + l;
113
+            if(tolower(*a++) != tolower(*b++)) break;
114
+        }
115
+        b = substring;
116
+    }
117
+    return NULL;
118
+}
119
+
120
+static char* strstri(char* string, int len, char* substring)
121
+{
122
+	return strstrin(string, len, substring, strlen(substring));
123
+}
124
+
125
+static int sel_lost(str* res, select_t* s, struct sip_msg* msg)
126
+{ /* dummy */
127
+	return 0;
128
+}
129
+
130
+char* CheckParamHdr(str* s, char* paramname, char* paramval)
131
+{
132
+	str ts;
133
+	char *pos, *respos;
134
+	ts = *s;
135
+	pos = strstri(ts.s, ts.len, paramname);
136
+	if (pos)	//paramname found
137
+	{
138
+		respos = pos;
139
+		ts.len = ts.len - (pos - ts.s);
140
+		ts.s = pos;
141
+		trim_leading(&ts);
142
+		pos = strstri(ts.s, ts.len, "=");
143
+		if (pos)	//"=" found
144
+		{
145
+			ts.len = ts.len - (pos - ts.s);
146
+			ts.s = pos;
147
+			trim_leading(&ts);
148
+			pos = strstri(ts.s, ts.len, paramval);
149
+			if (pos) return respos;	//param found, return paramname ptr
150
+		}
151
+	}
152
+	return NULL;
153
+}
154
+
155
+char *GetHdrValueEnd(str* hs)
156
+{
157
+	int l, q = 0;
158
+	for (l = 0; l < hs->len; l++)
159
+	{
160
+		switch (hs->s[l])
161
+		{
162
+		case '"': q ^= 1; break;
163
+		case ',': if (!q) return hs->s + l;
164
+		}
165
+	}
166
+	return hs->s + l;
167
+}
168
+
169
+int GetNextHdrValue(str* body, str* res)
170
+{
171
+	char *pos;
172
+
173
+	res->s += res->len;
174
+	res->len = body->len - (res->s - body->s);
175
+	for(; res->len > 0; res->len--, res->s++)
176
+	{
177
+		if ((*(res->s) != ' ') && (*(res->s) != '\t') && (*(res->s) != '\r') && (*(res->s) != '\n') && (*(res->s) != ','))
178
+			break;
179
+	}
180
+	if (!res->len) return 0;	// no more values
181
+
182
+	pos = GetHdrValueEnd(res);
183
+	res->len = pos - res->s;
184
+	return 1;	// OK
185
+}
186
+
187
+#define _ALLOC_INC_SIZE 1024
188
+// select all headers with purpose=prps or purpose=prps2
189
+// return headers count or negative value on error
190
+static int sel_hdrs(str* res, select_t* s, struct sip_msg* msg, char *prps, char *prps2)
191
+{
192
+	int indx = 0;
193
+	int l, check, cnt = 0;
194
+	str ts;
195
+	struct hdr_field *hf;
196
+	char *buf = NULL;
197
+	int buf_len = _ALLOC_INC_SIZE;
198
+	char* posarr[1024];
199
+	res->s = NULL;
200
+	res->len = 0;
201
+
202
+	if(parse_headers(msg, HDR_CALLINFO_F, 0) < 0)
203
+	{
204
+		LM_ERR("error while parsing message headers\n");
205
+		return -1;
206
+	}
207
+	buf = pkg_malloc(buf_len);
208
+	if(!buf) {
209
+		LM_ERR("out of memory\n");
210
+		res->len = 0;
211
+		return E_OUT_OF_MEM;
212
+	}
213
+	buf[0] = 0;
214
+
215
+	l = 0;
216
+	for (hf = msg->headers; hf; hf = hf->next)
217
+	{
218
+		if (HDR_CALLINFO_T == hf->type)
219
+		{
220
+			ts.s = hf->body.s;
221
+			ts.len = 0;
222
+			while (GetNextHdrValue(&hf->body, &ts))
223
+			{
224
+				check = CheckParamHdr(&ts, "purpose", prps)?1:0;
225
+				if (prps2) check |= (CheckParamHdr(&ts, "purpose", prps2)?2:0);
226
+				if (check)
227
+				{
228
+					l = strlen(buf);
229
+					if (l + ts.len + 1 > buf_len)
230
+					{
231
+						buf_len = l + ts.len + _ALLOC_INC_SIZE;
232
+						res->s = pkg_realloc(buf, buf_len);
233
+						if (!res->s)
234
+						{
235
+							pkg_free(buf);
236
+							LM_ERR("cannot realloc buffer\n");
237
+							res->len = 0;
238
+							return E_OUT_OF_MEM;
239
+						}
240
+						buf = res->s;
241
+					}
242
+					if (l) { strcat(buf, ","); l++; }
243
+					posarr[cnt] = buf + l;
244
+					memcpy(buf + l, ts.s, ts.len);
245
+					l += ts.len;
246
+					buf[l] = 0;
247
+					cnt++;
248
+				}
249
+			}
250
+			posarr[cnt] = buf + strlen(buf);
251
+		}
252
+	}
253
+	if ((s->n > 3) && (s->params[3].type==SEL_PARAM_INT))
254
+		indx = s->params[3].v.i;
255
+
256
+	ts.s = buf;
257
+	ts.len = strlen(buf);
258
+
259
+	if (indx)
260
+	{
261
+		// select only data_name[indx]
262
+		if (indx < 0)
263
+		{	// take real positive index for negative indx
264
+			indx = 1 + cnt + indx;
265
+		}
266
+
267
+		if ((indx < 1) || (indx > cnt))
268
+		{
269
+			ts.s = NULL;
270
+			ts.len = 0;
271
+		}
272
+		else
273
+		{
274
+			ts.s = posarr[indx - 1];
275
+			ts.len = posarr[indx] - posarr[indx - 1] - 1;
276
+		}
277
+	}
278
+
279
+	res->len = ts.len;
280
+	res->s = get_static_buffer(res->len);
281
+	if(!res->s)
282
+	{
283
+		pkg_free(buf);
284
+		res->len = 0;
285
+		LM_ERR("cannot allocate static buffer\n");
286
+		return E_OUT_OF_MEM;
287
+	}
288
+	memcpy(res->s, ts.s, res->len);
289
+	pkg_free(buf);
290
+	return cnt;
291
+}
292
+
293
+// @lost.nena
294
+static int sel_nena(str* res, select_t* s, struct sip_msg* msg)
295
+{
296
+	// @lost.nena - all Call-Info headers with “purpose” param “nena-CallId” or “nena-IncidentId”;
297
+	int err = sel_hdrs(res, s, msg, "nena-CallId", "nena-IncidentId");
298
+	return (err < 0)?err:0;
299
+}
300
+
301
+// 	@lost.nena.call_id
302
+static int sel_call_id(str* res, select_t* s, struct sip_msg* msg)
303
+{
304
+	str ts;
305
+	int err = sel_hdrs(res, s, msg, "nena-CallId", NULL);
306
+	err = (err < 0)?err:0;
307
+	if (!err)
308
+	{
309
+		ts.s = res->s;
310
+		ts.len = 0;
311
+		if (!GetNextHdrValue(res, &ts)) return -1;
312
+		res->s = ts.s;
313
+		res->len = ts.len;
314
+	}
315
+	return err;
316
+}
317
+
318
+// 	@lost.nena.incident_id
319
+static int sel_incident_id(str* res, select_t* s, struct sip_msg* msg)
320
+{
321
+	str ts;
322
+	int err = sel_hdrs(res, s, msg, "nena-IncidentId", NULL);
323
+	err = (err < 0)?err:0;
324
+	if (!err)
325
+	{
326
+		ts.s = res->s;
327
+		ts.len = 0;
328
+		if (!GetNextHdrValue(res, &ts)) return -1;
329
+		res->s = ts.s;
330
+		res->len = ts.len;
331
+	}
332
+	return err;
333
+}
334
+
335
+// 	@lost.emergency_call_data
336
+static int sel_emergency_call_data(str* res, select_t* s, struct sip_msg* msg)
337
+{
338
+	// “purpose=EmergencyCallData”
339
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData", NULL);
340
+	return (err < 0)?err:0;
341
+}
342
+
343
+// @lost.emergency_call_data.provider_info -
344
+static int sel_provider_info(str* res, select_t* s, struct sip_msg* msg)
345
+{
346
+	// all Call-Info headers with “purpose=EmergencyCallData.ProviderInfo”;
347
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.ProviderInfo", NULL);
348
+	return (err < 0)?err:0;
349
+}
350
+
351
+//@lost.emergency_call_data.provider_info.counter - counter of present Call-Info headers with relevant emergency call data type;
352
+static int sel_provider_info_cnt(str* res, select_t* s, struct sip_msg* msg)
353
+{
354
+	// all Call-Info headers with “purpose=EmergencyCallData.ProviderInfo”;
355
+	s->params[3].v.i = 0;
356
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.ProviderInfo", NULL);
357
+	res->s = int2str((err > 0)?err:0, &res->len);
358
+	return (err < 0)?err:0;
359
+}
360
+
361
+static int sel_hdr_uri(str* res)
362
+{
363
+	char *pos, *pos2;
364
+	pos = strstri(res->s, res->len, "<");
365
+	if (!pos) return -1;
366
+	pos2 = strstri(pos+1, res->len - (pos - res->s), ">");
367
+	if (!pos2) return -2;
368
+
369
+	res->len = pos2 - pos - 1;
370
+	res->s = pos + 1;
371
+	return 0;
372
+}
373
+
374
+// @lost.emergency_call_data.provider_info[%i].uri - content of header inside “<>”;
375
+static int sel_provider_info_uri(str* res, select_t* s, struct sip_msg* msg)
376
+{
377
+	// @lost.emergency_call_data.provider_info[%i]
378
+	int err = sel_provider_info(res, s, msg);
379
+	if (!err) err = sel_hdr_uri(res);
380
+	return err;
381
+}
382
+
383
+SELECT_F(select_uri_type)
384
+
385
+//static struct sip_uri uri;
386
+
387
+// @lost.emergency_call_data.provider_info[%i].uri_type;
388
+static int sel_provider_info_uri_type(str* res, select_t* s, struct sip_msg* msg)
389
+{
390
+	// @lost.emergency_call_data.provider_info[%i]
391
+	int err = sel_provider_info_uri(res, s, msg);
392
+	if (!err)
393
+	{
394
+		// `http`, `https`, `cid` or `sip`
395
+		char* pos = strstri(res->s, res->len, ":");
396
+		if (pos) res->len = pos - res->s;
397
+		else res->len = 0;
398
+	}
399
+	return err;
400
+}
401
+
402
+static int GetNextBodyPartHdr(str *bodypart, str *bhr)
403
+{
404
+	str ts = *bodypart;
405
+	char *start = bodypart->s;
406
+	int len = bodypart->len;
407
+
408
+	trim_leading(&ts);
409
+	start = ts.s;
410
+	len = ts.len;
411
+	if (bhr->len > 0)
412
+	{
413
+		start = bhr->s + bhr->len;
414
+		len -= start - ts.s;
415
+	}
416
+	if (len > 0)
417
+	{
418
+		char* pos = strstri(start, len, "\r\n");
419
+		if (pos)
420
+		{
421
+			len = 2 + pos - start;
422
+			bhr->s = start;
423
+			bhr->len = len;
424
+			ts = *bhr;
425
+			trim(&ts);
426
+			return (ts.len > 0)?1:0;	// stop on void line
427
+		}
428
+	}
429
+	return 0;	// no more headers
430
+}
431
+
432
+static int sel_uri_raw(str* res, select_t* s, struct sip_msg* msg)
433
+{
434
+	char* pos = strstri(res->s, res->len, "cid:");
435
+	if (pos)
436
+	{
437
+		int content_length;
438
+		char *d;
439
+		str cid;
440
+		char *buf;
441
+		int l = strlen("cid:");
442
+		
443
+		// get Content-Id:
444
+		cid.len = res->len - l - (pos - res->s);
445
+		cid.s = pos + l;
446
+		buf = pkg_malloc(cid.len + 1);
447
+		memcpy(buf, cid.s, cid.len);
448
+		buf[cid.len] = 0;
449
+		
450
+		// get body part - filter => Content-Id
451
+		d = get_body_part_by_filter(msg, 0, 0, buf, NULL, &content_length);
452
+		if (!d) content_length = 0;
453
+		res->len = content_length;
454
+		res->s = d;
455
+		pkg_free(buf);
456
+	}
457
+	else res->len = 0;
458
+	return 0;
459
+}
460
+
461
+// @lost.emergency_call_data.provider_info[%i].raw;
462
+static int sel_provider_info_raw(str* res, select_t* s, struct sip_msg* msg)
463
+{
464
+	int err = sel_provider_info_uri(res, s, msg);
465
+	if (!err) err = sel_uri_raw(res, s, msg);
466
+	return err;
467
+}
468
+
469
+static int sel_raw_body(str* res, select_t* s, struct sip_msg* msg)
470
+{
471
+	str bodypart;
472
+	str bhr;
473
+	bodypart = *res;
474
+	bhr.len = 0;
475
+	while (GetNextBodyPartHdr(&bodypart, &bhr))
476
+	{
477
+		res->s = bhr.s + bhr.len;
478
+		res->len = bodypart.len - (res->s - bodypart.s);
479
+	}
480
+	return 0;
481
+}
482
+
483
+//@lost.emergency_call_data.provider_info[%i].body
484
+// - if call-info header contains `cid` value (emergency call data passed BY_VALUE), then contains `body` of relevant multipart part;
485
+static int sel_provider_info_body(str* res, select_t* s, struct sip_msg* msg)
486
+{
487
+	// @lost.emergency_call_data.provider_info[%i]
488
+	int err = sel_provider_info_raw(res, s, msg);
489
+	if (!err) err = sel_raw_body(res, s, msg);
490
+	return err;
491
+}
492
+
493
+static int sel_provider_info_header(str *res, select_t *s, struct sip_msg *msg)
494
+{ /* dummy */
495
+	return 0;
496
+}
497
+
498
+static int sel_raw_header_name(str *res, select_t *s, struct sip_msg *msg)
499
+{
500
+	str hname = {0, 0};
501
+	str bodypart;
502
+	str bhr;
503
+	int i, indx = 1, cnt;
504
+
505
+	if(s->params[5].type == SEL_PARAM_STR)
506
+	{
507
+		for(i = s->params[5].v.s.len - 1; i > 0; i--)
508
+		{
509
+			if(s->params[5].v.s.s[i] == '_')
510
+				s->params[5].v.s.s[i] = '-';
511
+		}
512
+		hname.len = s->params[5].v.s.len;
513
+		hname.s = s->params[5].v.s.s;
514
+
515
+	}
516
+	if ((s->n > 6) && (s->params[6].type==SEL_PARAM_INT))
517
+		indx = s->params[6].v.i;
518
+
519
+	bodypart = *res;
520
+	cnt = indx;
521
+	if (indx < 0)
522
+	{	// take real positive index for negative indx
523
+		cnt = 0;
524
+		bhr.len = 0;
525
+		while (GetNextBodyPartHdr(&bodypart, &bhr))
526
+			if (!strncasecmp(bhr.s, hname.s, hname.len)) cnt++;
527
+
528
+		indx = 1 + cnt + indx;
529
+	}
530
+
531
+	res->s = NULL;
532
+	res->len = 0;
533
+	if ((indx > 0) && (indx <= cnt))
534
+	{
535
+		bhr.len = 0;
536
+		cnt = 0;
537
+		while (!res->len && GetNextBodyPartHdr(&bodypart, &bhr))
538
+		{
539
+			if (!strncasecmp(bhr.s, hname.s, hname.len))
540
+			{
541
+				cnt++;
542
+				if (indx == cnt)
543
+				{
544
+					res->s = bhr.s;
545
+					res->len = bhr.len;
546
+					break;
547
+				}
548
+			}
549
+		}
550
+	}
551
+	return 0;
552
+}
553
+
554
+//@lost.emergency_call_data.provider_info[%i].header.%s[%i] - if call-info header contains `cid` value 
555
+// (emergency call data passed BY_VALUE), then provide access to multipart part headers like 
556
+// `Content-Type`, `Content-Disposition`;
557
+static int sel_provider_info_header_name(str *res, select_t *s, struct sip_msg *msg)
558
+{
559
+	int err = sel_provider_info_raw(res, s, msg);
560
+	if (!err) err = sel_raw_header_name(res, s, msg);
561
+	return err;
562
+}
563
+
564
+
565
+/*
566
+ * @lost.emergency_call_data.service_info -
567
+ */
568
+
569
+static int sel_service_info(str* res, select_t* s, struct sip_msg* msg)
570
+{
571
+	// all Call-Info headers with “purpose=EmergencyCallData.ServiceInfo”;
572
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.ServiceInfo", NULL);
573
+	return (err < 0)?err:0;
574
+}
575
+
576
+static int sel_service_info_cnt(str* res, select_t* s, struct sip_msg* msg)
577
+{
578
+	s->params[3].v.i = 0;
579
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.ServiceInfo", NULL);
580
+	res->s = int2str((err > 0)?err:0, &res->len);
581
+	return (err < 0)?err:0;
582
+}
583
+
584
+static int sel_service_info_uri(str* res, select_t* s, struct sip_msg* msg)
585
+{
586
+	// @lost.emergency_call_data.provider_info[%i]
587
+	int err = sel_service_info(res, s, msg);
588
+	if (!err) err = sel_hdr_uri(res);
589
+	return err;
590
+}
591
+
592
+static int sel_service_info_uri_type(str* res, select_t* s, struct sip_msg* msg)
593
+{
594
+	int err = sel_service_info_uri(res, s, msg);
595
+	if (!err)
596
+	{
597
+		// `http`, `https`, `cid` or `sip`
598
+		char* pos = strstri(res->s, res->len, ":");
599
+		if (pos) res->len = pos - res->s;
600
+		else res->len = 0;
601
+	}
602
+	return err;
603
+}
604
+
605
+static int sel_service_info_raw(str* res, select_t* s, struct sip_msg* msg)
606
+{
607
+	int err = sel_service_info_uri(res, s, msg);
608
+	if (!err) err = sel_uri_raw(res, s, msg);
609
+	return err;
610
+}
611
+
612
+static int sel_service_info_body(str* res, select_t* s, struct sip_msg* msg)
613
+{
614
+	int err = sel_service_info_raw(res, s, msg);
615
+	if (!err) err = sel_raw_body(res, s, msg);
616
+	return err;
617
+}
618
+
619
+static int sel_service_info_header(str *res, select_t *s, struct sip_msg *msg)
620
+{ /* dummy */
621
+	return 0;
622
+}
623
+
624
+static int sel_service_info_header_name(str *res, select_t *s, struct sip_msg *msg)
625
+{
626
+	int err = sel_service_info_raw(res, s, msg);
627
+	if (!err) err = sel_raw_header_name(res, s, msg);
628
+	return err;
629
+}
630
+
631
+
632
+
633
+/*
634
+ * @lost.emergency_call_data.device_info -
635
+ */
636
+
637
+static int sel_device_info(str* res, select_t* s, struct sip_msg* msg)
638
+{
639
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.DeviceInfo", NULL);
640
+	return (err < 0)?err:0;
641
+}
642
+
643
+static int sel_device_info_cnt(str* res, select_t* s, struct sip_msg* msg)
644
+{
645
+	s->params[3].v.i = 0;
646
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.DeviceInfo", NULL);
647
+	res->s = int2str((err > 0)?err:0, &res->len);
648
+	return (err < 0)?err:0;
649
+}
650
+
651
+static int sel_device_info_uri(str* res, select_t* s, struct sip_msg* msg)
652
+{
653
+	int err = sel_device_info(res, s, msg);
654
+	if (!err) err = sel_hdr_uri(res);
655
+	return err;
656
+}
657
+
658
+static int sel_device_info_uri_type(str* res, select_t* s, struct sip_msg* msg)
659
+{
660
+	int err = sel_device_info_uri(res, s, msg);
661
+	if (!err)
662
+	{
663
+		char* pos = strstri(res->s, res->len, ":");
664
+		if (pos) res->len = pos - res->s;
665
+		else res->len = 0;
666
+	}
667
+	return err;
668
+}
669
+
670
+static int sel_device_info_raw(str* res, select_t* s, struct sip_msg* msg)
671
+{
672
+	int err = sel_device_info_uri(res, s, msg);
673
+	if (!err) err = sel_uri_raw(res, s, msg);
674
+	return err;
675
+}
676
+
677
+static int sel_device_info_body(str* res, select_t* s, struct sip_msg* msg)
678
+{
679
+	int err = sel_device_info_raw(res, s, msg);
680
+	if (!err) err = sel_raw_body(res, s, msg);
681
+	return err;
682
+}
683
+
684
+static int sel_device_info_header(str *res, select_t *s, struct sip_msg *msg)
685
+{ /* dummy */
686
+	return 0;
687
+}
688
+
689
+static int sel_device_info_header_name(str *res, select_t *s, struct sip_msg *msg)
690
+{
691
+	int err = sel_device_info_raw(res, s, msg);
692
+	if (!err) err = sel_raw_header_name(res, s, msg);
693
+	return err;
694
+}
695
+
696
+/*
697
+ * @lost.emergency_call_data.subscriber_info -
698
+ */
699
+
700
+static int sel_subscriber_info(str* res, select_t* s, struct sip_msg* msg)
701
+{
702
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.SubscriberInfo", NULL);
703
+	return (err < 0)?err:0;
704
+}
705
+
706
+static int sel_subscriber_info_cnt(str* res, select_t* s, struct sip_msg* msg)
707
+{
708
+	s->params[3].v.i = 0;
709
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.SubscriberInfo", NULL);
710
+	res->s = int2str((err > 0)?err:0, &res->len);
711
+	return (err < 0)?err:0;
712
+}
713
+
714
+static int sel_subscriber_info_uri(str* res, select_t* s, struct sip_msg* msg)
715
+{
716
+	int err = sel_subscriber_info(res, s, msg);
717
+	if (!err) err = sel_hdr_uri(res);
718
+	return err;
719
+}
720
+
721
+static int sel_subscriber_info_uri_type(str* res, select_t* s, struct sip_msg* msg)
722
+{
723
+	int err = sel_subscriber_info_uri(res, s, msg);
724
+	if (!err)
725
+	{
726
+		char* pos = strstri(res->s, res->len, ":");
727
+		if (pos) res->len = pos - res->s;
728
+		else res->len = 0;
729
+	}
730
+	return err;
731
+}
732
+
733
+static int sel_subscriber_info_raw(str* res, select_t* s, struct sip_msg* msg)
734
+{
735
+	int err = sel_subscriber_info_uri(res, s, msg);
736
+	if (!err) err = sel_uri_raw(res, s, msg);
737
+	return err;
738
+}
739
+
740
+static int sel_subscriber_info_body(str* res, select_t* s, struct sip_msg* msg)
741
+{
742
+	int err = sel_subscriber_info_raw(res, s, msg);
743
+	if (!err) err = sel_raw_body(res, s, msg);
744
+	return err;
745
+}
746
+
747
+static int sel_subscriber_info_header(str *res, select_t *s, struct sip_msg *msg)
748
+{ /* dummy */
749
+	return 0;
750
+}
751
+
752
+static int sel_subscriber_info_header_name(str *res, select_t *s, struct sip_msg *msg)
753
+{
754
+	int err = sel_subscriber_info_raw(res, s, msg);
755
+	if (!err) err = sel_raw_header_name(res, s, msg);
756
+	return err;
757
+}
758
+
759
+/*
760
+ * @lost.emergency_call_data.comment -
761
+ */
762
+
763
+static int sel_comment(str* res, select_t* s, struct sip_msg* msg)
764
+{
765
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.Comment", NULL);
766
+	return (err < 0)?err:0;
767
+}
768
+
769
+static int sel_comment_cnt(str* res, select_t* s, struct sip_msg* msg)
770
+{
771
+	s->params[3].v.i = 0;
772
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.Comment", NULL);
773
+	res->s = int2str((err > 0)?err:0, &res->len);
774
+	return (err < 0)?err:0;
775
+}
776
+
777
+static int sel_comment_uri(str* res, select_t* s, struct sip_msg* msg)
778
+{
779
+	int err = sel_comment(res, s, msg);
780
+	if (!err) err = sel_hdr_uri(res);
781
+	return err;
782
+}
783
+
784
+static int sel_comment_uri_type(str* res, select_t* s, struct sip_msg* msg)
785
+{
786
+	int err = sel_comment_uri(res, s, msg);
787
+	if (!err)
788
+	{
789
+		char* pos = strstri(res->s, res->len, ":");
790
+		if (pos) res->len = pos - res->s;
791
+		else res->len = 0;
792
+	}
793
+	return err;
794
+}
795
+
796
+static int sel_comment_raw(str* res, select_t* s, struct sip_msg* msg)
797
+{
798
+	int err = sel_comment_uri(res, s, msg);
799
+	if (!err) err = sel_uri_raw(res, s, msg);
800
+	return err;
801
+}
802
+
803
+static int sel_comment_body(str* res, select_t* s, struct sip_msg* msg)
804
+{
805
+	int err = sel_comment_raw(res, s, msg);
806
+	if (!err) err = sel_raw_body(res, s, msg);
807
+	return err;
808
+}
809
+
810
+static int sel_comment_header(str *res, select_t *s, struct sip_msg *msg)
811
+{ /* dummy */
812
+	return 0;
813
+}
814
+
815
+static int sel_comment_header_name(str *res, select_t *s, struct sip_msg *msg)
816
+{
817
+	int err = sel_comment_raw(res, s, msg);
818
+	if (!err) err = sel_raw_header_name(res, s, msg);
819
+	return err;
820
+}
821
+
822
+select_row_t lost_sel[] = {
823
+	/* Current cipher parameters */
824
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("lost"), sel_lost, SEL_PARAM_EXPECTED},
825
+
826
+	{ sel_lost, SEL_PARAM_STR, STR_STATIC_INIT("nena"), sel_nena, 0},
827
+	{ sel_nena, SEL_PARAM_STR, STR_STATIC_INIT("call_id"), sel_call_id, 0},
828
+	{ sel_nena, SEL_PARAM_STR, STR_STATIC_INIT("incident_id"), sel_incident_id, 0},
829
+
830
+	{ sel_lost, SEL_PARAM_STR, STR_STATIC_INIT("emergency_call_data"), sel_emergency_call_data, 0},
831
+	{ sel_emergency_call_data, SEL_PARAM_STR, STR_STATIC_INIT("provider_info"), sel_provider_info, CONSUME_NEXT_INT | OPTIONAL},
832
+	{ sel_provider_info, SEL_PARAM_STR, STR_STATIC_INIT("counter"), sel_provider_info_cnt, 0},
833
+	{ sel_provider_info, SEL_PARAM_STR, STR_STATIC_INIT("urib"), sel_provider_info_uri, 0},
834
+	{ sel_provider_info, SEL_PARAM_STR, STR_STATIC_INIT("uri_type"), sel_provider_info_uri_type, 0},
835
+	{ sel_provider_info, SEL_PARAM_STR, STR_STATIC_INIT("raw"), sel_provider_info_raw, 0},
836
+	{ sel_provider_info, SEL_PARAM_STR, STR_STATIC_INIT("body"), sel_provider_info_body, 0},
837
+	{ sel_provider_info, SEL_PARAM_STR, STR_STATIC_INIT("header"), sel_provider_info_header, SEL_PARAM_EXPECTED},
838
+	{ sel_provider_info_header, SEL_PARAM_STR, STR_NULL, sel_provider_info_header_name, CONSUME_NEXT_INT | OPTIONAL },
839
+
840
+	{ sel_emergency_call_data, SEL_PARAM_STR, STR_STATIC_INIT("service_info"), sel_service_info, CONSUME_NEXT_INT | OPTIONAL},
841
+	{ sel_service_info, SEL_PARAM_STR, STR_STATIC_INIT("counter"), sel_service_info_cnt, 0},
842
+	{ sel_service_info, SEL_PARAM_STR, STR_STATIC_INIT("urib"), sel_service_info_uri, 0},
843
+	{ sel_service_info, SEL_PARAM_STR, STR_STATIC_INIT("uri_type"), sel_service_info_uri_type, 0},
844
+	{ sel_service_info, SEL_PARAM_STR, STR_STATIC_INIT("raw"), sel_service_info_raw, 0},
845
+	{ sel_service_info, SEL_PARAM_STR, STR_STATIC_INIT("body"), sel_service_info_body, 0},
846
+	{ sel_service_info, SEL_PARAM_STR, STR_STATIC_INIT("header"), sel_service_info_header, SEL_PARAM_EXPECTED},
847
+	{ sel_service_info_header, SEL_PARAM_STR, STR_NULL, sel_service_info_header_name, CONSUME_NEXT_INT | OPTIONAL },
848
+
849
+	{ sel_emergency_call_data, SEL_PARAM_STR, STR_STATIC_INIT("device_info"), sel_device_info, CONSUME_NEXT_INT | OPTIONAL},
850
+	{ sel_device_info, SEL_PARAM_STR, STR_STATIC_INIT("counter"), sel_device_info_cnt, 0},
851
+	{ sel_device_info, SEL_PARAM_STR, STR_STATIC_INIT("urib"), sel_device_info_uri, 0},
852
+	{ sel_device_info, SEL_PARAM_STR, STR_STATIC_INIT("uri_type"), sel_device_info_uri_type, 0},
853
+	{ sel_device_info, SEL_PARAM_STR, STR_STATIC_INIT("raw"), sel_device_info_raw, 0},
854
+	{ sel_device_info, SEL_PARAM_STR, STR_STATIC_INIT("body"), sel_device_info_body, 0},
855
+	{ sel_device_info, SEL_PARAM_STR, STR_STATIC_INIT("header"), sel_device_info_header, SEL_PARAM_EXPECTED},
856
+	{ sel_device_info_header, SEL_PARAM_STR, STR_NULL, sel_device_info_header_name, CONSUME_NEXT_INT | OPTIONAL },
857
+
858
+	{ sel_emergency_call_data, SEL_PARAM_STR, STR_STATIC_INIT("subscriber_info"), sel_subscriber_info, CONSUME_NEXT_INT | OPTIONAL},
859
+	{ sel_subscriber_info, SEL_PARAM_STR, STR_STATIC_INIT("counter"), sel_subscriber_info_cnt, 0},
860
+	{ sel_subscriber_info, SEL_PARAM_STR, STR_STATIC_INIT("urib"), sel_subscriber_info_uri, 0},
861
+	{ sel_subscriber_info, SEL_PARAM_STR, STR_STATIC_INIT("uri_type"), sel_subscriber_info_uri_type, 0},
862
+	{ sel_subscriber_info, SEL_PARAM_STR, STR_STATIC_INIT("raw"), sel_subscriber_info_raw, 0},
863
+	{ sel_subscriber_info, SEL_PARAM_STR, STR_STATIC_INIT("body"), sel_subscriber_info_body, 0},
864
+	{ sel_subscriber_info, SEL_PARAM_STR, STR_STATIC_INIT("header"), sel_subscriber_info_header, SEL_PARAM_EXPECTED},
865
+	{ sel_subscriber_info_header, SEL_PARAM_STR, STR_NULL, sel_subscriber_info_header_name, CONSUME_NEXT_INT | OPTIONAL },
866
+
867
+	{ sel_emergency_call_data, SEL_PARAM_STR, STR_STATIC_INIT("comment"), sel_comment, CONSUME_NEXT_INT | OPTIONAL},
868
+	{ sel_comment, SEL_PARAM_STR, STR_STATIC_INIT("counter"), sel_comment_cnt, 0},
869
+	{ sel_comment, SEL_PARAM_STR, STR_STATIC_INIT("urib"), sel_comment_uri, 0},
870
+	{ sel_comment, SEL_PARAM_STR, STR_STATIC_INIT("uri_type"), sel_comment_uri_type, 0},
871
+	{ sel_comment, SEL_PARAM_STR, STR_STATIC_INIT("raw"), sel_comment_raw, 0},
872
+	{ sel_comment, SEL_PARAM_STR, STR_STATIC_INIT("body"), sel_comment_body, 0},
873
+	{ sel_comment, SEL_PARAM_STR, STR_STATIC_INIT("header"), sel_comment_header, SEL_PARAM_EXPECTED},
874
+	{ sel_comment_header, SEL_PARAM_STR, STR_NULL, sel_comment_header_name, CONSUME_NEXT_INT | OPTIONAL },
875
+
876
+	{ NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
877
+};
0 878
new file mode 100644
... ...
@@ -0,0 +1,39 @@
1
+/*
2
+ * lost module - select interface
3
+ *
4
+ * Copyright (C) 2021 Eugene Sukhanov
5
+ * NGA911
6
+ *
7
+ * This file is part of Kamailio, a free SIP server.
8
+ *
9
+ * Kamailio is free software; you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation; either version 2 of the License, or
12
+ * (at your option) any later version
13
+ *
14
+ * Kamailio is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with this program; if not, write to the Free Software
21
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22
+ *
23
+ */
24
+
25
+/*!
26
+ * \file
27
+ * \brief Kamailio lost :: Select interface.
28
+ * \ingroup lost
29
+ * Module: \ref lost
30
+ */
31
+
32
+#ifndef _LOST_SELECT_H
33
+#define _LOST_SELECT_H
34
+
35
+#include "../../core/select.h"
36
+
37
+extern select_row_t lost_sel[];
38
+
39
+#endif /* _LOST_SELECT_H */