Browse code

sca: end of line normalization to linux line ending format

Henning Westerholt authored on 09/09/2019 19:29:09
Showing 1 changed files
... ...
@@ -1,477 +1,477 @@
1
-/*
2
- * Copyright (C) 2012 Andrew Mortensen
3
- *
4
- * This file is part of the sca module for Kamailio, a free SIP server.
5
- *
6
- * The sca module is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License as published by
8
- * the Free Software Foundation; either version 2 of the License, or
9
- * (at your option) any later version
10
- *
11
- * The sca module is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- * GNU General Public License for more details.
15
- *
16
- * You should have received a copy of the GNU General Public License
17
- * along with this program; if not, write to the Free Software
18
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA. 02110-1301 USA
19
- */
20
-#include "sca_common.h"
21
-#include "sca.h"
22
-#include <assert.h>
23
-
24
-#include "sca_util.h"
25
-#include "../../core/dset.h"
26
-#include "../../core/parser/sdp/sdp.h"
27
-
28
-int sca_get_msg_method(sip_msg_t *msg)
29
-{
30
-	assert(msg != NULL);
31
-
32
-	if (msg->first_line.type == SIP_REQUEST) {
33
-		return (msg->REQ_METHOD);
34
-	}
35
-
36
-	return (sca_get_msg_cseq_method(msg));
37
-}
38
-
39
-int sca_get_msg_contact_uri(sip_msg_t *msg, str *contact_uri)
40
-{
41
-	contact_body_t *contact_body;
42
-
43
-	assert(msg != NULL);
44
-	assert(contact_uri != NULL);
45
-
46
-	if (SCA_HEADER_EMPTY(msg->contact)) {
47
-		LM_DBG("Empty Contact header\n");
48
-		contact_uri->s = NULL;
49
-		contact_uri->len = 0;
50
-
51
-		return (0);
52
-	}
53
-
54
-	if (parse_contact(msg->contact) < 0) {
55
-		LM_ERR("Failed to parse Contact header: %.*s\n",
56
-				STR_FMT(&msg->contact->body));
57
-		return (-1);
58
-	}
59
-	if ((contact_body = (contact_body_t *) msg->contact->parsed) == NULL) {
60
-		LM_ERR("Invalid Contact header: %.*s\n", STR_FMT(&msg->contact->body));
61
-		return (-1);
62
-	}
63
-	if (contact_body->star) {
64
-		LM_ERR("Invalid Contact header: SCA Contact must not be \"*\"\n");
65
-		return (-1);
66
-	}
67
-	if (contact_body->contacts == NULL) {
68
-		LM_ERR("Invalid Contact header: parser found no contacts\n");
69
-		return (-1);
70
-	}
71
-	if (contact_body->contacts->next) {
72
-		LM_ERR("Invalid Contact header: Contact may only contain one URI\n");
73
-		return (-1);
74
-	}
75
-
76
-	contact_uri->s = contact_body->contacts->uri.s;
77
-	contact_uri->len = contact_body->contacts->uri.len;
78
-
79
-	return (1);
80
-}
81
-
82
-int sca_get_msg_cseq_number(sip_msg_t *msg)
83
-{
84
-	int cseq;
85
-
86
-	assert(msg != NULL);
87
-
88
-	if (SCA_HEADER_EMPTY(msg->cseq)) {
89
-		LM_ERR("Empty Cseq header\n");
90
-		return (-1);
91
-	}
92
-	if (str2int(&(get_cseq(msg)->number), (unsigned int *) &cseq) != 0) {
93
-		LM_ERR("Bad Cseq header: %.*s\n", STR_FMT(&msg->cseq->body));
94
-		return (-1);
95
-	}
96
-
97
-	return (cseq);
98
-}
99
-
100
-/*
101
- *  assumes cseq header in msg is already parsed
102
- */
103
-int sca_get_msg_cseq_method(sip_msg_t *msg)
104
-{
105
-	assert(msg != NULL);
106
-
107
-	if (SCA_HEADER_EMPTY(msg->cseq)) {
108
-		LM_ERR("Empty Cseq header\n");
109
-		return (-1);
110
-	}
111
-
112
-	return (get_cseq(msg)->method_id);
113
-}
114
-
115
-int sca_get_msg_from_header(sip_msg_t *msg, struct to_body **from)
116
-{
117
-	struct to_body *f;
118
-
119
-	assert(msg != NULL);
120
-	assert(from != NULL);
121
-
122
-	if (SCA_HEADER_EMPTY(msg->from)) {
123
-		LM_ERR("Empty From header\n");
124
-		return (-1);
125
-	}
126
-	if (parse_from_header(msg) < 0) {
127
-		LM_ERR("Bad From header\n");
128
-		return (-1);
129
-	}
130
-	f = get_from(msg);
131
-	if (SCA_STR_EMPTY(&f->tag_value)) {
132
-		LM_ERR("Bad From header: no tag parameter\n");
133
-		return (-1);
134
-	}
135
-
136
-	// ensure the URI is parsed for future use
137
-	if (parse_uri(f->uri.s, f->uri.len, GET_FROM_PURI(msg)) < 0) {
138
-		LM_ERR("Failed to parse From URI %.*s\n", STR_FMT(&f->uri));
139
-		return (-1);
140
-	}
141
-
142
-	*from = f;
143
-
144
-	return (0);
145
-}
146
-
147
-int sca_get_msg_to_header(sip_msg_t *msg, struct to_body **to)
148
-{
149
-	struct to_body parsed_to;
150
-	struct to_body *t = NULL;
151
-
152
-	assert(msg != NULL);
153
-	assert(to != NULL);
154
-
155
-	if (SCA_HEADER_EMPTY(msg->to)) {
156
-		LM_ERR("Empty To header\n");
157
-		return (-1);
158
-	}
159
-	t = get_to(msg);
160
-	if (t == NULL) {
161
-		parse_to(msg->to->body.s, msg->to->body.s + msg->to->body.len + 1, // end of buffer
162
-		&parsed_to);
163
-		if (parsed_to.error != PARSE_OK) {
164
-			LM_ERR("Bad To header\n");
165
-			return (-1);
166
-		}
167
-		t = &parsed_to;
168
-	}
169
-
170
-	// ensure the URI is parsed for future use
171
-	if (parse_uri(t->uri.s, t->uri.len, GET_TO_PURI(msg)) < 0) {
172
-		LM_ERR("Failed to parse To URI %.*s\n", STR_FMT(&t->uri));
173
-		return (-1);
174
-	}
175
-
176
-	*to = t;
177
-
178
-	return (0);
179
-}
180
-
181
-/*
182
- * caller needs to call free_to for *body
183
- */
184
-int sca_build_to_body_from_uri(sip_msg_t *msg, struct to_body **body, str *uri)
185
-{
186
-	assert(msg != NULL);
187
-	assert(body != NULL);
188
-	assert(uri != NULL);
189
-
190
-	*body = pkg_malloc(sizeof(struct to_body));
191
-	if(*body == NULL) {
192
-		LM_ERR("cannot allocate pkg memory\n");
193
-		return(-1);
194
-	}
195
-
196
-	parse_to(uri->s, uri->s + uri->len + 1, *body);
197
-	if ((*body)->error != PARSE_OK) {
198
-		LM_ERR("Bad uri value[%.*s]\n", STR_FMT(uri));
199
-		free_to(*body);
200
-		return(-1);
201
-	}
202
-	return (0);
203
-}
204
-
205
-/*
206
- *  count characters requiring escape as defined by escape_common
207
- */
208
-int sca_uri_display_escapes_count(str *display) {
209
-	int c = 0;
210
-	int i;
211
-
212
-	if (SCA_STR_EMPTY(display)) {
213
-		return (0);
214
-	}
215
-
216
-	for (i = 0; i < display->len; i++) {
217
-		switch (display->s[i]) {
218
-		case '\'':
219
-		case '"':
220
-		case '\\':
221
-		case '\0':
222
-			c++;
223
-
224
-		default:
225
-			break;
226
-		}
227
-	}
228
-
229
-	return (c);
230
-}
231
-
232
-int sca_uri_extract_aor(str *uri, str *aor)
233
-{
234
-	char *semi;
235
-
236
-	assert(aor != NULL);
237
-
238
-	if (uri == NULL) {
239
-		aor->s = NULL;
240
-		aor->len = 0;
241
-		return (-1);
242
-	}
243
-
244
-	aor->s = uri->s;
245
-	semi = memchr(uri->s, ';', uri->len);
246
-	if (semi != NULL) {
247
-		aor->len = semi - uri->s;
248
-	} else {
249
-		aor->len = uri->len;
250
-	}
251
-
252
-	return (0);
253
-}
254
-
255
-int sca_uri_build_aor(str *aor, int maxlen, str *contact_uri, str *domain_uri)
256
-{
257
-	char *p;
258
-	char *dp;
259
-	int len;
260
-
261
-	assert(aor != NULL);
262
-	assert(contact_uri != NULL);
263
-	assert(domain_uri != NULL);
264
-
265
-	if (contact_uri->len + domain_uri->len >= maxlen) {
266
-		return (-1);
267
-	}
268
-
269
-	p = memchr(contact_uri->s, '@', contact_uri->len);
270
-	if (p == NULL) {
271
-		// no username, by definition can't be an SCA line
272
-		aor->s = NULL;
273
-		aor->len = 0;
274
-
275
-		return (0);
276
-	}
277
-	dp = memchr(domain_uri->s, '@', domain_uri->len);
278
-	if (dp == NULL) {
279
-		// may be nameless URI
280
-		dp = memchr(domain_uri->s, ':', domain_uri->len);
281
-		if (dp == NULL) {
282
-			// bad domain URI
283
-			return (-1);
284
-		}
285
-	}
286
-	dp++;
287
-
288
-	len = p - contact_uri->s;
289
-	memcpy(aor->s, contact_uri->s, len);
290
-	aor->s[len] = '@';
291
-	len += 1;
292
-	aor->len = len;
293
-
294
-	len = domain_uri->len - (dp - domain_uri->s);
295
-	memcpy(aor->s + aor->len, dp, len);
296
-	aor->len += len;
297
-
298
-	return (aor->len);
299
-}
300
-
301
-int sca_aor_create_from_info(str *aor, uri_type type, str *user, str *domain,
302
-		str *port)
303
-{
304
-	str scheme = STR_NULL;
305
-	int len = 0;
306
-
307
-	assert(aor != NULL);
308
-
309
-	uri_type_to_str(type, &scheme);
310
-
311
-	// +1 for ':', +1 for '@'
312
-	len = scheme.len + 1 + user->len + 1 + domain->len;
313
-	if (!SCA_STR_EMPTY(port)) {
314
-		// +1 for ':'
315
-		len += 1 + port->len;
316
-	}
317
-
318
-	aor->s = (char *) pkg_malloc(len);
319
-	if (aor->s == NULL) {
320
-		LM_ERR("sca_aor_create_from_info: pkg_malloc %d bytes failed\n", len);
321
-		return (-1);
322
-	}
323
-
324
-	len = 0;
325
-	SCA_STR_COPY(aor, &scheme);
326
-	len += scheme.len;
327
-
328
-	*(aor->s + len) = ':';
329
-	aor->len++;
330
-	len++;
331
-
332
-	SCA_STR_APPEND(aor, user);
333
-	len += user->len;
334
-
335
-	*(aor->s + len) = '@';
336
-	aor->len++;
337
-	len++;
338
-
339
-	SCA_STR_APPEND(aor, domain);
340
-	len += domain->len;
341
-
342
-	if (!SCA_STR_EMPTY(port)) {
343
-		*(aor->s + len) = ':';
344
-		len += 1;
345
-
346
-		SCA_STR_APPEND(aor, port);
347
-		len += port->len;
348
-	}
349
-
350
-	return (aor->len);
351
-}
352
-
353
-int sca_create_canonical_aor_for_ua(sip_msg_t *msg, str *c_aor, int ua_opts)
354
-{
355
-	struct to_body *tf = NULL;
356
-	sip_uri_t c_uri;
357
-	str tf_aor = STR_NULL;
358
-	str contact_uri = STR_NULL;
359
-	int rc = -1;
360
-
361
-	assert(msg != NULL);
362
-	assert(c_aor != NULL);
363
-
364
-	memset(c_aor, 0, sizeof(str));
365
-
366
-	if ((ua_opts & SCA_AOR_TYPE_AUTO)) {
367
-		if (msg->first_line.type == SIP_REQUEST) {
368
-			ua_opts = SCA_AOR_TYPE_UAC;
369
-		} else {
370
-			ua_opts = SCA_AOR_TYPE_UAS;
371
-		}
372
-	}
373
-
374
-	if ((ua_opts & SCA_AOR_TYPE_UAC)) {
375
-		if (sca_get_msg_from_header(msg, &tf) < 0) {
376
-			LM_ERR("sca_create_canonical_aor: failed to get From header\n");
377
-			goto done;
378
-		}
379
-	} else {
380
-		if (sca_get_msg_to_header(msg, &tf) < 0) {
381
-			LM_ERR("sca_create_canonical_aor: failed to get To header\n");
382
-			goto done;
383
-		}
384
-	}
385
-
386
-	if (sca_uri_extract_aor(&tf->uri, &tf_aor) < 0) {
387
-		LM_ERR("sca_create_canonical_aor: failed to extract AoR from "
388
-				"URI <%.*s>\n", STR_FMT(&tf->uri));
389
-		goto done;
390
-	}
391
-
392
-	memset(&c_uri, 0, sizeof(sip_uri_t));
393
-	if ((rc = sca_get_msg_contact_uri(msg, &contact_uri)) < 0) {
394
-		LM_ERR("sca_create_canonical_aor: failed to get contact URI from "
395
-				"Contact <%.*s>\n", STR_FMT(&msg->contact->body));
396
-		goto done;
397
-	}
398
-	if (rc > 0) {
399
-		if (parse_uri(contact_uri.s, contact_uri.len, &c_uri) < 0) {
400
-			LM_ERR("sca_create_canonical_aor: failed to parse Contact URI "
401
-					"<%.*s>\n", STR_FMT(&contact_uri));
402
-			rc = -1;
403
-			goto done;
404
-		}
405
-	}
406
-
407
-	if (SCA_STR_EMPTY(&c_uri.user) ||
408
-	SCA_STR_EQ(&c_uri.user, &tf->parsed_uri.user)) {
409
-		// empty contact header or Contact user matches To/From AoR
410
-		c_aor->s = (char *) pkg_malloc(tf_aor.len);
411
-		c_aor->len = tf_aor.len;
412
-		memcpy(c_aor->s, tf_aor.s, tf_aor.len);
413
-	} else {
414
-		// Contact user and To/From user mismatch
415
-		if (sca_aor_create_from_info(c_aor, c_uri.type, &c_uri.user,
416
-				&tf->parsed_uri.host, &tf->parsed_uri.port) < 0) {
417
-			LM_ERR("sca_create_canonical_aor: failed to create AoR from "
418
-					"Contact <%.*s> and URI <%.*s>\n",
419
-					STR_FMT(&contact_uri), STR_FMT(&tf_aor));
420
-			goto done;
421
-		}
422
-	}
423
-
424
-	rc = 1;
425
-
426
-	done: return (rc);
427
-}
428
-
429
-int sca_create_canonical_aor(sip_msg_t *msg, str *c_aor)
430
-{
431
-	return (sca_create_canonical_aor_for_ua(msg, c_aor, SCA_AOR_TYPE_AUTO));
432
-}
433
-
434
-/*
435
- * XXX this considers any held stream to mean the call is on hold. correct?
436
- */
437
-int sca_call_is_held(sip_msg_t *msg)
438
-{
439
-	sdp_session_cell_t *session;
440
-	sdp_stream_cell_t *stream;
441
-	int n_sess;
442
-	int n_str;
443
-	int is_held = 0;
444
-	int rc;
445
-
446
-	if(sca->cfg->onhold_bflag >= 0) {
447
-		if (isbflagset(0, (flag_t)sca->cfg->onhold_bflag)==1) {
448
-			LM_DBG("onhold_bflag set, skip parse_sdp and set held\n");
449
-			return ( 1 );
450
-		}
451
-	}
452
-	rc = parse_sdp(msg);
453
-	if (rc < 0) {
454
-		LM_ERR("sca_call_is_held: parse_sdp body failed\n");
455
-		return (0);
456
-	} else if (rc > 0) {
457
-		LM_DBG("sca_call_is_held: parse_sdp returned %d, no SDP body\n", rc);
458
-		return (0);
459
-	}
460
-
461
-	// Cf. modules_k/textops's exported is_audio_on_hold
462
-	for (n_sess = 0, session = get_sdp_session(msg, n_sess); session != NULL;
463
-			n_sess++, session = get_sdp_session(msg, n_sess)) {
464
-
465
-		for (n_str = 0, stream = get_sdp_stream(msg, n_sess, n_str);
466
-				stream != NULL;
467
-				n_str++, stream = get_sdp_stream(msg, n_sess, n_str)) {
468
-			if (stream->is_on_hold) {
469
-				LM_DBG("sca_call_is_held: parse_sdp detected stream is on hold\n");
470
-				is_held = 1;
471
-				goto done;
472
-			}
473
-		}
474
-	}
475
-
476
-	done: return (is_held);
477
-}
1
+/*
2
+ * Copyright (C) 2012 Andrew Mortensen
3
+ *
4
+ * This file is part of the sca module for Kamailio, a free SIP server.
5
+ *
6
+ * The sca module is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version
10
+ *
11
+ * The sca module is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with this program; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA. 02110-1301 USA
19
+ */
20
+#include "sca_common.h"
21
+#include "sca.h"
22
+#include <assert.h>
23
+
24
+#include "sca_util.h"
25
+#include "../../core/dset.h"
26
+#include "../../core/parser/sdp/sdp.h"
27
+
28
+int sca_get_msg_method(sip_msg_t *msg)
29
+{
30
+	assert(msg != NULL);
31
+
32
+	if (msg->first_line.type == SIP_REQUEST) {
33
+		return (msg->REQ_METHOD);
34
+	}
35
+
36
+	return (sca_get_msg_cseq_method(msg));
37
+}
38
+
39
+int sca_get_msg_contact_uri(sip_msg_t *msg, str *contact_uri)
40
+{
41
+	contact_body_t *contact_body;
42
+
43
+	assert(msg != NULL);
44
+	assert(contact_uri != NULL);
45
+
46
+	if (SCA_HEADER_EMPTY(msg->contact)) {
47
+		LM_DBG("Empty Contact header\n");
48
+		contact_uri->s = NULL;
49
+		contact_uri->len = 0;
50
+
51
+		return (0);
52
+	}
53
+
54
+	if (parse_contact(msg->contact) < 0) {
55
+		LM_ERR("Failed to parse Contact header: %.*s\n",
56
+				STR_FMT(&msg->contact->body));
57
+		return (-1);
58
+	}
59
+	if ((contact_body = (contact_body_t *) msg->contact->parsed) == NULL) {
60
+		LM_ERR("Invalid Contact header: %.*s\n", STR_FMT(&msg->contact->body));
61
+		return (-1);
62
+	}
63
+	if (contact_body->star) {
64
+		LM_ERR("Invalid Contact header: SCA Contact must not be \"*\"\n");
65
+		return (-1);
66
+	}
67
+	if (contact_body->contacts == NULL) {
68
+		LM_ERR("Invalid Contact header: parser found no contacts\n");
69
+		return (-1);
70
+	}
71
+	if (contact_body->contacts->next) {
72
+		LM_ERR("Invalid Contact header: Contact may only contain one URI\n");
73
+		return (-1);
74
+	}
75
+
76
+	contact_uri->s = contact_body->contacts->uri.s;
77
+	contact_uri->len = contact_body->contacts->uri.len;
78
+
79
+	return (1);
80
+}
81
+
82
+int sca_get_msg_cseq_number(sip_msg_t *msg)
83
+{
84
+	int cseq;
85
+
86
+	assert(msg != NULL);
87
+
88
+	if (SCA_HEADER_EMPTY(msg->cseq)) {
89
+		LM_ERR("Empty Cseq header\n");
90
+		return (-1);
91
+	}
92
+	if (str2int(&(get_cseq(msg)->number), (unsigned int *) &cseq) != 0) {
93
+		LM_ERR("Bad Cseq header: %.*s\n", STR_FMT(&msg->cseq->body));
94
+		return (-1);
95
+	}
96
+
97
+	return (cseq);
98
+}
99
+
100
+/*
101
+ *  assumes cseq header in msg is already parsed
102
+ */
103
+int sca_get_msg_cseq_method(sip_msg_t *msg)
104
+{
105
+	assert(msg != NULL);
106
+
107
+	if (SCA_HEADER_EMPTY(msg->cseq)) {
108
+		LM_ERR("Empty Cseq header\n");
109
+		return (-1);
110
+	}
111
+
112
+	return (get_cseq(msg)->method_id);
113
+}
114
+
115
+int sca_get_msg_from_header(sip_msg_t *msg, struct to_body **from)
116
+{
117
+	struct to_body *f;
118
+
119
+	assert(msg != NULL);
120
+	assert(from != NULL);
121
+
122
+	if (SCA_HEADER_EMPTY(msg->from)) {
123
+		LM_ERR("Empty From header\n");
124
+		return (-1);
125
+	}
126
+	if (parse_from_header(msg) < 0) {
127
+		LM_ERR("Bad From header\n");
128
+		return (-1);
129
+	}
130
+	f = get_from(msg);
131
+	if (SCA_STR_EMPTY(&f->tag_value)) {
132
+		LM_ERR("Bad From header: no tag parameter\n");
133
+		return (-1);
134
+	}
135
+
136
+	// ensure the URI is parsed for future use
137
+	if (parse_uri(f->uri.s, f->uri.len, GET_FROM_PURI(msg)) < 0) {
138
+		LM_ERR("Failed to parse From URI %.*s\n", STR_FMT(&f->uri));
139
+		return (-1);
140
+	}
141
+
142
+	*from = f;
143
+
144
+	return (0);
145
+}
146
+
147
+int sca_get_msg_to_header(sip_msg_t *msg, struct to_body **to)
148
+{
149
+	struct to_body parsed_to;
150
+	struct to_body *t = NULL;
151
+
152
+	assert(msg != NULL);
153
+	assert(to != NULL);
154
+
155
+	if (SCA_HEADER_EMPTY(msg->to)) {
156
+		LM_ERR("Empty To header\n");
157
+		return (-1);
158
+	}
159
+	t = get_to(msg);
160
+	if (t == NULL) {
161
+		parse_to(msg->to->body.s, msg->to->body.s + msg->to->body.len + 1, // end of buffer
162
+		&parsed_to);
163
+		if (parsed_to.error != PARSE_OK) {
164
+			LM_ERR("Bad To header\n");
165
+			return (-1);
166
+		}
167
+		t = &parsed_to;
168
+	}
169
+
170
+	// ensure the URI is parsed for future use
171
+	if (parse_uri(t->uri.s, t->uri.len, GET_TO_PURI(msg)) < 0) {
172
+		LM_ERR("Failed to parse To URI %.*s\n", STR_FMT(&t->uri));
173
+		return (-1);
174
+	}
175
+
176
+	*to = t;
177
+
178
+	return (0);
179
+}
180
+
181
+/*
182
+ * caller needs to call free_to for *body
183
+ */
184
+int sca_build_to_body_from_uri(sip_msg_t *msg, struct to_body **body, str *uri)
185
+{
186
+	assert(msg != NULL);
187
+	assert(body != NULL);
188
+	assert(uri != NULL);
189
+
190
+	*body = pkg_malloc(sizeof(struct to_body));
191
+	if(*body == NULL) {
192
+		LM_ERR("cannot allocate pkg memory\n");
193
+		return(-1);
194
+	}
195
+
196
+	parse_to(uri->s, uri->s + uri->len + 1, *body);
197
+	if ((*body)->error != PARSE_OK) {
198
+		LM_ERR("Bad uri value[%.*s]\n", STR_FMT(uri));
199
+		free_to(*body);
200
+		return(-1);
201
+	}
202
+	return (0);
203
+}
204
+
205
+/*
206
+ *  count characters requiring escape as defined by escape_common
207
+ */
208
+int sca_uri_display_escapes_count(str *display) {
209
+	int c = 0;
210
+	int i;
211
+
212
+	if (SCA_STR_EMPTY(display)) {
213
+		return (0);
214
+	}
215
+
216
+	for (i = 0; i < display->len; i++) {
217
+		switch (display->s[i]) {
218
+		case '\'':
219
+		case '"':
220
+		case '\\':
221
+		case '\0':
222
+			c++;
223
+
224
+		default:
225
+			break;
226
+		}
227
+	}
228
+
229
+	return (c);
230
+}
231
+
232
+int sca_uri_extract_aor(str *uri, str *aor)
233
+{
234
+	char *semi;
235
+
236
+	assert(aor != NULL);
237
+
238
+	if (uri == NULL) {
239
+		aor->s = NULL;
240
+		aor->len = 0;
241
+		return (-1);
242
+	}
243
+
244
+	aor->s = uri->s;
245
+	semi = memchr(uri->s, ';', uri->len);
246
+	if (semi != NULL) {
247
+		aor->len = semi - uri->s;
248
+	} else {
249
+		aor->len = uri->len;
250
+	}
251
+
252
+	return (0);
253
+}
254
+
255
+int sca_uri_build_aor(str *aor, int maxlen, str *contact_uri, str *domain_uri)
256
+{
257
+	char *p;
258
+	char *dp;
259
+	int len;
260
+
261
+	assert(aor != NULL);
262
+	assert(contact_uri != NULL);
263
+	assert(domain_uri != NULL);
264
+
265
+	if (contact_uri->len + domain_uri->len >= maxlen) {
266
+		return (-1);
267
+	}
268
+
269
+	p = memchr(contact_uri->s, '@', contact_uri->len);
270
+	if (p == NULL) {
271
+		// no username, by definition can't be an SCA line
272
+		aor->s = NULL;
273
+		aor->len = 0;
274
+
275
+		return (0);
276
+	}
277
+	dp = memchr(domain_uri->s, '@', domain_uri->len);
278
+	if (dp == NULL) {
279
+		// may be nameless URI
280
+		dp = memchr(domain_uri->s, ':', domain_uri->len);
281
+		if (dp == NULL) {
282
+			// bad domain URI
283
+			return (-1);
284
+		}
285
+	}
286
+	dp++;
287
+
288
+	len = p - contact_uri->s;
289
+	memcpy(aor->s, contact_uri->s, len);
290
+	aor->s[len] = '@';
291
+	len += 1;
292
+	aor->len = len;
293
+
294
+	len = domain_uri->len - (dp - domain_uri->s);
295
+	memcpy(aor->s + aor->len, dp, len);
296
+	aor->len += len;
297
+
298
+	return (aor->len);
299
+}
300
+
301
+int sca_aor_create_from_info(str *aor, uri_type type, str *user, str *domain,
302
+		str *port)
303
+{
304
+	str scheme = STR_NULL;
305
+	int len = 0;
306
+
307
+	assert(aor != NULL);
308
+
309
+	uri_type_to_str(type, &scheme);
310
+
311
+	// +1 for ':', +1 for '@'
312
+	len = scheme.len + 1 + user->len + 1 + domain->len;
313
+	if (!SCA_STR_EMPTY(port)) {
314
+		// +1 for ':'
315
+		len += 1 + port->len;
316
+	}
317
+
318
+	aor->s = (char *) pkg_malloc(len);
319
+	if (aor->s == NULL) {
320
+		LM_ERR("sca_aor_create_from_info: pkg_malloc %d bytes failed\n", len);
321
+		return (-1);
322
+	}
323
+
324
+	len = 0;
325
+	SCA_STR_COPY(aor, &scheme);
326
+	len += scheme.len;
327
+
328
+	*(aor->s + len) = ':';
329
+	aor->len++;
330
+	len++;
331
+
332
+	SCA_STR_APPEND(aor, user);
333
+	len += user->len;
334
+
335
+	*(aor->s + len) = '@';
336
+	aor->len++;
337
+	len++;
338
+
339
+	SCA_STR_APPEND(aor, domain);
340
+	len += domain->len;
341
+
342
+	if (!SCA_STR_EMPTY(port)) {
343
+		*(aor->s + len) = ':';
344
+		len += 1;
345
+
346
+		SCA_STR_APPEND(aor, port);
347
+		len += port->len;
348
+	}
349
+
350
+	return (aor->len);
351
+}
352
+
353
+int sca_create_canonical_aor_for_ua(sip_msg_t *msg, str *c_aor, int ua_opts)
354
+{
355
+	struct to_body *tf = NULL;
356
+	sip_uri_t c_uri;
357
+	str tf_aor = STR_NULL;
358
+	str contact_uri = STR_NULL;
359
+	int rc = -1;
360
+
361
+	assert(msg != NULL);
362
+	assert(c_aor != NULL);
363
+
364
+	memset(c_aor, 0, sizeof(str));
365
+
366
+	if ((ua_opts & SCA_AOR_TYPE_AUTO)) {
367
+		if (msg->first_line.type == SIP_REQUEST) {
368
+			ua_opts = SCA_AOR_TYPE_UAC;
369
+		} else {
370
+			ua_opts = SCA_AOR_TYPE_UAS;
371
+		}
372
+	}
373
+
374
+	if ((ua_opts & SCA_AOR_TYPE_UAC)) {
375
+		if (sca_get_msg_from_header(msg, &tf) < 0) {
376
+			LM_ERR("sca_create_canonical_aor: failed to get From header\n");
377
+			goto done;
378
+		}
379
+	} else {
380
+		if (sca_get_msg_to_header(msg, &tf) < 0) {
381
+			LM_ERR("sca_create_canonical_aor: failed to get To header\n");
382
+			goto done;
383
+		}
384
+	}
385
+
386
+	if (sca_uri_extract_aor(&tf->uri, &tf_aor) < 0) {
387
+		LM_ERR("sca_create_canonical_aor: failed to extract AoR from "
388
+				"URI <%.*s>\n", STR_FMT(&tf->uri));
389
+		goto done;
390
+	}
391
+
392
+	memset(&c_uri, 0, sizeof(sip_uri_t));
393
+	if ((rc = sca_get_msg_contact_uri(msg, &contact_uri)) < 0) {
394
+		LM_ERR("sca_create_canonical_aor: failed to get contact URI from "
395
+				"Contact <%.*s>\n", STR_FMT(&msg->contact->body));
396
+		goto done;
397
+	}
398
+	if (rc > 0) {
399
+		if (parse_uri(contact_uri.s, contact_uri.len, &c_uri) < 0) {
400
+			LM_ERR("sca_create_canonical_aor: failed to parse Contact URI "
401
+					"<%.*s>\n", STR_FMT(&contact_uri));
402
+			rc = -1;
403
+			goto done;
404
+		}
405
+	}
406
+
407
+	if (SCA_STR_EMPTY(&c_uri.user) ||
408
+	SCA_STR_EQ(&c_uri.user, &tf->parsed_uri.user)) {
409
+		// empty contact header or Contact user matches To/From AoR
410
+		c_aor->s = (char *) pkg_malloc(tf_aor.len);
411
+		c_aor->len = tf_aor.len;
412
+		memcpy(c_aor->s, tf_aor.s, tf_aor.len);
413
+	} else {
414
+		// Contact user and To/From user mismatch
415
+		if (sca_aor_create_from_info(c_aor, c_uri.type, &c_uri.user,
416
+				&tf->parsed_uri.host, &tf->parsed_uri.port) < 0) {
417
+			LM_ERR("sca_create_canonical_aor: failed to create AoR from "
418
+					"Contact <%.*s> and URI <%.*s>\n",
419
+					STR_FMT(&contact_uri), STR_FMT(&tf_aor));
420
+			goto done;
421
+		}
422
+	}
423
+
424
+	rc = 1;
425
+
426
+	done: return (rc);
427
+}
428
+
429
+int sca_create_canonical_aor(sip_msg_t *msg, str *c_aor)
430
+{
431
+	return (sca_create_canonical_aor_for_ua(msg, c_aor, SCA_AOR_TYPE_AUTO));
432
+}
433
+
434
+/*
435
+ * XXX this considers any held stream to mean the call is on hold. correct?
436
+ */
437
+int sca_call_is_held(sip_msg_t *msg)
438
+{
439
+	sdp_session_cell_t *session;
440
+	sdp_stream_cell_t *stream;
441
+	int n_sess;
442
+	int n_str;
443
+	int is_held = 0;
444
+	int rc;
445
+
446
+	if(sca->cfg->onhold_bflag >= 0) {
447
+		if (isbflagset(0, (flag_t)sca->cfg->onhold_bflag)==1) {
448
+			LM_DBG("onhold_bflag set, skip parse_sdp and set held\n");
449
+			return ( 1 );
450
+		}
451
+	}
452
+	rc = parse_sdp(msg);
453
+	if (rc < 0) {
454
+		LM_ERR("sca_call_is_held: parse_sdp body failed\n");
455
+		return (0);
456
+	} else if (rc > 0) {
457
+		LM_DBG("sca_call_is_held: parse_sdp returned %d, no SDP body\n", rc);
458
+		return (0);
459
+	}
460
+
461
+	// Cf. modules_k/textops's exported is_audio_on_hold
462
+	for (n_sess = 0, session = get_sdp_session(msg, n_sess); session != NULL;
463
+			n_sess++, session = get_sdp_session(msg, n_sess)) {
464
+
465
+		for (n_str = 0, stream = get_sdp_stream(msg, n_sess, n_str);
466
+				stream != NULL;
467
+				n_str++, stream = get_sdp_stream(msg, n_sess, n_str)) {
468
+			if (stream->is_on_hold) {
469
+				LM_DBG("sca_call_is_held: parse_sdp detected stream is on hold\n");
470
+				is_held = 1;
471
+				goto done;
472
+			}
473
+		}
474
+	}
475
+
476
+	done: return (is_held);
477
+}