Browse code

Merge 477e3f1652f2fed9873f4bbd938b862ce27aca16 into 9ec9d9ceb0b69d46d5a4d90a86b1185951feb9d4

sergey-safarov authored on 12/07/2021 08:55:04 • GitHub committed on 12/07/2021 08:55:04
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,881 @@
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 = NULL;
281
+	if (res->len > 0)
282
+	{
283
+		res->s = get_static_buffer(res->len);
284
+		if(!res->s)
285
+		{
286
+			res->len = 0;
287
+			LM_ERR("cannot allocate static buffer\n");
288
+			cnt = E_OUT_OF_MEM;
289
+		}
290
+		else
291
+			memcpy(res->s, ts.s, res->len);
292
+	}
293
+	pkg_free(buf);
294
+	return cnt;
295
+}
296
+
297
+// @lost.nena
298
+static int sel_nena(str* res, select_t* s, struct sip_msg* msg)
299
+{
300
+	// @lost.nena - all Call-Info headers with “purpose” param “nena-CallId” or “nena-IncidentId”;
301
+	int err = sel_hdrs(res, s, msg, "nena-CallId", "nena-IncidentId");
302
+	return (err < 0)?err:0;
303
+}
304
+
305
+// 	@lost.nena.call_id
306
+static int sel_call_id(str* res, select_t* s, struct sip_msg* msg)
307
+{
308
+	str ts;
309
+	int err = sel_hdrs(res, s, msg, "nena-CallId", NULL);
310
+	err = (err < 0)?err:0;
311
+	if (!err)
312
+	{
313
+		ts.s = res->s;
314
+		ts.len = 0;
315
+		if (!GetNextHdrValue(res, &ts)) return -1;
316
+		res->s = ts.s;
317
+		res->len = ts.len;
318
+	}
319
+	return err;
320
+}
321
+
322
+// 	@lost.nena.incident_id
323
+static int sel_incident_id(str* res, select_t* s, struct sip_msg* msg)
324
+{
325
+	str ts;
326
+	int err = sel_hdrs(res, s, msg, "nena-IncidentId", NULL);
327
+	err = (err < 0)?err:0;
328
+	if (!err)
329
+	{
330
+		ts.s = res->s;
331
+		ts.len = 0;
332
+		if (!GetNextHdrValue(res, &ts)) return -1;
333
+		res->s = ts.s;
334
+		res->len = ts.len;
335
+	}
336
+	return err;
337
+}
338
+
339
+// 	@lost.emergency_call_data
340
+static int sel_emergency_call_data(str* res, select_t* s, struct sip_msg* msg)
341
+{
342
+	// “purpose=EmergencyCallData”
343
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData", NULL);
344
+	return (err < 0)?err:0;
345
+}
346
+
347
+// @lost.emergency_call_data.provider_info -
348
+static int sel_provider_info(str* res, select_t* s, struct sip_msg* msg)
349
+{
350
+	// all Call-Info headers with “purpose=EmergencyCallData.ProviderInfo”;
351
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.ProviderInfo", NULL);
352
+	return (err < 0)?err:0;
353
+}
354
+
355
+//@lost.emergency_call_data.provider_info.counter - counter of present Call-Info headers with relevant emergency call data type;
356
+static int sel_provider_info_cnt(str* res, select_t* s, struct sip_msg* msg)
357
+{
358
+	// all Call-Info headers with “purpose=EmergencyCallData.ProviderInfo”;
359
+	s->params[3].v.i = 0;
360
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.ProviderInfo", NULL);
361
+	res->s = int2str((err > 0)?err:0, &res->len);
362
+	return (err < 0)?err:0;
363
+}
364
+
365
+static int sel_hdr_uri(str* res)
366
+{
367
+	char *pos, *pos2;
368
+	pos = strstri(res->s, res->len, "<");
369
+	if (!pos) return -1;
370
+	pos2 = strstri(pos+1, res->len - (pos - res->s), ">");
371
+	if (!pos2) return -2;
372
+
373
+	res->len = pos2 - pos - 1;
374
+	res->s = pos + 1;
375
+	return 0;
376
+}
377
+
378
+// @lost.emergency_call_data.provider_info[%i].uri - content of header inside “<>”;
379
+static int sel_provider_info_uri(str* res, select_t* s, struct sip_msg* msg)
380
+{
381
+	// @lost.emergency_call_data.provider_info[%i]
382
+	int err = sel_provider_info(res, s, msg);
383
+	if (!err) err = sel_hdr_uri(res);
384
+	return err;
385
+}
386
+
387
+SELECT_F(select_uri_type)
388
+
389
+//static struct sip_uri uri;
390
+
391
+// @lost.emergency_call_data.provider_info[%i].uri_type;
392
+static int sel_provider_info_uri_type(str* res, select_t* s, struct sip_msg* msg)
393
+{
394
+	// @lost.emergency_call_data.provider_info[%i]
395
+	int err = sel_provider_info_uri(res, s, msg);
396
+	if (!err)
397
+	{
398
+		// `http`, `https`, `cid` or `sip`
399
+		char* pos = strstri(res->s, res->len, ":");
400
+		if (pos) res->len = pos - res->s;
401
+		else res->len = 0;
402
+	}
403
+	return err;
404
+}
405
+
406
+static int GetNextBodyPartHdr(str *bodypart, str *bhr)
407
+{
408
+	str ts = *bodypart;
409
+	char *start = bodypart->s;
410
+	int len = bodypart->len;
411
+
412
+	trim_leading(&ts);
413
+	start = ts.s;
414
+	len = ts.len;
415
+	if (bhr->len > 0)
416
+	{
417
+		start = bhr->s + bhr->len;
418
+		len -= start - ts.s;
419
+	}
420
+	if (len > 0)
421
+	{
422
+		char* pos = strstri(start, len, "\r\n");
423
+		if (pos)
424
+		{
425
+			len = 2 + pos - start;
426
+			bhr->s = start;
427
+			bhr->len = len;
428
+			ts = *bhr;
429
+			trim(&ts);
430
+			return (ts.len > 0)?1:0;	// stop on void line
431
+		}
432
+	}
433
+	return 0;	// no more headers
434
+}
435
+
436
+static int sel_uri_raw(str* res, select_t* s, struct sip_msg* msg)
437
+{
438
+	char* pos = strstri(res->s, res->len, "cid:");
439
+	if (pos)
440
+	{
441
+		int content_length;
442
+		char *d;
443
+		str cid;
444
+		char *buf;
445
+		int l = strlen("cid:");
446
+		
447
+		// get Content-Id:
448
+		cid.len = res->len - l - (pos - res->s);
449
+		cid.s = pos + l;
450
+		buf = pkg_malloc(cid.len + 1);
451
+		memcpy(buf, cid.s, cid.len);
452
+		buf[cid.len] = 0;
453
+		
454
+		// get body part - filter => Content-Id
455
+		d = get_body_part_by_filter(msg, 0, 0, buf, NULL, &content_length);
456
+		if (!d) content_length = 0;
457
+		res->len = content_length;
458
+		res->s = d;
459
+		pkg_free(buf);
460
+	}
461
+	else res->len = 0;
462
+	return 0;
463
+}
464
+
465
+// @lost.emergency_call_data.provider_info[%i].raw;
466
+static int sel_provider_info_raw(str* res, select_t* s, struct sip_msg* msg)
467
+{
468
+	int err = sel_provider_info_uri(res, s, msg);
469
+	if (!err) err = sel_uri_raw(res, s, msg);
470
+	return err;
471
+}
472
+
473
+static int sel_raw_body(str* res, select_t* s, struct sip_msg* msg)
474
+{
475
+	str bodypart;
476
+	str bhr;
477
+	bodypart = *res;
478
+	bhr.len = 0;
479
+	while (GetNextBodyPartHdr(&bodypart, &bhr))
480
+	{
481
+		res->s = bhr.s + bhr.len;
482
+		res->len = bodypart.len - (res->s - bodypart.s);
483
+	}
484
+	return 0;
485
+}
486
+
487
+//@lost.emergency_call_data.provider_info[%i].body
488
+// - if call-info header contains `cid` value (emergency call data passed BY_VALUE), then contains `body` of relevant multipart part;
489
+static int sel_provider_info_body(str* res, select_t* s, struct sip_msg* msg)
490
+{
491
+	// @lost.emergency_call_data.provider_info[%i]
492
+	int err = sel_provider_info_raw(res, s, msg);
493
+	if (!err) err = sel_raw_body(res, s, msg);
494
+	return err;
495
+}
496
+
497
+static int sel_provider_info_header(str *res, select_t *s, struct sip_msg *msg)
498
+{ /* dummy */
499
+	return 0;
500
+}
501
+
502
+static int sel_raw_header_name(str *res, select_t *s, struct sip_msg *msg)
503
+{
504
+	str hname = {0, 0};
505
+	str bodypart;
506
+	str bhr;
507
+	int i, indx = 1, cnt;
508
+
509
+	if(s->params[5].type == SEL_PARAM_STR)
510
+	{
511
+		for(i = s->params[5].v.s.len - 1; i > 0; i--)
512
+		{
513
+			if(s->params[5].v.s.s[i] == '_')
514
+				s->params[5].v.s.s[i] = '-';
515
+		}
516
+		hname.len = s->params[5].v.s.len;
517
+		hname.s = s->params[5].v.s.s;
518
+
519
+	}
520
+	if ((s->n > 6) && (s->params[6].type==SEL_PARAM_INT))
521
+		indx = s->params[6].v.i;
522
+
523
+	bodypart = *res;
524
+	cnt = indx;
525
+	if (indx < 0)
526
+	{	// take real positive index for negative indx
527
+		cnt = 0;
528
+		bhr.len = 0;
529
+		while (GetNextBodyPartHdr(&bodypart, &bhr))
530
+			if (!strncasecmp(bhr.s, hname.s, hname.len)) cnt++;
531
+
532
+		indx = 1 + cnt + indx;
533
+	}
534
+
535
+	res->s = NULL;
536
+	res->len = 0;
537
+	if ((indx > 0) && (indx <= cnt))
538
+	{
539
+		bhr.len = 0;
540
+		cnt = 0;
541
+		while (!res->len && GetNextBodyPartHdr(&bodypart, &bhr))
542
+		{
543
+			if (!strncasecmp(bhr.s, hname.s, hname.len))
544
+			{
545
+				cnt++;
546
+				if (indx == cnt)
547
+				{
548
+					res->s = bhr.s;
549
+					res->len = bhr.len;
550
+					break;
551
+				}
552
+			}
553
+		}
554
+	}
555
+	return 0;
556
+}
557
+
558
+//@lost.emergency_call_data.provider_info[%i].header.%s[%i] - if call-info header contains `cid` value 
559
+// (emergency call data passed BY_VALUE), then provide access to multipart part headers like 
560
+// `Content-Type`, `Content-Disposition`;
561
+static int sel_provider_info_header_name(str *res, select_t *s, struct sip_msg *msg)
562
+{
563
+	int err = sel_provider_info_raw(res, s, msg);
564
+	if (!err) err = sel_raw_header_name(res, s, msg);
565
+	return err;
566
+}
567
+
568
+
569
+/*
570
+ * @lost.emergency_call_data.service_info -
571
+ */
572
+
573
+static int sel_service_info(str* res, select_t* s, struct sip_msg* msg)
574
+{
575
+	// all Call-Info headers with “purpose=EmergencyCallData.ServiceInfo”;
576
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.ServiceInfo", NULL);
577
+	return (err < 0)?err:0;
578
+}
579
+
580
+static int sel_service_info_cnt(str* res, select_t* s, struct sip_msg* msg)
581
+{
582
+	s->params[3].v.i = 0;
583
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.ServiceInfo", NULL);
584
+	res->s = int2str((err > 0)?err:0, &res->len);
585
+	return (err < 0)?err:0;
586
+}
587
+
588
+static int sel_service_info_uri(str* res, select_t* s, struct sip_msg* msg)
589
+{
590
+	// @lost.emergency_call_data.provider_info[%i]
591
+	int err = sel_service_info(res, s, msg);
592
+	if (!err) err = sel_hdr_uri(res);
593
+	return err;
594
+}
595
+
596
+static int sel_service_info_uri_type(str* res, select_t* s, struct sip_msg* msg)
597
+{
598
+	int err = sel_service_info_uri(res, s, msg);
599
+	if (!err)
600
+	{
601
+		// `http`, `https`, `cid` or `sip`
602
+		char* pos = strstri(res->s, res->len, ":");
603
+		if (pos) res->len = pos - res->s;
604
+		else res->len = 0;
605
+	}
606
+	return err;
607
+}
608
+
609
+static int sel_service_info_raw(str* res, select_t* s, struct sip_msg* msg)
610
+{
611
+	int err = sel_service_info_uri(res, s, msg);
612
+	if (!err) err = sel_uri_raw(res, s, msg);
613
+	return err;
614
+}
615
+
616
+static int sel_service_info_body(str* res, select_t* s, struct sip_msg* msg)
617
+{
618
+	int err = sel_service_info_raw(res, s, msg);
619
+	if (!err) err = sel_raw_body(res, s, msg);
620
+	return err;
621
+}
622
+
623
+static int sel_service_info_header(str *res, select_t *s, struct sip_msg *msg)
624
+{ /* dummy */
625
+	return 0;
626
+}
627
+
628
+static int sel_service_info_header_name(str *res, select_t *s, struct sip_msg *msg)
629
+{
630
+	int err = sel_service_info_raw(res, s, msg);
631
+	if (!err) err = sel_raw_header_name(res, s, msg);
632
+	return err;
633
+}
634
+
635
+
636
+
637
+/*
638
+ * @lost.emergency_call_data.device_info -
639
+ */
640
+
641
+static int sel_device_info(str* res, select_t* s, struct sip_msg* msg)
642
+{
643
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.DeviceInfo", NULL);
644
+	return (err < 0)?err:0;
645
+}
646
+
647
+static int sel_device_info_cnt(str* res, select_t* s, struct sip_msg* msg)
648
+{
649
+	s->params[3].v.i = 0;
650
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.DeviceInfo", NULL);
651
+	res->s = int2str((err > 0)?err:0, &res->len);
652
+	return (err < 0)?err:0;
653
+}
654
+
655
+static int sel_device_info_uri(str* res, select_t* s, struct sip_msg* msg)
656
+{
657
+	int err = sel_device_info(res, s, msg);
658
+	if (!err) err = sel_hdr_uri(res);
659
+	return err;
660
+}
661
+
662
+static int sel_device_info_uri_type(str* res, select_t* s, struct sip_msg* msg)
663
+{
664
+	int err = sel_device_info_uri(res, s, msg);
665
+	if (!err)
666
+	{
667
+		char* pos = strstri(res->s, res->len, ":");
668
+		if (pos) res->len = pos - res->s;
669
+		else res->len = 0;
670
+	}
671
+	return err;
672
+}
673
+
674
+static int sel_device_info_raw(str* res, select_t* s, struct sip_msg* msg)
675
+{
676
+	int err = sel_device_info_uri(res, s, msg);
677
+	if (!err) err = sel_uri_raw(res, s, msg);
678
+	return err;
679
+}
680
+
681
+static int sel_device_info_body(str* res, select_t* s, struct sip_msg* msg)
682
+{
683
+	int err = sel_device_info_raw(res, s, msg);
684
+	if (!err) err = sel_raw_body(res, s, msg);
685
+	return err;
686
+}
687
+
688
+static int sel_device_info_header(str *res, select_t *s, struct sip_msg *msg)
689
+{ /* dummy */
690
+	return 0;
691
+}
692
+
693
+static int sel_device_info_header_name(str *res, select_t *s, struct sip_msg *msg)
694
+{
695
+	int err = sel_device_info_raw(res, s, msg);
696
+	if (!err) err = sel_raw_header_name(res, s, msg);
697
+	return err;
698
+}
699
+
700
+/*
701
+ * @lost.emergency_call_data.subscriber_info -
702
+ */
703
+
704
+static int sel_subscriber_info(str* res, select_t* s, struct sip_msg* msg)
705
+{
706
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.SubscriberInfo", NULL);
707
+	return (err < 0)?err:0;
708
+}
709
+
710
+static int sel_subscriber_info_cnt(str* res, select_t* s, struct sip_msg* msg)
711
+{
712
+	s->params[3].v.i = 0;
713
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.SubscriberInfo", NULL);
714
+	res->s = int2str((err > 0)?err:0, &res->len);
715
+	return (err < 0)?err:0;
716
+}
717
+
718
+static int sel_subscriber_info_uri(str* res, select_t* s, struct sip_msg* msg)
719
+{
720
+	int err = sel_subscriber_info(res, s, msg);
721
+	if (!err) err = sel_hdr_uri(res);
722
+	return err;
723
+}
724
+
725
+static int sel_subscriber_info_uri_type(str* res, select_t* s, struct sip_msg* msg)
726
+{
727
+	int err = sel_subscriber_info_uri(res, s, msg);
728
+	if (!err)
729
+	{
730
+		char* pos = strstri(res->s, res->len, ":");
731
+		if (pos) res->len = pos - res->s;
732
+		else res->len = 0;
733
+	}
734
+	return err;
735
+}
736
+
737
+static int sel_subscriber_info_raw(str* res, select_t* s, struct sip_msg* msg)
738
+{
739
+	int err = sel_subscriber_info_uri(res, s, msg);
740
+	if (!err) err = sel_uri_raw(res, s, msg);
741
+	return err;
742
+}
743
+
744
+static int sel_subscriber_info_body(str* res, select_t* s, struct sip_msg* msg)
745
+{
746
+	int err = sel_subscriber_info_raw(res, s, msg);
747
+	if (!err) err = sel_raw_body(res, s, msg);
748
+	return err;
749
+}
750
+
751
+static int sel_subscriber_info_header(str *res, select_t *s, struct sip_msg *msg)
752
+{ /* dummy */
753
+	return 0;
754
+}
755
+
756
+static int sel_subscriber_info_header_name(str *res, select_t *s, struct sip_msg *msg)
757
+{
758
+	int err = sel_subscriber_info_raw(res, s, msg);
759
+	if (!err) err = sel_raw_header_name(res, s, msg);
760
+	return err;
761
+}
762
+
763
+/*
764
+ * @lost.emergency_call_data.comment -
765
+ */
766
+
767
+static int sel_comment(str* res, select_t* s, struct sip_msg* msg)
768
+{
769
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.Comment", NULL);
770
+	return (err < 0)?err:0;
771
+}
772
+
773
+static int sel_comment_cnt(str* res, select_t* s, struct sip_msg* msg)
774
+{
775
+	s->params[3].v.i = 0;
776
+	int err = sel_hdrs(res, s, msg, "EmergencyCallData.Comment", NULL);
777
+	res->s = int2str((err > 0)?err:0, &res->len);
778
+	return (err < 0)?err:0;
779
+}
780
+
781
+static int sel_comment_uri(str* res, select_t* s, struct sip_msg* msg)
782
+{
783
+	int err = sel_comment(res, s, msg);
784
+	if (!err) err = sel_hdr_uri(res);
785
+	return err;
786
+}
787
+
788
+static int sel_comment_uri_type(str* res, select_t* s, struct sip_msg* msg)
789
+{
790
+	int err = sel_comment_uri(res, s, msg);
791
+	if (!err)
792
+	{
793
+		char* pos = strstri(res->s, res->len, ":");
794
+		if (pos) res->len = pos - res->s;
795
+		else res->len = 0;
796
+	}
797
+	return err;
798
+}
799
+
800
+static int sel_comment_raw(str* res, select_t* s, struct sip_msg* msg)
801
+{
802
+	int err = sel_comment_uri(res, s, msg);
803
+	if (!err) err = sel_uri_raw(res, s, msg);
804
+	return err;
805
+}
806
+
807
+static int sel_comment_body(str* res, select_t* s, struct sip_msg* msg)
808
+{
809
+	int err = sel_comment_raw(res, s, msg);
810
+	if (!err) err = sel_raw_body(res, s, msg);
811
+	return err;
812
+}
813
+
814
+static int sel_comment_header(str *res, select_t *s, struct sip_msg *msg)
815
+{ /* dummy */
816
+	return 0;
817
+}
818
+
819
+static int sel_comment_header_name(str *res, select_t *s, struct sip_msg *msg)
820
+{
821
+	int err = sel_comment_raw(res, s, msg);
822
+	if (!err) err = sel_raw_header_name(res, s, msg);
823
+	return err;
824
+}
825
+
826
+select_row_t lost_sel[] = {
827
+	/* Current cipher parameters */
828
+	{ NULL, SEL_PARAM_STR, STR_STATIC_INIT("lost"), sel_lost, SEL_PARAM_EXPECTED},
829
+
830
+	{ sel_lost, SEL_PARAM_STR, STR_STATIC_INIT("nena"), sel_nena, 0},
831
+	{ sel_nena, SEL_PARAM_STR, STR_STATIC_INIT("call_id"), sel_call_id, 0},
832
+	{ sel_nena, SEL_PARAM_STR, STR_STATIC_INIT("incident_id"), sel_incident_id, 0},
833
+
834
+	{ sel_lost, SEL_PARAM_STR, STR_STATIC_INIT("emergency_call_data"), sel_emergency_call_data, 0},
835
+	{ sel_emergency_call_data, SEL_PARAM_STR, STR_STATIC_INIT("provider_info"), sel_provider_info, CONSUME_NEXT_INT | OPTIONAL},
836
+	{ sel_provider_info, SEL_PARAM_STR, STR_STATIC_INIT("counter"), sel_provider_info_cnt, 0},
837
+	{ sel_provider_info, SEL_PARAM_STR, STR_STATIC_INIT("urib"), sel_provider_info_uri, 0},
838
+	{ sel_provider_info, SEL_PARAM_STR, STR_STATIC_INIT("uri_type"), sel_provider_info_uri_type, 0},
839
+	{ sel_provider_info, SEL_PARAM_STR, STR_STATIC_INIT("raw"), sel_provider_info_raw, 0},
840
+	{ sel_provider_info, SEL_PARAM_STR, STR_STATIC_INIT("body"), sel_provider_info_body, 0},
841
+	{ sel_provider_info, SEL_PARAM_STR, STR_STATIC_INIT("header"), sel_provider_info_header, SEL_PARAM_EXPECTED},
842
+	{ sel_provider_info_header, SEL_PARAM_STR, STR_NULL, sel_provider_info_header_name, CONSUME_NEXT_INT | OPTIONAL },
843
+
844
+	{ sel_emergency_call_data, SEL_PARAM_STR, STR_STATIC_INIT("service_info"), sel_service_info, CONSUME_NEXT_INT | OPTIONAL},
845
+	{ sel_service_info, SEL_PARAM_STR, STR_STATIC_INIT("counter"), sel_service_info_cnt, 0},
846
+	{ sel_service_info, SEL_PARAM_STR, STR_STATIC_INIT("urib"), sel_service_info_uri, 0},
847
+	{ sel_service_info, SEL_PARAM_STR, STR_STATIC_INIT("uri_type"), sel_service_info_uri_type, 0},
848
+	{ sel_service_info, SEL_PARAM_STR, STR_STATIC_INIT("raw"), sel_service_info_raw, 0},
849
+	{ sel_service_info, SEL_PARAM_STR, STR_STATIC_INIT("body"), sel_service_info_body, 0},
850
+	{ sel_service_info, SEL_PARAM_STR, STR_STATIC_INIT("header"), sel_service_info_header, SEL_PARAM_EXPECTED},
851
+	{ sel_service_info_header, SEL_PARAM_STR, STR_NULL, sel_service_info_header_name, CONSUME_NEXT_INT | OPTIONAL },
852
+
853
+	{ sel_emergency_call_data, SEL_PARAM_STR, STR_STATIC_INIT("device_info"), sel_device_info, CONSUME_NEXT_INT | OPTIONAL},
854
+	{ sel_device_info, SEL_PARAM_STR, STR_STATIC_INIT("counter"), sel_device_info_cnt, 0},
855
+	{ sel_device_info, SEL_PARAM_STR, STR_STATIC_INIT("urib"), sel_device_info_uri, 0},
856
+	{ sel_device_info, SEL_PARAM_STR, STR_STATIC_INIT("uri_type"), sel_device_info_uri_type, 0},
857
+	{ sel_device_info, SEL_PARAM_STR, STR_STATIC_INIT("raw"), sel_device_info_raw, 0},
858
+	{ sel_device_info, SEL_PARAM_STR, STR_STATIC_INIT("body"), sel_device_info_body, 0},
859
+	{ sel_device_info, SEL_PARAM_STR, STR_STATIC_INIT("header"), sel_device_info_header, SEL_PARAM_EXPECTED},
860
+	{ sel_device_info_header, SEL_PARAM_STR, STR_NULL, sel_device_info_header_name, CONSUME_NEXT_INT | OPTIONAL },
861
+
862
+	{ sel_emergency_call_data, SEL_PARAM_STR, STR_STATIC_INIT("subscriber_info"), sel_subscriber_info, CONSUME_NEXT_INT | OPTIONAL},
863
+	{ sel_subscriber_info, SEL_PARAM_STR, STR_STATIC_INIT("counter"), sel_subscriber_info_cnt, 0},
864
+	{ sel_subscriber_info, SEL_PARAM_STR, STR_STATIC_INIT("urib"), sel_subscriber_info_uri, 0},
865
+	{ sel_subscriber_info, SEL_PARAM_STR, STR_STATIC_INIT("uri_type"), sel_subscriber_info_uri_type, 0},
866
+	{ sel_subscriber_info, SEL_PARAM_STR, STR_STATIC_INIT("raw"), sel_subscriber_info_raw, 0},
867
+	{ sel_subscriber_info, SEL_PARAM_STR, STR_STATIC_INIT("body"), sel_subscriber_info_body, 0},
868
+	{ sel_subscriber_info, SEL_PARAM_STR, STR_STATIC_INIT("header"), sel_subscriber_info_header, SEL_PARAM_EXPECTED},
869
+	{ sel_subscriber_info_header, SEL_PARAM_STR, STR_NULL, sel_subscriber_info_header_name, CONSUME_NEXT_INT | OPTIONAL },
870
+
871
+	{ sel_emergency_call_data, SEL_PARAM_STR, STR_STATIC_INIT("comment"), sel_comment, CONSUME_NEXT_INT | OPTIONAL},
872
+	{ sel_comment, SEL_PARAM_STR, STR_STATIC_INIT("counter"), sel_comment_cnt, 0},
873
+	{ sel_comment, SEL_PARAM_STR, STR_STATIC_INIT("urib"), sel_comment_uri, 0},
874
+	{ sel_comment, SEL_PARAM_STR, STR_STATIC_INIT("uri_type"), sel_comment_uri_type, 0},
875
+	{ sel_comment, SEL_PARAM_STR, STR_STATIC_INIT("raw"), sel_comment_raw, 0},
876
+	{ sel_comment, SEL_PARAM_STR, STR_STATIC_INIT("body"), sel_comment_body, 0},
877
+	{ sel_comment, SEL_PARAM_STR, STR_STATIC_INIT("header"), sel_comment_header, SEL_PARAM_EXPECTED},
878
+	{ sel_comment_header, SEL_PARAM_STR, STR_NULL, sel_comment_header_name, CONSUME_NEXT_INT | OPTIONAL },
879
+
880
+	{ NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
881
+};
0 882
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 */