1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  * Ken Rice <krice@freeswitch.org>
28  * Paul D. Tinsley <pdt at jackhammer.org>
29  * Bret McDanel <trixter AT 0xdecafbad.com>
30  * Marcel Barbulescu <marcelbarbulescu@gmail.com>
31  * Norman Brandinger
32  * Raymond Chandler <intralanman@freeswitch.org>
33  * Nathan Patrick <npatrick at corp.sonic.net>
34  * Joseph Sullivan <jossulli@amazon.com>
35  * Emmanuel Schmidbauer <e.schmidbauer@gmail.com>
36  * William King <william.king@quentustech.com>
37  * David Knell <david.knell@telng.com>
38  *
39  * sofia.c -- SOFIA SIP Endpoint (sofia code)
40  *
41  */
42 #include "mod_sofia.h"
43 
44 
45 extern su_log_t tport_log[];
46 extern su_log_t iptsec_log[];
47 extern su_log_t nea_log[];
48 extern su_log_t nta_log[];
49 extern su_log_t nth_client_log[];
50 extern su_log_t nth_server_log[];
51 extern su_log_t nua_log[];
52 extern su_log_t soa_log[];
53 extern su_log_t sresolv_log[];
54 #ifdef HAVE_SOFIA_STUN
55 extern su_log_t stun_log[];
56 #endif
57 extern su_log_t su_log_default[];
58 
59 static void config_sofia_profile_urls(sofia_profile_t * profile);
60 static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag, const char *gwname);
61 static void parse_domain_tag(sofia_profile_t *profile, switch_xml_t x_domain_tag, const char *dname, const char *parse, const char *alias);
62 
63 void sofia_handle_sip_i_reinvite(switch_core_session_t *session,
64 								 nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
65 								sofia_dispatch_event_t *de,
66 								 tagi_t tags[]);
67 
68 static void set_variable_sip_param(switch_channel_t *channel, char *header_type, sip_param_t const *params);
69 
70 
71 
72 static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
73 									 char const *phrase,
74 									 nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
75 								sofia_dispatch_event_t *de,
76 									 tagi_t tags[]);
77 
78 static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status,
79 									  char const *phrase,
80 									  nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
81 								sofia_dispatch_event_t *de,
82 									  tagi_t tags[]);
83 static void sofia_handle_sip_r_options(switch_core_session_t *session, int status, char const *phrase, nua_t *nua, sofia_profile_t *profile,
84 									   nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
85 								sofia_dispatch_event_t *de, tagi_t tags[]);
86 
sofia_set_accept_language_channel_variable(switch_channel_t * channel,sip_t const * sip)87 static void sofia_set_accept_language_channel_variable(switch_channel_t *channel, sip_t const *sip)
88 {
89 	if (sip->sip_accept_language) {
90 		sip_accept_language_t *sip_accept_language = NULL;
91 		int count = 0;
92 
93 		for(sip_accept_language = sip->sip_accept_language; sip_accept_language; sip_accept_language = sip_accept_language->aa_next) {
94 			char var_name[64] = "";
95 
96 			if (zstr(sip_accept_language->aa_value)) {
97 				continue;
98 
99 			}
100 			if (count == 0) {
101 				switch_channel_set_variable(channel, "sip_accept_language", sip_accept_language->aa_value);
102 			}
103 
104 			switch_snprintf(var_name, sizeof(var_name), "sip_accept_language_%d_value", count);
105 			switch_channel_set_variable(channel, var_name, sip_accept_language->aa_value);
106 
107 			if (!zstr(sip_accept_language->aa_q)) {
108 				switch_snprintf(var_name, sizeof(var_name), "sip_accept_language_%d_q", count);
109 				switch_channel_set_variable(channel, var_name, sip_accept_language->aa_q);
110 			}
111 
112 			count++;
113 		}
114 		switch_channel_set_variable_printf(channel, "sip_accept_language_count", "%d", count);
115 	}
116 }
117 
sofia_handle_sip_r_notify(switch_core_session_t * session,int status,char const * phrase,nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,sofia_private_t * sofia_private,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])118 void sofia_handle_sip_r_notify(switch_core_session_t *session, int status,
119 							   char const *phrase,
120 							   nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
121 								sofia_dispatch_event_t *de, tagi_t tags[])
122 {
123 	private_object_t *tech_pvt = switch_core_session_get_private(session);
124 	switch_core_session_t *other_session;
125 
126 	if (tech_pvt->proxy_refer_uuid && (other_session = switch_core_session_locate(tech_pvt->proxy_refer_uuid))) {
127 		switch_core_session_message_t *msg;
128 
129 		msg = switch_core_session_alloc(other_session, sizeof(*msg));
130 		msg->message_id = SWITCH_MESSAGE_INDICATE_RESPOND;
131 		msg->from = __FILE__;
132 		msg->numeric_arg = status;
133 		msg->string_arg = switch_core_session_strdup(other_session, phrase);
134 		switch_core_session_queue_message(other_session, msg);
135 		switch_core_session_rwunlock(other_session);
136 	} else {
137 		tech_pvt->proxy_refer_uuid = NULL;
138 	}
139 
140 
141 	if (status == 481 && sip && !sip->sip_retry_after && sip->sip_call_id && (!sofia_private || !sofia_private->is_call)) {
142 		char *sql;
143 
144 		sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", sip->sip_call_id->i_id);
145 		switch_assert(sql != NULL);
146 		sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
147 		nua_handle_destroy(nh);
148 	}
149 
150 }
151 
152 #define url_set_chanvars(session, url, varprefix) _url_set_chanvars(session, url, #varprefix "_user", #varprefix "_host", #varprefix "_port", #varprefix "_uri", #varprefix "_params")
153 
_url_set_chanvars(switch_core_session_t * session,url_t * url,const char * user_var,const char * host_var,const char * port_var,const char * uri_var,const char * params_var)154 static const char *_url_set_chanvars(switch_core_session_t *session, url_t *url, const char *user_var,
155 									 const char *host_var, const char *port_var, const char *uri_var, const char *params_var)
156 {
157 	const char *user = NULL, *host = NULL, *port = NULL;
158 	char *uri = NULL;
159 	switch_channel_t *channel = switch_core_session_get_channel(session);
160 	char new_port[25] = "";
161 
162 	if (url) {
163 		user = url->url_user;
164 		host = url->url_host;
165 		port = url->url_port;
166 		if (!zstr(url->url_params)) {
167 			switch_channel_set_variable(channel, params_var, url->url_params);
168 		}
169 	}
170 
171 	if (zstr(user)) {
172 		user = "nobody";
173 	}
174 
175 	if (zstr(host)) {
176 		host = "nowhere";
177 	}
178 
179 	check_decode(user, session);
180 
181 	if (user) {
182 		switch_channel_set_variable(channel, user_var, user);
183 	}
184 
185 
186 	if (port) {
187 		switch_snprintf(new_port, sizeof(new_port), ":%s", port);
188 	}
189 
190 	switch_channel_set_variable(channel, port_var, port);
191 	if (host) {
192 		if (user) {
193 			uri = switch_core_session_sprintf(session, "%s@%s%s", user, host, new_port);
194 		} else {
195 			uri = switch_core_session_sprintf(session, "%s%s", host, new_port);
196 		}
197 		switch_channel_set_variable(channel, uri_var, uri);
198 		switch_channel_set_variable(channel, host_var, host);
199 	}
200 
201 	return uri;
202 }
203 
strip_quotes(const char * in)204 static char *strip_quotes(const char *in)
205 {
206 	char *t = (char *) in;
207 	char *r = (char *) in;
208 
209 	if (t && *t == '"') {
210 		t++;
211 
212 		if (end_of(t) == '"') {
213 			r = strdup(t);
214 			switch_assert(r);
215 			end_of(r) = '\0';
216 		}
217 	}
218 
219 	return r;
220 }
221 
extract_header_vars(sofia_profile_t * profile,sip_t const * sip,switch_core_session_t * session,nua_handle_t * nh)222 static void extract_header_vars(sofia_profile_t *profile, sip_t const *sip,
223 								switch_core_session_t *session, nua_handle_t *nh)
224 {
225 	switch_channel_t *channel = switch_core_session_get_channel(session);
226 	char *full;
227 
228 	if (sip) {
229 		if (sip->sip_route) {
230 			const char *v = switch_channel_get_variable(channel, "sip_full_route");
231 
232 			if (!v) {
233 				sip_route_t *rp;
234 				switch_stream_handle_t stream = { 0 };
235 				int x = 0;
236 
237 				SWITCH_STANDARD_STREAM(stream);
238 
239 				for (rp = sip->sip_route; rp; rp = rp->r_next) {
240 					char *route = sip_header_as_string(nh->nh_home, (void *) rp);
241 					stream.write_function(&stream, x == 0 ? "%s" : ",%s", route);
242 					su_free(nh->nh_home, route);
243 					x++;
244 				}
245 				switch_channel_set_variable(channel, "sip_full_route", stream.data);
246 				free(stream.data);
247 			}
248 		}
249 
250 		if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
251 			if (sip->sip_contact) {
252 				char *c = sip_header_as_string(nh->nh_home, (void *) sip->sip_contact);
253 				switch_channel_set_variable(channel, "sip_recover_contact", c);
254 				su_free(nh->nh_home, c);
255 			}
256 		}
257 
258 		if (sip->sip_record_route) {
259 			sip_record_route_t *rrp;
260 			switch_stream_handle_t forward_stream = { 0 };
261 			switch_stream_handle_t reverse_stream = { 0 };
262 			int x = 0;
263 			char *tmp[128] = { 0 };
264 			int y = 0;
265 
266 			SWITCH_STANDARD_STREAM(forward_stream);
267 			SWITCH_STANDARD_STREAM(reverse_stream);
268 
269 			for(rrp = sip->sip_record_route; rrp; rrp = rrp->r_next) {
270 				char *rr = sip_header_as_string(nh->nh_home, (void *) rrp);
271 				forward_stream.write_function(&forward_stream, x == 0 ? "%s" : ",%s", rr);
272 				tmp[y++] = rr;
273 				if (y == 127) break;
274 				x++;
275 			}
276 
277 			y--;
278 
279 			x = 0;
280 
281 			while(y >= 0) {
282 				reverse_stream.write_function(&reverse_stream, x == 0 ? "%s" : ",%s", tmp[y]);
283 				su_free(nh->nh_home, tmp[y]);
284 				y--;
285 				x++;
286 			}
287 
288 			if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND || switch_channel_test_flag(channel, CF_RECOVERED)) {
289 				switch_channel_set_variable(channel, "sip_invite_route_uri", (char *)reverse_stream.data);
290 				switch_channel_set_variable(channel, "sip_invite_record_route", (char *)forward_stream.data);
291 			} else {
292 				switch_channel_set_variable(channel, "sip_invite_route_uri", (char *)forward_stream.data);
293 				switch_channel_set_variable(channel, "sip_invite_record_route", (char *)reverse_stream.data);
294 			}
295 
296 			free(reverse_stream.data);
297 			free(forward_stream.data);
298 		}
299 
300 		if (sip->sip_via) {
301 			sip_via_t *vp;
302 			switch_stream_handle_t stream = { 0 };
303 			int x = 0;
304 
305 			SWITCH_STANDARD_STREAM(stream);
306 
307 			for(vp = sip->sip_via; vp; vp = vp->v_next) {
308 				char *v = sip_header_as_string(nh->nh_home, (void *) vp);
309 
310 				stream.write_function(&stream, x == 0 ? "%s" : ",%s", v);
311 				su_free(nh->nh_home, v);
312 
313 				x++;
314 			}
315 
316 			switch_channel_set_variable(channel, "sip_full_via", (char *)stream.data);
317 
318 			if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND || switch_stristr("TCP", (char *)stream.data)) {
319 				switch_channel_set_variable(channel, "sip_recover_via", (char *)stream.data);
320 			}
321 
322 			free(stream.data);
323 
324 		}
325 
326 		if (sip->sip_from) {
327 			char *p = strip_quotes(sip->sip_from->a_display);
328 
329 			if (p) {
330 				switch_channel_set_variable(channel, "sip_from_display", p);
331 			}
332 			if (p != sip->sip_from->a_display) free(p);
333 			if ((full = sip_header_as_string(nh->nh_home, (void *) sip->sip_from))) {
334 				switch_channel_set_variable(channel, "sip_full_from", full);
335 				su_free(nh->nh_home, full);
336 			}
337 		}
338 
339 		if (sip->sip_to) {
340 			char *p = strip_quotes(sip->sip_to->a_display);
341 
342 			if (p) {
343 				switch_channel_set_variable(channel, "sip_to_display", p);
344 			}
345 
346 			if (p != sip->sip_to->a_display) free(p);
347 
348 			if ((full = sip_header_as_string(nh->nh_home, (void *) sip->sip_to))) {
349 				switch_channel_set_variable(channel, "sip_full_to", full);
350 				su_free(nh->nh_home, full);
351 			}
352 		}
353 
354 	}
355 }
356 
extract_vars(sofia_profile_t * profile,sip_t const * sip,switch_core_session_t * session)357 static void extract_vars(sofia_profile_t *profile, sip_t const *sip,
358 						 switch_core_session_t *session)
359 {
360 	switch_channel_t *channel = switch_core_session_get_channel(session);
361 
362 	if (sip) {
363 		if (sip->sip_from)
364 			url_set_chanvars(session, sip->sip_from->a_url, sip_from);
365 		if (sip->sip_request)
366 			url_set_chanvars(session, sip->sip_request->rq_url, sip_req);
367 		if (sip->sip_to)
368 			url_set_chanvars(session, sip->sip_to->a_url, sip_to);
369 		if (sip->sip_contact)
370 			url_set_chanvars(session, sip->sip_contact->m_url, sip_contact);
371 		if (sip->sip_referred_by)
372 			url_set_chanvars(session, sip->sip_referred_by->b_url, sip_referred_by);
373 		if (sip->sip_to && sip->sip_to->a_tag) {
374 			switch_channel_set_variable(channel, "sip_to_tag", sip->sip_to->a_tag);
375 		}
376 		if (sip->sip_from && sip->sip_from->a_tag) {
377 			switch_channel_set_variable(channel, "sip_from_tag", sip->sip_from->a_tag);
378 		}
379 		if (sip->sip_cseq && sip->sip_cseq->cs_seq) {
380 			char sip_cseq[40] = "";
381 			switch_snprintf(sip_cseq, sizeof(sip_cseq), "%d", sip->sip_cseq->cs_seq);
382 			switch_channel_set_variable(channel, "sip_cseq", sip_cseq);
383 		}
384 		if (sip->sip_call_id && sip->sip_call_id->i_id) {
385 			switch_channel_set_variable(channel, "sip_call_id", sip->sip_call_id->i_id);
386 		}
387 	}
388 }
389 
390 /**
391  * Add a specific SIP INVITE header to the channel variables, prefixed with "sip_i_"
392  */
sofia_add_invite_header_to_chanvars(switch_channel_t * channel,nua_handle_t * nh,void * sip_header,const char * var)393 static void sofia_add_invite_header_to_chanvars(switch_channel_t *channel, nua_handle_t *nh, void *sip_header, const char *var)
394 {
395 	switch_assert(channel);
396 	switch_assert(nh);
397 	switch_assert(var);
398 
399 	if (sip_header) {
400 		char *full;
401 		if ((full = sip_header_as_string(nh->nh_home, sip_header))) {
402 			switch_channel_set_variable(channel, var, full);
403 			su_free(nh->nh_home, full);
404 		}
405 	}
406 }
407 
408 /**
409  * Deep search into the SIP message to recreate the original headers, including multiple Diversions, etc.
410  * Finally sets the "sip_invite_headers" to a string containing the 'original' SIP headers, except that the order may have changed.
411  * Multiple headers will have the original internal order, though.
412  *
413  * @param sip A sip_t struct containing the parsed message
414  * @param session A call session
415  * @param nh A NUA handle for string allocation
416  */
sofia_parse_all_invite_headers(sip_t const * sip,switch_core_session_t * session,nua_handle_t * nh)417 static void sofia_parse_all_invite_headers(sip_t const *sip, switch_core_session_t *session, nua_handle_t *nh)
418 {
419 	switch_channel_t *channel = switch_core_session_get_channel(session);
420 	sip_unknown_t *un;
421 	sip_p_asserted_identity_t *passerted;
422 	sip_p_preferred_identity_t *ppreferred;
423 	sip_remote_party_id_t *rpid;
424 	sip_reply_to_t *reply_to;
425 	sip_alert_info_t *alert_info;
426 
427 	if (!sip) return;
428 
429 	/* Add simple (unique) headers first */
430 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_from, "sip_i_from");
431 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_to, "sip_i_to");
432 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_call_id, "sip_i_call_id");
433 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_cseq, "sip_i_cseq");
434 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_route, "sip_i_route");
435 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_max_forwards, "sip_i_max_forwards");
436 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_proxy_require, "sip_i_proxy_require");
437 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_contact, "sip_i_contact");
438 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_user_agent, "sip_i_user_agent");
439 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_subject, "sip_i_subject");
440 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_priority, "sip_i_priority");
441 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_organization, "sip_i_organization");
442 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_in_reply_to, "sip_i_in_reply_to");
443 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_accept_encoding, "sip_i_accept_encoding");
444 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_accept_language, "sip_i_accept_language");
445 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_allow, "sip_i_allow");
446 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_require, "sip_i_require");
447 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_supported, "sip_i_supported");
448 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_date, "sip_i_date");
449 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_timestamp, "sip_i_timestamp");
450 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_expires, "sip_i_expires");
451 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_min_expires, "sip_i_min_expires");
452 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_session_expires, "sip_i_session_expires");
453 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_min_se, "sip_i_min_se");
454 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_privacy, "sip_i_privacy");
455 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_mime_version, "sip_i_mime_version");
456 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_content_type, "sip_i_content_type");
457 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_content_encoding, "sip_i_content_encoding");
458 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_content_language, "sip_i_content_language");
459 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_content_disposition, "sip_i_content_disposition");
460 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_content_length, "sip_i_content_length");
461 
462 	/* Add all other headers - which might exist more than once */
463 
464 	if (sip->sip_via) {
465 		sip_via_t *vp;
466 		for (vp = sip->sip_via; vp; vp = vp->v_next) {
467 			char *v = sip_header_as_string(nh->nh_home, (void *) vp);
468 			switch_channel_add_variable_var_check(channel, "sip_i_via", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
469 			su_free(nh->nh_home, v);
470 		}
471 	}
472 
473 	if (sip->sip_record_route) {
474 		sip_record_route_t *rrp;
475 		for (rrp = sip->sip_record_route; rrp; rrp = rrp->r_next) {
476 			char *rr = sip_header_as_string(nh->nh_home, (void *) rrp);
477 			switch_channel_add_variable_var_check(channel, "sip_i_record_route", rr, SWITCH_FALSE, SWITCH_STACK_PUSH);
478 			su_free(nh->nh_home, rr);
479 		}
480 	}
481 
482 	if (sip->sip_proxy_authorization) {
483 		sip_proxy_authorization_t *vp;
484 		for (vp = sip->sip_proxy_authorization; vp; vp = vp->au_next) {
485 			char *v = sip_header_as_string(nh->nh_home, (void *) vp);
486 			switch_channel_add_variable_var_check(channel, "sip_i_proxy_authorization", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
487 			su_free(nh->nh_home, v);
488 		}
489 	}
490 
491 	if (sip->sip_call_info) {
492 		sip_call_info_t *vp;
493 		for (vp = sip->sip_call_info; vp; vp = vp->ci_next) {
494 			char *v = sip_header_as_string(nh->nh_home, (void *) vp);
495 			switch_channel_add_variable_var_check(channel, "sip_i_call_info", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
496 			su_free(nh->nh_home, v);
497 		}
498 	}
499 
500 	if (sip->sip_accept) {
501 		sip_accept_t *vp;
502 		for (vp = sip->sip_accept; vp; vp = vp->ac_next) {
503 			char *v = sip_header_as_string(nh->nh_home, (void *) vp);
504 			switch_channel_add_variable_var_check(channel, "sip_i_accept", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
505 			su_free(nh->nh_home, v);
506 		}
507 	}
508 
509 	if (sip->sip_authorization) {
510 		sip_authorization_t *vp;
511 		for (vp = sip->sip_authorization; vp; vp = vp->au_next) {
512 			char *v = sip_header_as_string(nh->nh_home, (void *) vp);
513 			switch_channel_add_variable_var_check(channel, "sip_i_authorization", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
514 			su_free(nh->nh_home, v);
515 		}
516 	}
517 
518 	if ((alert_info = sip_alert_info(sip))) {
519 		sip_alert_info_t *vp;
520 		for (vp = alert_info; vp; vp = vp->ai_next) {
521 			char *v = sip_header_as_string(nh->nh_home, (void *) vp);
522 			switch_channel_add_variable_var_check(channel, "sip_i_alert_info", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
523 			su_free(nh->nh_home, v);
524 		}
525 	}
526 
527 	if ((passerted = sip_p_asserted_identity(sip))) {
528 		sip_p_asserted_identity_t *vp;
529 		for (vp = passerted; vp; vp = vp->paid_next) {
530 			char *v = sip_header_as_string(nh->nh_home, (void *) vp);
531 			switch_channel_add_variable_var_check(channel, "sip_i_p_asserted_identity", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
532 			su_free(nh->nh_home, v);
533 		}
534 	}
535 
536 	if ((ppreferred = sip_p_preferred_identity(sip))) {
537 		sip_p_preferred_identity_t *vp;
538 		for (vp = ppreferred; vp; vp = vp->ppid_next) {
539 			char *v = sip_header_as_string(nh->nh_home, (void *) vp);
540 			switch_channel_add_variable_var_check(channel, "sip_i_p_preferred_identity", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
541 			su_free(nh->nh_home, v);
542 		}
543 	}
544 
545 	if ((rpid = sip_remote_party_id(sip))) {
546 		sip_remote_party_id_t *vp;
547 		for (vp = rpid; vp; vp = vp->rpid_next) {
548 			char *v = sip_header_as_string(nh->nh_home, (void *) vp);
549 			switch_channel_add_variable_var_check(channel, "sip_i_remote_party_id", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
550 			su_free(nh->nh_home, v);
551 		}
552 	}
553 
554 	if ((reply_to = sip_reply_to(sip))) {
555 		sip_reply_to_t *vp;
556 		for (vp = reply_to; vp; vp = vp->rplyto_next) {
557 			char *v = sip_header_as_string(nh->nh_home, (void *) vp);
558 			switch_channel_add_variable_var_check(channel, "sip_i_reply_to", v, SWITCH_FALSE, SWITCH_STACK_PUSH);
559 			su_free(nh->nh_home, v);
560 		}
561 	}
562 
563 	/* Loop through the unknown headers */
564 	for (un = sip->sip_unknown; un; un = un->un_next) {
565 		if (!zstr(un->un_name) && !zstr(un->un_value)) {
566 			char *parsed_name;
567 			if ((parsed_name = switch_mprintf("sip_i_%s", un->un_name))) {
568 				char *p, *x = parsed_name;
569 				switch_tolower_max(x);
570 				while ((p = strchr(x, '-'))) {
571 					*p = '_';
572 					x = ++p;
573 				}
574 				switch_channel_add_variable_var_check(channel, parsed_name, un->un_value, SWITCH_FALSE, SWITCH_STACK_PUSH);
575 				free(parsed_name);
576 			}
577 		}
578 	}
579 }
580 
sofia_pass_notify(switch_core_session_t * session,const char * uuid,const char * payload)581 static switch_status_t sofia_pass_notify(switch_core_session_t *session, const char *uuid, const char *payload)
582 {
583 	switch_core_session_t *other_session;
584 
585 	if ((other_session = switch_core_session_locate(uuid))) {
586 		switch_core_session_message_t *msg;
587 
588 		msg = switch_core_session_alloc(other_session, sizeof(*msg));
589 		MESSAGE_STAMP_FFL(msg);
590 		msg->message_id = SWITCH_MESSAGE_INDICATE_BLIND_TRANSFER_RESPONSE;
591 		msg->string_arg = switch_core_session_strdup(other_session, payload);
592 		msg->from = __FILE__;
593 		switch_core_session_queue_message(other_session, msg);
594 		switch_core_session_rwunlock(other_session);
595 		return SWITCH_STATUS_SUCCESS;
596 	}
597 
598 	return SWITCH_STATUS_FALSE;
599 }
600 
601 
sofia_handle_sip_i_notify(switch_core_session_t * session,int status,char const * phrase,nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,sofia_private_t * sofia_private,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])602 void sofia_handle_sip_i_notify(switch_core_session_t *session, int status,
603 							   char const *phrase,
604 							   nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
605 								sofia_dispatch_event_t *de, tagi_t tags[])
606 {
607 	switch_channel_t *channel = NULL;
608 	private_object_t *tech_pvt = NULL;
609 	switch_event_t *s_event = NULL;
610 	sofia_gateway_subscription_t *gw_sub_ptr;
611 	int sub_state;
612 	sofia_gateway_t *gateway = NULL;
613 	const char *session_id_header = sofia_glue_session_id_header(session, profile);
614 
615 	tl_gets(tags, NUTAG_SUBSTATE_REF(sub_state), TAG_END());
616 
617 	/* make sure we have a proper event */
618 	if (!sip || !sip->sip_event) {
619 		goto error;
620 	}
621 
622 	/* Automatically return a 200 OK for Event: keep-alive */
623 	if (!strcasecmp(sip->sip_event->o_type, "keep-alive")) {
624 		/* XXX MTK - is this right? in this case isn't sofia is already sending a 200 itself also? */
625 		nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
626 		goto end;
627 	}
628 
629 	if (session) {
630 		channel = switch_core_session_get_channel(session);
631 		switch_assert(channel != NULL);
632 		tech_pvt = switch_core_session_get_private(session);
633 		switch_assert(tech_pvt != NULL);
634 	}
635 
636 
637 	if (tech_pvt && tech_pvt->proxy_refer_uuid && sofia_test_pflag(profile, PFLAG_PROXY_REFER) && sip->sip_payload && sip->sip_payload->pl_data &&
638 		sip->sip_content_type && sip->sip_content_type->c_type && switch_stristr("sipfrag", sip->sip_content_type->c_type)) {
639 
640 		if (sofia_pass_notify(session, tech_pvt->proxy_refer_uuid, sip->sip_payload->pl_data) == SWITCH_STATUS_SUCCESS) {
641 			if (tech_pvt->proxy_refer_msg) {
642 				msg_ref_destroy(tech_pvt->proxy_refer_msg);
643 				tech_pvt->proxy_refer_msg = NULL;
644 			}
645 			tech_pvt->proxy_refer_msg = msg_ref_create(de->data->e_msg);
646 			//nua_respond(nh, SIP_202_ACCEPTED, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
647 		} else {
648 			switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
649 		}
650 
651 		goto end;
652 	}
653 
654 	/* For additional NOTIFY event packages see http://www.iana.org/assignments/sip-events. */
655 	if (sip->sip_content_type &&
656 		sip->sip_content_type->c_type && sip->sip_payload && sip->sip_payload->pl_data && !strcasecmp(sip->sip_event->o_type, "refer")) {
657 		if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_NOTIFY_REFER) == SWITCH_STATUS_SUCCESS) {
658 			switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "content-type", sip->sip_content_type->c_type);
659 			switch_event_add_body(s_event, "%s", sip->sip_payload->pl_data);
660 		}
661 	}
662 
663 	/* add common headers for the NOTIFY to the switch_event and fire if it exists */
664 	if (s_event != NULL) {
665 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event-package", sip->sip_event->o_type);
666 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event-id", sip->sip_event->o_id);
667 
668 		if (sip->sip_contact) {
669 			switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "contact", "%s@%s",
670 									sip->sip_contact->m_url->url_user, sip->sip_contact->m_url->url_host);
671 		}
672 
673 		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", sip->sip_from->a_url->url_user, sip->sip_from->a_url->url_host);
674 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-tag", sip->sip_from->a_tag);
675 		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host);
676 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "to-tag", sip->sip_to->a_tag);
677 
678 		if (sip->sip_call_id && sip->sip_call_id->i_id) {
679 			switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "call-id", sip->sip_call_id->i_id);
680 		}
681 		if (sip->sip_subscription_state && sip->sip_subscription_state->ss_substate) {
682 			switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "subscription-substate", sip->sip_subscription_state->ss_substate);
683 		}
684 		if (sip->sip_subscription_state && sip->sip_subscription_state->ss_reason) {
685 			switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "subscription-reason", sip->sip_subscription_state->ss_reason);
686 		}
687 		if (sip->sip_subscription_state && sip->sip_subscription_state->ss_retry_after) {
688 			switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "subscription-retry-after", sip->sip_subscription_state->ss_retry_after);
689 		}
690 		if (sip->sip_subscription_state && sip->sip_subscription_state->ss_expires) {
691 			switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "subscription-expires", sip->sip_subscription_state->ss_expires);
692 		}
693 		if (session) {
694 			switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "UniqueID", switch_core_session_get_uuid(session));
695 		}
696 		switch_event_fire(&s_event);
697 	}
698 
699 	if (!strcasecmp(sip->sip_event->o_type, "refer")) {
700 		if (session && channel && tech_pvt) {
701 			if (sip->sip_payload && sip->sip_payload->pl_data) {
702 				char *p;
703 				int status_val = 0;
704 				if ((p = strchr(sip->sip_payload->pl_data, ' '))) {
705 					p++;
706 					status_val = atoi(p);
707 				}
708 				if (!status_val || status_val >= 200) {
709 					switch_channel_set_variable(channel, "sip_refer_reply", sip->sip_payload->pl_data);
710 					if (status_val == 200) {
711 						switch_channel_hangup(channel, SWITCH_CAUSE_BLIND_TRANSFER);
712 					}
713 					if ((int)tech_pvt->want_event == 9999) {
714 						tech_pvt->want_event = 0;
715 					}
716 				}
717 			}
718 		}
719 		nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
720 	}
721 
722 	/* if no session, assume it could be an incoming notify from a gateway subscription */
723 	if (session) {
724 		if (!zstr(profile->proxy_notify_events) && (!strcasecmp(profile->proxy_notify_events, "all") || strstr(profile->proxy_notify_events, sip->sip_event->o_type))) {
725 			switch_core_session_t *other_session;
726 			if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
727 				private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
728 				const char *full_to = NULL;
729 				char *pl = NULL;
730 				char *unknown = NULL;
731 
732 				full_to = switch_str_nil(switch_channel_get_variable(switch_core_session_get_channel(other_session), "sip_full_to"));
733 				if (sip->sip_payload && sip->sip_payload->pl_data) {
734 					pl = switch_core_session_strdup(other_session, (char*)sip->sip_payload->pl_data);
735 				}
736 				unknown = sofia_glue_get_non_extra_unknown_headers(sip);
737 				nua_notify(other_tech_pvt->nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active),
738 							TAG_IF((full_to), SIPTAG_TO_STR(full_to)), SIPTAG_SUBSCRIPTION_STATE_STR("active"),
739 							SIPTAG_EVENT_STR(sip->sip_event->o_type), TAG_IF(!zstr(unknown), SIPTAG_HEADER_STR(unknown)),
740 							TAG_IF(!zstr(pl), SIPTAG_PAYLOAD_STR(pl)),
741 							TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
742 							TAG_END());
743 				switch_safe_free(unknown);
744 				switch_core_session_rwunlock(other_session);
745 			}
746 			nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg),
747 						TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
748 			goto end;
749 		}
750 		/* make sure we have a proper "talk" event */
751 		if (strcasecmp(sip->sip_event->o_type, "talk")) {
752 			goto error;
753 		}
754 
755 		if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
756 			switch_channel_answer(channel);
757 			switch_channel_set_variable(channel, "auto_answer_destination", switch_channel_get_variable(channel, "destination_number"));
758 			switch_ivr_session_transfer(session, "auto_answer", NULL, NULL);
759 			nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg),
760 						TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
761 			goto end;
762 		}
763 	}
764 
765 	if (!sofia_private || zstr(sofia_private->gateway_name)) {
766 		if (profile->debug) {
767 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Gateway information missing Subscription Event: %s\n",
768 							  sip->sip_event->o_type);
769 		}
770 		goto error;
771 	}
772 
773 
774 	if (!(gateway = sofia_reg_find_gateway(sofia_private->gateway_name))) {
775 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Gateway information missing\n");
776 		goto error;
777 	}
778 
779 	/* find the corresponding gateway subscription (if any) */
780 	if (!(gw_sub_ptr = sofia_find_gateway_subscription(gateway, sip->sip_event->o_type))) {
781 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
782 						  "Could not find gateway subscription.  Gateway: %s.  Subscription Event: %s\n",
783 						  gateway->name, sip->sip_event->o_type);
784 		goto error;
785 	}
786 
787 	if (!(gw_sub_ptr->state == SUB_STATE_SUBED || gw_sub_ptr->state == SUB_STATE_SUBSCRIBE)) {
788 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Ignoring notify due to subscription state: %d\n", gw_sub_ptr->state);
789 		goto error;
790 	}
791 
792 	if (sip->sip_subscription_state && sip->sip_subscription_state->ss_expires) {
793 		int delta = atoi(sip->sip_subscription_state->ss_expires);
794 
795 		delta /= 2;
796 
797 		if (delta < 1) {
798 			delta = 1;
799 		}
800 		gw_sub_ptr->expires = switch_epoch_time_now(NULL) + delta;
801 	}
802 
803 	/* dispatch freeswitch event */
804 	if (switch_event_create(&s_event, SWITCH_EVENT_NOTIFY_IN) == SWITCH_STATUS_SUCCESS) {
805 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event", sip->sip_event->o_type);
806 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "pl_data", sip->sip_payload ? sip->sip_payload->pl_data : "");
807 		if ( sip->sip_content_type != NULL )
808 			switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "sip_content_type", sip->sip_content_type->c_type);
809 		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "port", "%d", gateway->profile->sip_port);
810 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "module_name", "mod_sofia");
811 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile_name", gateway->profile->name);
812 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile_uri", gateway->profile->url);
813 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "gateway_name", gateway->name);
814 		if ( sip->sip_call_info != NULL ) {
815 			sip_call_info_t *call_info = sip->sip_call_info;
816 			char *nua_hold = sip_header_as_string(nua_handle_home(nh), (void *) call_info);
817 			size_t cur_len = strlen(nua_hold);
818 			char *hold = strdup(nua_hold);
819 			su_free(nua_handle_home(nh), nua_hold);
820 
821 			while ((call_info = call_info->ci_next) != NULL) {
822 				char *tmp = sip_header_as_string(nua_handle_home(nh), (void *) call_info);
823 				size_t tmp_len = strlen(tmp);
824 				char *tmp_hold = realloc(hold, cur_len + tmp_len + 2);
825 				if (!tmp_hold) {
826 					/* Avoid leak if realloc failed */
827 					free(hold);
828 				}
829 				switch_assert(tmp_hold);
830 				hold = tmp_hold;
831 				strncpy(hold + cur_len, ",", 2);
832 				strncpy(hold + cur_len + 1, tmp, tmp_len +1);
833 				su_free(nua_handle_home(nh), tmp);
834 				cur_len = cur_len + tmp_len + 2;
835 			}
836 			switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Call-Info", hold);
837 			switch_safe_free(hold);
838 		}
839 		switch_event_fire(&s_event);
840 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "dispatched freeswitch event for message-summary NOTIFY\n");
841 	} else {
842 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to create event\n");
843 		goto error;
844 	}
845 
846 	goto end;
847 
848   error:
849 
850 
851 	if (sip && sip->sip_event && sip->sip_event->o_type && !strcasecmp(sip->sip_event->o_type, "message-summary")) {
852 		/* unsolicited mwi, just say ok */
853 		nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg),
854 					TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),  TAG_END());
855 
856 		if (sofia_test_pflag(profile, PFLAG_FORWARD_MWI_NOTIFY)) {
857 			const char *mwi_status = NULL;
858 			char network_ip[80];
859 			uint32_t x = 0;
860 			int acl_ok = 1;
861 			char *last_acl = NULL;
862 
863 			if (sip->sip_to && sip->sip_to->a_url->url_user && sip->sip_to->a_url->url_host
864 				&& sip->sip_payload && sip->sip_payload->pl_data ) {
865 
866 				sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), NULL);
867 				for (x = 0; x < profile->acl_count; x++) {
868 					last_acl = profile->acl[x];
869 					if (!(acl_ok = switch_check_network_list_ip(network_ip, last_acl))) {
870 						break;
871 					}
872 				}
873 
874 				if ( acl_ok )
875 				{
876 					mwi_status = switch_stristr("Messages-Waiting: ", sip->sip_payload->pl_data);
877 
878 					if ( mwi_status ) {
879 						char *mwi_stat;
880 						mwi_status += strlen( "Messages-Waiting: " );
881 						mwi_stat = switch_strip_whitespace( mwi_status );
882 
883 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
884 										  "Forwarding unsolicited MWI ( %s : %s@%s )\n",
885 										  mwi_stat, sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host );
886 						if (switch_event_create(&s_event, SWITCH_EVENT_MESSAGE_WAITING) == SWITCH_STATUS_SUCCESS) {
887 							switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "MWI-Messages-Waiting", mwi_stat );
888 							switch_event_add_header(s_event, SWITCH_STACK_BOTTOM,
889 													"MWI-Message-Account", "%s@%s", sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host );
890 							switch_event_fire(&s_event);
891 						}
892 						switch_safe_free(mwi_stat);
893 					}
894 				} else {
895 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Dropping unsolicited MWI ( %s@%s ) because of ACL\n",
896 									  sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host );
897 				};
898 
899 			}
900 		}
901 
902 	} else {
903 		nua_respond(nh, 481, "Subscription Does Not Exist", NUTAG_WITH_THIS_MSG(de->data->e_msg),
904 					TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
905 	}
906 
907   end:
908 
909 	if (!gateway && sub_state == nua_substate_terminated && sofia_private && sofia_private != &mod_sofia_globals.destroy_private &&
910 		sofia_private != &mod_sofia_globals.keep_private) {
911 		sofia_private->destroy_nh = 1;
912 		sofia_private->destroy_me = 1;
913 	}
914 
915 	if (gateway) {
916 		sofia_reg_release_gateway(gateway);
917 	}
918 
919 }
920 
921 /*
922  * This will fire an event containing X-headers from the BYE response
923  */
sofia_handle_sip_r_bye(switch_core_session_t * session,int status,char const * phrase,nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,sofia_private_t * sofia_private,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])924 void sofia_handle_sip_r_bye(switch_core_session_t *session, int status,
925 							char const *phrase,
926 							nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
927 								sofia_dispatch_event_t *de, tagi_t tags[])
928 {
929 	if (profile && sofia_test_pflag(profile, PFLAG_FIRE_BYE_RESPONSE_EVENTS) && sip && sip->sip_call_id && !zstr(sip->sip_call_id->i_id) && sofia_private && !zstr_buf(sofia_private->uuid_str)) {
930 		switch_event_t *bye_response_event = NULL;
931 		sip_unknown_t *un;
932 		if (switch_event_create_subclass(&bye_response_event, SWITCH_EVENT_CUSTOM, MY_EVENT_BYE_RESPONSE) == SWITCH_STATUS_SUCCESS) {
933 			switch_event_add_header(bye_response_event, SWITCH_STACK_BOTTOM, "call-id", "%s", sip->sip_call_id->i_id);
934 			switch_event_add_header(bye_response_event, SWITCH_STACK_BOTTOM, "Unique-ID", "%s", sofia_private->uuid_str);
935 			for (un = sip->sip_unknown; un; un = un->un_next) {
936 				if (!zstr(un->un_value)) {
937 					switch_event_add_header(bye_response_event, SWITCH_STACK_BOTTOM, un->un_name, "%s", un->un_value);
938 				}
939 			}
940 			switch_event_fire(&bye_response_event);
941 		}
942 	}
943 }
944 
sofia_handle_sip_i_bye(switch_core_session_t * session,int status,char const * phrase,nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,sofia_private_t * sofia_private,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])945 void sofia_handle_sip_i_bye(switch_core_session_t *session, int status,
946 							char const *phrase,
947 							nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
948 								sofia_dispatch_event_t *de, tagi_t tags[])
949 {
950 	const char *tmp;
951 	switch_channel_t *channel;
952 	private_object_t *tech_pvt;
953 	char *extra_headers;
954 	const char *call_info = NULL;
955 	const char *vval = NULL;
956 	const char *session_id_header = sofia_glue_session_id_header(session, profile);
957 #ifdef MANUAL_BYE
958 	int cause;
959 	char st[80] = "";
960 #endif
961 
962 	if (!session) {
963 		return;
964 	}
965 
966 	channel = switch_core_session_get_channel(session);
967 	tech_pvt = switch_core_session_get_private(session);
968 
969 #ifdef MANUAL_BYE
970 	status = 200;
971 	phrase = "OK";
972 
973 	if (switch_channel_test_flag(tech_pvt->channel, CF_SLA_BARGING)) {
974 		const char *bargee_uuid = switch_channel_get_variable(channel, "sip_barging_uuid");
975 		switch_core_session_t *bargee_session;
976 		uint32_t ttl = 0;
977 
978 		if ((bargee_session = switch_core_session_locate(bargee_uuid))) {
979 			//switch_channel_t *bargee_channel = switch_core_session_get_channel(bargee_session);
980 			if ((ttl = switch_core_media_bug_count(bargee_session, "eavesdrop")) == 1) {
981 				if (switch_core_session_check_interface(bargee_session, sofia_endpoint_interface)) {
982 					switch_channel_clear_flag(switch_core_session_get_channel(bargee_session), CF_SLA_BARGE);
983 				}
984 			}
985 			switch_core_session_rwunlock(bargee_session);
986 		}
987 	}
988 
989 	if (switch_channel_test_flag(tech_pvt->channel, CF_SLA_BARGE)) {
990 		switch_core_session_t *new_session, *other_session;
991 		const char *other_uuid = switch_channel_get_partner_uuid(tech_pvt->channel);
992 		char *cmd = NULL;
993 
994 		if (!zstr(other_uuid) && (other_session = switch_core_session_locate(other_uuid))) {
995 			switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
996 
997 			switch_mutex_lock(profile->ireg_mutex);
998 			if (switch_ivr_eavesdrop_pop_eavesdropper(session, &new_session) == SWITCH_STATUS_SUCCESS) {
999 				switch_channel_t *new_channel = switch_core_session_get_channel(new_session);
1000 				const char *new_uuid = switch_core_session_get_uuid(new_session);
1001 				switch_caller_profile_t *cp = switch_channel_get_caller_profile(new_channel);
1002 
1003 				cp->caller_id_name = cp->orig_caller_id_name;
1004 				cp->caller_id_number = cp->orig_caller_id_number;
1005 
1006 
1007 				switch_channel_set_variable(new_channel, SWITCH_SIGNAL_BOND_VARIABLE, NULL);
1008 
1009 				switch_channel_set_flag(other_channel, CF_REDIRECT);
1010 
1011 				switch_channel_set_state(new_channel, CS_RESET);
1012 
1013 				switch_ivr_uuid_bridge(new_uuid, other_uuid);
1014 				cmd = switch_core_session_sprintf(session, "sleep:500,sofia_sla:%s inline", new_uuid);
1015 
1016 				switch_channel_clear_flag(other_channel, CF_REDIRECT);
1017 
1018 				switch_core_session_rwunlock(new_session);
1019 			}
1020 			switch_mutex_unlock(profile->ireg_mutex);
1021 
1022 			switch_core_session_rwunlock(other_session);
1023 		}
1024 
1025 		if (!zstr(cmd)) {
1026 			switch_ivr_eavesdrop_exec_all(session, "transfer", cmd);
1027 		}
1028 	}
1029 
1030 	sofia_set_flag_locked(tech_pvt, TFLAG_BYE);
1031 	call_info = switch_channel_get_variable(channel, "presence_call_info_full");
1032 
1033 	if (sip->sip_reason) {
1034 		char *reason_header = sip_header_as_string(nh->nh_home, (void *) sip->sip_reason);
1035 
1036 		if (!zstr(reason_header)) {
1037 			switch_channel_set_variable(channel, "sip_reason", reason_header);
1038 			switch_channel_set_variable_partner(channel, "sip_reason", reason_header);
1039 		}
1040 	}
1041 
1042 	if (sip->sip_reason && sip->sip_reason->re_protocol && (!strcasecmp(sip->sip_reason->re_protocol, "Q.850")
1043 															|| !strcasecmp(sip->sip_reason->re_protocol, "FreeSWITCH")
1044 															|| !strcasecmp(sip->sip_reason->re_protocol, profile->sdp_username)) && sip->sip_reason->re_cause) {
1045 		tech_pvt->q850_cause = atoi(sip->sip_reason->re_cause);
1046 		cause = tech_pvt->q850_cause;
1047 	} else {
1048 		cause = sofia_glue_sip_cause_to_freeswitch(status);
1049 	}
1050 
1051 	if (sip->sip_content_type && sip->sip_content_type->c_type) {
1052 		switch_channel_set_variable(channel, "sip_bye_content_type", sip->sip_content_type->c_type);
1053 	}
1054 
1055 	if (sip->sip_payload && sip->sip_payload->pl_data) {
1056 		switch_channel_set_variable(channel, "sip_bye_payload", sip->sip_payload->pl_data);
1057 	}
1058 
1059 	switch_snprintf(st, sizeof(st), "%d", status);
1060 	switch_channel_set_variable(channel, "sip_term_status", st);
1061 	switch_snprintf(st, sizeof(st), "sip:%d", status);
1062 	switch_channel_set_variable(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st);
1063 
1064 	switch_channel_set_variable_partner(channel, "sip_hangup_phrase", phrase);
1065 
1066 	switch_snprintf(st, sizeof(st), "%d", cause);
1067 	switch_channel_set_variable(channel, "sip_term_cause", st);
1068 
1069 	extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_BYE_HEADER_PREFIX);
1070 	sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_BYE_HEADER_PREFIX);
1071 
1072 	if (!(vval = switch_channel_get_variable(channel, "sip_copy_custom_headers")) || switch_true(vval)) {
1073 		switch_core_session_t *nsession = NULL;
1074 
1075 		switch_core_session_get_partner(session, &nsession);
1076 
1077 		if (nsession) {
1078 			const char *vval;
1079 			switch_channel_t *nchannel = switch_core_session_get_channel(nsession);
1080 
1081 			if (!(vval = switch_channel_get_variable(nchannel, "sip_copy_custom_headers")) || switch_true(vval)) {
1082 				switch_ivr_transfer_variable(session, nsession, SOFIA_SIP_BYE_HEADER_PREFIX_T);
1083 			}
1084 			switch_core_session_rwunlock(nsession);
1085 		}
1086 	}
1087 
1088 
1089 	switch_channel_hangup(channel, cause);
1090 	nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg),
1091 				TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info)), TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
1092 				TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
1093 
1094 	switch_safe_free(extra_headers);
1095 
1096 	if (sofia_private) {
1097 		sofia_private->destroy_me = 1;
1098 		sofia_private->destroy_nh = 1;
1099 	}
1100 #endif
1101 
1102 
1103 	if (sip->sip_user_agent && !zstr(sip->sip_user_agent->g_string)) {
1104 		switch_channel_set_variable(channel, "sip_user_agent", sip->sip_user_agent->g_string);
1105 	} else if (sip->sip_server && !zstr(sip->sip_server->g_string)) {
1106 		switch_channel_set_variable(channel, "sip_user_agent", sip->sip_server->g_string);
1107 	}
1108 
1109 	sofia_set_accept_language_channel_variable(channel, sip);
1110 
1111 	if ((tmp = sofia_glue_get_unknown_header(sip, "rtp-txstat"))) {
1112 		switch_channel_set_variable(channel, "sip_rtp_txstat", tmp);
1113 	}
1114 	if ((tmp = sofia_glue_get_unknown_header(sip, "rtp-rxstat"))) {
1115 		switch_channel_set_variable(channel, "sip_rtp_rxstat", tmp);
1116 	}
1117 	if ((tmp = sofia_glue_get_unknown_header(sip, "P-RTP-Stat"))) {
1118 		switch_channel_set_variable(channel, "sip_p_rtp_stat", tmp);
1119 	}
1120 
1121 	tech_pvt->got_bye = 1;
1122 	switch_channel_set_variable(channel, "sip_hangup_disposition", "recv_bye");
1123 
1124 	return;
1125 }
1126 
sofia_handle_sip_r_message(int status,sofia_profile_t * profile,nua_handle_t * nh,sip_t const * sip)1127 void sofia_handle_sip_r_message(int status, sofia_profile_t *profile, nua_handle_t *nh, sip_t const *sip)
1128 {
1129 	const char *call_id;
1130 	int *mstatus;
1131 
1132 	if (!(sip && sip->sip_call_id)) {
1133 		nua_handle_destroy(nh);
1134 		return;
1135 	}
1136 
1137 	call_id = sip->sip_call_id->i_id;
1138 
1139 
1140 
1141 	switch_mutex_lock(profile->flag_mutex);
1142 	mstatus = switch_core_hash_find(profile->chat_hash, call_id);
1143 	switch_mutex_unlock(profile->flag_mutex);
1144 
1145 	if (mstatus) {
1146 		*mstatus = status;
1147 	}
1148 
1149 }
1150 
sofia_wait_for_reply(struct private_object * tech_pvt,nua_event_t event,uint32_t timeout)1151 void sofia_wait_for_reply(struct private_object *tech_pvt, nua_event_t event, uint32_t timeout)
1152 {
1153 	time_t exp = switch_epoch_time_now(NULL) + timeout;
1154 
1155 	tech_pvt->want_event = event;
1156 
1157 	while (switch_channel_ready(tech_pvt->channel) && tech_pvt->want_event && switch_epoch_time_now(NULL) < exp) {
1158 		switch_yield(100000);
1159 	}
1160 
1161 }
1162 
sofia_send_callee_id(switch_core_session_t * session,const char * name,const char * number)1163 void sofia_send_callee_id(switch_core_session_t *session, const char *name, const char *number)
1164 {
1165 	const char *uuid;
1166 	switch_core_session_t *session_b;
1167 	switch_channel_t *channel = switch_core_session_get_channel(session);
1168 	switch_caller_profile_t *caller_profile = switch_channel_get_caller_profile(channel);
1169 
1170 
1171 	if (switch_channel_inbound_display(channel)) {
1172 		if (zstr(name)) {
1173 			name = caller_profile->caller_id_name;
1174 		}
1175 
1176 		if (zstr(number)) {
1177 			number = caller_profile->caller_id_number;
1178 		}
1179 
1180 		if (zstr(name)) {
1181 			name = number;
1182 		}
1183 
1184 		if (zstr(number)) {
1185 			name = number = "UNKNOWN";
1186 		}
1187 
1188 		if (!zstr(name) && !strcmp(name,"_undef_")) {
1189 			name = "";
1190 		}
1191 	} else {
1192 		if (zstr(name)) {
1193 			name = caller_profile->callee_id_name;
1194 		}
1195 
1196 		if (zstr(number)) {
1197 			number = caller_profile->callee_id_number;
1198 		}
1199 
1200 		if (zstr(name)) {
1201 			name = number;
1202 		}
1203 
1204 		if (zstr(number)) {
1205 			number = caller_profile->destination_number;
1206 		}
1207 
1208 		if (!zstr(name) && !strcmp(name,"_undef_")) {
1209 			name = "";
1210 		}
1211 	}
1212 
1213 	if ((uuid = switch_channel_get_partner_uuid(channel)) && (session_b = switch_core_session_locate(uuid))) {
1214 		switch_core_session_message_t *msg;
1215 		//switch_channel_t *channel_b = switch_core_session_get_channel(session_b);
1216 
1217 		//switch_channel_set_profile_var(channel_b, "callee_id_name", name);
1218 		//switch_channel_set_profile_var(channel_b, "callee_id_number", number);
1219 
1220 		msg = switch_core_session_alloc(session_b, sizeof(*msg));
1221 		MESSAGE_STAMP_FFL(msg);
1222 		msg->message_id = SWITCH_MESSAGE_INDICATE_DISPLAY;
1223 		msg->string_array_arg[0] = switch_core_session_strdup(session_b, name);
1224 		msg->string_array_arg[1] = switch_core_session_strdup(session_b, number);
1225 		msg->from = __FILE__;
1226 		switch_core_session_queue_message(session_b, msg);
1227 		switch_core_session_rwunlock(session_b);
1228 	}
1229 }
1230 
sofia_update_callee_id(switch_core_session_t * session,sofia_profile_t * profile,sip_t const * sip,switch_bool_t send)1231 void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *profile, sip_t const *sip,
1232 							switch_bool_t send)
1233 {
1234 	switch_channel_t *channel = switch_core_session_get_channel(session);
1235 	sip_p_asserted_identity_t *passerted = NULL;
1236 	char *name = NULL;
1237 	const char *number = "unknown", *tmp;
1238 	switch_caller_profile_t *caller_profile;
1239 	char *dup = NULL;
1240 	switch_event_t *event;
1241 	const char *val;
1242 	int fs = 0, lazy = 0, att = 0;
1243 	const char *name_var = "callee_id_name";
1244 	const char *num_var = "callee_id_number";
1245 
1246 	if (switch_true(switch_channel_get_variable(channel, SWITCH_IGNORE_DISPLAY_UPDATES_VARIABLE)) || !sofia_test_pflag(profile, PFLAG_SEND_DISPLAY_UPDATE)) {
1247 		return;
1248 	}
1249 
1250 
1251 	if (switch_channel_inbound_display(channel)) {
1252 		name_var = "caller_id_name";
1253 		num_var = "caller_id_number";
1254 	}
1255 
1256 
1257 	number = (char *) switch_channel_get_variable(channel, num_var);
1258 	name = (char *) switch_channel_get_variable(channel, name_var);
1259 
1260 
1261 	if (zstr(number) && sip->sip_to) {
1262 		number = sip->sip_to->a_url->url_user;
1263 	}
1264 
1265 	if ((val = sofia_glue_get_unknown_header(sip, "X-FS-Display-Number"))) {
1266 		number = val;
1267 		fs++;
1268 	}
1269 
1270 	if ((val = sofia_glue_get_unknown_header(sip, "X-FS-Display-Name"))) {
1271 		name = (char *) val;
1272 		check_decode(name, session);
1273 		fs++;
1274 	}
1275 
1276 	if ((val = sofia_glue_get_unknown_header(sip, "X-FS-Lazy-Attended-Transfer"))) {
1277 		lazy = switch_true(val);
1278 		fs++;
1279 	}
1280 
1281 	if ((val = sofia_glue_get_unknown_header(sip, "X-FS-Attended-Transfer"))) {
1282 		att = switch_true(val);
1283 		fs++;
1284 	}
1285 
1286 	if (!fs) {
1287 		sip_remote_party_id_t *rpid;
1288 		if ((passerted = sip_p_asserted_identity(sip))) {
1289 			if (passerted->paid_url->url_user) {
1290 				number = passerted->paid_url->url_user;
1291 			}
1292 			if (!zstr(passerted->paid_display)) {
1293 				dup = strdup(passerted->paid_display);
1294 				switch_assert(dup);
1295 				if (*dup == '"') {
1296 					name = dup + 1;
1297 				} else {
1298 					name = dup;
1299 				}
1300 				if (end_of(name) == '"') {
1301 					end_of(name) = '\0';
1302 				}
1303 			}
1304 		} else if ((rpid = sip_remote_party_id(sip))) {
1305 			if (rpid->rpid_url->url_user) {
1306 				number = rpid->rpid_url->url_user;
1307 			}
1308 			if (!zstr(rpid->rpid_display)) {
1309 				dup = strdup(rpid->rpid_display);
1310 				switch_assert(dup);
1311 				if (*dup == '"') {
1312 					name = dup + 1;
1313 				} else {
1314 					name = dup;
1315 				}
1316 				if (end_of(name) == '"') {
1317 					end_of(name) = '\0';
1318 				}
1319 			}
1320 		}
1321 	}
1322 
1323 
1324 	if (zstr(number)) {
1325 		if ((tmp = switch_channel_get_variable(channel, num_var)) && !zstr(tmp)) {
1326 			number = (char *) tmp;
1327 		}
1328 
1329 		if (zstr(number)) {
1330 			number = "unknown";
1331 		}
1332 	}
1333 
1334 	if (zstr(name)) {
1335 		if ((tmp = switch_channel_get_variable(channel, name_var)) && !zstr(tmp)) {
1336 			name = (char *) tmp;
1337 		}
1338 	}
1339 
1340 	if (zstr(name)) {
1341 		name = (char *) number;
1342 	}
1343 
1344 	if (zstr(name) || zstr(number)) {
1345 		goto end;
1346 	}
1347 
1348 	caller_profile = switch_channel_get_caller_profile(channel);
1349 
1350 	if (switch_channel_inbound_display(channel)) {
1351 
1352 		if (!strcmp(caller_profile->caller_id_name, name) && !strcmp(caller_profile->caller_id_number, number)) {
1353 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s Same Caller ID \"%s\" <%s>\n", switch_channel_get_name(channel), name, number);
1354 			send = 0;
1355 		} else {
1356 			caller_profile->caller_id_name = switch_sanitize_number(switch_core_strdup(caller_profile->pool, name));
1357 			caller_profile->caller_id_number = switch_sanitize_number(switch_core_strdup(caller_profile->pool, number));
1358 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Update Caller ID to \"%s\" <%s>\n", switch_channel_get_name(channel), name, number);
1359 		}
1360 
1361 	} else {
1362 
1363 		if (!strcmp(caller_profile->callee_id_name, name) && !strcmp(caller_profile->callee_id_number, number)) {
1364 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "%s Same Callee ID \"%s\" <%s>\n", switch_channel_get_name(channel), name, number);
1365 			send = 0;
1366 		} else {
1367 			caller_profile->callee_id_name = switch_sanitize_number(switch_core_strdup(caller_profile->pool, name));
1368 			caller_profile->callee_id_number = switch_sanitize_number(switch_core_strdup(caller_profile->pool, number));
1369 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Update Callee ID to \"%s\" <%s>\n", switch_channel_get_name(channel), name, number);
1370 
1371 			if (lazy || (att && !switch_channel_get_partner_uuid(channel))) {
1372 				switch_channel_flip_cid(channel);
1373 			}
1374 		}
1375 	}
1376 
1377 	if (send) {
1378 
1379 		if (switch_event_create(&event, SWITCH_EVENT_CALL_UPDATE) == SWITCH_STATUS_SUCCESS) {
1380 			const char *uuid = switch_channel_get_partner_uuid(channel);
1381 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Direction", "RECV");
1382 			if (uuid) {
1383 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridged-To", uuid);
1384 			}
1385 			switch_channel_event_set_data(channel, event);
1386 			switch_event_fire(&event);
1387 		}
1388 
1389 		sofia_send_callee_id(session, NULL, NULL);
1390 	}
1391 
1392   end:
1393 	switch_safe_free(dup);
1394 }
1395 
tech_send_ack(nua_handle_t * nh,private_object_t * tech_pvt,const char * r_sdp)1396 static void tech_send_ack(nua_handle_t *nh, private_object_t *tech_pvt, const char *r_sdp)
1397 {
1398 	const char *invite_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_from");
1399 	const char *invite_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_to");
1400 	int soa = sofia_use_soa(tech_pvt);
1401 	const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
1402 
1403 	if (sofia_test_pflag(tech_pvt->profile, PFLAG_TRACK_CALLS)) {
1404 		const char *invite_full_via = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_via");
1405 		const char *invite_route_uri = switch_channel_get_variable(tech_pvt->channel, "sip_invite_route_uri");
1406 
1407 		nua_ack(nh,
1408 				TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)),
1409 				TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
1410 				TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
1411 				TAG_IF((zstr(tech_pvt->user_via) && !zstr(invite_full_via)), SIPTAG_VIA_STR(invite_full_via)),
1412 				TAG_IF(!zstr(invite_route_uri), SIPTAG_ROUTE_STR(invite_route_uri)),
1413 				TAG_IF(r_sdp && soa, SOATAG_USER_SDP_STR(r_sdp)),
1414 				TAG_IF(r_sdp && soa, SOATAG_REUSE_REJECTED(1)),
1415 				TAG_IF(r_sdp && soa, SOATAG_AUDIO_AUX("cn telephone-event")),
1416 				TAG_IF(r_sdp && !soa, SIPTAG_CONTENT_TYPE_STR("application/sdp")),
1417 				TAG_IF(r_sdp && !soa, SIPTAG_PAYLOAD_STR(r_sdp)),
1418 				TAG_IF(r_sdp && !soa, NUTAG_MEDIA_ENABLE(0)),
1419 				TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
1420 				TAG_END());
1421 	} else {
1422 		nua_ack(nh,
1423 				TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)),
1424 				TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
1425 				TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
1426 				TAG_IF(r_sdp && soa, SOATAG_USER_SDP_STR(r_sdp)),
1427 				TAG_IF(r_sdp && soa, SOATAG_REUSE_REJECTED(1)),
1428 				TAG_IF(r_sdp && soa, SOATAG_AUDIO_AUX("cn telephone-event")),
1429 				TAG_IF(r_sdp && !soa, SIPTAG_CONTENT_TYPE_STR("application/sdp")),
1430 				TAG_IF(r_sdp && !soa, SIPTAG_PAYLOAD_STR(r_sdp)),
1431 				TAG_IF(r_sdp && !soa, NUTAG_MEDIA_ENABLE(0)),
1432 				TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
1433 				TAG_END());
1434 	}
1435 
1436 }
1437 
notify_watched_header(switch_core_session_t * session,const char * msgline,const char * hdrname,const char * hdrval)1438 static void notify_watched_header(switch_core_session_t *session, const char *msgline, const char *hdrname, const char *hdrval)
1439 {
1440 	switch_event_t *event = NULL;
1441 	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Found known watched header in message '%s', %s: %s\n", msgline, hdrname, hdrval);
1442 	if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_NOTIFY_WATCHED_HEADER) == SWITCH_STATUS_SUCCESS) {
1443 		switch_channel_t *channel = switch_core_session_get_channel(session);
1444 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SIP-Message", msgline);
1445 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Header-Name", hdrname);
1446 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Header-Value", hdrval);
1447 		switch_channel_event_set_data(channel, event);
1448 		switch_event_fire(&event);
1449 	} else {
1450 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failed creating event of type %s!\n", MY_EVENT_NOTIFY_WATCHED_HEADER);
1451 	}
1452 }
1453 
1454 
sofia_handle_sip_r_refer(nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,switch_core_session_t * session,int status,const char * phrase,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])1455 static void sofia_handle_sip_r_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, switch_core_session_t *session, int status, const char *phrase, sip_t const *sip, sofia_dispatch_event_t *de, tagi_t tags[])
1456 {
1457 	private_object_t *tech_pvt = switch_core_session_get_private(session);
1458 	switch_core_session_t *other_session;
1459 	switch_channel_t *channel = switch_core_session_get_channel(session);
1460 
1461 	switch_channel_set_variable_printf(channel, "sip_refer_status_code", "%d", status);
1462 
1463 	if (status < 200) {
1464 		return;
1465 	}
1466 
1467 	if (tech_pvt->proxy_refer_uuid && (other_session = switch_core_session_locate(tech_pvt->proxy_refer_uuid))) {
1468 		switch_core_session_message_t *msg;
1469 
1470 		msg = switch_core_session_alloc(other_session, sizeof(*msg));
1471 		msg->message_id = SWITCH_MESSAGE_INDICATE_RESPOND;
1472 		msg->from = __FILE__;
1473 		msg->numeric_arg = status;
1474 		msg->string_arg = switch_core_session_strdup(other_session, phrase);
1475 		switch_core_session_queue_message(other_session, msg);
1476 		switch_core_session_rwunlock(other_session);
1477 	} else {
1478 		tech_pvt->proxy_refer_uuid = NULL;
1479 	}
1480 }
1481 
1482 
1483 
1484 
1485 //sofia_dispatch_event_t *de
our_sofia_event_callback(nua_event_t event,int status,char const * phrase,nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,sofia_private_t * sofia_private,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])1486 static void our_sofia_event_callback(nua_event_t event,
1487 						  int status,
1488 						  char const *phrase,
1489 						  nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
1490 								sofia_dispatch_event_t *de, tagi_t tags[])
1491 {
1492 	struct private_object *tech_pvt = NULL;
1493 	auth_res_t auth_res = AUTH_FORBIDDEN;
1494 	switch_core_session_t *session = NULL;
1495 	switch_channel_t *channel = NULL;
1496 	sofia_gateway_t *gateway = NULL;
1497 	int locked = 0;
1498 	int check_destroy = 1;
1499 
1500 	profile->last_sip_event = switch_time_now();
1501 
1502 	/* sofia_private will be == &mod_sofia_globals.keep_private whenever a request is done with a new handle that has to be
1503 	  freed whenever the request is done */
1504 	if (nh && sofia_private == &mod_sofia_globals.keep_private) {
1505 		if (status >= 300) {
1506 			nua_handle_bind(nh, NULL);
1507 			nua_handle_destroy(nh);
1508 			return;
1509 		}
1510 	}
1511 
1512 
1513 	if (sofia_private && sofia_private != &mod_sofia_globals.destroy_private && sofia_private != &mod_sofia_globals.keep_private) {
1514 		if (!zstr(sofia_private->gateway_name)) {
1515 			if (!(gateway = sofia_reg_find_gateway(sofia_private->gateway_name))) {
1516 				return;
1517 			}
1518 		} else if (!zstr(sofia_private->uuid)) {
1519 			if ((session = de->init_session)) {
1520 				de->init_session = NULL;
1521 			} else if ((session = de->session) || (session = switch_core_session_locate(sofia_private->uuid))) {
1522 				tech_pvt = switch_core_session_get_private(session);
1523 				channel = switch_core_session_get_channel(session);
1524 				if (tech_pvt) {
1525 					switch_mutex_lock(tech_pvt->sofia_mutex);
1526 					locked = 1;
1527 				} else {
1528 					if (session != de->session) switch_core_session_rwunlock(session);
1529 					return;
1530 				}
1531 
1532 				if (status >= 180 && !*sofia_private->auth_gateway_name) {
1533 					const char *gwname = switch_channel_get_variable(channel, "sip_use_gateway");
1534 					if (!zstr(gwname)) {
1535 						switch_set_string(sofia_private->auth_gateway_name, gwname);
1536 					}
1537 				}
1538 				if (!tech_pvt->call_id && sip && sip->sip_call_id && sip->sip_call_id->i_id) {
1539 					tech_pvt->call_id = switch_core_session_strdup(session, sip->sip_call_id->i_id);
1540 					switch_channel_set_variable(channel, "sip_call_id", tech_pvt->call_id);
1541 				}
1542 
1543 				if (tech_pvt->gateway_name) {
1544 					gateway = sofia_reg_find_gateway(tech_pvt->gateway_name);
1545 				}
1546 
1547 				if (channel && switch_channel_down(channel)) {
1548 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Channel is already hungup.\n");
1549 					goto done;
1550 				}
1551 			} else {
1552 				/* we can't find the session it must be hanging up or something else, its too late to do anything with it. */
1553 				return;
1554 			}
1555 		}
1556 	}
1557 
1558 	if (session && tech_pvt && tech_pvt->watch_headers && sip) {
1559 		char msgline[512];
1560 		int hi;
1561 		msg_header_t *h = NULL;
1562 		if (sip->sip_request) {
1563 			h = (msg_header_t *)sip->sip_request;
1564 			msg_header_field_e(msgline, sizeof(msgline), h, 0);
1565 		} else if (sip->sip_status) {
1566 			h = (msg_header_t *)sip->sip_status;
1567 			msg_header_field_e(msgline, sizeof(msgline), h, 0);
1568 		}
1569 		if (h) {
1570 			sip_unknown_t *un = NULL;
1571 			char buf[512];
1572 			char *c = NULL;
1573 
1574 			msgline[sizeof(msgline)-1] = '\0';
1575 			c = strchr(msgline, '\r');
1576 			if (c) {
1577 				*c = '\0';
1578 			}
1579 
1580 			/* Faster (ie hash-based) search here would be nice? ie, make watch_headers a hash? */
1581 
1582 			/* Search first in the valid headers */
1583 			for (h = h->sh_succ; h; h = h->sh_succ) {
1584 				sip_header_t *sh = (sip_header_t *)h;
1585 				if (!sh->sh_class->hc_name) {
1586 					continue;
1587 				}
1588 				for (hi = 0; tech_pvt->watch_headers[hi]; hi++) {
1589 					if (!strcasecmp(tech_pvt->watch_headers[hi], sh->sh_class->hc_name)) {
1590 						msg_header_field_e(buf, sizeof(buf), h, 0);
1591 						buf[sizeof(buf)-1] = '\0';
1592 						notify_watched_header(session, msgline, sh->sh_class->hc_name, buf);
1593 					}
1594 				}
1595 			}
1596 
1597 			/* Search now in the unknown headers */
1598 			for (un = sip->sip_unknown; un; un = un->un_next) {
1599 				for (hi = 0; tech_pvt->watch_headers[hi]; hi++) {
1600 					if (!strcasecmp(tech_pvt->watch_headers[hi], un->un_name)) {
1601 						notify_watched_header(session, msgline, un->un_name, un->un_value);
1602 					}
1603 				}
1604 			}
1605 		}
1606 	}
1607 
1608 	if (sofia_test_pflag(profile, PFLAG_AUTH_ALL) && tech_pvt && tech_pvt->key && sip && (event < nua_r_set_params || event > nua_r_authenticate)) {
1609 		sip_authorization_t const *authorization = NULL;
1610 
1611 		if (sip->sip_authorization) {
1612 			authorization = sip->sip_authorization;
1613 		} else if (sip->sip_proxy_authorization) {
1614 			authorization = sip->sip_proxy_authorization;
1615 		}
1616 
1617 		if (authorization) {
1618 			char network_ip[80];
1619 			int network_port;
1620 			sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
1621 			auth_res = sofia_reg_parse_auth(profile, authorization, sip, de,
1622 											(char *) sip->sip_request->rq_method_name, tech_pvt->key, strlen(tech_pvt->key), network_ip, network_port, NULL, 0,
1623 											REG_INVITE, NULL, NULL, NULL, NULL);
1624 		}
1625 
1626 		if ((auth_res != AUTH_OK && auth_res != AUTH_RENEWED)) {
1627 			//switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
1628 			nua_respond(nh, SIP_401_UNAUTHORIZED, TAG_END());
1629 			goto done;
1630 		}
1631 
1632 		if (channel) {
1633 			switch_channel_set_variable(channel, "sip_authorized", "true");
1634 		}
1635 	}
1636 
1637 	if (sip && (status == 401 || status == 407)) {
1638 		sofia_reg_handle_sip_r_challenge(status, phrase, nua, profile, nh, sofia_private, session, gateway, sip, de, tags);
1639 		goto done;
1640 	}
1641 
1642 	if (sip && sip->sip_payload && sip->sip_payload->pl_data) {
1643 		if (sip->sip_payload->pl_len != strlen(sip->sip_payload->pl_data)) {
1644 			sip->sip_payload->pl_data = su_strndup(nh->nh_home, sip->sip_payload->pl_data, sip->sip_payload->pl_len);
1645 		}
1646 	}
1647 
1648 	switch (event) {
1649 	case nua_r_get_params:
1650 	case nua_i_fork:
1651 	case nua_r_info:
1652 		break;
1653 	case nua_r_unregister:
1654 	case nua_r_unsubscribe:
1655 	case nua_i_terminated:
1656 	case nua_r_publish:
1657 	case nua_i_error:
1658 	case nua_i_active:
1659 	case nua_r_set_params:
1660 	case nua_i_prack:
1661 	case nua_r_prack:
1662 		break;
1663 
1664 	case nua_i_cancel:
1665 
1666 		if (sip && channel) {
1667 			switch_channel_set_variable(channel, "sip_hangup_disposition", "recv_cancel");
1668 			switch_channel_set_variable(channel, "sip_invite_failure_status", "487");
1669 			switch_channel_set_variable(channel, "sip_invite_failure_phrase", "CANCEL");
1670 
1671 			if (sip->sip_reason) {
1672 				char *reason_header = sip_header_as_string(nh->nh_home, (void *) sip->sip_reason);
1673 
1674 				if (!zstr(reason_header)) {
1675 					switch_channel_set_variable(channel, "sip_reason", reason_header);
1676 					switch_channel_set_variable_partner(channel, "sip_reason", reason_header);
1677 				}
1678 			}
1679 		}
1680 
1681 		break;
1682 	case nua_r_cancel:
1683 		{
1684 			if (status > 299 && nh) {
1685 				nua_handle_destroy(nh);
1686 			}
1687 		}
1688 		break;
1689 	case nua_i_ack:
1690 		{
1691 			if (channel && sip) {
1692 				const char *r_sdp = NULL;
1693 				sofia_glue_store_session_id(session, profile, sip, 0);
1694 
1695 				if (sip->sip_payload && sip->sip_payload->pl_data) {
1696 					if (sofia_test_flag(tech_pvt, TFLAG_PASS_ACK)) {
1697 						r_sdp = sip->sip_payload->pl_data;
1698 
1699 						if (tech_pvt->mparams.last_sdp_str) {
1700 							tech_pvt->mparams.prev_sdp_str = tech_pvt->mparams.last_sdp_str;
1701 						}
1702 						tech_pvt->mparams.last_sdp_str = NULL;
1703 
1704 
1705 						if (!zstr(tech_pvt->mparams.prev_sdp_str) && strcmp(tech_pvt->mparams.prev_sdp_str, sip->sip_payload->pl_data)) {
1706 							switch_channel_set_variable(channel, "sip_reinvite_sdp", sip->sip_payload->pl_data);
1707 							tech_pvt->mparams.last_sdp_str = switch_core_session_strdup(session, sip->sip_payload->pl_data);
1708 						} else {
1709 							tech_pvt->mparams.last_sdp_str = tech_pvt->mparams.prev_sdp_str;
1710 						}
1711 					} else {
1712 						switch_channel_set_variable(channel, "sip_reinvite_sdp", sip->sip_payload->pl_data);
1713 						tech_pvt->mparams.last_sdp_str = switch_core_session_strdup(session, sip->sip_payload->pl_data);
1714 					}
1715 				}
1716 
1717 				if (sip->sip_to && sip->sip_to->a_tag) {
1718 					switch_channel_set_variable(channel, "sip_to_tag", sip->sip_to->a_tag);
1719 				}
1720 
1721 				if (sip->sip_from && sip->sip_from->a_tag) {
1722 					switch_channel_set_variable(channel, "sip_from_tag", sip->sip_from->a_tag);
1723 				}
1724 
1725 				if (sip->sip_cseq && sip->sip_cseq->cs_seq) {
1726 					char sip_cseq[40] = "";
1727 					switch_snprintf(sip_cseq, sizeof(sip_cseq), "%d", sip->sip_cseq->cs_seq);
1728 					switch_channel_set_variable(channel, "sip_cseq", sip_cseq);
1729 				}
1730 
1731 				if (sip->sip_call_id && sip->sip_call_id->i_id) {
1732 					switch_channel_set_variable(channel, "sip_call_id", sip->sip_call_id->i_id);
1733 				}
1734 
1735 				extract_header_vars(profile, sip, session, nh);
1736 				switch_core_recovery_track(session);
1737 				sofia_set_flag(tech_pvt, TFLAG_GOT_ACK);
1738 
1739 				if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA) && r_sdp) {
1740 					if (sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY)) {
1741 						switch_channel_set_variable_partner(tech_pvt->channel, SWITCH_B_SDP_VARIABLE, r_sdp);
1742 
1743 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Got my ACK\n");
1744 						sofia_media_activate_rtp(tech_pvt);
1745 						switch_core_media_proxy_remote_addr(tech_pvt->session, r_sdp);
1746 						sofia_set_flag(tech_pvt, TFLAG_3PCC_HAS_ACK);
1747 						sofia_clear_flag(tech_pvt, TFLAG_PASS_ACK);
1748 
1749 					}
1750 
1751 				}
1752 
1753 
1754 				if (sofia_test_flag(tech_pvt, TFLAG_PASS_ACK)) {
1755 					switch_core_session_t *other_session;
1756 
1757 					sofia_clear_flag(tech_pvt, TFLAG_PASS_ACK);
1758 
1759 					if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
1760 						if (switch_core_session_compare(session, other_session)) {
1761 							private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
1762 							tech_send_ack(other_tech_pvt->nh, other_tech_pvt, r_sdp);
1763 						}
1764 						switch_core_session_rwunlock(other_session);
1765 					}
1766 
1767 				}
1768 
1769 
1770 			}
1771 		}
1772 	case nua_r_ack:
1773 		if (channel)
1774 			switch_channel_set_flag(channel, CF_MEDIA_ACK);
1775 		break;
1776 	case nua_r_shutdown:
1777 		if (status >= 200) {
1778 			sofia_set_pflag(profile, PFLAG_SHUTDOWN);
1779 			su_root_break(profile->s_root);
1780 		}
1781 		break;
1782 	case nua_r_message:
1783 		sofia_handle_sip_r_message(status, profile, nh, sip);
1784 		break;
1785 	case nua_r_invite:
1786 		sofia_handle_sip_r_invite(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
1787 		break;
1788 	case nua_r_options:
1789 		sofia_handle_sip_r_options(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
1790 		break;
1791 	case nua_i_bye:
1792 		sofia_handle_sip_i_bye(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
1793 		break;
1794 	case nua_r_bye:
1795 		sofia_handle_sip_r_bye(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
1796 		break;
1797 	case nua_r_notify:
1798 		if (session) {
1799 			sofia_handle_sip_r_notify(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
1800 		}
1801 		break;
1802 	case nua_i_notify:
1803 		sofia_handle_sip_i_notify(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
1804 		break;
1805 	case nua_r_register:
1806 		sofia_reg_handle_sip_r_register(status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
1807 		break;
1808 	case nua_i_options:
1809 		sofia_handle_sip_i_options(status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
1810 		break;
1811 	case nua_i_invite:
1812 		if (session && sofia_private) {
1813 			if (sofia_private->is_call > 1) {
1814 				sofia_handle_sip_i_reinvite(session, nua, profile, nh, sofia_private, sip, de, tags);
1815 			} else {
1816 				sofia_private->is_call++;
1817 				sofia_handle_sip_i_invite(session, nua, profile, nh, sofia_private, sip, de, tags);
1818 			}
1819 		}
1820 		break;
1821 	case nua_i_publish:
1822 		sofia_presence_handle_sip_i_publish(nua, profile, nh, sofia_private, sip, de, tags);
1823 		break;
1824 	case nua_i_register:
1825 		//nua_respond(nh, SIP_200_OK, SIPTAG_CONTACT(sip->sip_contact), NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
1826 		//nua_handle_destroy(nh);
1827 		sofia_reg_handle_sip_i_register(nua, profile, nh, &sofia_private, sip, de, tags);
1828 		break;
1829 	case nua_i_state:
1830 		sofia_handle_sip_i_state(session, status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
1831 		break;
1832 	case nua_i_message:
1833 		{
1834 			int handle_message = 1;
1835 			int proxy_message = sofia_test_pflag(profile, PFLAG_PROXY_MESSAGE);
1836 
1837 			if (!proxy_message && session) {
1838 				switch_channel_t *channel = switch_core_session_get_channel(session);
1839 				proxy_message = switch_channel_var_true(channel, "sip_proxy_message");
1840 			}
1841 
1842 			if (proxy_message) {
1843 				if (sofia_proxy_sip_i_message(nua, profile, nh, session, sip, de, tags) == SWITCH_STATUS_SUCCESS) {
1844 					handle_message = 0;
1845 				}
1846 			}
1847 
1848 			if (handle_message) {
1849 				sofia_presence_handle_sip_i_message(status, phrase, nua, profile, nh, session, sofia_private, sip, de, tags);
1850 			}
1851 		}
1852 		break;
1853 	case nua_i_info:
1854 		{
1855 			int handle_info = 1;
1856 			int proxy_info = sofia_test_pflag(profile, PFLAG_PROXY_INFO);
1857 
1858 			if (!proxy_info && session) {
1859 				switch_channel_t *channel = switch_core_session_get_channel(session);
1860 				proxy_info = switch_channel_var_true(channel, "sip_proxy_info");
1861 			}
1862 
1863 			if (proxy_info) {
1864 				if (sofia_proxy_sip_i_info(nua, profile, nh, session, sip, de, tags) == SWITCH_STATUS_SUCCESS) {
1865 					handle_info = 0;
1866 				}
1867 			}
1868 
1869 			if (handle_info) {
1870 				sofia_handle_sip_i_info(nua, profile, nh, session, sip, de, tags);
1871 			}
1872 
1873 		}
1874 		break;
1875 	case nua_i_update:
1876 		if (session) {
1877 			sofia_update_callee_id(session, profile, sip, SWITCH_TRUE);
1878 		}
1879 		break;
1880 	case nua_r_update:
1881 		if (session && tech_pvt && locked) {
1882 			sofia_clear_flag_locked(tech_pvt, TFLAG_UPDATING_DISPLAY);
1883 		}
1884 		break;
1885 	case nua_r_refer:
1886 		if (session) {
1887 			sofia_handle_sip_r_refer(nua, profile, nh, session, status, phrase, sip, de, tags);
1888 		}
1889 		break;
1890 	case nua_i_refer:
1891 		if (session) {
1892 			sofia_handle_sip_i_refer(nua, profile, nh, session, sip, de, tags);
1893 		} else if (sip) {
1894 			const char *req_user = NULL, *req_host = NULL, *action = NULL, *ref_by_user = NULL, *ref_to_user = NULL, *ref_to_host = NULL;
1895 			char *refer_to = NULL, *referred_by = NULL, *method = NULL, *full_url = NULL;
1896 			char *params = NULL, *iparams = NULL;
1897 			switch_event_t *event;
1898 			char *tmp;
1899 
1900 			if (sip->sip_refer_to) {
1901 				ref_to_user = sip->sip_refer_to->r_url->url_user;
1902 				ref_to_host = sip->sip_refer_to->r_url->url_host;
1903 
1904 				if (sip->sip_refer_to->r_url->url_params && switch_stristr("method=", sip->sip_refer_to->r_url->url_params)) {
1905 					params = su_strdup(nua_handle_home(nh), sip->sip_refer_to->r_url->url_params);
1906 				}
1907 
1908 
1909 				if ((refer_to = sip_header_as_string(nua_handle_home(nh), (void *) sip->sip_refer_to))) {
1910 					if ((iparams = strchr(refer_to, ';'))) {
1911 						*iparams++ = '\0';
1912 
1913 						if (!params || !switch_stristr("method=", params)) {
1914 							params = iparams;
1915 						}
1916 					}
1917 
1918 					if ((tmp = sofia_glue_get_url_from_contact(refer_to, 0))) {
1919 						refer_to = tmp;
1920 					}
1921 				}
1922 
1923 				if (params) {
1924 					method = switch_find_parameter(params, "method", NULL);
1925 					full_url = switch_find_parameter(params, "full_url", NULL);
1926 				}
1927 
1928 
1929 			}
1930 
1931 			if (!method) {
1932 				method = strdup("INVITE");
1933 				switch_assert(method);
1934 			}
1935 
1936 			if (!strcasecmp(method, "INVITE")) {
1937 				action = "call";
1938 			} else if (!strcasecmp(method, "BYE")) {
1939 				action = "end";
1940 			} else {
1941 				action = method;
1942 			}
1943 
1944 			if (sip->sip_referred_by) {
1945 				referred_by = sofia_glue_get_url_from_contact(sip_header_as_string(nua_handle_home(nh), (void *) sip->sip_referred_by), 0);
1946 				ref_by_user = sip->sip_referred_by->b_url->url_user;
1947 			} else if(sip->sip_to){
1948 				referred_by = sofia_glue_get_url_from_contact(sip_header_as_string(nua_handle_home(nh), (void *) sip->sip_to), 0);
1949 				ref_by_user = sip->sip_to->a_url->url_user;
1950 			}
1951 
1952 			if (sip->sip_to) {
1953 				req_user = sip->sip_to->a_url->url_user;
1954 				req_host = sip->sip_to->a_url->url_host;
1955 			}
1956 
1957 			if (switch_event_create(&event, SWITCH_EVENT_CALL_SETUP_REQ) == SWITCH_STATUS_SUCCESS) {
1958 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Requesting-Component", "mod_sofia");
1959 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Target-Component", req_user);
1960 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Target-Domain", req_host);
1961 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Request-Action", action);
1962 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Request-Target", "sofia/%s/%s", profile->name, refer_to);
1963 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Request-Target-URI", "%s", refer_to);
1964 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Request-Target-Extension", ref_to_user);
1965 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Request-Target-Domain", ref_to_host);
1966 				if (switch_true(full_url)) {
1967 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "full_url", "true");
1968 				}
1969 
1970 				if (sip->sip_call_id && sip->sip_call_id->i_id) {
1971 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Request-Call-ID", sip->sip_call_id->i_id);
1972 				}
1973 
1974 				if (!zstr(referred_by)) {
1975 					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Request-Sender", "sofia/%s/%s", profile->name, referred_by);
1976 				}
1977 
1978 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "var_origination_caller_id_number", ref_by_user);
1979 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "var_origination_caller_id_name", ref_by_user);
1980 				switch_event_fire(&event);
1981 			}
1982 
1983 
1984 
1985 			{
1986 				char *sql;
1987 				sofia_nat_parse_t np = { { 0 } };
1988 				char *contact_str;
1989 				char *proto = "sip", *orig_proto = "sip";
1990 				const char *call_id, *full_from, *full_to, *full_via, *from_user = NULL, *from_host = NULL, *to_user, *to_host, *full_agent;
1991 				char to_tag[13] = "";
1992 				char *event_str = "refer";
1993 				sip_accept_t *ap = sip->sip_accept;
1994 				char accept_header[256] = "";
1995 
1996 				np.fs_path = 1;
1997 				contact_str = sofia_glue_gen_contact_str(profile, sip, nh, de, &np);
1998 
1999 				call_id = sip->sip_call_id ? sip->sip_call_id->i_id : "";
2000 				full_from = sip_header_as_string(nh->nh_home, (void *) sip->sip_from);
2001 				full_to = sip_header_as_string(nh->nh_home, (void *) sip->sip_to);
2002 				full_via = sip_header_as_string(nh->nh_home, (void *) sip->sip_via);
2003 
2004 				full_agent = sip_header_as_string(nh->nh_home, (void *) sip->sip_user_agent);
2005 
2006 				switch_stun_random_string(to_tag, 12, NULL);
2007 
2008 				if (sip->sip_from) {
2009 					from_user = sip->sip_from->a_url->url_user;
2010 					from_host = sip->sip_from->a_url->url_host;
2011 				} else {
2012 					from_user = "n/a";
2013 					from_host = "n/a";
2014 				}
2015 
2016 				if (sip->sip_to) {
2017 					to_user = sip->sip_to->a_url->url_user;
2018 					to_host = sip->sip_to->a_url->url_host;
2019 				} else {
2020 					to_user = "n/a";
2021 					to_host = "n/a";
2022 				}
2023 
2024 				while (ap) {
2025 					switch_snprintf(accept_header + strlen(accept_header), sizeof(accept_header) - strlen(accept_header),
2026 									"%s%s ", ap->ac_type, ap->ac_next ? "," : "");
2027 					ap = ap->ac_next;
2028 				}
2029 
2030 				sql = switch_mprintf("insert into sip_subscriptions "
2031 									 "(proto,sip_user,sip_host,sub_to_user,sub_to_host,presence_hosts,event,contact,call_id,full_from,"
2032 									 "full_via,expires,user_agent,accept,profile_name,hostname,network_port,network_ip,version,orig_proto, full_to) "
2033 									 "values ('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld,'%q','%q','%q','%q','%d','%q',-1,'%q','%q;tag=%q')",
2034 									 proto, from_user, from_host, to_user, to_host, profile->presence_hosts ? profile->presence_hosts : "",
2035 									 event_str, contact_str, call_id, full_from, full_via,
2036 									 (long) switch_epoch_time_now(NULL) + 60,
2037 									 full_agent, accept_header, profile->name, mod_sofia_globals.hostname,
2038 									 np.network_port, np.network_ip, orig_proto, full_to, to_tag);
2039 
2040 				switch_assert(sql != NULL);
2041 
2042 
2043 				if (mod_sofia_globals.debug_presence > 0 || mod_sofia_globals.debug_sla > 0) {
2044 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "%s REFER SUBSCRIBE %s@%s %s@%s\n%s\n",
2045 									  profile->name, from_user, from_host, to_user, to_host, sql);
2046 				}
2047 
2048 
2049 				sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
2050 
2051 				sip_to_tag(nh->nh_home, sip->sip_to, to_tag);
2052 			}
2053 
2054 			nua_respond(nh, SIP_202_ACCEPTED, SIPTAG_TO(sip->sip_to), NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
2055 			switch_safe_free(method);
2056 			switch_safe_free(full_url);
2057 
2058 		}
2059 		break;
2060 	case nua_r_subscribe:
2061 		sofia_presence_handle_sip_r_subscribe(status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
2062 		break;
2063 	case nua_i_subscribe:
2064 		sofia_presence_handle_sip_i_subscribe(status, phrase, nua, profile, nh, sofia_private, sip, de, tags);
2065 		break;
2066 	case nua_i_media_error:
2067 		{
2068 
2069 			if (sofia_private && sofia_private->call_id && sofia_private->network_ip && sofia_private->network_port) {
2070 				char *sql;
2071 				switch_event_t *event = NULL;
2072 
2073 				sql = switch_mprintf("delete from sip_registrations where call_id='%q' and network_ip='%q' and network_port='%q'",
2074 										   sofia_private->call_id, sofia_private->network_ip, sofia_private->network_port);
2075 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "SOCKET DISCONNECT: %s %s:%s\n",
2076 								  sofia_private->call_id, sofia_private->network_ip, sofia_private->network_port);
2077 				sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
2078 
2079 				switch_core_del_registration(sofia_private->user, sofia_private->realm, sofia_private->call_id);
2080 
2081 
2082 
2083 				if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
2084 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
2085 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "unknown");
2086 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
2087 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "user-agent",
2088 												   (sip && sip->sip_user_agent) ? sip->sip_user_agent->g_string : "unknown");
2089 					switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", sofia_private->user, sofia_private->realm);
2090 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "Unregistered");
2091 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-source", "register");
2092 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
2093 					switch_event_fire(&event);
2094 				}
2095 
2096 
2097 				if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_UNREGISTER) == SWITCH_STATUS_SUCCESS) {
2098 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
2099 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from-user", sofia_private->user);
2100 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from-host", sofia_private->realm);
2101 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-id", sofia_private->call_id);
2102 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", "unknown");
2103 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "reason", "socket-disconnection");
2104 					switch_event_fire(&event);
2105 				}
2106 
2107 
2108 				sofia_reg_check_socket(profile, sofia_private->call_id, sofia_private->network_ip, sofia_private->network_port);
2109 			        nua_handle_destroy(nh);
2110 			}
2111 		}
2112 		break;
2113 	case nua_r_authenticate:
2114 
2115 		if (status >= 500) {
2116 			if (sofia_private && !zstr(sofia_private->gateway_name)) {
2117 				sofia_gateway_t *gateway = NULL;
2118 
2119 				if ((gateway = sofia_reg_find_gateway(sofia_private->gateway_name))) {
2120 					gateway->state = REG_STATE_FAILED;
2121 					gateway->failure_status = status;
2122 					sofia_reg_release_gateway(gateway);
2123 				}
2124 			} else {
2125 				nua_handle_destroy(nh);
2126 			}
2127 		}
2128 
2129 		break;
2130 	default:
2131 		if (status > 100) {
2132 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s: unknown event %d: %03d %s\n", nua_event_name(event), event,
2133 							  status, phrase);
2134 		} else {
2135 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s: unknown event %d\n", nua_event_name(event), event);
2136 		}
2137 		break;
2138 	}
2139 
2140   done:
2141 
2142 	if (tech_pvt && tech_pvt->want_event && event == tech_pvt->want_event) {
2143 		tech_pvt->want_event = 0;
2144 	}
2145 
2146 	if (sofia_private && sofia_private->call_id) {
2147 		check_destroy = 0;
2148 	}
2149 
2150 	switch (event) {
2151 	case nua_i_subscribe:
2152 	case nua_r_notify:
2153 		check_destroy = 0;
2154 		break;
2155 
2156 	case nua_i_notify:
2157 
2158 		if (sip && sip->sip_event && !strcmp(sip->sip_event->o_type, "dialog") && sip->sip_event->o_params && !strcmp(sip->sip_event->o_params[0], "sla")) {
2159 			check_destroy = 0;
2160 		}
2161 
2162 		break;
2163 	default:
2164 		break;
2165 	}
2166 
2167 	if ((sofia_private && sofia_private == &mod_sofia_globals.destroy_private)) {
2168 		nua_handle_bind(nh, NULL);
2169 		nua_handle_destroy(nh);
2170 		nh = NULL;
2171 	}
2172 
2173 	if (check_destroy) {
2174 		if (nh && ((sofia_private && sofia_private->destroy_nh) || !nua_handle_magic(nh))) {
2175 			if (sofia_private) {
2176 				nua_handle_bind(nh, NULL);
2177 			}
2178 
2179 			if (tech_pvt && (tech_pvt->nh == nh)) {
2180 				tech_pvt->nh = NULL;
2181 			}
2182 
2183 			nua_handle_destroy(nh);
2184 			nh = NULL;
2185 		}
2186 	}
2187 
2188 	if (sofia_private && sofia_private->destroy_me) {
2189 		if (tech_pvt) {
2190 			tech_pvt->sofia_private = NULL;
2191 		}
2192 
2193 		if (nh) {
2194 			nua_handle_bind(nh, NULL);
2195 		}
2196 		sofia_private->destroy_me = 12;
2197 		sofia_private_free(sofia_private);
2198 
2199 	}
2200 
2201 	if (gateway) {
2202 		sofia_reg_release_gateway(gateway);
2203 	}
2204 
2205 	if (locked && tech_pvt) {
2206 		switch_mutex_unlock(tech_pvt->sofia_mutex);
2207 	}
2208 
2209 	if (session && session != de->session) {
2210 		switch_core_session_rwunlock(session);
2211 	}
2212 }
2213 
2214 static uint32_t DE_THREAD_CNT = 0;
2215 
sofia_msg_thread_run_once(switch_thread_t * thread,void * obj)2216 void *SWITCH_THREAD_FUNC sofia_msg_thread_run_once(switch_thread_t *thread, void *obj)
2217 {
2218 	sofia_dispatch_event_t *de = (sofia_dispatch_event_t *) obj;
2219 	switch_memory_pool_t *pool = NULL;
2220 
2221 	switch_mutex_lock(mod_sofia_globals.mutex);
2222 	DE_THREAD_CNT++;
2223 	switch_mutex_unlock(mod_sofia_globals.mutex);
2224 
2225 	if (de) {
2226 		pool = de->pool;
2227 		de->pool = NULL;
2228 		sofia_process_dispatch_event(&de);
2229 	}
2230 
2231 	if (pool) {
2232 		switch_core_destroy_memory_pool(&pool);
2233 	}
2234 
2235 	switch_mutex_lock(mod_sofia_globals.mutex);
2236 	DE_THREAD_CNT--;
2237 	switch_mutex_unlock(mod_sofia_globals.mutex);
2238 
2239 	return NULL;
2240 }
2241 
sofia_process_dispatch_event_in_thread(sofia_dispatch_event_t ** dep)2242 void sofia_process_dispatch_event_in_thread(sofia_dispatch_event_t **dep)
2243 {
2244 	sofia_dispatch_event_t *de = *dep;
2245 	switch_memory_pool_t *pool;
2246 	//sofia_profile_t *profile = (*dep)->profile;
2247 	switch_thread_data_t *td;
2248 
2249 	switch_core_new_memory_pool(&pool);
2250 
2251 	*dep = NULL;
2252 	de->pool = pool;
2253 
2254 	td = switch_core_alloc(pool, sizeof(*td));
2255 	td->func = sofia_msg_thread_run_once;
2256 	td->obj = de;
2257 
2258 	switch_thread_pool_launch_thread(&td);
2259 }
2260 
sofia_process_dispatch_event(sofia_dispatch_event_t ** dep)2261 void sofia_process_dispatch_event(sofia_dispatch_event_t **dep)
2262 {
2263 	sofia_dispatch_event_t *de = *dep;
2264 	nua_handle_t *nh = de->nh;
2265 	nua_t *nua = de->nua;
2266 	sofia_profile_t *profile = de->profile;
2267 	sofia_private_t *sofia_private = nua_handle_magic(de->nh);
2268 	*dep = NULL;
2269 
2270 	our_sofia_event_callback(de->data->e_event, de->data->e_status, de->data->e_phrase, de->nua, de->profile,
2271 							 de->nh, sofia_private, de->sip, de, (tagi_t *) de->data->e_tags);
2272 
2273 	nua_destroy_event(de->event);
2274 	su_free(nh->nh_home, de);
2275 
2276 	switch_mutex_lock(profile->flag_mutex);
2277 	profile->queued_events--;
2278 	switch_mutex_unlock(profile->flag_mutex);
2279 
2280 	nua_handle_unref(nh);
2281 	nua_stack_unref(nua);
2282 }
2283 
2284 
2285 
2286 static int msg_queue_threads = 0;
2287 //static int count = 0;
2288 
sofia_msg_thread_run(switch_thread_t * thread,void * obj)2289 void *SWITCH_THREAD_FUNC sofia_msg_thread_run(switch_thread_t *thread, void *obj)
2290 {
2291 	void *pop;
2292 	switch_queue_t *q = (switch_queue_t *) obj;
2293 	int my_id;
2294 
2295 
2296 	for (my_id = 0; my_id < mod_sofia_globals.msg_queue_len; my_id++) {
2297 		if (mod_sofia_globals.msg_queue_thread[my_id] == thread) {
2298 			break;
2299 		}
2300 	}
2301 
2302 	switch_mutex_lock(mod_sofia_globals.mutex);
2303 	msg_queue_threads++;
2304 	switch_mutex_unlock(mod_sofia_globals.mutex);
2305 
2306 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "MSG Thread %d Started\n", my_id);
2307 
2308 
2309 	for(;;) {
2310 
2311 		if (switch_queue_pop(q, &pop) != SWITCH_STATUS_SUCCESS) {
2312 			switch_cond_next();
2313 			continue;
2314 		}
2315 
2316 		if (pop) {
2317 			sofia_dispatch_event_t *de = (sofia_dispatch_event_t *) pop;
2318 			sofia_process_dispatch_event(&de);
2319 		} else {
2320 			break;
2321 		}
2322 	}
2323 
2324 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "MSG Thread Ended\n");
2325 
2326 	switch_mutex_lock(mod_sofia_globals.mutex);
2327 	msg_queue_threads--;
2328 	switch_mutex_unlock(mod_sofia_globals.mutex);
2329 
2330 	return NULL;
2331 }
2332 
sofia_msg_thread_start(int idx)2333 void sofia_msg_thread_start(int idx)
2334 {
2335 
2336 	if (idx >= mod_sofia_globals.max_msg_queues ||
2337 		idx >= SOFIA_MAX_MSG_QUEUE || (idx < mod_sofia_globals.msg_queue_len && mod_sofia_globals.msg_queue_thread[idx])) {
2338 		return;
2339 	}
2340 
2341 	switch_mutex_lock(mod_sofia_globals.mutex);
2342 
2343 	if (idx >= mod_sofia_globals.msg_queue_len) {
2344 		int i;
2345 		mod_sofia_globals.msg_queue_len = idx + 1;
2346 
2347 		for (i = 0; i < mod_sofia_globals.msg_queue_len; i++) {
2348 			if (!mod_sofia_globals.msg_queue_thread[i]) {
2349 				switch_threadattr_t *thd_attr = NULL;
2350 
2351 				switch_threadattr_create(&thd_attr, mod_sofia_globals.pool);
2352 				switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
2353 				//switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME);
2354 				switch_thread_create(&mod_sofia_globals.msg_queue_thread[i],
2355 									 thd_attr,
2356 									 sofia_msg_thread_run,
2357 									 mod_sofia_globals.msg_queue,
2358 									 mod_sofia_globals.pool);
2359 			}
2360 		}
2361 	}
2362 
2363 	switch_mutex_unlock(mod_sofia_globals.mutex);
2364 }
2365 
2366 //static int foo = 0;
sofia_queue_message(sofia_dispatch_event_t * de)2367 void sofia_queue_message(sofia_dispatch_event_t *de)
2368 {
2369 	int launch = 0;
2370 
2371 	if (mod_sofia_globals.running == 0 || !mod_sofia_globals.msg_queue) {
2372 		sofia_process_dispatch_event(&de);
2373 		return;
2374 	}
2375 
2376 
2377 	if (de->profile && sofia_test_pflag(de->profile, PFLAG_THREAD_PER_REG) &&
2378 		de->data->e_event == nua_i_register && DE_THREAD_CNT < mod_sofia_globals.max_reg_threads) {
2379 		sofia_process_dispatch_event_in_thread(&de);
2380 		return;
2381 	}
2382 
2383 
2384 	if ((switch_queue_size(mod_sofia_globals.msg_queue) > (SOFIA_MSG_QUEUE_SIZE * (unsigned int)msg_queue_threads))) {
2385 		launch++;
2386 	}
2387 
2388 
2389 	if (launch) {
2390 		if (mod_sofia_globals.msg_queue_len < mod_sofia_globals.max_msg_queues) {
2391 			sofia_msg_thread_start(mod_sofia_globals.msg_queue_len + 1);
2392 		}
2393 	}
2394 
2395 	switch_queue_push(mod_sofia_globals.msg_queue, de);
2396 }
2397 
set_call_id(private_object_t * tech_pvt,sip_t const * sip)2398 static void set_call_id(private_object_t *tech_pvt, sip_t const *sip)
2399 {
2400 	if (!tech_pvt->call_id && tech_pvt->session && tech_pvt->channel && sip && sip->sip_call_id && sip->sip_call_id->i_id) {
2401 		tech_pvt->call_id = switch_core_session_strdup(tech_pvt->session, sip->sip_call_id->i_id);
2402 		switch_channel_set_variable(tech_pvt->channel, "sip_call_id", tech_pvt->call_id);
2403 	}
2404 }
2405 
2406 
sofia_event_callback(nua_event_t event,int status,char const * phrase,nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,sofia_private_t * sofia_private,sip_t const * sip,tagi_t tags[])2407 void sofia_event_callback(nua_event_t event,
2408 						  int status,
2409 						  char const *phrase,
2410 						  nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
2411 						  tagi_t tags[])
2412 {
2413 	sofia_dispatch_event_t *de;
2414 	int critical = (((SOFIA_MSG_QUEUE_SIZE * mod_sofia_globals.max_msg_queues) * 900) / 1000);
2415 	uint32_t sess_count = switch_core_session_count();
2416 	uint32_t sess_max = switch_core_session_limit(0);
2417 
2418 	switch(event) {
2419 	case nua_i_terminated:
2420 		if ((status == 401 || status == 407 || status == 403) && sofia_private) {
2421 			switch_core_session_t *session;
2422 
2423 			if ((session = switch_core_session_locate(sofia_private->uuid))) {
2424 				switch_channel_t *channel = switch_core_session_get_channel(session);
2425 				int end = 0;
2426 
2427 				if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND && !switch_channel_test_flag(channel, CF_ANSWERED)) {
2428 					private_object_t *tech_pvt = switch_core_session_get_private(session);
2429 
2430 					if (status == 403) {
2431 						switch_channel_set_flag(channel, CF_NO_CDR);
2432 						switch_channel_hangup(channel, SWITCH_CAUSE_CALL_REJECTED);
2433 					} else {
2434 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "detaching session %s\n", sofia_private->uuid);
2435 
2436 						if (!zstr(tech_pvt->call_id)) {
2437 							tech_pvt->sofia_private = NULL;
2438 							tech_pvt->nh = NULL;
2439 							sofia_set_flag(tech_pvt, TFLAG_BYE);
2440 							switch_mutex_lock(profile->flag_mutex);
2441 							switch_core_hash_insert_auto_free(profile->chat_hash, tech_pvt->call_id, strdup(switch_core_session_get_uuid(session)));
2442 							switch_mutex_unlock(profile->flag_mutex);
2443 							nua_handle_destroy(nh);
2444 						} else {
2445 							switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
2446 						}
2447 					}
2448 					end++;
2449 				}
2450 
2451 				switch_core_session_rwunlock(session);
2452 
2453 				if (end) {
2454 					goto end;
2455 				}
2456 			}
2457 		}
2458 		break;
2459 	case nua_i_invite:
2460 	case nua_i_register:
2461 	case nua_i_options:
2462 	case nua_i_notify:
2463 	case nua_i_info:
2464 
2465 
2466 		if (event == nua_i_invite) {
2467 			if (sip->sip_session_expires && profile->minimum_session_expires) {
2468 				if (sip->sip_session_expires->x_delta < profile->minimum_session_expires) {
2469 					char buf[64] = "";
2470 					switch_snprintf(buf, sizeof(buf), "Min-SE: %d", profile->minimum_session_expires);
2471 					nua_respond(nh, SIP_422_SESSION_TIMER_TOO_SMALL, SIPTAG_HEADER_STR(buf),TAG_END());
2472 					goto end;
2473 				}
2474 			}
2475 		}
2476 
2477 		if (!sofia_private) {
2478 			if (sess_count >= sess_max || !sofia_test_pflag(profile, PFLAG_RUNNING) || !switch_core_ready_inbound()) {
2479 				nua_respond(nh, 503, "Maximum Calls In Progress", SIPTAG_RETRY_AFTER_STR("300"), NUTAG_WITH_THIS(nua), TAG_END());
2480 				goto end;
2481 			}
2482 
2483 
2484 			if (switch_queue_size(mod_sofia_globals.msg_queue) > (unsigned int)critical) {
2485 				nua_respond(nh, 503, "System Busy", SIPTAG_RETRY_AFTER_STR("300"), NUTAG_WITH_THIS(nua), TAG_END());
2486 				goto end;
2487 			}
2488 
2489 			if (sofia_test_pflag(profile, PFLAG_STANDBY)) {
2490 				nua_respond(nh, 503, "System Paused", NUTAG_WITH_THIS(nua), TAG_END());
2491 				goto end;
2492 			}
2493 		}
2494 
2495 		break;
2496 
2497 	default:
2498 		break;
2499 
2500 	}
2501 
2502 	switch_mutex_lock(profile->flag_mutex);
2503 	profile->queued_events++;
2504 	switch_mutex_unlock(profile->flag_mutex);
2505 
2506 	de = su_alloc(nh->nh_home, sizeof(*de));
2507 	memset(de, 0, sizeof(*de));
2508 	nua_save_event(nua, de->event);
2509 	de->nh = nua_handle_ref(nh);
2510 	de->data = nua_event_data(de->event);
2511 	de->sip = sip_object(de->data->e_msg);
2512 	de->profile = profile;
2513 	de->nua = nua_stack_ref(nua);
2514 
2515 	if (event == nua_i_invite && !sofia_private) {
2516 		switch_core_session_t *session;
2517 		private_object_t *tech_pvt = NULL;
2518 
2519 		if (!(sofia_private = su_alloc(nh->nh_home, sizeof(*sofia_private)))) {
2520 			abort();
2521 		}
2522 
2523 		memset(sofia_private, 0, sizeof(*sofia_private));
2524 		sofia_private->is_call++;
2525 		sofia_private->is_static++;
2526 		nua_handle_bind(nh, sofia_private);
2527 
2528 
2529 		if (sip->sip_call_id && sip->sip_call_id->i_id) {
2530 			char *uuid = NULL, *tmp;
2531 
2532 			switch_mutex_lock(profile->flag_mutex);
2533 			if ((tmp = (char *) switch_core_hash_find(profile->chat_hash, sip->sip_call_id->i_id))) {
2534 				uuid = strdup(tmp);
2535 				switch_core_hash_delete(profile->chat_hash, sip->sip_call_id->i_id);
2536 			}
2537 			switch_mutex_unlock(profile->flag_mutex);
2538 
2539 			if (uuid) {
2540 				if ((session = switch_core_session_locate(uuid))) {
2541 					tech_pvt = switch_core_session_get_private(session);
2542 					switch_copy_string(sofia_private->uuid_str, switch_core_session_get_uuid(session), sizeof(sofia_private->uuid_str));
2543 					sofia_private->uuid = sofia_private->uuid_str;
2544 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Re-attaching to session %s\n", sofia_private->uuid);
2545 					de->init_session = session;
2546 					sofia_clear_flag(tech_pvt, TFLAG_BYE);
2547 					tech_pvt->sofia_private = NULL;
2548 					tech_pvt->nh = NULL;
2549 					switch_core_session_queue_signal_data(session, de);
2550 					switch_core_session_rwunlock(session);
2551 					session = NULL;
2552 					free(uuid);
2553 					uuid = NULL;
2554 					goto end;
2555 				} else {
2556 					free(uuid);
2557 					uuid = NULL;
2558 					sip = NULL;
2559 				}
2560 			}
2561 		}
2562 
2563 		if (!sip || !sip->sip_call_id || zstr(sip->sip_call_id->i_id)) {
2564 			nua_respond(nh, 503, "INVALID INVITE", TAG_END());
2565 			nua_destroy_event(de->event);
2566 			su_free(nh->nh_home, de);
2567 
2568 			switch_mutex_lock(profile->flag_mutex);
2569 			profile->queued_events--;
2570 			switch_mutex_unlock(profile->flag_mutex);
2571 
2572 			nua_handle_unref(nh);
2573 			nua_stack_unref(nua);
2574 
2575 			goto end;
2576 		}
2577 
2578 		if (sofia_test_pflag(profile, PFLAG_CALLID_AS_UUID)) {
2579 			session = switch_core_session_request_uuid(sofia_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL, sip->sip_call_id->i_id);
2580 		} else {
2581 			session = switch_core_session_request(sofia_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL);
2582 		}
2583 
2584 		if (session) {
2585 			const char *channel_name = NULL;
2586 			tech_pvt = sofia_glue_new_pvt(session);
2587 
2588 			if (sip->sip_from) {
2589 				channel_name = url_set_chanvars(session, sip->sip_from->a_url, sip_from);
2590 			}
2591 			if (!channel_name && sip->sip_contact) {
2592 				channel_name = url_set_chanvars(session, sip->sip_contact->m_url, sip_contact);
2593 			}
2594 			if (sip->sip_referred_by) {
2595 				channel_name = url_set_chanvars(session, sip->sip_referred_by->b_url, sip_referred_by);
2596 			}
2597 
2598 			sofia_glue_attach_private(session, profile, tech_pvt, channel_name);
2599 
2600 			set_call_id(tech_pvt, sip);
2601 		} else {
2602 			nua_respond(nh, 503, "Maximum Calls In Progress", SIPTAG_RETRY_AFTER_STR("300"), TAG_END());
2603 			nua_destroy_event(de->event);
2604 			su_free(nh->nh_home, de);
2605 
2606 			switch_mutex_lock(profile->flag_mutex);
2607 			profile->queued_events--;
2608 			switch_mutex_unlock(profile->flag_mutex);
2609 
2610 			nua_handle_unref(nh);
2611 			nua_stack_unref(nua);
2612 
2613 			goto end;
2614 		}
2615 
2616 
2617 		if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
2618 			char *uuid;
2619 
2620 			if (!switch_core_session_running(session) && !switch_core_session_started(session)) {
2621 				nua_handle_bind(nh, NULL);
2622 				sofia_private_free(sofia_private);
2623 				switch_core_session_destroy(&session);
2624 				nua_respond(nh, 503, "Maximum Calls In Progress", SIPTAG_RETRY_AFTER_STR("300"), TAG_END());
2625 			}
2626 			switch_mutex_lock(profile->flag_mutex);
2627 			if ((uuid = switch_core_hash_find(profile->chat_hash, tech_pvt->call_id))) {
2628 				free(uuid);
2629 				uuid = NULL;
2630 				switch_core_hash_delete(profile->chat_hash, tech_pvt->call_id);
2631 			}
2632 			switch_mutex_unlock(profile->flag_mutex);
2633 
2634 			goto end;
2635 		}
2636 
2637 		switch_copy_string(sofia_private->uuid_str, switch_core_session_get_uuid(session), sizeof(sofia_private->uuid_str));
2638 		sofia_private->uuid = sofia_private->uuid_str;
2639 
2640 		de->init_session = session;
2641 		switch_core_session_queue_signal_data(session, de);
2642 		goto end;
2643 	}
2644 
2645 	if (sofia_private && sofia_private != &mod_sofia_globals.destroy_private && sofia_private != &mod_sofia_globals.keep_private) {
2646 		switch_core_session_t *session;
2647 
2648 		if ((session = switch_core_session_locate(sofia_private->uuid))) {
2649 			switch_core_session_queue_signal_data(session, de);
2650 			switch_core_session_rwunlock(session);
2651 			goto end;
2652 		}
2653 	}
2654 
2655 	sofia_queue_message(de);
2656 
2657  end:
2658 	//switch_cond_next();
2659 
2660 	return;
2661 }
2662 
2663 
event_handler(switch_event_t * event)2664 void event_handler(switch_event_t *event)
2665 {
2666 	char *subclass, *sql;
2667 	char *class;
2668 	switch_event_t *pevent;
2669 
2670 	/* Get Original Event Name */
2671 	class = switch_event_get_header_nil(event, "orig-event-name");
2672 	if (!strcasecmp(class, "PRESENCE_IN")) {
2673 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "\nGot Presence IN event via MultiCast\n");
2674 		if (switch_event_create(&pevent, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
2675 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "alt_event_type", switch_event_get_header_nil(event, "orig-alt_event_type"));
2676 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "answer-state", switch_event_get_header_nil(event, "orig-answer-state"));
2677 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "astate", switch_event_get_header_nil(event, "orig-astate"));
2678 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "call-direction", switch_event_get_header_nil(event, "orig-call-direction"));
2679 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "Caller-Callee-ID-Number", switch_event_get_header_nil(event, "Orig-Caller-Callee-ID-Number"));
2680 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "Caller-Caller-ID-Name", switch_event_get_header_nil(event, "Orig-Caller-Caller-ID-Name"));
2681 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "Caller-Caller-ID-Number", switch_event_get_header_nil(event, "Orig-Caller-Caller-ID-Number"));
2682 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "Caller-Destination-Number", switch_event_get_header_nil(event, "Orig-Caller-Destination-Number"));
2683 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "Caller-Direction", switch_event_get_header_nil(event, "Orig-Caller-Direction"));
2684 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "Caller-Username", switch_event_get_header_nil(event, "Orig-Caller-Username"));
2685 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "channel-state", switch_event_get_header_nil(event, "orig-channel-state"));
2686 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "force-status", switch_event_get_header_nil(event, "orig-force-status"));
2687 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "from", switch_event_get_header_nil(event, "orig-from"));
2688 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "login", switch_event_get_header_nil(event, "orig-login"));
2689 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "Other-Leg-Caller-ID-Name", switch_event_get_header_nil(event, "Orig-Other-Leg-Caller-ID-Name"));
2690 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "Other-Leg-Caller-ID-Number", switch_event_get_header_nil(event, "Orig-Other-Leg-Caller-ID-Number"));
2691 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "presence-call-direction", switch_event_get_header_nil(event, "orig-presence-call-direction"));
2692 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "presence-call-info-state", switch_event_get_header_nil(event, "orig-presence-call-info-state"));
2693 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "Presence-Privacy", switch_event_get_header_nil(event, "Orig-Presence-Privacy"));
2694 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "proto", switch_event_get_header_nil(event, "orig-proto"));
2695 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "register-source", switch_event_get_header_nil(event, "orig-register-source"));
2696 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "resub", switch_event_get_header_nil(event, "orig-resub"));
2697 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "rpid", switch_event_get_header_nil(event, "orig-rpid"));
2698 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "status", switch_event_get_header_nil(event, "orig-status"));
2699 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "Unique-ID", switch_event_get_header_nil(event, "Orig-Unique-ID"));
2700 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "variable_sip_from_user", switch_event_get_header_nil(event, "Orig-variable_sip_from_user"));
2701 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "variable_sip_to_user", switch_event_get_header_nil(event, "Orig-variable_sip_to_user"));
2702 
2703 			/* we cannot use switch_event_fire, or otherwise we'll start an endless loop */
2704 			sofia_presence_event_handler(pevent);
2705 			return;
2706 		} else {
2707 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "\nCannot inject PRESENCE_IN event\n");
2708 			return;
2709 		}
2710 	} else if (!strcasecmp(class, "MESSAGE_WAITING")) {
2711 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "\nGot MWI event via MultiCast\n");
2712 		if (switch_event_create(&pevent, SWITCH_EVENT_MESSAGE_WAITING) == SWITCH_STATUS_SUCCESS) {
2713 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "MWI-Messages-Waiting", switch_event_get_header_nil(event, "orig-MWI-Messages-Waiting"));
2714 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "MWI-Message-Account", switch_event_get_header_nil(event, "orig-MWI-Message-Account"));
2715 			switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "MWI-Voice-Message", switch_event_get_header_nil(event, "orig-MWI-Voice-Message"));
2716 			/* we cannot use switch_event_fire, or otherwise we'll start an endless loop */
2717 			sofia_presence_event_handler(pevent);
2718 			return;
2719 		} else {
2720 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "\nCannot inject MWI event\n");
2721 			return;
2722 		}
2723 	} else if ((subclass = switch_event_get_header_nil(event, "orig-event-subclass")) && !strcasecmp(subclass, MY_EVENT_UNREGISTER)) {
2724 		char *profile_name = switch_event_get_header_nil(event, "orig-profile-name");
2725 		char *from_user = switch_event_get_header_nil(event, "orig-from-user");
2726 		char *from_host = switch_event_get_header_nil(event, "orig-from-host");
2727 		char *call_id = switch_event_get_header_nil(event, "orig-call-id");
2728 		char *contact_str = switch_event_get_header_nil(event, "orig-contact");
2729 
2730 		sofia_profile_t *profile = NULL;
2731 
2732 		if (!profile_name || !(profile = sofia_glue_find_profile(profile_name))) {
2733 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Profile\n");
2734 			return;
2735 		}
2736 
2737 		if (sofia_test_pflag(profile, PFLAG_MULTIREG)) {
2738 			sql = switch_mprintf("delete from sip_registrations where call_id='%q'", call_id);
2739 		} else {
2740 			sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", from_user, from_host);
2741 		}
2742 
2743 		sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
2744 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Expired propagated registration for %s@%s->%s\n", from_user, from_host, contact_str);
2745 
2746 		sofia_glue_release_profile(profile);
2747 	} else if ((subclass = switch_event_get_header_nil(event, "orig-event-subclass")) && !strcasecmp(subclass, MY_EVENT_REGISTER)) {
2748 		char *from_user = switch_event_get_header_nil(event, "orig-from-user");
2749 		char *from_host = switch_event_get_header_nil(event, "orig-from-host");
2750 		char *to_host = switch_event_get_header_nil(event, "orig-to-host");
2751 		char *contact_str = switch_event_get_header_nil(event, "orig-contact");
2752 		char *exp_str = switch_event_get_header_nil(event, "orig-expires");
2753 		char *rpid = switch_event_get_header_nil(event, "orig-rpid");
2754 		char *call_id = switch_event_get_header_nil(event, "orig-call-id");
2755 		char *user_agent = switch_event_get_header_nil(event, "orig-user-agent");
2756 		long expires = (long) switch_epoch_time_now(NULL);
2757 		char *profile_name = switch_event_get_header_nil(event, "orig-profile-name");
2758 		char *to_user = switch_event_get_header_nil(event, "orig-to-user");
2759 		char *presence_hosts = switch_event_get_header_nil(event, "orig-presence-hosts");
2760 		char *network_ip = switch_event_get_header_nil(event, "orig-network-ip");
2761 		char *network_port = switch_event_get_header_nil(event, "orig-network-port");
2762 		char *username = switch_event_get_header_nil(event, "orig-username");
2763 		char *realm = switch_event_get_header_nil(event, "orig-realm");
2764 		char *orig_server_host = switch_event_get_header_nil(event, "orig-FreeSWITCH-IPv4");
2765 		char *orig_hostname = switch_event_get_header_nil(event, "orig-FreeSWITCH-Hostname");
2766 		char *fixed_contact_str = NULL;
2767 
2768 		sofia_profile_t *profile = NULL;
2769 		char guess_ip4[256];
2770 
2771 		char *mwi_account = NULL;
2772 		char *dup_mwi_account = NULL;
2773 		char *mwi_user = NULL;
2774 		char *mwi_host = NULL;
2775 
2776 		if ((mwi_account = switch_event_get_header_nil(event, "orig-mwi-account"))) {
2777 			dup_mwi_account = strdup(mwi_account);
2778 			switch_assert(dup_mwi_account != NULL);
2779 			switch_split_user_domain(dup_mwi_account, &mwi_user, &mwi_host);
2780 		}
2781 
2782 		if (!mwi_user) {
2783 			mwi_user = (char *) from_user;
2784 		}
2785 		if (!mwi_host) {
2786 			mwi_host = (char *) from_host;
2787 		}
2788 
2789 		if (exp_str) {
2790 			expires += atol(exp_str);
2791 		}
2792 
2793 		if (!rpid) {
2794 			rpid = "unknown";
2795 		}
2796 
2797 		if (!profile_name || !(profile = sofia_glue_find_profile(profile_name))) {
2798 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Profile\n");
2799 			goto end;
2800 		}
2801 		if (sofia_test_pflag(profile, PFLAG_MULTIREG)) {
2802 			sql = switch_mprintf("delete from sip_registrations where call_id='%q'", call_id);
2803 		} else {
2804 			sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", from_user, from_host);
2805 		}
2806 
2807 		if (mod_sofia_globals.rewrite_multicasted_fs_path && contact_str) {
2808 			const char *needle = ";fs_path=";
2809 			char *sptr, *eptr = NULL;
2810 			/* allocate enough room for worst-case scenario, depends on rewrite_multicased_fs_path setting */
2811 			size_t len;
2812 			switch (mod_sofia_globals.rewrite_multicasted_fs_path) {
2813 				case 1:
2814 					len = strlen(contact_str) + strlen(to_host) + 14;
2815 				break;
2816 				case 2:
2817 					len = strlen(contact_str) + strlen(orig_server_host) + 14;
2818 				break;
2819 				case 3:
2820 					len = strlen(contact_str) + strlen(orig_hostname) + 14;
2821 				break;
2822 				default:
2823 					len = strlen(contact_str) + strlen(to_host) + 14;
2824 				break;
2825 			}
2826 
2827 			fixed_contact_str = malloc(len);
2828 			switch_assert(fixed_contact_str);
2829 			switch_copy_string(fixed_contact_str, contact_str, len);
2830 
2831 			if ((sptr = strstr(fixed_contact_str, needle))) {
2832 				char *origsptr = strstr(contact_str, needle);
2833 				eptr = strchr(++origsptr, ';');
2834 			} else {
2835 				sptr = strchr(fixed_contact_str, '\0') - 1;
2836 			}
2837 
2838 			switch (mod_sofia_globals.rewrite_multicasted_fs_path) {
2839 				case 1:
2840 					switch_snprintf(sptr, len - (sptr - fixed_contact_str), ";fs_path=sip:%s%s", to_host, eptr ? eptr : ">");
2841 				break;
2842 				case 2:
2843 					switch_snprintf(sptr, len - (sptr - fixed_contact_str), ";fs_path=sip:%s%s", orig_server_host, eptr ? eptr : ">");
2844 				break;
2845 				case 3:
2846 					switch_snprintf(sptr, len - (sptr - fixed_contact_str), ";fs_path=sip:%s%s", orig_hostname, eptr ? eptr : ">");
2847 				break;
2848 				default:
2849 					switch_snprintf(sptr, len - (sptr - fixed_contact_str), ";fs_path=sip:%s%s", to_host, eptr ? eptr : ">");
2850 				break;
2851 			}
2852 
2853 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Rewrote contact string from '%s' to '%s'\n", contact_str, fixed_contact_str);
2854 			contact_str = fixed_contact_str;
2855 		}
2856 
2857 
2858 		sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
2859 
2860 		switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL, AF_INET);
2861 		sql = switch_mprintf("insert into sip_registrations "
2862 							 "(call_id, sip_user, sip_host, presence_hosts, contact, status, rpid, expires,"
2863 							 "user_agent, server_user, server_host, profile_name, hostname, network_ip, network_port, sip_username, sip_realm,"
2864 							 "mwi_user, mwi_host, orig_server_host, orig_hostname, ping_status, ping_count) "
2865 							 "values ('%q','%q','%q','%q','%q','Registered','%q',%ld, '%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q', '%q', %d)",
2866 							 call_id, from_user, from_host, presence_hosts, contact_str, rpid, expires, user_agent, to_user, guess_ip4,
2867 							 profile_name, mod_sofia_globals.hostname, network_ip, network_port, username, realm, mwi_user, mwi_host,
2868 							 orig_server_host, orig_hostname, "Reachable", 0);
2869 
2870 		if (sql) {
2871 			sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
2872 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Propagating registration for %s@%s->%s\n", from_user, from_host, contact_str);
2873 		}
2874 
2875 
2876 		sofia_glue_release_profile(profile);
2877 	  end:
2878 		switch_safe_free(fixed_contact_str);
2879 		switch_safe_free(dup_mwi_account);
2880 	} else if ((subclass = switch_event_get_header_nil(event, "orig-event-subclass")) && !strcasecmp(subclass, MY_EVENT_SIP_USER_STATE)) {
2881 		char *profile_name = switch_event_get_header_nil(event, "orig-profile-name");
2882 		char *from_user = switch_event_get_header_nil(event, "orig-from-user");
2883 		char *from_host = switch_event_get_header_nil(event, "orig-from-host");
2884 		const char *call_id = switch_event_get_header_nil(event, "orig-call-id");
2885 		char *ping_status = switch_event_get_header_nil(event, "orig-Ping-Status");
2886 		sofia_profile_t *profile = NULL;
2887 
2888 		if (!profile_name || !(profile = sofia_glue_find_profile(profile_name))) {
2889 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Profile\n");
2890 		} else {
2891 			if (!strcmp(ping_status, "REACHABLE")) {
2892 				sql = switch_mprintf("update sip_registrations set ping_status='%q' where sip_user='%q' and sip_host='%q' and call_id='%q'",
2893 								 	"Reachable", from_user, from_host, call_id);
2894 			} else {
2895 				sql = switch_mprintf("update sip_registrations set ping_status='%q' where sip_user='%q' and sip_host='%q' and call_id='%q'",
2896 								 	"Unreachable", from_user, from_host, call_id);
2897 			}
2898 			if (sql) {
2899 				sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
2900 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Propagating sip_user_state for %s@%s. Ping-Status: %s\n", from_user, from_host, ping_status);
2901 			}
2902 
2903 			sofia_glue_release_profile(profile);
2904         }
2905 	}
2906 }
2907 
sofia_perform_profile_start_failure(sofia_profile_t * profile,char * profile_name,char * file,int line)2908 static void sofia_perform_profile_start_failure(sofia_profile_t *profile, char *profile_name, char *file, int line)
2909 {
2910 	int arg = 0;
2911 	switch_event_t *s_event;
2912 
2913 	if (profile) {
2914 		if (!strcasecmp(profile->shutdown_type, "true")) {
2915 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile %s could not load! Shutting down!\n", profile->name);
2916 			switch_core_session_ctl(SCSC_SHUTDOWN, &arg);
2917 		} else if (!strcasecmp(profile->shutdown_type, "elegant")) {
2918 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile %s could not load! Waiting for calls to finish, then shutting down!\n",
2919 							  profile->name);
2920 			switch_core_session_ctl(SCSC_SHUTDOWN_ELEGANT, &arg);
2921 		} else if (!strcasecmp(profile->shutdown_type, "asap")) {
2922 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile %s could not load! Shutting down ASAP!\n", profile->name);
2923 			switch_core_session_ctl(SCSC_SHUTDOWN_ASAP, &arg);
2924 		} else if (!strcasecmp(profile->shutdown_type, "reincarnate-now")) {
2925 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile %s could not load! Asking for reincarnation now!\n", profile->name);
2926 			switch_core_session_ctl(SCSC_REINCARNATE_NOW, &arg);
2927 		}
2928 	}
2929 
2930 	if ((switch_event_create(&s_event, SWITCH_EVENT_FAILURE) == SWITCH_STATUS_SUCCESS)) {
2931 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "module_name", "mod_sofia");
2932 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile_name", profile_name);
2933 		if (profile) {
2934 			switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile_uri", profile->url);
2935 		}
2936 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "failure_message", "Profile failed to start.");
2937 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "file", file);
2938 		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "line", "%d", line);
2939 
2940 		switch_event_fire(&s_event);
2941 	}
2942 }
2943 
2944 /* not a static function so that it's still visible on stacktraces */
watchdog_triggered_abort(void)2945 void watchdog_triggered_abort(void) {
2946 	abort();
2947 }
2948 
2949 #define sofia_profile_start_failure(p, xp) sofia_perform_profile_start_failure(p, xp, __FILE__, __LINE__)
2950 
2951 
2952 #define SQLLEN 1024 * 1024
sofia_profile_worker_thread_run(switch_thread_t * thread,void * obj)2953 void *SWITCH_THREAD_FUNC sofia_profile_worker_thread_run(switch_thread_t *thread, void *obj)
2954 {
2955 	sofia_profile_t *profile = (sofia_profile_t *) obj;
2956 	uint32_t ireg_loops = profile->ireg_seconds;					/* Number of loop iterations done when we haven't checked for registrations */
2957 	uint32_t iping_loops = profile->iping_freq;					/* Number of loop iterations done when we haven't checked for ping expires */
2958 	uint32_t gateway_loops = GATEWAY_SECONDS;			/* Number of loop iterations done when we haven't checked for gateways */
2959 	void *pop;
2960 	int tick = 0, x = 0;
2961 
2962 	sofia_set_pflag_locked(profile, PFLAG_WORKER_RUNNING);
2963 
2964 	while ((mod_sofia_globals.running == 1 && sofia_test_pflag(profile, PFLAG_RUNNING))) {
2965 
2966 		if (tick) {
2967 			if (profile->watchdog_enabled) {
2968 				uint32_t event_diff = 0, step_diff = 0, event_fail = 0, step_fail = 0;
2969 
2970 				if (profile->step_timeout) {
2971 					step_diff = (uint32_t) ((switch_time_now() - profile->last_root_step) / 1000);
2972 
2973 					if (step_diff > profile->step_timeout) {
2974 						step_fail = 1;
2975 					}
2976 				}
2977 
2978 				if (profile->event_timeout) {
2979 					event_diff = (uint32_t) ((switch_time_now() - profile->last_sip_event) / 1000);
2980 
2981 					if (event_diff > profile->event_timeout) {
2982 						event_fail = 1;
2983 					}
2984 				}
2985 
2986 				if (step_fail && profile->event_timeout && !event_fail) {
2987 					step_fail = 0;
2988 				}
2989 
2990 				if (event_fail || step_fail) {
2991 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile %s: SIP STACK FAILURE DETECTED BY WATCHDOG!\n"
2992 									  "GOODBYE CRUEL WORLD, I'M LEAVING YOU TODAY....GOODBYE, GOODBYE, GOOD BYE\n", profile->name);
2993 					switch_yield(2000000);
2994 					watchdog_triggered_abort();
2995 				}
2996 			}
2997 
2998 
2999 			if (!sofia_test_pflag(profile, PFLAG_STANDBY)) {
3000 				if (++ireg_loops >= (uint32_t)profile->ireg_seconds) {
3001 					time_t now = switch_epoch_time_now(NULL);
3002 					sofia_reg_check_expire(profile, now, 0);
3003 					ireg_loops = 0;
3004 				}
3005 
3006 				if(++iping_loops >= (uint32_t)profile->iping_freq) {
3007 					time_t now = switch_epoch_time_now(NULL);
3008 					sofia_reg_check_ping_expire(profile, now, profile->iping_seconds);
3009 					iping_loops = 0;
3010 				}
3011 
3012 				if (++gateway_loops >= GATEWAY_SECONDS) {
3013 					sofia_reg_check_gateway(profile, switch_epoch_time_now(NULL));
3014 					sofia_sub_check_gateway(profile, switch_epoch_time_now(NULL));
3015 					gateway_loops = 0;
3016 				}
3017 			}
3018 
3019 			tick = 0;
3020 		}
3021 
3022 		if (switch_queue_pop_timeout(mod_sofia_globals.general_event_queue, &pop, 100000) == SWITCH_STATUS_SUCCESS) {
3023 
3024 			do {
3025 				switch_event_t *event = (switch_event_t *) pop;
3026 				general_event_handler(event);
3027 				switch_event_destroy(&event);
3028 
3029 				pop = NULL;
3030 				switch_queue_trypop(mod_sofia_globals.general_event_queue, &pop);
3031 			} while (pop);
3032 
3033 		}
3034 
3035 		sofia_glue_fire_events(profile);
3036 
3037 		if (++x == 10) {
3038 			tick = 1;
3039 			x = 0;
3040 		}
3041 
3042 	}
3043 
3044 	sofia_clear_pflag_locked(profile, PFLAG_WORKER_RUNNING);
3045 
3046 	return NULL;
3047 }
3048 
launch_sofia_worker_thread(sofia_profile_t * profile)3049 switch_thread_t *launch_sofia_worker_thread(sofia_profile_t *profile)
3050 {
3051 	switch_thread_t *thread = NULL;
3052 	switch_threadattr_t *thd_attr = NULL;
3053 	int x = 0;
3054 	switch_xml_t cfg = NULL, xml = NULL, xprofile = NULL, xprofiles = NULL, gateways_tag = NULL, domains_tag = NULL, domain_tag = NULL;
3055 	switch_event_t *params = NULL;
3056 	char *cf = "sofia.conf";
3057 
3058 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Launching worker thread for %s\n", profile->name);
3059 
3060 	/* Parse gateways */
3061 	switch_event_create(&params, SWITCH_EVENT_REQUEST_PARAMS);
3062 	switch_assert(params);
3063 	switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "profile", profile->name);
3064 
3065 	if (!(xml = switch_xml_open_cfg(cf, &cfg, params))) {
3066 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
3067 		goto end;
3068 	}
3069 
3070 	if ((xprofiles = switch_xml_child(cfg, "profiles"))) {
3071 		if ((xprofile = switch_xml_find_child(xprofiles, "profile", "name", profile->name))) {
3072 
3073 			if ((gateways_tag = switch_xml_child(xprofile, "gateways"))) {
3074 				parse_gateways(profile, gateways_tag, NULL);
3075 			}
3076 
3077 			if ((domains_tag = switch_xml_child(xprofile, "domains"))) {
3078 				switch_event_t *xml_params;
3079 				switch_event_create(&xml_params, SWITCH_EVENT_REQUEST_PARAMS);
3080 				switch_assert(xml_params);
3081 				switch_event_add_header_string(xml_params, SWITCH_STACK_BOTTOM, "purpose", "gateways");
3082 				switch_event_add_header_string(xml_params, SWITCH_STACK_BOTTOM, "profile", profile->name);
3083 
3084 				for (domain_tag = switch_xml_child(domains_tag, "domain"); domain_tag; domain_tag = domain_tag->next) {
3085 					switch_xml_t droot, x_domain_tag;
3086 					const char *dname = switch_xml_attr_soft(domain_tag, "name");
3087 					const char *parse = switch_xml_attr_soft(domain_tag, "parse");
3088 					const char *alias = switch_xml_attr_soft(domain_tag, "alias");
3089 
3090 					if (!zstr(dname)) {
3091 						if (!strcasecmp(dname, "all")) {
3092 							switch_xml_t xml_root, x_domains;
3093 							if (switch_xml_locate("directory", NULL, NULL, NULL, &xml_root, &x_domains, xml_params, SWITCH_FALSE) ==
3094 								SWITCH_STATUS_SUCCESS) {
3095 								for (x_domain_tag = switch_xml_child(x_domains, "domain"); x_domain_tag; x_domain_tag = x_domain_tag->next) {
3096 									dname = switch_xml_attr_soft(x_domain_tag, "name");
3097 									parse_domain_tag(profile, x_domain_tag, dname, parse, alias);
3098 								}
3099 								switch_xml_free(xml_root);
3100 							}
3101 						} else if (switch_xml_locate_domain(dname, xml_params, &droot, &x_domain_tag) == SWITCH_STATUS_SUCCESS) {
3102 							parse_domain_tag(profile, x_domain_tag, dname, parse, alias);
3103 							switch_xml_free(droot);
3104 						}
3105 					}
3106 				}
3107 
3108 				switch_event_destroy(&xml_params);
3109 			}
3110 
3111 		}
3112 	}
3113 
3114 	switch_threadattr_create(&thd_attr, profile->pool);
3115 	switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
3116 	//switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME);
3117 	switch_thread_create(&thread, thd_attr, sofia_profile_worker_thread_run, profile, profile->pool);
3118 
3119 	while (!sofia_test_pflag(profile, PFLAG_WORKER_RUNNING)) {
3120 		switch_yield(100000);
3121 		if (++x >= 100) {
3122 			break;
3123 		}
3124 	}
3125 
3126  end:
3127 	switch_event_destroy(&params);
3128 
3129 	if (xml) {
3130 		switch_xml_free(xml);
3131 	}
3132 
3133 	return thread;
3134 }
3135 
sofia_profile_thread_run(switch_thread_t * thread,void * obj)3136 void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void *obj)
3137 {
3138 	sofia_profile_t *profile = (sofia_profile_t *) obj;
3139 	//switch_memory_pool_t *pool;
3140 	sip_alias_node_t *node;
3141 	switch_event_t *s_event;
3142 	int use_100rel = !sofia_test_pflag(profile, PFLAG_DISABLE_100REL);
3143 	int use_timer = !sofia_test_pflag(profile, PFLAG_DISABLE_TIMER);
3144 	int use_rfc_5626 = sofia_test_pflag(profile, PFLAG_ENABLE_RFC5626);
3145 	const char *supported = NULL;
3146 	int sanity, attempts = 0;
3147 	switch_thread_t *worker_thread;
3148 	switch_status_t st;
3149 	char qname [128] = "";
3150 
3151 	switch_mutex_lock(mod_sofia_globals.mutex);
3152 	mod_sofia_globals.threads++;
3153 	switch_mutex_unlock(mod_sofia_globals.mutex);
3154 
3155 	profile->s_root = su_root_create(NULL);
3156 	//profile->home = su_home_new(sizeof(*profile->home));
3157 
3158 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Creating agent for %s\n", profile->name);
3159 
3160 	if (!sofia_glue_init_sql(profile)) {
3161 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open SQL Database [%s]!\n", profile->name);
3162 		sofia_profile_start_failure(profile, profile->name);
3163 		sofia_glue_del_profile(profile);
3164 		goto end;
3165 	}
3166 
3167 	supported = switch_core_sprintf(profile->pool, "%s%s%spath, replaces", use_100rel ? "precondition, 100rel, " : "", use_timer ? "timer, " : "", use_rfc_5626 ? "outbound, " : "");
3168 
3169 	if (sofia_test_pflag(profile, PFLAG_AUTO_NAT) && switch_nat_get_type()) {
3170 		if ( (! sofia_test_pflag(profile, PFLAG_TLS) || ! profile->tls_only) && switch_nat_add_mapping(profile->sip_port, SWITCH_NAT_UDP, NULL, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
3171 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Created UDP nat mapping for %s port %d\n", profile->name, profile->sip_port);
3172 		}
3173 		if (switch_nat_add_mapping(profile->sip_port, SWITCH_NAT_TCP, NULL, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
3174 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Created TCP nat mapping for %s port %d\n", profile->name, profile->sip_port);
3175 		}
3176 		if (sofia_test_pflag(profile, PFLAG_TLS)
3177 			&& switch_nat_add_mapping(profile->tls_sip_port, SWITCH_NAT_TCP, NULL, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
3178 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Created TCP/TLS nat mapping for %s port %d\n", profile->name, profile->tls_sip_port);
3179 		}
3180 	}
3181 
3182 	/* We have to init the verify_subjects here as during config stage profile->home isn't setup, it should be freed when profile->home is freed */
3183 	if ( (profile->tls_verify_policy & TPTLS_VERIFY_SUBJECTS_IN)  && profile->tls_verify_in_subjects_str && ! profile->tls_verify_in_subjects) {
3184 		profile->tls_verify_in_subjects = su_strlst_dup_split((su_home_t *)profile->nua, profile->tls_verify_in_subjects_str, "|");
3185 	}
3186 
3187 	do {
3188 		profile->nua = nua_create(profile->s_root,	/* Event loop */
3189 								  sofia_event_callback,	/* Callback for processing events */
3190 								  profile,	/* Additional data to pass to callback */
3191 								  TAG_IF( ! sofia_test_pflag(profile, PFLAG_TLS) || ! profile->tls_only, NUTAG_URL(profile->bindurl)),
3192 								  NTATAG_USER_VIA(1),
3193 								  TPTAG_PONG2PING(1),
3194 								  NTATAG_TCP_RPORT(0),
3195 								  NTATAG_TLS_RPORT(0),
3196 								  NUTAG_RETRY_AFTER_ENABLE(0),
3197 								  NUTAG_AUTO_INVITE_100(0),
3198 								  TAG_IF(!strchr(profile->sipip, ':'),
3199 										 SOATAG_AF(SOA_AF_IP4_ONLY)),
3200 								  TAG_IF(strchr(profile->sipip, ':'),
3201 										 SOATAG_AF(SOA_AF_IP6_ONLY)),
3202 								  TAG_IF(sofia_test_pflag(profile, PFLAG_TLS),
3203 										 NUTAG_SIPS_URL(profile->tls_bindurl)),
3204 								  TAG_IF(profile->ws_bindurl,
3205 										 NUTAG_WS_URL(profile->ws_bindurl)),
3206 								  TAG_IF(profile->wss_bindurl,
3207 										 NUTAG_WSS_URL(profile->wss_bindurl)),
3208 								  TAG_IF(profile->tls_cert_dir,
3209 										 NUTAG_CERTIFICATE_DIR(profile->tls_cert_dir)),
3210 								  TAG_IF(sofia_test_pflag(profile, PFLAG_TLS) && profile->tls_passphrase,
3211 										 TPTAG_TLS_PASSPHRASE(profile->tls_passphrase)),
3212 								  TAG_IF(sofia_test_pflag(profile, PFLAG_TLS),
3213 										 TPTAG_TLS_VERIFY_POLICY(profile->tls_verify_policy)),
3214 								  TAG_IF(sofia_test_pflag(profile, PFLAG_TLS),
3215 										 TPTAG_TLS_VERIFY_DEPTH(profile->tls_verify_depth)),
3216 								  TAG_IF(sofia_test_pflag(profile, PFLAG_TLS),
3217 										 TPTAG_TLS_VERIFY_DATE(profile->tls_verify_date)),
3218 								  TAG_IF(sofia_test_pflag(profile, PFLAG_TLS) && profile->tls_verify_in_subjects,
3219 										 TPTAG_TLS_VERIFY_SUBJECTS(profile->tls_verify_in_subjects)),
3220 								  TAG_IF(sofia_test_pflag(profile, PFLAG_TLS),
3221 										 TPTAG_TLS_CIPHERS(profile->tls_ciphers)),
3222 								  TAG_IF(sofia_test_pflag(profile, PFLAG_TLS),
3223 										 TPTAG_TLS_VERSION(profile->tls_version)),
3224 								  TAG_IF(sofia_test_pflag(profile, PFLAG_TLS) && profile->tls_timeout,
3225 										 TPTAG_TLS_TIMEOUT(profile->tls_timeout)),
3226 								  TAG_IF(!strchr(profile->sipip, ':'),
3227 										 NTATAG_UDP_MTU(65535)),
3228 								  TAG_IF(sofia_test_pflag(profile, PFLAG_DISABLE_SRV),
3229 										 NTATAG_USE_SRV(0)),
3230 								  TAG_IF(sofia_test_pflag(profile, PFLAG_DISABLE_NAPTR),
3231 										 NTATAG_USE_NAPTR(0)),
3232 								  TAG_IF(sofia_test_pflag(profile, PFLAG_TCP_PINGPONG),
3233 										 TPTAG_PINGPONG(profile->tcp_pingpong)),
3234 								  TAG_IF(sofia_test_pflag(profile, PFLAG_TCP_PING2PONG),
3235 										 TPTAG_PINGPONG(profile->tcp_ping2pong)),
3236 								  TAG_IF(sofia_test_pflag(profile, PFLAG_DISABLE_SRV503),
3237 										 NTATAG_SRV_503(0)),
3238 								  TAG_IF(sofia_test_pflag(profile, PFLAG_SOCKET_TCP_KEEPALIVE),
3239 										 TPTAG_SOCKET_KEEPALIVE(profile->socket_tcp_keepalive)),
3240 								  TAG_IF(sofia_test_pflag(profile, PFLAG_TCP_KEEPALIVE),
3241 										 TPTAG_KEEPALIVE(profile->tcp_keepalive)),
3242 								  NTATAG_DEFAULT_PROXY(profile->outbound_proxy),
3243 								  NTATAG_SERVER_RPORT(profile->server_rport_level),
3244 								  NTATAG_CLIENT_RPORT(profile->client_rport_level),
3245 								  TPTAG_LOG(sofia_test_flag(profile, TFLAG_TPORT_LOG)),
3246 								  TPTAG_CAPT(sofia_test_flag(profile, TFLAG_CAPTURE) ? mod_sofia_globals.capture_server : NULL),
3247 								  TAG_IF(sofia_test_pflag(profile, PFLAG_SIPCOMPACT),
3248 										 NTATAG_SIPFLAGS(MSG_DO_COMPACT)),
3249 								  TAG_IF(profile->timer_t1, NTATAG_SIP_T1(profile->timer_t1)),
3250 								  TAG_IF(profile->timer_t1x64, NTATAG_SIP_T1X64(profile->timer_t1x64)),
3251 								  TAG_IF(profile->timer_t2, NTATAG_SIP_T2(profile->timer_t2)),
3252 								  TAG_IF(profile->timer_t4, NTATAG_SIP_T4(profile->timer_t4)),
3253 								  SIPTAG_ACCEPT_STR("application/sdp, multipart/mixed"),
3254 								  TAG_IF(sofia_test_pflag(profile, PFLAG_NO_CONNECTION_REUSE),
3255 										 TPTAG_REUSE(0)),
3256 								  TAG_END());	/* Last tag should always finish the sequence */
3257 
3258 		if (!profile->nua) {
3259 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Creating SIP UA for profile: %s (%s) ATTEMPT %d (RETRY IN %d SEC)\n",
3260 							  profile->name, profile->bindurl, attempts + 1, profile->bind_attempt_interval);
3261 			if (attempts < profile->bind_attempts) {
3262 				switch_yield(1000000 * profile->bind_attempt_interval);
3263 			}
3264 		}
3265 
3266 	} while (!profile->nua && attempts++ < profile->bind_attempts);
3267 
3268 	if (!profile->nua) {
3269 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Creating SIP UA for profile: %s (%s)\n"
3270 						  "The likely causes for this are:\n" "1) Another application is already listening on the specified address.\n"
3271 						  "2) The IP the profile is attempting to bind to is not local to this system.\n", profile->name, profile->bindurl);
3272 		sofia_profile_start_failure(profile, profile->name);
3273 		sofia_glue_del_profile(profile);
3274 		goto end;
3275 	}
3276 
3277 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Created agent for %s\n", profile->name);
3278 
3279 	nua_set_params(profile->nua,
3280 				   SIPTAG_ALLOW_STR("INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO"),
3281 				   SIPTAG_USER_AGENT(SIP_NONE),
3282 				   NUTAG_AUTOANSWER(0),
3283 				   NUTAG_AUTOACK(0),
3284 				   NUTAG_AUTOALERT(0),
3285 				   NUTAG_ENABLEMESSENGER(1),
3286 				   NTATAG_EXTRA_100(0),
3287 				   TAG_IF(sofia_test_pflag(profile, PFLAG_ALLOW_UPDATE), NUTAG_ALLOW("UPDATE")),
3288 				   TAG_IF((profile->mflags & MFLAG_REGISTER), NUTAG_ALLOW("REGISTER")),
3289 				   TAG_IF((profile->mflags & MFLAG_REFER), NUTAG_ALLOW("REFER")),
3290 				   TAG_IF(!sofia_test_pflag(profile, PFLAG_DISABLE_100REL), NUTAG_ALLOW("PRACK")),
3291 				   NUTAG_ALLOW("INFO"),
3292 				   NUTAG_ALLOW("NOTIFY"),
3293 				   NUTAG_ALLOW_EVENTS("talk"),
3294 				   NUTAG_ALLOW_EVENTS("hold"),
3295 				   NUTAG_ALLOW_EVENTS("conference"),
3296 				   NUTAG_APPL_METHOD("OPTIONS"),
3297 				   NUTAG_APPL_METHOD("INVITE"),
3298 				   NUTAG_APPL_METHOD("REFER"),
3299 				   NUTAG_APPL_METHOD("REGISTER"),
3300 				   NUTAG_APPL_METHOD("NOTIFY"), NUTAG_APPL_METHOD("INFO"), NUTAG_APPL_METHOD("ACK"), NUTAG_APPL_METHOD("SUBSCRIBE"),
3301 #ifdef MANUAL_BYE
3302 				   NUTAG_APPL_METHOD("BYE"),
3303 #endif
3304 				   NUTAG_APPL_METHOD("MESSAGE"),
3305 
3306 				   TAG_IF(profile->session_timeout && profile->minimum_session_expires, NUTAG_MIN_SE(profile->minimum_session_expires)),
3307 				   NUTAG_SESSION_TIMER(profile->session_timeout),
3308 				   NTATAG_MAX_PROCEEDING(profile->max_proceeding),
3309 				   TAG_IF(profile->pres_type, NUTAG_ALLOW("PUBLISH")),
3310 				   TAG_IF(profile->pres_type, NUTAG_ALLOW("SUBSCRIBE")),
3311 				   TAG_IF(profile->pres_type, NUTAG_ENABLEMESSAGE(1)),
3312 				   TAG_IF(profile->pres_type, NUTAG_ALLOW_EVENTS("presence")),
3313 				   TAG_IF(profile->pres_type, NUTAG_ALLOW_EVENTS("as-feature-event")),
3314 				   TAG_IF((profile->pres_type || sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)), NUTAG_ALLOW_EVENTS("dialog")),
3315 				   TAG_IF((profile->pres_type || sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)), NUTAG_ALLOW_EVENTS("line-seize")),
3316 				   TAG_IF(profile->pres_type, NUTAG_ALLOW_EVENTS("call-info")),
3317 				   TAG_IF((profile->pres_type || sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)), NUTAG_ALLOW_EVENTS("sla")),
3318 				   TAG_IF(profile->pres_type, NUTAG_ALLOW_EVENTS("include-session-description")),
3319 				   TAG_IF(profile->pres_type, NUTAG_ALLOW_EVENTS("presence.winfo")),
3320 				   TAG_IF(profile->pres_type, NUTAG_ALLOW_EVENTS("message-summary")),
3321 				   TAG_IF(profile->pres_type == PRES_TYPE_PNP, NUTAG_ALLOW_EVENTS("ua-profile")),
3322 				   NUTAG_ALLOW_EVENTS("refer"), SIPTAG_SUPPORTED_STR(supported),
3323 				   TAG_IF(strcasecmp(profile->user_agent, "_undef_"), SIPTAG_USER_AGENT_STR(profile->user_agent)),
3324 				   TAG_END());
3325 
3326 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set params for %s\n", profile->name);
3327 
3328 	if (sofia_test_pflag(profile, PFLAG_AUTO_ASSIGN_PORT) || sofia_test_pflag(profile, PFLAG_AUTO_ASSIGN_TLS_PORT)) {
3329 		sip_via_t *vias = nta_agent_via(profile->nua->nua_nta);
3330 		sip_via_t *via = NULL;
3331 
3332 		for (via = vias; via; via = via->v_next) {
3333 			if (sofia_test_pflag(profile, PFLAG_AUTO_ASSIGN_PORT) && !strcmp(via->v_protocol, "SIP/2.0/UDP")) {
3334 				profile->sip_port = (switch_port_t)atoi(via->v_port);
3335 				if (!profile->extsipport) profile->extsipport = profile->sip_port;
3336 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found auto sip port %d for %s\n", profile->sip_port, profile->name);
3337 			}
3338 
3339 			if (sofia_test_pflag(profile, PFLAG_AUTO_ASSIGN_TLS_PORT) && !strcmp(via->v_protocol, "SIP/2.0/TLS")) {
3340 				profile->tls_sip_port = (switch_port_t)atoi(via->v_port);
3341 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found auto sip port %d for %s (TLS)\n", profile->tls_sip_port, profile->name);
3342 			}
3343 
3344 		}
3345 
3346 		config_sofia_profile_urls(profile);
3347 	}
3348 
3349 	for (node = profile->aliases; node; node = node->next) {
3350 		node->nua = nua_create(profile->s_root,	/* Event loop */
3351 							   sofia_event_callback,	/* Callback for processing events */
3352 							   profile,	/* Additional data to pass to callback */
3353 							   NTATAG_SERVER_RPORT(profile->server_rport_level), NUTAG_URL(node->url), TAG_END());	/* Last tag should always finish the sequence */
3354 
3355 		nua_set_params(node->nua,
3356 					   SIPTAG_USER_AGENT(SIP_NONE),
3357 					   NUTAG_APPL_METHOD("OPTIONS"),
3358 					   NUTAG_APPL_METHOD("REFER"),
3359 					   NUTAG_APPL_METHOD("SUBSCRIBE"),
3360 					   NUTAG_AUTOANSWER(0),
3361 					   NUTAG_AUTOACK(0),
3362 					   NUTAG_AUTOALERT(0),
3363 					   TAG_IF((profile->mflags & MFLAG_REGISTER), NUTAG_ALLOW("REGISTER")),
3364 					   TAG_IF((profile->mflags & MFLAG_REFER), NUTAG_ALLOW("REFER")),
3365 					   NUTAG_ALLOW("INFO"),
3366 					   TAG_IF(profile->pres_type, NUTAG_ALLOW("PUBLISH")),
3367 					   TAG_IF(profile->pres_type, NUTAG_ENABLEMESSAGE(1)),
3368 					   SIPTAG_SUPPORTED_STR(supported),
3369 					   TAG_IF(strcasecmp(profile->user_agent, "_undef_"), SIPTAG_USER_AGENT_STR(profile->user_agent)),
3370 					   TAG_END());
3371 	}
3372 
3373 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Activated db for %s\n", profile->name);
3374 
3375 	switch_mutex_init(&profile->ireg_mutex, SWITCH_MUTEX_NESTED, profile->pool);
3376 	switch_mutex_init(&profile->dbh_mutex, SWITCH_MUTEX_NESTED, profile->pool);
3377 	switch_mutex_init(&profile->gateway_mutex, SWITCH_MUTEX_NESTED, profile->pool);
3378 	switch_queue_create(&profile->event_queue, SOFIA_QUEUE_SIZE, profile->pool);
3379 
3380 
3381 	switch_snprintf(qname, sizeof(qname), "sofia:%s", profile->name);
3382 	switch_sql_queue_manager_init_name(qname,
3383 									   &profile->qm,
3384 									   2,
3385 									   profile->odbc_dsn ? profile->odbc_dsn : profile->dbname,
3386 									   SWITCH_MAX_TRANS,
3387 									   profile->pre_trans_execute,
3388 									   profile->post_trans_execute,
3389 									   profile->inner_pre_trans_execute,
3390 									   profile->inner_post_trans_execute);
3391 	switch_sql_queue_manager_start(profile->qm);
3392 
3393 	if (switch_event_create(&s_event, SWITCH_EVENT_PUBLISH) == SWITCH_STATUS_SUCCESS) {
3394 		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "service", "_sip._udp,_sip._tcp,_sip._sctp%s",
3395 								(sofia_test_pflag(profile, PFLAG_TLS)) ? ",_sips._tcp" : "");
3396 
3397 		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "port", "%d", profile->sip_port);
3398 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "module_name", "mod_sofia");
3399 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile_name", profile->name);
3400 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile_uri", profile->url);
3401 
3402 		if (sofia_test_pflag(profile, PFLAG_TLS)) {
3403 			switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "tls_port", "%d", profile->tls_sip_port);
3404 			switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile_tls_uri", profile->tls_url);
3405 		}
3406 		switch_event_fire(&s_event);
3407 	}
3408 
3409 	sofia_glue_add_profile(profile->name, profile);
3410 
3411 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Starting thread for %s\n", profile->name);
3412 
3413 	profile->started = switch_epoch_time_now(NULL);
3414 
3415 	sofia_set_pflag_locked(profile, PFLAG_RUNNING);
3416 	worker_thread = launch_sofia_worker_thread(profile);
3417 
3418 	switch_yield(1000000);
3419 
3420 
3421 	while (mod_sofia_globals.running == 1 && sofia_test_pflag(profile, PFLAG_RUNNING) && sofia_test_pflag(profile, PFLAG_WORKER_RUNNING)) {
3422 		su_root_step(profile->s_root, 1000);
3423 		profile->last_root_step = switch_time_now();
3424 	}
3425 
3426 	sofia_clear_pflag_locked(profile, PFLAG_RUNNING);
3427 	sofia_reg_close_handles(profile);
3428 
3429 	switch_core_session_hupall_matching_var("sofia_profile_name", profile->name, SWITCH_CAUSE_MANAGER_REQUEST);
3430 	sanity = 10;
3431 	while (profile->inuse) {
3432 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Waiting for %d session(s)\n", profile->inuse);
3433 		su_root_step(profile->s_root, 1000);
3434 		if (!--sanity) {
3435 			break;
3436 		} else if (sanity == 5) {
3437 			switch_core_session_hupall_matching_var("sofia_profile_name", profile->name, SWITCH_CAUSE_MANAGER_REQUEST);
3438 		}
3439 	}
3440 
3441 
3442 	sofia_reg_unregister(profile);
3443 	nua_shutdown(profile->nua);
3444 
3445 	sanity = 100;
3446 	while (!sofia_test_pflag(profile, PFLAG_SHUTDOWN) || profile->queued_events > 0) {
3447 		su_root_step(profile->s_root, 1000);
3448 		if (!--sanity) {
3449 			break;
3450 		}
3451 	}
3452 
3453 	sofia_clear_pflag_locked(profile, PFLAG_RUNNING);
3454 	sofia_clear_pflag_locked(profile, PFLAG_SHUTDOWN);
3455 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Waiting for worker thread\n");
3456 
3457 	if ( worker_thread ) {
3458 		switch_thread_join(&st, worker_thread);
3459 	} else {
3460 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: Sofia worker thead failed to start\n");
3461 	}
3462 
3463 	sanity = 4;
3464 	while (profile->inuse) {
3465 		switch_core_session_hupall_matching_var("sofia_profile_name", profile->name, SWITCH_CAUSE_MANAGER_REQUEST);
3466 		switch_yield(5000000);
3467 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Waiting for %d session(s)\n", profile->inuse);
3468 		if (!--sanity) {
3469 			break;
3470 		}
3471 	}
3472 	nua_destroy(profile->nua);
3473 
3474 	switch_mutex_lock(profile->ireg_mutex);
3475 	switch_mutex_unlock(profile->ireg_mutex);
3476 
3477 	switch_mutex_lock(profile->flag_mutex);
3478 	switch_mutex_unlock(profile->flag_mutex);
3479 
3480 	switch_sql_queue_manager_destroy(&profile->qm);
3481 
3482 	if (switch_event_create(&s_event, SWITCH_EVENT_UNPUBLISH) == SWITCH_STATUS_SUCCESS) {
3483 		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "service", "_sip._udp,_sip._tcp,_sip._sctp%s",
3484 								(sofia_test_pflag(profile, PFLAG_TLS)) ? ",_sips._tcp" : "");
3485 
3486 		switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "port", "%d", profile->sip_port);
3487 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "module_name", "mod_sofia");
3488 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile_name", profile->name);
3489 		switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile_uri", profile->url);
3490 
3491 		if (sofia_test_pflag(profile, PFLAG_TLS)) {
3492 			switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "tls_port", "%d", profile->tls_sip_port);
3493 			switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile_tls_uri", profile->tls_url);
3494 		}
3495 		switch_event_fire(&s_event);
3496 	}
3497 
3498 	if (sofia_test_pflag(profile, PFLAG_AUTO_NAT) && switch_nat_get_type()) {
3499 		if (switch_nat_del_mapping(profile->sip_port, SWITCH_NAT_UDP) == SWITCH_STATUS_SUCCESS) {
3500 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deleted UDP nat mapping for %s port %d\n", profile->name, profile->sip_port);
3501 		}
3502 		if (switch_nat_del_mapping(profile->sip_port, SWITCH_NAT_TCP) == SWITCH_STATUS_SUCCESS) {
3503 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deleted TCP nat mapping for %s port %d\n", profile->name, profile->sip_port);
3504 		}
3505 		if (sofia_test_pflag(profile, PFLAG_TLS) && switch_nat_del_mapping(profile->tls_sip_port, SWITCH_NAT_TCP) == SWITCH_STATUS_SUCCESS) {
3506 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Deleted TCP/TLS nat mapping for %s port %d\n", profile->name, profile->tls_sip_port);
3507 		}
3508 	}
3509 
3510 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write lock %s\n", profile->name);
3511 	switch_thread_rwlock_wrlock(profile->rwlock);
3512 
3513 	//su_home_unref(profile->home);
3514 	su_root_destroy(profile->s_root);
3515 	//pool = profile->pool;
3516 
3517 	sofia_glue_del_profile(profile);
3518 	switch_core_hash_destroy(&profile->chat_hash);
3519 	switch_core_hash_destroy(&profile->reg_nh_hash);
3520 	switch_core_hash_destroy(&profile->mwi_debounce_hash);
3521 
3522 	switch_thread_rwlock_unlock(profile->rwlock);
3523 	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Write unlock %s\n", profile->name);
3524 
3525 	if (sofia_test_pflag(profile, PFLAG_RESPAWN)) {
3526 		config_sofia(SOFIA_CONFIG_RESPAWN, profile->name);
3527 	}
3528 
3529 	sofia_profile_destroy(profile);
3530 
3531   end:
3532 	switch_mutex_lock(mod_sofia_globals.mutex);
3533 	mod_sofia_globals.threads--;
3534 	switch_mutex_unlock(mod_sofia_globals.mutex);
3535 
3536 	return NULL;
3537 }
3538 
sofia_profile_destroy(sofia_profile_t * profile)3539 void sofia_profile_destroy(sofia_profile_t *profile)
3540 {
3541 	if (!profile->inuse) {
3542 		switch_memory_pool_t *pool = profile->pool;
3543 		switch_core_destroy_memory_pool(&pool);
3544 	} else {
3545 		sofia_set_pflag(profile, PFLAG_DESTROY);
3546 	}
3547 }
3548 
launch_sofia_profile_thread(sofia_profile_t * profile)3549 void launch_sofia_profile_thread(sofia_profile_t *profile)
3550 {
3551 	//switch_thread_t *thread;
3552 	switch_threadattr_t *thd_attr = NULL;
3553 
3554 	switch_threadattr_create(&thd_attr, profile->pool);
3555 	switch_threadattr_detach_set(thd_attr, 1);
3556 	switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
3557 	switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME);
3558 	switch_thread_create(&profile->thread, thd_attr, sofia_profile_thread_run, profile, profile->pool);
3559 }
3560 
logger(void * logarg,char const * fmt,va_list ap)3561 static void logger(void *logarg, char const *fmt, va_list ap)
3562 {
3563 	if (!fmt) return;
3564 
3565 	switch_log_vprintf(SWITCH_CHANNEL_LOG_CLEAN, mod_sofia_globals.tracelevel, fmt, ap);
3566 }
3567 
sofia_get_logger(const char * name)3568 static su_log_t *sofia_get_logger(const char *name)
3569 {
3570 	if (!strcasecmp(name, "tport")) {
3571 		return tport_log;
3572 	} else if (!strcasecmp(name, "iptsec")) {
3573 		return iptsec_log;
3574 	} else if (!strcasecmp(name, "nea")) {
3575 		return nea_log;
3576 	} else if (!strcasecmp(name, "nta")) {
3577 		return nta_log;
3578 	} else if (!strcasecmp(name, "nth_client")) {
3579 		return nth_client_log;
3580 	} else if (!strcasecmp(name, "nth_server")) {
3581 		return nth_server_log;
3582 	} else if (!strcasecmp(name, "nua")) {
3583 		return nua_log;
3584 	} else if (!strcasecmp(name, "soa")) {
3585 		return soa_log;
3586 	} else if (!strcasecmp(name, "sresolv")) {
3587 		return sresolv_log;
3588 #ifdef HAVE_SOFIA_STUN
3589 	} else if (!strcasecmp(name, "stun")) {
3590 		return stun_log;
3591 #endif
3592 	} else if (!strcasecmp(name, "default")) {
3593 		return su_log_default;
3594 	} else {
3595 		return NULL;
3596 	}
3597 }
3598 
sofia_set_loglevel(const char * name,int level)3599 switch_status_t sofia_set_loglevel(const char *name, int level)
3600 {
3601 	su_log_t *log = NULL;
3602 
3603 	if (level < 0 || level > 9) {
3604 		return SWITCH_STATUS_FALSE;
3605 	}
3606 
3607 	if (!strcasecmp(name, "all")) {
3608 		su_log_set_level(su_log_default, level);
3609 		su_log_set_level(tport_log, level);
3610 		su_log_set_level(iptsec_log, level);
3611 		su_log_set_level(nea_log, level);
3612 		su_log_set_level(nta_log, level);
3613 		su_log_set_level(nth_client_log, level);
3614 		su_log_set_level(nth_server_log, level);
3615 		su_log_set_level(nua_log, level);
3616 		su_log_set_level(soa_log, level);
3617 		su_log_set_level(sresolv_log, level);
3618 #ifdef HAVE_SOFIA_STUN
3619 		su_log_set_level(stun_log, level);
3620 #endif
3621 		return SWITCH_STATUS_SUCCESS;
3622 	}
3623 
3624 	if (!(log = sofia_get_logger(name))) {
3625 		return SWITCH_STATUS_FALSE;
3626 	}
3627 
3628 	su_log_set_level(log, level);
3629 
3630 	return SWITCH_STATUS_SUCCESS;
3631 }
3632 
sofia_get_loglevel(const char * name)3633 int sofia_get_loglevel(const char *name)
3634 {
3635 	su_log_t *log = NULL;
3636 
3637 	if ((log = sofia_get_logger(name))) {
3638 		return log->log_level;
3639 	} else {
3640 		return -1;
3641 	}
3642 }
3643 
parse_gateway_subscriptions(sofia_profile_t * profile,sofia_gateway_t * gateway,switch_xml_t gw_subs_tag)3644 static void parse_gateway_subscriptions(sofia_profile_t *profile, sofia_gateway_t *gateway, switch_xml_t gw_subs_tag)
3645 {
3646 	switch_xml_t subscription_tag, param;
3647 
3648 	for (subscription_tag = switch_xml_child(gw_subs_tag, "subscription"); subscription_tag; subscription_tag = subscription_tag->next) {
3649 		sofia_gateway_subscription_t *gw_sub;
3650 
3651 		if ((gw_sub = switch_core_alloc(profile->pool, sizeof(*gw_sub)))) {
3652 			char *expire_seconds = "3600", *retry_seconds = "30", *content_type = "NO_CONTENT_TYPE";
3653 			uint32_t username_in_request = 0;
3654 			char *event = (char *) switch_xml_attr_soft(subscription_tag, "event");
3655 			gw_sub->event = switch_core_strdup(gateway->pool, event);
3656 			gw_sub->gateway = gateway;
3657 			gw_sub->next = NULL;
3658 
3659 			for (param = switch_xml_child(subscription_tag, "param"); param; param = param->next) {
3660 				char *var = (char *) switch_xml_attr_soft(param, "name");
3661 				char *val = (char *) switch_xml_attr_soft(param, "value");
3662 				if (!strcmp(var, "expire-seconds")) {
3663 					expire_seconds = val;
3664 				} else if (!strcmp(var, "retry-seconds")) {
3665 					retry_seconds = val;
3666 				} else if (!strcmp(var, "content-type")) {
3667 					content_type = val;
3668 				} else if (!strcmp(var, "username-in-request")) {
3669 					username_in_request = switch_true(val);
3670 				}
3671 			}
3672 
3673 			gw_sub->retry_seconds = atoi(retry_seconds);
3674 			if (gw_sub->retry_seconds < 10) {
3675 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "INVALID: retry_seconds correcting the value to 30\n");
3676 				gw_sub->retry_seconds = 30;
3677 			}
3678 
3679 			gw_sub->expires_str = switch_core_strdup(gateway->pool, expire_seconds);
3680 
3681 			if ((gw_sub->freq = atoi(gw_sub->expires_str)) < 5) {
3682 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid Freq: %d.  Setting Register-Frequency to 3600\n", gw_sub->freq);
3683 				gw_sub->freq = 3600;
3684 			}
3685 
3686 			if(username_in_request) {
3687 				gw_sub->request_uri = gateway->register_to;
3688 			} else {
3689 				gw_sub->request_uri = gateway->register_url;
3690 			}
3691 
3692 			gw_sub->freq -= 2;
3693 			gw_sub->content_type = switch_core_strdup(gateway->pool, content_type);
3694 			gw_sub->next = gateway->subscriptions;
3695 		}
3696 		gateway->subscriptions = gw_sub;
3697 	}
3698 }
3699 
parse_gateways(sofia_profile_t * profile,switch_xml_t gateways_tag,const char * gwname)3700 static void parse_gateways(sofia_profile_t *profile, switch_xml_t gateways_tag, const char *gwname)
3701 {
3702 	switch_xml_t gateway_tag, param = NULL, x_params, gw_subs_tag;
3703 	sofia_gateway_t *gp;
3704 
3705 	for (gateway_tag = switch_xml_child(gateways_tag, "gateway"); gateway_tag; gateway_tag = gateway_tag->next) {
3706 		char *name = (char *) switch_xml_attr_soft(gateway_tag, "name");
3707 		sofia_gateway_t *gateway;
3708 		char *pkey = switch_mprintf("%s::%s", profile->name, name);
3709 
3710 		if (zstr(name) || switch_regex_match(name, "^[\\w\\.\\-\\_]+$") != SWITCH_STATUS_SUCCESS) {
3711 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Ignoring invalid name '%s'\n", name ? name : "NULL");
3712 			free(pkey);
3713 			goto skip;
3714 		}
3715 
3716 		if (gwname && strcmp(gwname, name)) {
3717 			free(pkey);
3718 			goto skip;
3719 		}
3720 
3721 		switch_mutex_lock(mod_sofia_globals.hash_mutex);
3722 		if ((gp = switch_core_hash_find(mod_sofia_globals.gateway_hash, name)) && (gp = switch_core_hash_find(mod_sofia_globals.gateway_hash, pkey)) && !gp->deleted) {
3723 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring duplicate gateway '%s'\n", name);
3724 			switch_mutex_unlock(mod_sofia_globals.hash_mutex);
3725 			free(pkey);
3726 			goto skip;
3727 		}
3728 		free(pkey);
3729 		switch_mutex_unlock(mod_sofia_globals.hash_mutex);
3730 
3731 		if ((gateway = switch_core_alloc(profile->pool, sizeof(*gateway)))) {
3732 			const char *sipip, *format;
3733 			switch_uuid_t uuid;
3734 			uint32_t ping_freq = 0, extension_in_contact = 0, contact_in_ping = 0, ping_monitoring = 0, distinct_to = 0, rfc_5626 = 0;
3735 			int ping_max = 1, ping_min = 1;
3736 			char *register_str = "true", *scheme = "Digest",
3737 				*realm = NULL,
3738 				*username = NULL,
3739 				*auth_username = NULL,
3740 				*password = NULL,
3741 				*caller_id_in_from = "false",
3742 				*extension = NULL,
3743 				*proxy = NULL,
3744 				*options_user_agent = NULL,
3745 				*context = profile->context,
3746 				*expire_seconds = "3600",
3747 				*retry_seconds = "30",
3748 				*fail_908_retry_seconds = NULL,
3749 				*timeout_seconds = "60",
3750 				*from_user = "", *from_domain = NULL, *outbound_proxy = NULL, *register_proxy = NULL, *contact_host = NULL,
3751 				*contact_params = "", *params = NULL, *register_transport = NULL,
3752 				*reg_id = NULL, *str_rfc_5626 = "";
3753 
3754 			if (!context) {
3755 				context = "default";
3756 			}
3757 
3758 			switch_uuid_get(&uuid);
3759 			switch_uuid_format(gateway->uuid_str, &uuid);
3760 
3761 			gateway->register_transport = SOFIA_TRANSPORT_UDP;
3762 			gateway->pool = profile->pool;
3763 			gateway->profile = profile;
3764 			gateway->name = switch_core_strdup(gateway->pool, name);
3765 			gateway->freq = 0;
3766 			gateway->next = NULL;
3767 			gateway->ping = 0;
3768 			gateway->ping_freq = 0;
3769 			gateway->ping_max = 0;
3770 			gateway->ping_min = 0;
3771 			gateway->ping_sent = 0;
3772 			gateway->ping_time = 0;
3773 			gateway->ping_count = 0;
3774 			gateway->ping_monitoring = SWITCH_FALSE;
3775 			gateway->ib_calls = 0;
3776 			gateway->ob_calls = 0;
3777 			gateway->ib_failed_calls = 0;
3778 			gateway->ob_failed_calls = 0;
3779 			gateway->destination_prefix = "";
3780 
3781 			if ((x_params = switch_xml_child(gateway_tag, "variables"))) {
3782 				param = switch_xml_child(x_params, "variable");
3783 			} else {
3784 				param = switch_xml_child(gateway_tag, "variable");
3785 			}
3786 
3787 
3788 			for (; param; param = param->next) {
3789 				const char *var = switch_xml_attr(param, "name");
3790 				const char *val = switch_xml_attr(param, "value");
3791 				const char *direction = switch_xml_attr(param, "direction");
3792 				int in = 0, out = 0;
3793 
3794 				if (var && val) {
3795 					if (direction) {
3796 						if (!strcasecmp(direction, "inbound")) {
3797 							in = 1;
3798 						} else if (!strcasecmp(direction, "outbound")) {
3799 							out = 1;
3800 						}
3801 					} else {
3802 						in = out = 1;
3803 					}
3804 
3805 					if (in) {
3806 						if (!gateway->ib_vars) {
3807 							switch_event_create_plain(&gateway->ib_vars, SWITCH_EVENT_GENERAL);
3808 						}
3809 						switch_event_add_header_string(gateway->ib_vars, SWITCH_STACK_BOTTOM, var, val);
3810 					}
3811 
3812 					if (out) {
3813 						if (!gateway->ob_vars) {
3814 							switch_event_create_plain(&gateway->ob_vars, SWITCH_EVENT_GENERAL);
3815 						}
3816 						switch_event_add_header_string(gateway->ob_vars, SWITCH_STACK_BOTTOM, var, val);
3817 					}
3818 				}
3819 			}
3820 
3821 			if ((x_params = switch_xml_child(gateway_tag, "params"))) {
3822 				param = switch_xml_child(x_params, "param");
3823 			} else {
3824 				param = switch_xml_child(gateway_tag, "param");
3825 			}
3826 
3827 			for (; param; param = param->next) {
3828 				char *var = (char *) switch_xml_attr_soft(param, "name");
3829 				char *val = (char *) switch_xml_attr_soft(param, "value");
3830 
3831 				if (!strcmp(var, "register")) {
3832 					register_str = val;
3833 				} else if (!strcmp(var, "scheme")) {
3834 					scheme = val;
3835 				} else if (!strcmp(var, "realm")) {
3836 					realm = val;
3837 				} else if (!strcmp(var, "username")) {
3838 					username = val;
3839 				} else if (!strcmp(var, "extension-in-contact")) {
3840 					extension_in_contact = switch_true(val);
3841 				} else if (!strcmp(var, "auth-username")) {
3842 					auth_username = val;
3843 				} else if (!strcmp(var, "password")) {
3844 					password = val;
3845 				} else if (!strcmp(var, "caller-id-in-from")) {
3846 					caller_id_in_from = val;
3847 				} else if (!strcmp(var, "extension")) {
3848 					extension = val;
3849 				} else if (!strcmp(var, "contact-in-ping")) {
3850 					contact_in_ping = switch_true(val);
3851 				} else if (!strcmp(var, "ping")) {
3852 					ping_freq = atoi(val);
3853 				} else if (!strcmp(var, "ping-max")) {
3854 					ping_max = atoi(val);
3855 				} else if (!strcmp(var, "ping-min")) {
3856 					ping_min = atoi(val);
3857 				} else if (!strcmp(var, "ping-user-agent")) {
3858 					options_user_agent = val;
3859 				} else if (!strcmp(var, "ping-monitoring")) { // if true then every gw ping result will fire a gateway status event
3860 					ping_monitoring = switch_true(val);
3861 				} else if (!strcmp(var, "proxy")) {
3862 					proxy = val;
3863 				} else if (!strcmp(var, "context")) {
3864 					context = val;
3865 				} else if (!strcmp(var, "expire-seconds")) {
3866 					expire_seconds = val;
3867 				} else if (!strcmp(var, "908-retry-seconds")) {
3868 					fail_908_retry_seconds = val;
3869 				} else if (!strcmp(var, "retry-seconds")) {
3870 					retry_seconds = val;
3871 				} else if (!strcmp(var, "timeout-seconds")) {
3872 					timeout_seconds = val;
3873 				} else if (!strcmp(var, "retry_seconds")) {	// support typo for back compat
3874 					retry_seconds = val;
3875 				} else if (!strcmp(var, "from-user")) {
3876 					from_user = val;
3877 				} else if (!strcmp(var, "from-domain")) {
3878 					from_domain = val;
3879 				} else if (!strcmp(var, "contact-host")) {
3880 					contact_host = val;
3881 				} else if (!strcmp(var, "register-proxy")) {
3882 					register_proxy = val;
3883 				} else if (!strcmp(var, "outbound-proxy")) {
3884 					outbound_proxy = val;
3885 				} else if (!strcmp(var, "distinct-to")) {
3886 					distinct_to = switch_true(val);
3887 				} else if (!strcmp(var, "destination-prefix")) {
3888 					if (!zstr(val)) {
3889 						gateway->destination_prefix = switch_core_strdup(gateway->pool, val);
3890 					}
3891 				} else if (!strcmp(var, "rfc-5626")) {
3892 					rfc_5626 = switch_true(val);
3893 				} else if (!strcmp(var, "reg-id")) {
3894 					reg_id = val;
3895 				} else if (!strcmp(var, "contact-params")) {
3896 					contact_params = val;
3897 				} else if (!strcmp(var, "register-transport")) {
3898 					sofia_transport_t transport = sofia_glue_str2transport(val);
3899 
3900 					if (transport == SOFIA_TRANSPORT_UNKNOWN || (!sofia_test_pflag(profile, PFLAG_TLS) && sofia_glue_transport_has_tls(transport))) {
3901 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: unsupported transport\n");
3902 						goto skip;
3903 					}
3904 
3905 					gateway->register_transport = transport;
3906 				}
3907 			}
3908 
3909 			/* RFC 5626 enable in the GW profile and the UA profile */
3910 			if (rfc_5626 && sofia_test_pflag(profile, PFLAG_ENABLE_RFC5626)) {
3911 				char str_guid[su_guid_strlen + 1];
3912 				su_guid_t guid[1];
3913 				su_guid_generate(guid);
3914 				su_guid_sprintf(str_guid, su_guid_strlen + 1, guid);
3915 				str_rfc_5626 = switch_core_sprintf(gateway->pool, ";reg-id=%s;+sip.instance=\"<urn:uuid:%s>\"",reg_id,str_guid);
3916 			}
3917 
3918 			if (zstr(realm)) {
3919 				if (zstr(proxy)) {
3920 					realm = name;
3921 				} else {
3922 					realm = proxy;
3923 				}
3924 			}
3925 
3926 			if (switch_true(register_str)) {
3927 				if (zstr(username)) {
3928 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: username param is REQUIRED!\n");
3929 					goto skip;
3930 				}
3931 
3932 				if (zstr(password)) {
3933 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: password param is REQUIRED!\n");
3934 					goto skip;
3935 				}
3936 			} else {
3937 				if (zstr(username)) {
3938 					username = "FreeSWITCH";
3939 				}
3940 
3941 				if (zstr(password)) {
3942 					password = "";
3943 				}
3944 			}
3945 
3946 			if (zstr(from_user)) {
3947 				from_user = username;
3948 			}
3949 
3950 			if (zstr(proxy)) {
3951 				proxy = realm;
3952 			}
3953 
3954 			if (!switch_true(register_str)) {
3955 				gateway->state = REG_STATE_NOREG;
3956 				gateway->status = SOFIA_GATEWAY_UP;
3957 				gateway->uptime = switch_time_now();
3958 			}
3959 
3960 			if (zstr(auth_username)) {
3961 				auth_username = username;
3962 			}
3963 
3964 			if (!zstr(register_proxy)) {
3965 				if (strncasecmp(register_proxy, "sip:", 4) && strncasecmp(register_proxy, "sips:", 5)) {
3966 					gateway->register_sticky_proxy = switch_core_sprintf(gateway->pool, "sip:%s", register_proxy);
3967 				} else {
3968 					gateway->register_sticky_proxy = switch_core_strdup(gateway->pool, register_proxy);
3969 				}
3970 			}
3971 
3972 			if (!zstr(outbound_proxy)) {
3973 				if (strncasecmp(outbound_proxy, "sip:", 4) && strncasecmp(outbound_proxy, "sips:", 5)) {
3974 					gateway->outbound_sticky_proxy = switch_core_sprintf(gateway->pool, "sip:%s", outbound_proxy);
3975 				} else {
3976 					gateway->outbound_sticky_proxy = switch_core_strdup(gateway->pool, outbound_proxy);
3977 				}
3978 			}
3979 
3980 			gateway->retry_seconds = atoi(retry_seconds);
3981 
3982 			if (fail_908_retry_seconds) {
3983 				gateway->fail_908_retry_seconds = atoi(fail_908_retry_seconds);
3984 			}
3985 
3986 			if (gateway->retry_seconds < 5) {
3987 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid retry-seconds of %d on gateway %s, using the value of 30 instead.\n",
3988 								  gateway->retry_seconds, name);
3989 				gateway->retry_seconds = 30;
3990 			}
3991 
3992 			gateway->reg_timeout_seconds = atoi(timeout_seconds);
3993 
3994 			if (gateway->reg_timeout_seconds < 5) {
3995 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid timeout-seconds of %d on gateway %s, using the value of 60 instead.\n",
3996 								  gateway->reg_timeout_seconds, name);
3997 				gateway->reg_timeout_seconds = 60;
3998 			}
3999 
4000 
4001 			gateway->register_scheme = switch_core_strdup(gateway->pool, scheme);
4002 			gateway->register_context = switch_core_strdup(gateway->pool, context);
4003 			gateway->register_realm = switch_core_strdup(gateway->pool, realm);
4004 			gateway->register_username = switch_core_strdup(gateway->pool, username);
4005 			gateway->auth_username = switch_core_strdup(gateway->pool, auth_username);
4006 			gateway->register_password = switch_core_strdup(gateway->pool, password);
4007 			gateway->distinct_to = distinct_to;
4008 			gateway->options_user_agent = options_user_agent;
4009 
4010 			if (switch_true(caller_id_in_from)) {
4011 				sofia_set_flag(gateway, REG_FLAG_CALLERID);
4012 			}
4013 
4014 			register_transport = (char *) sofia_glue_transport2str(gateway->register_transport);
4015 
4016 			if (! zstr(contact_params)) {
4017 				if (*contact_params == ';') {
4018 					params = switch_core_sprintf(gateway->pool, "%s;transport=%s;gw=%s", contact_params, register_transport, gateway->name);
4019 				} else {
4020 					params = switch_core_sprintf(gateway->pool, ";%s;transport=%s;gw=%s", contact_params, register_transport, gateway->name);
4021 				}
4022 			} else {
4023 				params = switch_core_sprintf(gateway->pool, ";transport=%s;gw=%s", register_transport, gateway->name);
4024 			}
4025 
4026 			if (!zstr(from_domain)) {
4027 				gateway->from_domain = switch_core_strdup(gateway->pool, from_domain);
4028 			}
4029 
4030 			if (!zstr(register_transport) && !switch_stristr("transport=", proxy)) {
4031 				gateway->register_url = switch_core_sprintf(gateway->pool, "sip:%s;transport=%s", proxy, register_transport);
4032 			} else {
4033 				gateway->register_url = switch_core_sprintf(gateway->pool, "sip:%s", proxy);
4034 			}
4035 
4036 			gateway->register_from = switch_core_sprintf(gateway->pool, "<sip:%s@%s>",
4037 				 from_user, !zstr(from_domain) ? from_domain : proxy);
4038 
4039 			if (ping_freq) {
4040 				if (ping_freq >= 5) {
4041 					gateway->ping_freq = ping_freq;
4042 					gateway->ping_max = ping_max;
4043 					gateway->ping_min = ping_min;
4044 					gateway->ping_monitoring = ping_monitoring;
4045 					gateway->ping = switch_epoch_time_now(NULL) + ping_freq;
4046 					gateway->options_to_uri = switch_core_sprintf(gateway->pool, "<sip:%s>",
4047 						!zstr(from_domain) ? from_domain : proxy);
4048 					gateway->options_from_uri = gateway->options_to_uri;
4049 					if (contact_in_ping) {
4050 						gateway->contact_in_ping = contact_in_ping;
4051 					}
4052 				} else {
4053 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR: invalid ping!\n");
4054 				}
4055 			}
4056 
4057 			if (contact_host) {
4058 				if (!strcmp(contact_host, "sip-ip")) {
4059 					sipip = profile->sipip;
4060 				} else {
4061 					sipip = contact_host;
4062 				}
4063 			} else if (profile->extsipip) {
4064 				sipip = profile->extsipip;
4065 			} else {
4066 				sipip = profile->sipip;
4067 			}
4068 
4069 			if (zstr(extension)) {
4070 				extension = username;
4071 			} else {
4072 				gateway->real_extension = switch_core_strdup(gateway->pool, extension);
4073 			}
4074 
4075 			gateway->extension = switch_core_strdup(gateway->pool, extension);
4076 
4077 			if (!strncasecmp(proxy, "sip:", 4)) {
4078 				gateway->register_proxy = switch_core_strdup(gateway->pool, proxy);
4079 				gateway->register_to = switch_core_sprintf(gateway->pool, "sip:%s@%s", username, proxy + 4);
4080 			} else {
4081 				gateway->register_proxy = switch_core_sprintf(gateway->pool, "sip:%s", proxy);
4082 				gateway->register_to = switch_core_sprintf(gateway->pool, "sip:%s@%s", username, proxy);
4083 			}
4084 
4085 			/* This checks to make sure we provide the right contact on register for targets behind nat with us. */
4086 			if (sofia_test_pflag(profile, PFLAG_AUTO_NAT)) {
4087 				char *register_host = NULL;
4088 
4089 				register_host = sofia_glue_get_register_host(gateway->register_proxy);
4090 
4091 				if (register_host && switch_is_lan_addr(register_host)) {
4092 					sipip = profile->sipip;
4093 				}
4094 
4095 				switch_safe_free(register_host);
4096 			}
4097 
4098 			if (extension_in_contact) {
4099 				if (rfc_5626) {
4100 					format = strchr(sipip, ':') ? "<sip:%s@[%s]:%d>%s" : "<sip:%s@%s:%d%s>%s";
4101 					gateway->register_contact = switch_core_sprintf(gateway->pool, format, extension,
4102 							sipip,
4103 							sofia_glue_transport_has_tls(gateway->register_transport) ?
4104 							profile->tls_sip_port : profile->extsipport, params, str_rfc_5626);
4105 
4106 				} else {
4107 					format = strchr(sipip, ':') ? "<sip:%s@[%s]:%d%s>" : "<sip:%s@%s:%d%s>";
4108 					gateway->register_contact = switch_core_sprintf(gateway->pool, format, extension,
4109 							sipip,
4110 							sofia_glue_transport_has_tls(gateway->register_transport) ?
4111 							profile->tls_sip_port : profile->extsipport, params);
4112 				}
4113 			} else {
4114 				if (rfc_5626) {
4115 					format = strchr(sipip, ':') ? "<sip:gw+%s@[%s]:%d%s>%s" : "<sip:gw+%s@%s:%d%s>%s";
4116 					gateway->register_contact = switch_core_sprintf(gateway->pool, format, gateway->name,
4117 							sipip,
4118 							sofia_glue_transport_has_tls(gateway->register_transport) ?
4119 							profile->tls_sip_port : profile->extsipport, params, str_rfc_5626);
4120 
4121 				} else {
4122 					format = strchr(sipip, ':') ? "<sip:gw+%s@[%s]:%d%s>" : "<sip:gw+%s@%s:%d%s>";
4123 					gateway->register_contact = switch_core_sprintf(gateway->pool, format, gateway->name,
4124 							sipip,
4125 							sofia_glue_transport_has_tls(gateway->register_transport) ?
4126 							profile->tls_sip_port : profile->extsipport, params);
4127 
4128 				}
4129 			}
4130 
4131 			gateway->expires_str = switch_core_strdup(gateway->pool, expire_seconds);
4132 
4133 			if ((gateway->freq = atoi(gateway->expires_str)) < 5) {
4134 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
4135 								  "Invalid register-frequency of %d on gateway %s, using the value of 3600 instead\n", gateway->freq, name);
4136 				gateway->freq = 3600;
4137 			}
4138 
4139 			if ((gw_subs_tag = switch_xml_child(gateway_tag, "subscriptions"))) {
4140 				parse_gateway_subscriptions(profile, gateway, gw_subs_tag);
4141 			}
4142 
4143 			sofia_reg_add_gateway(profile, gateway->name, gateway);
4144 
4145 		}
4146 
4147 	  skip:
4148 		switch_assert(gateway_tag);
4149 	}
4150 }
4151 
parse_domain_tag(sofia_profile_t * profile,switch_xml_t x_domain_tag,const char * dname,const char * parse,const char * alias)4152 static void parse_domain_tag(sofia_profile_t *profile, switch_xml_t x_domain_tag, const char *dname, const char *parse, const char *alias)
4153 {
4154 	if (switch_true(alias)) {
4155 		if (sofia_glue_add_profile(switch_core_strdup(profile->pool, dname), profile) == SWITCH_STATUS_SUCCESS) {
4156 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Alias [%s] for profile [%s]\n", dname, profile->name);
4157 		} else {
4158 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Alias [%s] for profile [%s] (already exists)\n", dname, profile->name);
4159 		}
4160 	}
4161 
4162 	if (switch_true(parse)) {
4163 		switch_xml_t gts, gt, uts, ut, gateways_tag;
4164 		/* Backwards Compatibility */
4165 		for (ut = switch_xml_child(x_domain_tag, "user"); ut; ut = ut->next) {
4166 			if (((gateways_tag = switch_xml_child(ut, "gateways")))) {
4167 				parse_gateways(profile, gateways_tag, NULL);
4168 			}
4169 		}
4170 		/* New Method with <groups> tags and users are now inside a <users> tag */
4171 		for (gts = switch_xml_child(x_domain_tag, "groups"); gts; gts = gts->next) {
4172 			for (gt = switch_xml_child(gts, "group"); gt; gt = gt->next) {
4173 				for (uts = switch_xml_child(gt, "users"); uts; uts = uts->next) {
4174 					for (ut = switch_xml_child(uts, "user"); ut; ut = ut->next) {
4175 						if (((gateways_tag = switch_xml_child(ut, "gateways")))) {
4176 							parse_gateways(profile, gateways_tag, NULL);
4177 						}
4178 					}
4179 				}
4180 			}
4181 		}
4182 	}
4183 }
4184 
config_sofia_profile_urls(sofia_profile_t * profile)4185 static void config_sofia_profile_urls(sofia_profile_t * profile)
4186 {
4187 
4188 	if (profile->extsipip) {
4189 		char *ipv6 = strchr(profile->extsipip, ':');
4190 		profile->public_url = switch_core_sprintf(profile->pool,
4191 												  "sip:%s@%s%s%s:%d",
4192 												  profile->contact_user,
4193 												  ipv6 ? "[" : "", profile->extsipip, ipv6 ? "]" : "", profile->extsipport);
4194 	}
4195 
4196 	if (profile->extsipip && !sofia_test_pflag(profile, PFLAG_AUTO_NAT)) {
4197 		char *ipv6 = strchr(profile->extsipip, ':');
4198 		profile->url = switch_core_sprintf(profile->pool,
4199 										   "sip:%s@%s%s%s:%d",
4200 										   profile->contact_user, ipv6 ? "[" : "", profile->extsipip, ipv6 ? "]" : "", profile->extsipport);
4201 		profile->bindurl = switch_core_sprintf(profile->pool, "%s;maddr=%s", profile->url, profile->sipip);
4202 	} else {
4203 		char *ipv6 = strchr(profile->sipip, ':');
4204 		profile->url = switch_core_sprintf(profile->pool,
4205 										   "sip:%s@%s%s%s:%d",
4206 										   profile->contact_user, ipv6 ? "[" : "", profile->sipip, ipv6 ? "]" : "", profile->sip_port);
4207 		profile->bindurl = profile->url;
4208 	}
4209 
4210 	profile->tcp_contact = switch_core_sprintf(profile->pool, "<%s;transport=tcp>", profile->url);
4211 
4212 	if (profile->public_url) {
4213 		profile->tcp_public_contact = switch_core_sprintf(profile->pool, "<%s;transport=tcp>", profile->public_url);
4214 	}
4215 
4216 	if (profile->bind_params) {
4217 		char *bindurl;
4218 		if (!switch_stristr("transport=", profile->bind_params)) {
4219 			profile->bind_params = switch_core_sprintf(profile->pool, "%s;transport=udp,tcp", profile->bind_params);
4220 		}
4221 		bindurl = switch_core_sprintf(profile->pool, "%s;%s", profile->bindurl, profile->bind_params);
4222 		profile->bindurl = bindurl;
4223 	} else {
4224 		char *bindurl = switch_core_sprintf(profile->pool, "%s;transport=udp,tcp", profile->bindurl);
4225 		profile->bindurl = bindurl;
4226 	}
4227 
4228 
4229 	if ( profile->ws_port ) {
4230 		char *ip = !zstr(profile->ws_ip) ? profile->ws_ip : profile->sipip;
4231 		switch_port_t port = profile->ws_port;
4232 		char *ipv6 = strchr(ip, ':');
4233 		profile->ws_bindurl =
4234 			switch_core_sprintf(profile->pool,
4235 								"sip:%s@%s%s%s:%d;transport=ws",
4236 								profile->contact_user, ipv6 ? "[" : "", ip, ipv6 ? "]" : "", port);
4237 	}
4238 
4239 	if ( profile->wss_port ) {
4240 		char *ip = !zstr(profile->wss_ip) ? profile->wss_ip : profile->sipip;
4241 		switch_port_t port = profile->wss_port;
4242 		char *ipv6 = strchr(ip, ':');
4243 		profile->wss_bindurl =
4244 			switch_core_sprintf(profile->pool,
4245 								"sips:%s@%s%s%s:%d;transport=wss",
4246 								profile->contact_user, ipv6 ? "[" : "", ip, ipv6 ? "]" : "", port);
4247 	}
4248 
4249 	/*
4250 	 * handle TLS params #2
4251 	 */
4252 	if (sofia_test_pflag(profile, PFLAG_TLS)) {
4253 		if (!profile->tls_sip_port && !sofia_test_pflag(profile, PFLAG_AUTO_ASSIGN_TLS_PORT)) {
4254 			profile->tls_sip_port = (switch_port_t) atoi(SOFIA_DEFAULT_TLS_PORT);
4255 		}
4256 
4257 		if (profile->extsipip) {
4258 			char *ipv6 = strchr(profile->extsipip, ':');
4259 			profile->tls_public_url = switch_core_sprintf(profile->pool,
4260 														  "sip:%s@%s%s%s:%d",
4261 														  profile->contact_user,
4262 														  ipv6 ? "[" : "", profile->extsipip, ipv6 ? "]" : "", profile->tls_sip_port);
4263 		}
4264 
4265 		if (profile->extsipip && !sofia_test_pflag(profile, PFLAG_AUTO_NAT)) {
4266 			char *ipv6 = strchr(profile->extsipip, ':');
4267 			profile->tls_url =
4268 				switch_core_sprintf(profile->pool,
4269 									"sip:%s@%s%s%s:%d",
4270 									profile->contact_user, ipv6 ? "[" : "", profile->extsipip, ipv6 ? "]" : "", profile->tls_sip_port);
4271 			profile->tls_bindurl =
4272 				switch_core_sprintf(profile->pool,
4273 									"sips:%s@%s%s%s:%d;maddr=%s",
4274 									profile->contact_user,
4275 									ipv6 ? "[" : "", profile->extsipip, ipv6 ? "]" : "", profile->tls_sip_port, profile->sipip);
4276 		} else {
4277 			char *ipv6 = strchr(profile->sipip, ':');
4278 			profile->tls_url =
4279 				switch_core_sprintf(profile->pool,
4280 									"sip:%s@%s%s%s:%d",
4281 									profile->contact_user, ipv6 ? "[" : "", profile->sipip, ipv6 ? "]" : "", profile->tls_sip_port);
4282 			profile->tls_bindurl =
4283 				switch_core_sprintf(profile->pool,
4284 									"sips:%s@%s%s%s:%d",
4285 									profile->contact_user, ipv6 ? "[" : "", profile->sipip, ipv6 ? "]" : "", profile->tls_sip_port);
4286 		}
4287 
4288 		if (profile->tls_bind_params) {
4289 			char *tls_bindurl = profile->tls_bindurl;
4290 			profile->tls_bindurl = switch_core_sprintf(profile->pool, "%s;%s", tls_bindurl, profile->tls_bind_params);
4291 		}
4292 
4293 		profile->tls_contact = switch_core_sprintf(profile->pool, "<%s;transport=tls>", profile->tls_url);
4294 		if (profile->tls_public_url) {
4295 			profile->tls_public_contact = switch_core_sprintf(profile->pool, "<%s;transport=tls>", profile->tls_public_url);
4296 		}
4297 
4298 
4299 	}
4300 }
4301 
4302 #ifdef SOFIA_CUSTOM_TIME
4303 /* appears to not be granular enough */
sofia_time(su_time_t * tv)4304 static void sofia_time(su_time_t *tv)
4305 {
4306 	switch_time_t now;
4307 
4308 	if (tv) {
4309 		now = switch_micro_time_now();
4310 		tv->tv_sec = ((uint32_t) (now / 1000000)) + 2208988800UL;
4311 		tv->tv_usec = (uint32_t) (now % 1000000);
4312 	}
4313 
4314 }
4315 #endif
4316 
sofia_init(void)4317 switch_status_t sofia_init(void)
4318 {
4319 	su_init();
4320 	if (sip_update_default_mclass(sip_extend_mclass(NULL)) < 0) {
4321 		su_deinit();
4322 		sip_cloned_parser_destroy();
4323 		return SWITCH_STATUS_GENERR;
4324 	}
4325 
4326 #ifdef SOFIA_TIME
4327 	su_set_time_func(sofia_time);
4328 #endif
4329 
4330 	/* Redirect loggers in sofia */
4331 	su_log_redirect(su_log_default, logger, NULL);
4332 	su_log_redirect(tport_log, logger, NULL);
4333 	su_log_redirect(iptsec_log, logger, NULL);
4334 	su_log_redirect(nea_log, logger, NULL);
4335 	su_log_redirect(nta_log, logger, NULL);
4336 	su_log_redirect(nth_client_log, logger, NULL);
4337 	su_log_redirect(nth_server_log, logger, NULL);
4338 	su_log_redirect(nua_log, logger, NULL);
4339 	su_log_redirect(soa_log, logger, NULL);
4340 	su_log_redirect(sresolv_log, logger, NULL);
4341 #ifdef HAVE_SOFIA_STUN
4342 	su_log_redirect(stun_log, logger, NULL);
4343 #endif
4344 
4345 	return SWITCH_STATUS_SUCCESS;
4346 }
4347 
config_gateway(const char * profile_name,const char * gateway_name)4348 switch_status_t config_gateway(const char *profile_name, const char *gateway_name)
4349 {
4350 	switch_xml_t cfg, xml = NULL, xprofiles, xprofile, gateways_tag;
4351 	switch_status_t status = SWITCH_STATUS_SUCCESS;
4352 	sofia_profile_t *profile = NULL;
4353 	switch_event_t *params = NULL;
4354 	const char *cf = "sofia.conf";
4355 
4356 	if (zstr(profile_name) || !(profile = sofia_glue_find_profile(profile_name))) {
4357 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Profile [%s] does not exist.\n", profile_name);
4358 		status = SWITCH_STATUS_FALSE;
4359 		return status;
4360 	}
4361 
4362 	switch_event_create(&params, SWITCH_EVENT_REQUEST_PARAMS);
4363 	switch_assert(params);
4364 	switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "profile", profile_name);
4365 	switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "reconfig", "true");
4366 	switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "gateway", gateway_name);
4367 
4368 	if (!(xml = switch_xml_open_cfg(cf, &cfg, params))) {
4369 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", gateway_name);
4370 		status = SWITCH_STATUS_FALSE;
4371 		goto done;
4372 	}
4373 
4374 	if ((xprofiles = switch_xml_child(cfg, "profiles"))) {
4375 		if ((xprofile = switch_xml_find_child(xprofiles, "profile", "name", profile->name))) {
4376 			if ((gateways_tag = switch_xml_child(xprofile, "gateways"))) {
4377 				parse_gateways(profile, gateways_tag, strcmp(gateway_name, "_all_") ? gateway_name : NULL);
4378 			}
4379 		}
4380 	}
4381 
4382 	status = SWITCH_STATUS_SUCCESS;
4383 
4384 done:
4385 
4386 	sofia_glue_release_profile(profile);
4387 	if (xml) switch_xml_free(xml);
4388 
4389 	switch_event_destroy(&params);
4390 
4391 	return status;
4392 }
4393 
config_sofia(sofia_config_t reload,char * profile_name)4394 switch_status_t config_sofia(sofia_config_t reload, char *profile_name)
4395 {
4396 	char *cf = "sofia.conf";
4397 	switch_xml_t cfg, xml = NULL, xprofile, param, settings, profiles;
4398 	switch_status_t status = SWITCH_STATUS_SUCCESS;
4399 	sofia_profile_t *profile = NULL;
4400 	char url[512] = "";
4401 	int profile_found = 0;
4402 	switch_event_t *params = NULL;
4403 	sofia_profile_t *profile_already_started = NULL;
4404 
4405 	if (!zstr(profile_name) && (profile = sofia_glue_find_profile(profile_name))) {
4406 		if (reload == SOFIA_CONFIG_RESCAN) {
4407 			profile_already_started = profile;
4408 		} else {
4409 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Profile [%s] Already exists.\n", switch_str_nil(profile_name));
4410 			status = SWITCH_STATUS_FALSE;
4411 			sofia_glue_release_profile(profile);
4412 			return status;
4413 		}
4414 	}
4415 
4416 	switch_event_create(&params, SWITCH_EVENT_REQUEST_PARAMS);
4417 	switch_assert(params);
4418 	switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "profile", profile_name);
4419 	if (reload == SOFIA_CONFIG_RESCAN) {
4420 		switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "reconfig", "true");
4421 	}
4422 
4423 	if (!(xml = switch_xml_open_cfg(cf, &cfg, params))) {
4424 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
4425 		status = SWITCH_STATUS_FALSE;
4426 		goto done;
4427 	}
4428 
4429 	mod_sofia_globals.auto_restart = SWITCH_TRUE;
4430 	mod_sofia_globals.reg_deny_binding_fetch_and_no_lookup = SWITCH_FALSE; /* handle backwards compatilibity - by default use new behavior */
4431 	mod_sofia_globals.rewrite_multicasted_fs_path = SWITCH_FALSE;
4432 
4433 	if ((settings = switch_xml_child(cfg, "global_settings"))) {
4434 		for (param = switch_xml_child(settings, "param"); param; param = param->next) {
4435 			char *var = (char *) switch_xml_attr_soft(param, "name");
4436 			char *val = (char *) switch_xml_attr_soft(param, "value");
4437 			if (!strcasecmp(var, "log-level")) {
4438 				su_log_set_level(NULL, atoi(val));
4439 			} else if (!strcasecmp(var, "abort-on-empty-external-ip")) {
4440 				mod_sofia_globals.abort_on_empty_external_ip = switch_true(val);
4441 			} else if (!strcasecmp(var, "tracelevel")) {
4442 				mod_sofia_globals.tracelevel = switch_log_str2level(val);
4443 			} else if (!strcasecmp(var, "debug-presence")) {
4444 				mod_sofia_globals.debug_presence = atoi(val);
4445 			} else if (!strcasecmp(var, "debug-sla")) {
4446 				mod_sofia_globals.debug_sla = atoi(val);
4447 			} else if (!strcasecmp(var, "max-reg-threads") && val) {
4448 				int x = atoi(val);
4449 
4450 				if (x > 0) {
4451 					mod_sofia_globals.max_reg_threads = x;
4452 				}
4453 
4454 			} else if (!strcasecmp(var, "auto-restart")) {
4455 				mod_sofia_globals.auto_restart = switch_true(val);
4456 			} else if (!strcasecmp(var, "reg-deny-binding-fetch-and-no-lookup")) {          /* backwards compatibility */
4457 				mod_sofia_globals.reg_deny_binding_fetch_and_no_lookup = switch_true(val);  /* remove when noone complains about the extra lookup */
4458 				if (switch_true(val)) {
4459 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Enabling reg-deny-binding-fetch-and-no-lookup - this functionality is "
4460 															 "deprecated and will be removed - let FS devs know if you think it should stay\n");
4461 				}
4462 			} else if (!strcasecmp(var, "rewrite-multicasted-fs-path")) {
4463 				if( (!strcasecmp(val, "to_host")) || (!strcasecmp(val, "1")) ) {
4464 					/* old behaviour */
4465 									mod_sofia_globals.rewrite_multicasted_fs_path = 1;
4466 				} else if (!strcasecmp(val, "original_server_host")) {
4467 									mod_sofia_globals.rewrite_multicasted_fs_path = 2;
4468 				} else if (!strcasecmp(val, "original_hostname")) {
4469 									mod_sofia_globals.rewrite_multicasted_fs_path = 3;
4470 				} else {
4471 					mod_sofia_globals.rewrite_multicasted_fs_path = SWITCH_FALSE;
4472 				}
4473 			} else if (!strcasecmp(var, "capture-server")) {
4474 				mod_sofia_globals.capture_server = switch_core_strdup(mod_sofia_globals.pool, val);
4475 			}
4476 		}
4477 	}
4478 
4479 	if ((profiles = switch_xml_child(cfg, "profiles"))) {
4480 		for (xprofile = switch_xml_child(profiles, "profile"); xprofile; xprofile = xprofile->next) {
4481 			char *xprofilename = (char *) switch_xml_attr_soft(xprofile, "name");
4482 			char *xprofiledomain = (char *) switch_xml_attr(xprofile, "domain");
4483 			if (!(settings = switch_xml_child(xprofile, "settings"))) {
4484 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Settings, check the new config!\n");
4485 				sofia_profile_start_failure(NULL, xprofilename);
4486 			} else {
4487 				switch_memory_pool_t *pool = NULL;
4488 
4489 				if (!xprofilename) {
4490 					xprofilename = "unnamed";
4491 				}
4492 
4493 				if (profile_name) {
4494 					if (strcasecmp(profile_name, xprofilename)) {
4495 						continue;
4496 					} else {
4497 						profile_found = 1;
4498 					}
4499 				}
4500 
4501 				if (!profile_already_started) {
4502 
4503 					/* Setup the pool */
4504 					if ((status = switch_core_new_memory_pool(&pool)) != SWITCH_STATUS_SUCCESS) {
4505 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
4506 						sofia_profile_start_failure(NULL, xprofilename);
4507 						goto done;
4508 					}
4509 
4510 					if (!(profile = (sofia_profile_t *) switch_core_alloc(pool, sizeof(*profile)))) {
4511 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
4512 						sofia_profile_start_failure(NULL, xprofilename);
4513 						goto done;
4514 					}
4515 
4516 					profile->tls_verify_policy = TPTLS_VERIFY_NONE;
4517 					sofia_set_pflag(profile, PFLAG_AUTO_INVITE_100);
4518 					/* lib default */
4519 					profile->tls_verify_depth = 2;
4520 
4521 
4522 					switch_mutex_init(&profile->gw_mutex, SWITCH_MUTEX_NESTED, pool);
4523 
4524 					profile->trans_timeout = 100;
4525 
4526 					profile->auto_rtp_bugs = RTP_BUG_CISCO_SKIP_MARK_BIT_2833;// | RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833;
4527 
4528 					profile->pool = pool;
4529 
4530 					profile->user_agent = switch_core_sprintf(profile->pool, "FreeSWITCH-mod_sofia/%s", switch_version_full());
4531 
4532 					profile->sip_user_ping_max = 3;
4533 					profile->sip_user_ping_min = 1;
4534 
4535 					profile->name = switch_core_strdup(profile->pool, xprofilename);
4536 					switch_snprintf(url, sizeof(url), "sofia_reg_%s", xprofilename);
4537 
4538 					if (xprofiledomain) {
4539 						profile->domain_name = switch_core_strdup(profile->pool, xprofiledomain);
4540 					}
4541 
4542 					profile->dbname = switch_core_strdup(profile->pool, url);
4543 					switch_core_hash_init(&profile->chat_hash);
4544 					switch_core_hash_init(&profile->reg_nh_hash);
4545 					switch_core_hash_init(&profile->mwi_debounce_hash);
4546 					switch_thread_rwlock_create(&profile->rwlock, profile->pool);
4547 					switch_mutex_init(&profile->flag_mutex, SWITCH_MUTEX_NESTED, profile->pool);
4548 					profile->dtmf_duration = 100;
4549 					profile->rtp_digit_delay = 40;
4550 					profile->sip_force_expires = 0;
4551 					profile->sip_force_expires_min = 0;
4552 					profile->sip_force_expires_max = 0;
4553 					profile->sip_expires_max_deviation = 0;
4554 					profile->sip_expires_late_margin = 60;
4555 					profile->sip_subscription_max_deviation = 0;
4556 					profile->tls_ciphers = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH";
4557 					profile->tls_version = SOFIA_TLS_VERSION_TLSv1;
4558 					profile->tls_version |= SOFIA_TLS_VERSION_TLSv1_1;
4559 					profile->tls_version |= SOFIA_TLS_VERSION_TLSv1_2;
4560 					profile->tls_timeout = 300;
4561 					profile->mflags = MFLAG_REFER | MFLAG_REGISTER;
4562 					profile->server_rport_level = 1;
4563 					profile->client_rport_level = 1;
4564 					profile->tls_cert_dir = SWITCH_GLOBAL_dirs.certs_dir;
4565 					sofia_set_pflag(profile, PFLAG_DISABLE_100REL);
4566 					sofia_set_pflag(profile, PFLAG_ENABLE_CHAT);
4567 					profile->auto_restart = 1;
4568 					sofia_set_media_flag(profile, SCMF_AUTOFIX_TIMING);
4569 					sofia_set_media_flag(profile, SCMF_RTP_AUTOFLUSH_DURING_BRIDGE);
4570 					profile->contact_user = SOFIA_DEFAULT_CONTACT_USER;
4571 					sofia_set_pflag(profile, PFLAG_PASS_CALLEE_ID);
4572 					sofia_set_pflag(profile, PFLAG_ALLOW_UPDATE);
4573 					sofia_set_pflag(profile, PFLAG_SEND_DISPLAY_UPDATE);
4574 					sofia_set_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER);
4575 					//sofia_set_pflag(profile, PFLAG_PRESENCE_ON_FIRST_REGISTER);
4576 
4577 					sofia_clear_pflag(profile, PFLAG_CHANNEL_XML_FETCH_ON_NIGHTMARE_TRANSFER);
4578 					sofia_clear_pflag(profile, PFLAG_MAKE_EVERY_TRANSFER_A_NIGHTMARE);
4579 					sofia_clear_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS);
4580 					sofia_clear_pflag(profile, PFLAG_BLIND_AUTH_ENFORCE_RESULT);
4581 					sofia_clear_pflag(profile, PFLAG_BLIND_AUTH_REPLY_403);
4582 					sofia_clear_pflag(profile, PFLAG_AUTH_REQUIRE_USER);
4583 					sofia_clear_pflag(profile, PFLAG_AUTH_CALLS_ACL_ONLY);
4584 					sofia_clear_pflag(profile, PFLAG_USE_PORT_FOR_ACL_CHECK);
4585 					profile->shutdown_type = "false";
4586 					profile->local_network = "localnet.auto";
4587 					sofia_set_flag(profile, TFLAG_ENABLE_SOA);
4588 					sofia_set_pflag(profile, PFLAG_CID_IN_1XX);
4589 					profile->mndlb |= SM_NDLB_ALLOW_NONDUP_SDP;
4590 					profile->te = 101;
4591 					profile->ireg_seconds = IREG_SECONDS;
4592 					profile->iping_seconds = IPING_SECONDS;
4593 					profile->iping_freq = IPING_FREQUENCY;
4594 					profile->paid_type = PAID_DEFAULT;
4595 					profile->bind_attempts = 2;
4596 					profile->bind_attempt_interval = 5;
4597 					profile->dtmf_type = DTMF_2833;
4598 					profile->tls_verify_policy = TPTLS_VERIFY_NONE;
4599 					/* lib default */
4600 					profile->tls_verify_depth = 2;
4601 					profile->tls_verify_date = SWITCH_TRUE;
4602 				} else {
4603 
4604 					/* you could change profile->foo here if it was a minor change like context or dialplan ... */
4605 					profile->acl_count = 0;
4606 					profile->nat_acl_count = 0;
4607 					profile->reg_acl_count = 0;
4608 					profile->proxy_acl_count = 0;
4609 					sofia_set_pflag(profile, PFLAG_PASS_CALLEE_ID);
4610 					profile->ib_calls = 0;
4611 					profile->ob_calls = 0;
4612 					profile->ib_failed_calls = 0;
4613 					profile->ob_failed_calls = 0;
4614 					profile->shutdown_type = "false";
4615 					profile->rtpip_index = 0;
4616 					profile->rtpip_index6 = 0;
4617 
4618 					if (xprofiledomain) {
4619 						profile->domain_name = switch_core_strdup(profile->pool, xprofiledomain);
4620 					}
4621 				}
4622 
4623 				for (param = switch_xml_child(settings, "param"); param; param = param->next) {
4624 					char *var = (char *) switch_xml_attr_soft(param, "name");
4625 					char *val = (char *) switch_xml_attr_soft(param, "value");
4626 					int found = 1; // Used to break up long if/elseif chain (MSVC2015 fails (parser stack overflow) otherwise)
4627 
4628 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s [%s]\n", var, val);
4629 
4630 					if (!strcasecmp(var, "debug") && val) {
4631 						profile->debug = atoi(val);
4632 					} else if (!strcasecmp(var, "parse-invite-tel-params")) {
4633 						profile->parse_invite_tel_params = switch_true(val);
4634 					} else if (!strcasecmp(var, "keepalive-method") && !zstr(val)) {
4635 						if (!strcasecmp(val, "info")) {
4636 							profile->keepalive = KA_INFO;
4637 						} else {
4638 							profile->keepalive = KA_MESSAGE;
4639 						}
4640 					} else if (!strcasecmp(var, "bind-attempts") && val) {
4641 						int ba = atoi(val) - 1;
4642 
4643 						if (ba >= 0) {
4644 							profile->bind_attempts = ba;
4645 						}
4646 					} else if (!strcasecmp(var, "bind-attempt-interval") && val) {
4647 						int bai = atoi(val);
4648 
4649 						if (bai >= 0) {
4650 							profile->bind_attempt_interval = bai;
4651 						}
4652 					} else if (!strcasecmp(var, "shutdown-on-fail")) {
4653 						profile->shutdown_type = switch_core_strdup(profile->pool, val);
4654 					} else if (!strcasecmp(var, "sip-trace")) {
4655 						if (switch_true(val)) {
4656 							sofia_set_flag(profile, TFLAG_TPORT_LOG);
4657 						} else {
4658 							sofia_clear_flag(profile, TFLAG_TPORT_LOG);
4659 						}
4660 					} else if (!strcasecmp(var, "sip-capture")) {
4661 						if (switch_true(val)) {
4662 							sofia_set_flag(profile, TFLAG_CAPTURE);
4663 							nua_set_params(profile->nua, TPTAG_CAPT(mod_sofia_globals.capture_server), TAG_END());
4664 						} else {
4665 							sofia_clear_flag(profile, TFLAG_CAPTURE);
4666 						}
4667 					} else if (!strcasecmp(var, "socket-tcp-keepalive") && !zstr(val)) {
4668 						profile->socket_tcp_keepalive = atoi(val);
4669 						sofia_set_pflag(profile, PFLAG_SOCKET_TCP_KEEPALIVE);
4670 					} else if (!strcasecmp(var, "tcp-keepalive") && !zstr(val)) {
4671 						profile->tcp_keepalive = atoi(val);
4672 						sofia_set_pflag(profile, PFLAG_TCP_KEEPALIVE);
4673 					} else if (!strcasecmp(var, "tcp-pingpong") && !zstr(val)) {
4674 						profile->tcp_pingpong = atoi(val);
4675 						sofia_set_pflag(profile, PFLAG_TCP_PINGPONG);
4676 					} else if (!strcasecmp(var, "tcp-ping2pong") && !zstr(val)) {
4677 						profile->tcp_ping2pong = atoi(val);
4678 						sofia_set_pflag(profile, PFLAG_TCP_PING2PONG);
4679 					} else if ((!strcasecmp(var, "proxy-refer-replaces") || !strcasecmp(var, "proxy-refer")) && !zstr(val)) {
4680 						if (switch_true(val)) {
4681 							sofia_set_pflag(profile, PFLAG_PROXY_REFER);
4682 						} else {
4683 							sofia_clear_pflag(profile, PFLAG_PROXY_REFER);
4684 						}
4685 					} else if (!strcasecmp(var, "sip-messages-respond-200-ok") && !zstr(val)) {
4686 						if (switch_true(val)) {
4687 							sofia_set_pflag(profile, PFLAG_MESSAGES_RESPOND_200_OK);
4688 						} else {
4689 							sofia_clear_pflag(profile, PFLAG_MESSAGES_RESPOND_200_OK);
4690 						}
4691 					} else if (!strcasecmp(var, "sip-subscribe-respond-200-ok") && !zstr(val)) {
4692 						if (switch_true(val)) {
4693 							sofia_set_pflag(profile, PFLAG_SUBSCRIBE_RESPOND_200_OK);
4694 						} else {
4695 							sofia_clear_pflag(profile, PFLAG_SUBSCRIBE_RESPOND_200_OK);
4696 						}
4697 					} else if (!strcasecmp(var, "odbc-dsn") && !zstr(val)) {
4698 						profile->odbc_dsn = switch_core_strdup(profile->pool, val);
4699 					} else if (!strcasecmp(var, "db-pre-trans-execute") && !zstr(val)) {
4700 						profile->pre_trans_execute = switch_core_strdup(profile->pool, val);
4701 					} else if (!strcasecmp(var, "db-post-trans-execute") && !zstr(val)) {
4702 						profile->post_trans_execute = switch_core_strdup(profile->pool, val);
4703 					} else if (!strcasecmp(var, "db-inner-pre-trans-execute") && !zstr(val)) {
4704 						profile->inner_pre_trans_execute = switch_core_strdup(profile->pool, val);
4705 					} else if (!strcasecmp(var, "db-inner-post-trans-execute") && !zstr(val)) {
4706 						profile->inner_post_trans_execute = switch_core_strdup(profile->pool, val);
4707 					} else if (!strcasecmp(var, "forward-unsolicited-mwi-notify")) {
4708 						if (switch_true(val)) {
4709 							sofia_set_pflag(profile, PFLAG_FORWARD_MWI_NOTIFY);
4710 						} else {
4711 							sofia_clear_pflag(profile, PFLAG_FORWARD_MWI_NOTIFY);
4712 						}
4713 					} else if (!strcasecmp(var, "NDLB-proxy-never-patch-reinvites")) {
4714 						if (switch_true(val)) {
4715 							profile->mndlb |= SM_NDLB_NEVER_PATCH_REINVITE;
4716 						} else {
4717 							profile->mndlb &= ~SM_NDLB_NEVER_PATCH_REINVITE;
4718 						}
4719 					} else if (!strcasecmp(var, "registration-thread-frequency") && !zstr(val)) {
4720 						profile->ireg_seconds = atoi(val);
4721 						if (profile->ireg_seconds < 0) {
4722 							profile->ireg_seconds = IREG_SECONDS;
4723 						}
4724 					} else if (!strcasecmp(var, "ping-mean-interval") && !zstr(val)) {
4725 						profile->iping_seconds = atoi(val);
4726 						if (profile->iping_seconds < 0) {
4727 							profile->iping_seconds = IPING_SECONDS;
4728 						}
4729 					} else if (!strcasecmp(var, "ping-thread-frequency") && !zstr(val)) {
4730 						profile->iping_freq = atoi(val);
4731 						if (profile->iping_freq < 0) {
4732 							profile->iping_freq = IPING_FREQUENCY;
4733 						}
4734 					} else if (!strcasecmp(var, "user-agent-string")) {
4735 						profile->user_agent = switch_core_strdup(profile->pool, val);
4736 					} else if (!strcasecmp(var, "auto-restart")) {
4737 						profile->auto_restart = switch_true(val);
4738 					} else if (!strcasecmp(var, "log-auth-failures")) {
4739 						if (switch_true(val)) {
4740 							sofia_set_pflag(profile, PFLAG_LOG_AUTH_FAIL);
4741 						} else {
4742 							sofia_clear_pflag(profile, PFLAG_LOG_AUTH_FAIL);
4743 						}
4744 					} else if (!strcasecmp(var, "confirm-blind-transfer")) {
4745 						if (switch_true(val)) {
4746 							sofia_set_pflag(profile, PFLAG_CONFIRM_BLIND_TRANSFER);
4747 						} else {
4748 							sofia_clear_pflag(profile, PFLAG_CONFIRM_BLIND_TRANSFER);
4749 						}
4750 					} else if (!strcasecmp(var, "allow-update")) {
4751 						if (switch_true(val)) {
4752 							sofia_set_pflag(profile, PFLAG_ALLOW_UPDATE);
4753 						} else {
4754 							sofia_clear_pflag(profile, PFLAG_ALLOW_UPDATE);
4755 						}
4756 					} else if (!strcasecmp(var, "send-display-update")) {
4757 						if (switch_true(val)) {
4758 							sofia_set_pflag(profile, PFLAG_SEND_DISPLAY_UPDATE);
4759 						} else {
4760 							sofia_clear_pflag(profile, PFLAG_SEND_DISPLAY_UPDATE);
4761 						}
4762 					} else if (!strcasecmp(var, "mwi-use-reg-callid")) {
4763 						if (switch_true(val)) {
4764 							sofia_set_pflag(profile, PFLAG_MWI_USE_REG_CALLID);
4765 						} else {
4766 							sofia_clear_pflag(profile, PFLAG_MWI_USE_REG_CALLID);
4767 						}
4768 					} else if (!strcasecmp(var, "tcp-unreg-on-socket-close")) {
4769 						if (switch_true(val)) {
4770 							sofia_set_pflag(profile, PFLAG_TCP_UNREG_ON_SOCKET_CLOSE);
4771 						} else {
4772 							sofia_clear_pflag(profile, PFLAG_TCP_UNREG_ON_SOCKET_CLOSE);
4773 						}
4774 					} else if (!strcasecmp(var, "tcp-always-nat")) {
4775 						if (switch_true(val)) {
4776 							sofia_set_pflag(profile, PFLAG_TCP_ALWAYS_NAT);
4777 						} else {
4778 							sofia_clear_pflag(profile, PFLAG_TCP_ALWAYS_NAT);
4779 						}
4780 					} else if (!strcasecmp(var, "tls-always-nat")) {
4781 						if (switch_true(val)) {
4782 							sofia_set_pflag(profile, PFLAG_TLS_ALWAYS_NAT);
4783 						} else {
4784 							sofia_clear_pflag(profile, PFLAG_TLS_ALWAYS_NAT);
4785 						}
4786 					} else if (!strcasecmp(var, "presence-proto-lookup")) {
4787 						if (switch_true(val)) {
4788 							sofia_set_pflag(profile, PFLAG_PRESENCE_MAP);
4789 						} else {
4790 							sofia_clear_pflag(profile, PFLAG_PRESENCE_MAP);
4791 						}
4792 					} else if (!strcasecmp(var, "profile-standby")) {
4793 						if (switch_true(val)) {
4794 							sofia_set_pflag(profile, PFLAG_STANDBY);
4795 						} else {
4796 							sofia_clear_pflag(profile, PFLAG_STANDBY);
4797 						}
4798 					} else if (!strcasecmp(var, "liberal-dtmf")) {
4799 						if (switch_true(val)) {
4800 							sofia_set_pflag(profile, PFLAG_LIBERAL_DTMF);
4801 						} else {
4802 							sofia_clear_pflag(profile, PFLAG_LIBERAL_DTMF);
4803 						}
4804 					} else if (!strcasecmp(var, "rtp-digit-delay") && !zstr(val)) {
4805 						int delay = atoi(val);
4806 						if (delay < 0) {
4807 							delay = 0;
4808 						}
4809 						profile->rtp_digit_delay = (uint32_t) delay;
4810 					} else if (!strcasecmp(var, "watchdog-enabled")) {
4811 						profile->watchdog_enabled = switch_true(val);
4812 					} else if (!strcasecmp(var, "watchdog-step-timeout") && !zstr(val)) {
4813 						profile->step_timeout = atoi(val);
4814 					} else if (!strcasecmp(var, "watchdog-event-timeout") && !zstr(val)) {
4815 						profile->event_timeout = atoi(val);
4816 					} else if (!strcasecmp(var, "in-dialog-chat")) {
4817 						if (switch_true(val)) {
4818 							sofia_set_pflag(profile, PFLAG_IN_DIALOG_CHAT);
4819 						} else {
4820 							sofia_clear_pflag(profile, PFLAG_IN_DIALOG_CHAT);
4821 						}
4822 					} else if (!strcasecmp(var, "enable-chat")) {
4823 						if (switch_true(val)) {
4824 							sofia_set_pflag(profile, PFLAG_ENABLE_CHAT);
4825 						} else {
4826 							sofia_clear_pflag(profile, PFLAG_ENABLE_CHAT);
4827 						}
4828 					} else if (!strcasecmp(var, "fire-bye-response-events")) {
4829 						if (switch_true(val)) {
4830 							sofia_set_pflag(profile, PFLAG_FIRE_BYE_RESPONSE_EVENTS);
4831 						} else {
4832 							sofia_clear_pflag(profile, PFLAG_FIRE_BYE_RESPONSE_EVENTS);
4833 						}
4834 					} else if (!strcasecmp(var, "fire-message-events")) {
4835 						if (switch_true(val)) {
4836 							sofia_set_pflag(profile, PFLAG_FIRE_MESSAGE_EVENTS);
4837 						} else {
4838 							sofia_clear_pflag(profile, PFLAG_FIRE_MESSAGE_EVENTS);
4839 						}
4840 					} else if (!strcasecmp(var, "t38-passthru")) {
4841 						if (switch_true(val)) {
4842 							sofia_set_pflag(profile, PFLAG_T38_PASSTHRU);
4843 						} else {
4844 							sofia_clear_pflag(profile, PFLAG_T38_PASSTHRU);
4845 						}
4846 					} else if (!strcasecmp(var, "presence-disable-early")) {
4847 						if (switch_true(val)) {
4848 							sofia_set_pflag(profile, PFLAG_PRESENCE_DISABLE_EARLY);
4849 						} else {
4850 							sofia_clear_pflag(profile, PFLAG_PRESENCE_DISABLE_EARLY);
4851 						}
4852 					} else if (!strcasecmp(var, "ignore-183nosdp")) {
4853 						if (switch_true(val)) {
4854 							sofia_set_pflag(profile, PFLAG_IGNORE_183NOSDP);
4855 						} else {
4856 							sofia_clear_pflag(profile, PFLAG_IGNORE_183NOSDP);
4857 						}
4858 					} else if (!strcasecmp(var, "presence-probe-on-register")) {
4859 						if (switch_true(val)) {
4860 							sofia_set_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER);
4861 						} else {
4862 							sofia_clear_pflag(profile, PFLAG_PRESENCE_PROBE_ON_REGISTER);
4863 						}
4864 					} else if (!strcasecmp(var, "send-presence-on-register")) {
4865 						if (val && (switch_true(val) || !strcasecmp(val, "all"))) {
4866 							sofia_set_pflag(profile, PFLAG_PRESENCE_ON_REGISTER);
4867 						} else if (val && !strcasecmp(val, "first-only")) {
4868 							sofia_clear_pflag(profile, PFLAG_PRESENCE_ON_REGISTER);
4869 							sofia_set_pflag(profile, PFLAG_PRESENCE_ON_FIRST_REGISTER);
4870 						} else {
4871 							sofia_clear_pflag(profile, PFLAG_PRESENCE_ON_REGISTER);
4872 							sofia_clear_pflag(profile, PFLAG_PRESENCE_ON_FIRST_REGISTER);
4873 						}
4874 					} else if (!strcasecmp(var, "cid-in-1xx")) {
4875 						if (switch_true(val)) {
4876 							sofia_set_pflag(profile, PFLAG_CID_IN_1XX);
4877 						} else {
4878 							sofia_clear_pflag(profile, PFLAG_CID_IN_1XX);
4879 						}
4880 					} else if (!strcasecmp(var, "disable-hold")) {
4881 						if (switch_true(val)) {
4882 							sofia_set_media_flag(profile, SCMF_DISABLE_HOLD);
4883 						} else {
4884 							sofia_clear_media_flag(profile, SCMF_DISABLE_HOLD);
4885 						}
4886 					} else if (!strcasecmp(var, "auto-jitterbuffer-msec") && !zstr(val)) {
4887 						int msec = atoi(val);
4888 						if (msec > 19) {
4889 							profile->jb_msec = switch_core_strdup(profile->pool, val);
4890 						}
4891 					} else if (!strcasecmp(var, "dtmf-type")) {
4892 						if (val && !strcasecmp(val, "rfc2833")) {
4893 							profile->dtmf_type = DTMF_2833;
4894 						} else if (val && !strcasecmp(val, "info")) {
4895 							profile->dtmf_type = DTMF_INFO;
4896 						} else {
4897 							profile->dtmf_type = DTMF_NONE;
4898 						}
4899 					} else if (!strcasecmp(var, "NDLB-force-rport")) {
4900 						if (val && !strcasecmp(val, "safe")) {
4901 							profile->server_rport_level = 3;
4902 							profile->client_rport_level = 1;
4903 						} else if (val && !strcasecmp(val, "disabled")) {
4904 							profile->server_rport_level = 0;
4905 							profile->client_rport_level = 0;
4906 						} else if (val && !strcasecmp(val, "client-only")) {
4907 							profile->client_rport_level = 1;
4908 						} else if (val && !strcasecmp(val, "server-only")) {
4909 							profile->client_rport_level = 0;
4910 							profile->server_rport_level = 1;
4911 						} else if (switch_true(val)) {
4912 							profile->server_rport_level = 2;
4913 							profile->client_rport_level = 1;
4914 						}
4915 					} else if (!strcasecmp(var, "auto-rtp-bugs")) {
4916 						switch_core_media_parse_rtp_bugs(&profile->auto_rtp_bugs, val);
4917 					} else if (!strcasecmp(var, "manual-rtp-bugs")) {
4918 						switch_core_media_parse_rtp_bugs(&profile->manual_rtp_bugs, val);
4919 					} else if (!strcasecmp(var, "manual-video-rtp-bugs")) {
4920 						switch_core_media_parse_rtp_bugs(&profile->manual_video_rtp_bugs, val);
4921 					} else if (!strcasecmp(var, "dbname")) {
4922 						profile->dbname = switch_core_strdup(profile->pool, val);
4923 					} else if (!strcasecmp(var, "presence-hosts")) {
4924 						profile->presence_hosts = switch_core_strdup(profile->pool, val);
4925 					} else if (!strcasecmp(var, "caller-id-type")) {
4926 						profile->cid_type = sofia_cid_name2type(val);
4927 					} else if (!strcasecmp(var, "record-template")) {
4928 						profile->record_template = switch_core_strdup(profile->pool, val);
4929 					} else if (!strcasecmp(var, "record-path")) {
4930 						profile->record_path = switch_core_strdup(profile->pool, val);
4931 					} else if (!strcasecmp(var, "inbound-no-media") || !strcasecmp(var, "inbound-bypass-media")) {
4932 						if (switch_true(val)) {
4933 							sofia_set_flag(profile, TFLAG_INB_NOMEDIA);
4934 						} else {
4935 							sofia_clear_flag(profile, TFLAG_INB_NOMEDIA);
4936 						}
4937 					} else if (!strcasecmp(var, "inbound-late-negotiation")) {
4938 						if (switch_true(val)) {
4939 							sofia_set_flag(profile, TFLAG_LATE_NEGOTIATION);
4940 						} else {
4941 							sofia_clear_flag(profile, TFLAG_LATE_NEGOTIATION);
4942 						}
4943 					} else if (!strcasecmp(var, "rtp-notimer-during-bridge")) {
4944 						if (switch_true(val)) {
4945 							sofia_set_pflag(profile, PFLAG_RTP_NOTIMER_DURING_BRIDGE);
4946 						} else {
4947 							sofia_clear_pflag(profile, PFLAG_RTP_NOTIMER_DURING_BRIDGE);
4948 						}
4949 					} else if (!strcasecmp(var, "manual-redirect")) {
4950 						if (switch_true(val)) {
4951 							sofia_set_pflag(profile, PFLAG_MANUAL_REDIRECT);
4952 						} else {
4953 							sofia_clear_pflag(profile, PFLAG_MANUAL_REDIRECT);
4954 						}
4955 					} else if (!strcasecmp(var, "inbound-proxy-media")) {
4956 						if (switch_true(val)) {
4957 							sofia_set_flag(profile, TFLAG_PROXY_MEDIA);
4958 						} else {
4959 							sofia_clear_flag(profile, TFLAG_PROXY_MEDIA);
4960 						}
4961 					} else if (!strcasecmp(var, "inbound-zrtp-passthru")) {
4962 						if (switch_true(val)) {
4963 							sofia_set_flag(profile, TFLAG_ZRTP_PASSTHRU);
4964 						} else {
4965 							sofia_clear_flag(profile, TFLAG_ZRTP_PASSTHRU);
4966 						}
4967 					} else if (!strcasecmp(var, "force-subscription-expires") && !zstr(val)) {
4968 						int tmp = atoi(val);
4969 						if (tmp > 0) {
4970 							profile->force_subscription_expires = tmp;
4971 						}
4972 					} else if (!strcasecmp(var, "force-publish-expires") && !zstr(val)) {
4973 						int tmp = atoi(val);
4974 						if (tmp > 0) {
4975 							profile->force_publish_expires = tmp;
4976 						}
4977 					} else if (!strcasecmp(var, "send-message-query-on-register")) {
4978 						if (switch_true(val)) {
4979 							sofia_set_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER);
4980 						} else if (val && !strcasecmp(val, "first-only")) {
4981 							sofia_clear_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER);
4982 							sofia_set_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER);
4983 						} else {
4984 							sofia_clear_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER);
4985 							sofia_clear_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER);
4986 						}
4987 					} else if (!strcasecmp(var, "inbound-reg-in-new-thread") && val) {
4988 						if (switch_true(val)) {
4989 							sofia_set_pflag(profile, PFLAG_THREAD_PER_REG);
4990 						} else {
4991 							sofia_clear_pflag(profile, PFLAG_THREAD_PER_REG);
4992 						}
4993 					} else if (!strcasecmp(var, "inbound-use-callid-as-uuid")) {
4994 						if (switch_true(val)) {
4995 							sofia_set_pflag(profile, PFLAG_CALLID_AS_UUID);
4996 						} else {
4997 							sofia_clear_pflag(profile, PFLAG_CALLID_AS_UUID);
4998 						}
4999 					} else if (!strcasecmp(var, "outbound-use-uuid-as-callid")) {
5000 						if (switch_true(val)) {
5001 							sofia_set_pflag(profile, PFLAG_UUID_AS_CALLID);
5002 						} else {
5003 							sofia_clear_pflag(profile, PFLAG_UUID_AS_CALLID);
5004 						}
5005 					} else if (!strcasecmp(var, "track-calls")) {
5006 						if (switch_true(val)) {
5007 							sofia_set_pflag(profile, PFLAG_TRACK_CALLS);
5008 						}
5009 					} else if (!strcasecmp(var, "NDLB-received-in-nat-reg-contact")) {
5010 						if (switch_true(val)) {
5011 							sofia_set_pflag(profile, PFLAG_RECIEVED_IN_NAT_REG_CONTACT);
5012 						} else {
5013 							sofia_clear_pflag(profile, PFLAG_RECIEVED_IN_NAT_REG_CONTACT);
5014 						}
5015 					} else if (!strcasecmp(var, "aggressive-nat-detection")) {
5016 						if (switch_true(val)) {
5017 							sofia_set_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION);
5018 						} else {
5019 							sofia_clear_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION);
5020 						}
5021 					} else if (!strcasecmp(var, "disable-rtp-auto-adjust")) {
5022 						if (switch_true(val)) {
5023 							sofia_set_media_flag(profile, SCMF_DISABLE_RTP_AUTOADJ);
5024 						} else {
5025 							sofia_clear_media_flag(profile, SCMF_DISABLE_RTP_AUTOADJ);
5026 						}
5027 					} else if (!strcasecmp(var, "NDLB-support-asterisk-missing-srtp-auth")) {
5028 						if (switch_true(val)) {
5029 							profile->mndlb |= SM_NDLB_DISABLE_SRTP_AUTH;
5030 						} else {
5031 							profile->mndlb &= ~SM_NDLB_DISABLE_SRTP_AUTH;
5032 						}
5033 					} else if (!strcasecmp(var, "user-agent-filter")) {
5034 						profile->user_agent_filter = switch_core_strdup(profile->pool, val);
5035 					} else if (!strcasecmp(var, "max-registrations-per-extension") && !zstr(val)) {
5036 						profile->max_registrations_perext = atoi(val);
5037 					} else if (!strcasecmp(var, "rfc2833-pt") && !zstr(val)) {
5038 						profile->te = (switch_payload_t) atoi(val);
5039 					} else if (!strcasecmp(var, "cng-pt") && !sofia_test_media_flag(profile, SCMF_SUPPRESS_CNG) && !zstr(val)) {
5040 						profile->cng_pt = (switch_payload_t) atoi(val);
5041 					} else if (!strcasecmp(var, "sip-port") && !zstr(val)) {
5042 						if (!strcasecmp(val, "auto")) {
5043 							sofia_set_pflag(profile, PFLAG_AUTO_ASSIGN_PORT);
5044 						} else {
5045 							profile->sip_port = (switch_port_t) atoi(val);
5046 							if (!profile->extsipport) profile->extsipport = profile->sip_port;
5047 						}
5048 					} else if (!strcasecmp(var, "vad") && !zstr(val)) {
5049 						if (!strcasecmp(val, "in")) {
5050 							profile->vflags |= VAD_IN;
5051 						} else if (!strcasecmp(val, "out")) {
5052 							profile->vflags |= VAD_OUT;
5053 						} else if (!strcasecmp(val, "both")) {
5054 							profile->vflags |= VAD_OUT | VAD_IN;
5055 						} else if (strcasecmp(val, "none")) {
5056 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid option %s for VAD\n", val);
5057 						}
5058 					} else if (!strcasecmp(var, "ext-rtp-ip")) {
5059 						if (!zstr(val)) {
5060 							char *ip = mod_sofia_globals.guess_ip;
5061 
5062 							if (!strcmp(val, "0.0.0.0")) {
5063 								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid IP 0.0.0.0 replaced with %s\n",
5064 												  mod_sofia_globals.guess_ip);
5065 							} else if (!strcasecmp(val, "auto-nat")) {
5066 								ip = NULL;
5067 							} else {
5068 								ip = strcasecmp(val, "auto") ? val : mod_sofia_globals.guess_ip;
5069 								sofia_clear_pflag(profile, PFLAG_AUTO_NAT);
5070 							}
5071 							if (ip) {
5072 								if (!strncasecmp(ip, "autonat:", 8)) {
5073 									profile->extrtpip = switch_core_strdup(profile->pool, ip + 8);
5074 									if (zstr(profile->extsipip)) {
5075 										profile->extsipip = switch_core_strdup(profile->pool, profile->extrtpip);
5076 									}
5077 									sofia_set_pflag(profile, PFLAG_AUTO_NAT);
5078 								} else {
5079 									profile->extrtpip = switch_core_strdup(profile->pool, ip);
5080 								}
5081 							}
5082 						} else {
5083 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid ext-rtp-ip\n");
5084 							if (mod_sofia_globals.abort_on_empty_external_ip) {
5085 								switch_goto_status(SWITCH_STATUS_GENERR, done);
5086 							}
5087 						}
5088 					} else if (!strcasecmp(var, "rtp-ip")) {
5089 						char *ip = mod_sofia_globals.guess_ip;
5090 						char buf[64];
5091 
5092 						if (zstr(val)) {
5093 							ip = mod_sofia_globals.guess_ip;
5094 						} else if (!strcmp(val, "0.0.0.0")) {
5095 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid IP 0.0.0.0 replaced with %s\n", mod_sofia_globals.guess_ip);
5096 						} else if (!strncasecmp(val, "interface:", 10)) {
5097 							char *ifname = val+10;
5098 							int family = AF_UNSPEC;
5099 							if (!strncasecmp(ifname, "auto/", 5)) { ifname += 5; family = AF_UNSPEC; }
5100 							if (!strncasecmp(ifname, "ipv4/", 5)) { ifname += 5; family = AF_INET;   }
5101 							if (!strncasecmp(ifname, "ipv6/", 5)) { ifname += 5; family = AF_INET6;  }
5102 							if (switch_find_interface_ip(buf, sizeof(buf), NULL, ifname, family) == SWITCH_STATUS_SUCCESS) {
5103 								ip = buf;
5104 								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Using %s IP for interface %s for rtp-ip\n", ip, val+10);
5105 							} else {
5106 								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown IP for interface %s for rtp-ip\n", val+10);
5107 							}
5108 						} else {
5109 							ip = strcasecmp(val, "auto") ? val : mod_sofia_globals.guess_ip;
5110 						}
5111 
5112 						if (strchr(ip, ':')) {
5113 							if (profile->rtpip_index6 < MAX_RTPIP) {
5114 								profile->rtpip6[profile->rtpip_index6++] = switch_core_strdup(profile->pool, ip);
5115 							} else {
5116 								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Max IPs configured for profile %s.\n", profile->name);
5117 							}
5118 						} else {
5119 							if (profile->rtpip_index < MAX_RTPIP) {
5120 								profile->rtpip[profile->rtpip_index++] = switch_core_strdup(profile->pool, ip);
5121 							} else {
5122 								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Max IPs configured for profile %s.\n", profile->name);
5123 							}
5124 						}
5125 					} else if (!strcasecmp(var, "sip-ip") && val) {
5126 						char *ip = mod_sofia_globals.guess_ip;
5127 						char buf[64];
5128 
5129 						if (!strcmp(val, "0.0.0.0")) {
5130 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid IP 0.0.0.0 replaced with %s\n", mod_sofia_globals.guess_ip);
5131 						} else if (!strncasecmp(val, "interface:", 10)) {
5132 							char *ifname = val+10;
5133 							int family = AF_UNSPEC;
5134 							if (!strncasecmp(ifname, "auto/", 5)) { ifname += 5; family = AF_UNSPEC; }
5135 							if (!strncasecmp(ifname, "ipv4/", 5)) { ifname += 5; family = AF_INET;   }
5136 							if (!strncasecmp(ifname, "ipv6/", 5)) { ifname += 5; family = AF_INET6;  }
5137 							if (switch_find_interface_ip(buf, sizeof(buf), NULL, ifname, family) == SWITCH_STATUS_SUCCESS) {
5138 								ip = buf;
5139 								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Using %s IP for interface %s for sip-ip\n", ip, val+10);
5140 							} else {
5141 								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown IP for interface %s for sip-ip\n", val+10);
5142 							}
5143 						} else {
5144 							ip = strcasecmp(val, "auto") ? val : mod_sofia_globals.guess_ip;
5145 						}
5146 						profile->sipip = switch_core_strdup(profile->pool, ip);
5147 					} else if (!strcasecmp(var, "ext-sip-port") && val) {
5148 						int tmp = atoi(val);
5149 						if (tmp > 0) profile->extsipport = (switch_port_t)tmp;
5150 					} else if (!strcasecmp(var, "ext-sip-ip")) {
5151 						if (!zstr(val)) {
5152 							char *ip = mod_sofia_globals.guess_ip;
5153 							char stun_ip[50] = "";
5154 							char *myip = stun_ip;
5155 
5156 							switch_copy_string(stun_ip, ip, sizeof(stun_ip));
5157 
5158 							if (!strcasecmp(val, "0.0.0.0")) {
5159 								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid IP 0.0.0.0 replaced with %s\n",
5160 												  mod_sofia_globals.guess_ip);
5161 							} else if (!strcasecmp(val, "auto-nat")) {
5162 								ip = NULL;
5163 							} else if (strcasecmp(val, "auto")) {
5164 								if (sofia_glue_ext_address_lookup(profile, &myip, &profile->extsipport, val, profile->pool) == SWITCH_STATUS_SUCCESS) {
5165 									ip = myip;
5166 									sofia_clear_pflag(profile, PFLAG_AUTO_NAT);
5167 								} else {
5168 									switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get external ip.\n");
5169 								}
5170 							}
5171 							if (ip) {
5172 								if (!strncasecmp(ip, "autonat:", 8)) {
5173 									profile->extsipip = switch_core_strdup(profile->pool, ip + 8);
5174 									sofia_set_pflag(profile, PFLAG_AUTO_NAT);
5175 								} else {
5176 									profile->extsipip = switch_core_strdup(profile->pool, ip);
5177 								}
5178 							}
5179 						} else {
5180 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid ext-sip-ip\n");
5181 							switch_goto_status(SWITCH_STATUS_GENERR, done);
5182 						}
5183 					} else if (!strcasecmp(var, "local-network-acl")) {
5184 						if (val && !strcasecmp(val, "none")) {
5185 							profile->local_network = NULL;
5186 						} else {
5187 							profile->local_network = switch_core_strdup(profile->pool, val);
5188 						}
5189 					} else if (!strcasecmp(var, "force-register-domain")) {
5190 						profile->reg_domain = switch_core_strdup(profile->pool, val);
5191 					} else if (!strcasecmp(var, "force-register-db-domain")) {
5192 						profile->reg_db_domain = switch_core_strdup(profile->pool, val);
5193 					} else if (!strcasecmp(var, "force-subscription-domain")) {
5194 						profile->sub_domain = switch_core_strdup(profile->pool, val);
5195 					} else if (!strcasecmp(var, "bind-params")) {
5196 						profile->bind_params = switch_core_strdup(profile->pool, val);
5197 					} else if (!strcasecmp(var, "sip-domain")) {
5198 						profile->sipdomain = switch_core_strdup(profile->pool, val);
5199 					} else if (!strcasecmp(var, "rtp-timer-name")) {
5200 						profile->timer_name = switch_core_strdup(profile->pool, val);
5201 					} else if (!strcasecmp(var, "hold-music")) {
5202 						profile->hold_music = switch_core_strdup(profile->pool, val);
5203 					} else if (!strcasecmp(var, "outbound-proxy") && val) {
5204 						if (strncasecmp(val, "sip:", 4) && strncasecmp(val, "sips:", 5)) {
5205 							profile->outbound_proxy = switch_core_sprintf(profile->pool, "sip:%s", val);
5206 						} else {
5207 							profile->outbound_proxy = switch_core_strdup(profile->pool, val);
5208 						}
5209 					} else if (!strcasecmp(var, "rtcp-audio-interval-msec")) {
5210 						profile->rtcp_audio_interval_msec = switch_core_strdup(profile->pool, val);
5211 					} else if (!strcasecmp(var, "rtcp-video-interval-msec")) {
5212 						profile->rtcp_video_interval_msec = switch_core_strdup(profile->pool, val);
5213 					} else if (!strcasecmp(var, "session-timeout") && !zstr(val)) {
5214 						int v_session_timeout = atoi(val);
5215 						if (v_session_timeout >= 0) {
5216 							profile->session_timeout = v_session_timeout;
5217 						}
5218 					} else if (!strcasecmp(var, "max-proceeding") && !zstr(val)) {
5219 						int v_max_proceeding = atoi(val);
5220 						if (v_max_proceeding >= 0) {
5221 							profile->max_proceeding = v_max_proceeding;
5222 						}
5223 					} else if (!strcasecmp(var, "rtp-timeout-sec") && !zstr(val)) {
5224 						int v = atoi(val);
5225 						if (v >= 0) {
5226 							profile->rtp_timeout_sec = v;
5227 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
5228 											  "rtp-timeout-sec deprecated use media_timeout variable.\n");
5229 						}
5230 					} else if (!strcasecmp(var, "rtp-hold-timeout-sec") && !zstr(val)) {
5231 						int v = atoi(val);
5232 						if (v >= 0) {
5233 							profile->rtp_hold_timeout_sec = v;
5234 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
5235 											  "rtp-hold-timeout-sec deprecated use media_hold_timeout variable.\n");
5236 						}
5237 					} else if (!strcasecmp(var, "disable-transfer")) {
5238 						if (switch_true(val)) {
5239 							profile->mflags &= ~MFLAG_REFER;
5240 						} else {
5241 							profile->mflags |= MFLAG_REFER;
5242 						}
5243 					} else if (!strcasecmp(var, "disable-register")) {
5244 						if (switch_true(val)) {
5245 							profile->mflags &= ~MFLAG_REGISTER;
5246 						} else {
5247 							profile->mflags |= MFLAG_REGISTER;
5248 						}
5249 					} else if (!strcasecmp(var, "media-option") && !zstr(val)) {
5250 						if (!strcasecmp(val, "resume-media-on-hold")) {
5251 							profile->media_options |= MEDIA_OPT_MEDIA_ON_HOLD;
5252 						} else if (!strcasecmp(val, "bypass-media-after-att-xfer")) {
5253 							profile->media_options |= MEDIA_OPT_BYPASS_AFTER_ATT_XFER;
5254 						} else if (!strcasecmp(val, "bypass-media-after-hold")) {
5255 							if (profile->media_options & MEDIA_OPT_MEDIA_ON_HOLD) {
5256 								profile->media_options |= MEDIA_OPT_BYPASS_AFTER_HOLD;
5257 							} else {
5258 								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
5259 												  "bypass-media-after-hold can be set only with resume-media-on-hold media-option\n");
5260 							}
5261 						} else if (!strcasecmp(val, "none")) {
5262 							profile->media_options = 0;
5263 						}
5264 					} else if (!strcasecmp(var, "pnp-provision-url")) {
5265 						profile->pnp_prov_url = switch_core_strdup(profile->pool, val);
5266 					} else if (!strcasecmp(var, "manage-presence")) {
5267 						if (val && !strcasecmp(val, "passive")) {
5268 							profile->pres_type = PRES_TYPE_PASSIVE;
5269 
5270 						} else if (val && !strcasecmp(val, "pnp")) {
5271 							profile->pres_type = PRES_TYPE_PNP;
5272 						} else if (switch_true(val)) {
5273 							profile->pres_type = PRES_TYPE_FULL;
5274 						} else {
5275 							profile->pres_type = 0;
5276 						}
5277 					} else if (!strcasecmp(var, "presence-hold-state")) {
5278 						if (val && !strcasecmp(val, "confirmed")) {
5279 							profile->pres_held_type = PRES_HELD_CONFIRMED;
5280 						} else if (val && !strcasecmp(val, "terminated")) {
5281 							profile->pres_held_type = PRES_HELD_TERMINATED;
5282 						} else {
5283 							profile->pres_held_type = 0;
5284 						}
5285 					} else if (!strcasecmp(var, "presence-privacy")) {
5286 						if (switch_true(val)) {
5287 							sofia_set_pflag(profile, PFLAG_PRESENCE_PRIVACY);
5288 						} else {
5289 							sofia_clear_pflag(profile, PFLAG_PRESENCE_PRIVACY);
5290 						}
5291 					} else if (!strcasecmp(var, "update-refresher")) {
5292 						if (switch_true(val)) {
5293 							sofia_set_pflag(profile, PFLAG_UPDATE_REFRESHER);
5294 						} else {
5295 							sofia_clear_pflag(profile, PFLAG_UPDATE_REFRESHER);
5296 						}
5297 					} else if (!strcasecmp(var, "rfc-7989")) {
5298 						if (switch_true(val)) {
5299 							sofia_set_pflag(profile, PFLAG_RFC7989_SESSION_ID);
5300 						} else {
5301 							sofia_clear_pflag(profile, PFLAG_RFC7989_SESSION_ID);
5302 						}
5303 					} else if (!strcasecmp(var, "rfc-7989-filter")) {
5304 						profile->rfc7989_filter = switch_core_strdup(profile->pool, val);
5305 					} else if (!strcasecmp(var, "rfc-7989-force-old")) {
5306 						if (switch_true(val)) {
5307 							sofia_set_pflag(profile, PFLAG_RFC7989_FORCE_OLD);
5308 						} else {
5309 							sofia_clear_pflag(profile, PFLAG_RFC7989_FORCE_OLD);
5310 						}
5311 					} else if (!strcasecmp(var, "manage-shared-appearance")) {
5312 						if (switch_true(val)) {
5313 							sofia_set_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE);
5314 							profile->pres_type = PRES_TYPE_FULL;
5315 							sofia_set_pflag(profile, PFLAG_MULTIREG);
5316 
5317 						} else if (val && !strcasecmp(val, "sylantro")) {
5318 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
5319 											  "Sylantro support has been removed.\n"
5320 											  "It was incomplete anyway, and we fully support the broadsoft SCA shared line spec.");
5321 							sofia_clear_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE);
5322 						} else {
5323 							sofia_clear_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE);
5324 						}
5325 					} else if (!strcasecmp(var, "disable-srv")) {
5326 						if (switch_true(val)) {
5327 							sofia_set_pflag(profile, PFLAG_DISABLE_SRV);
5328 						} else {
5329 							sofia_clear_pflag(profile, PFLAG_DISABLE_SRV);
5330 						}
5331 					} else if (!strcasecmp(var, "disable-naptr")) {
5332 						if (switch_true(val)) {
5333 							sofia_set_pflag(profile, PFLAG_DISABLE_NAPTR);
5334 						} else {
5335 							sofia_clear_pflag(profile, PFLAG_DISABLE_NAPTR);
5336 						}
5337 					} else if (!strcasecmp(var, "disable-srv503")) {
5338 						if (switch_true(val)) {
5339 							sofia_set_pflag(profile, PFLAG_DISABLE_SRV503);
5340 						} else {
5341 							sofia_clear_pflag(profile, PFLAG_DISABLE_SRV503);
5342 						}
5343 					} else if (!strcasecmp(var, "unregister-on-options-fail")) {
5344 						if (switch_true(val)) {
5345 							sofia_set_pflag(profile, PFLAG_UNREG_OPTIONS_FAIL);
5346 						} else {
5347 							sofia_clear_pflag(profile, PFLAG_UNREG_OPTIONS_FAIL);
5348 						}
5349 					} else if (!strcasecmp(var, "sip-user-ping-max") && !zstr(val)) {
5350 						profile->sip_user_ping_max = atoi(val);
5351 					} else if (!strcasecmp(var, "sip-user-ping-min") && !zstr(val)) {
5352 						profile->sip_user_ping_min = atoi(val);
5353 					} else if (!strcasecmp(var, "require-secure-rtp")) {
5354 						if (switch_true(val)) {
5355 							sofia_set_pflag(profile, PFLAG_SECURE);
5356 						} else {
5357 							sofia_clear_pflag(profile, PFLAG_SECURE);
5358 						}
5359 					} else if (!strcasecmp(var, "auto-invite-100")) {
5360 						if (switch_true(val)) {
5361 							sofia_set_pflag(profile, PFLAG_AUTO_INVITE_100);
5362 						} else {
5363 							sofia_clear_pflag(profile, PFLAG_AUTO_INVITE_100);
5364 						}
5365 					} else {
5366 						found = 0;
5367 					}
5368 					if (found) continue;
5369 
5370 					if (!strcasecmp(var, "multiple-registrations")) {
5371 						if (val && !strcasecmp(val, "call-id")) {
5372 							sofia_set_pflag(profile, PFLAG_MULTIREG);
5373 						} else if (val && (!strcasecmp(val, "contact") || switch_true(val))) {
5374 							sofia_set_pflag(profile, PFLAG_MULTIREG);
5375 							sofia_set_pflag(profile, PFLAG_MULTIREG_CONTACT);
5376 						} else if (!switch_true(val)) {
5377 							sofia_clear_pflag(profile, PFLAG_MULTIREG);
5378 							sofia_clear_pflag(profile, PFLAG_MULTIREG_CONTACT);
5379 						}
5380 					} else if (!strcasecmp(var, "supress-cng") || !strcasecmp(var, "suppress-cng")) {
5381 						if (switch_true(val)) {
5382 							sofia_set_media_flag(profile, SCMF_SUPPRESS_CNG);
5383 							profile->cng_pt = 0;
5384 						} else {
5385 							sofia_clear_media_flag(profile, SCMF_SUPPRESS_CNG);
5386 						}
5387 					} else if (!strcasecmp(var, "NDLB-broken-auth-hash")) {
5388 						if (switch_true(val)) {
5389 							profile->ndlb |= PFLAG_NDLB_BROKEN_AUTH_HASH;
5390 						} else {
5391 							profile->ndlb &= ~PFLAG_NDLB_BROKEN_AUTH_HASH;
5392 						}
5393 					} else if (!strcasecmp(var, "NDLB-sendrecv-in-session")) {
5394 						if (switch_true(val)) {
5395 							profile->mndlb |= SM_NDLB_SENDRECV_IN_SESSION;
5396 						} else {
5397 							profile->mndlb &= ~SM_NDLB_SENDRECV_IN_SESSION;
5398 						}
5399 					} else if (!strcasecmp(var, "NDLB-allow-bad-iananame")) {
5400 						if (switch_true(val)) {
5401 							profile->ndlb |= SM_NDLB_ALLOW_BAD_IANANAME;
5402 						} else {
5403 							profile->ndlb &= ~SM_NDLB_ALLOW_BAD_IANANAME;
5404 						}
5405 					} else if (!strcasecmp(var, "NDLB-expires-in-register-response")) {
5406 						if (switch_true(val)) {
5407 							profile->ndlb |= PFLAG_NDLB_EXPIRES_IN_REGISTER_RESPONSE;
5408 						} else {
5409 							profile->ndlb &= ~PFLAG_NDLB_EXPIRES_IN_REGISTER_RESPONSE;
5410 						}
5411 					} else if (!strcasecmp(var, "NDLB-allow-crypto-in-avp")) {
5412 						if (switch_true(val)) {
5413 							profile->mndlb |= SM_NDLB_ALLOW_CRYPTO_IN_AVP;
5414 						} else {
5415 							profile->mndlb &= ~SM_NDLB_ALLOW_CRYPTO_IN_AVP;
5416 						}
5417 					} else if (!strcasecmp(var, "NDLB-allow-nondup-sdp")) {
5418 						if (switch_true(val)) {
5419 							profile->mndlb |= SM_NDLB_ALLOW_NONDUP_SDP;
5420 						} else {
5421 							profile->mndlb &= ~SM_NDLB_ALLOW_NONDUP_SDP;
5422 						}
5423 					} else if (!strcasecmp(var, "pass-rfc2833")) {
5424 						if (switch_true(val)) {
5425 							sofia_set_pflag(profile, PFLAG_PASS_RFC2833);
5426 						} else {
5427 							sofia_clear_pflag(profile, PFLAG_PASS_RFC2833);
5428 						}
5429 					} else if (!strcasecmp(var, "rtp-autofix-timing")) {
5430 						if (switch_true(val)) {
5431 							sofia_set_media_flag(profile, SCMF_AUTOFIX_TIMING);
5432 						} else {
5433 							sofia_clear_media_flag(profile, SCMF_AUTOFIX_TIMING);
5434 						}
5435 					} else if (!strcasecmp(var, "contact-user")) {
5436 						profile->contact_user = switch_core_strdup(profile->pool, val);
5437 					} else if (!strcasecmp(var, "nat-options-ping")) {
5438 						if (val && !strcasecmp(val, "udp-only")) {
5439 							sofia_set_pflag(profile, PFLAG_UDP_NAT_OPTIONS_PING);
5440 						} else if (switch_true(val)) {
5441 							sofia_set_pflag(profile, PFLAG_NAT_OPTIONS_PING);
5442 						} else {
5443 							sofia_clear_pflag(profile, PFLAG_NAT_OPTIONS_PING);
5444 							sofia_clear_pflag(profile, PFLAG_UDP_NAT_OPTIONS_PING);
5445 						}
5446 					} else if (!strcasecmp(var, "all-reg-options-ping")) {
5447 						if (switch_true(val)) {
5448 							sofia_set_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING);
5449 						} else {
5450 							sofia_clear_pflag(profile, PFLAG_ALL_REG_OPTIONS_PING);
5451 						}
5452 					} else if (!strcasecmp(var, "inbound-codec-negotiation")) {
5453 						if (val && !strcasecmp(val, "greedy")) {
5454 							sofia_set_media_flag(profile, SCMF_CODEC_GREEDY);
5455 						} else if (val && !strcasecmp(val, "scrooge")) {
5456 							sofia_set_media_flag(profile, SCMF_CODEC_GREEDY);
5457 							sofia_set_media_flag(profile, SCMF_CODEC_SCROOGE);
5458 						} else {
5459 							sofia_clear_media_flag(profile, SCMF_CODEC_SCROOGE);
5460 							sofia_clear_media_flag(profile, SCMF_CODEC_GREEDY);
5461 						}
5462 					} else if (!strcasecmp(var, "disable-transcoding")) {
5463 						if (switch_true(val)) {
5464 							sofia_set_media_flag(profile, SCMF_DISABLE_TRANSCODING);
5465 						} else {
5466 							sofia_clear_media_flag(profile, SCMF_DISABLE_TRANSCODING);
5467 						}
5468 					} else if (!strcasecmp(var, "rtp-rewrite-timestamps")) {
5469 						if (switch_true(val)) {
5470 							sofia_set_media_flag(profile, SCMF_REWRITE_TIMESTAMPS);
5471 						} else {
5472 							sofia_clear_media_flag(profile, SCMF_REWRITE_TIMESTAMPS);
5473 						}
5474 					} else if (!strcasecmp(var, "auth-calls")) {
5475 						if (switch_true(val)) {
5476 							sofia_set_pflag(profile, PFLAG_AUTH_CALLS);
5477 						} else {
5478 							sofia_clear_pflag(profile, PFLAG_AUTH_CALLS);
5479 						}
5480 					} else if (!strcasecmp(var, "auth-messages")) {
5481 						if (switch_true(val)) {
5482 							sofia_set_pflag(profile, PFLAG_AUTH_MESSAGES);
5483 						} else {
5484 							sofia_clear_pflag(profile, PFLAG_AUTH_MESSAGES);
5485 						}
5486 					} else if (!strcasecmp(var, "auth-subscriptions")) {
5487 						if (switch_true(val)) {
5488 							sofia_set_pflag(profile, PFLAG_AUTH_SUBSCRIPTIONS);
5489 						} else {
5490 							sofia_clear_pflag(profile, PFLAG_AUTH_SUBSCRIPTIONS);
5491 						}
5492 					} else if (!strcasecmp(var, "extended-info-parsing")) {
5493 						if (switch_true(val)) {
5494 							sofia_set_pflag(profile, PFLAG_EXTENDED_INFO_PARSING);
5495 						} else {
5496 							sofia_clear_pflag(profile, PFLAG_EXTENDED_INFO_PARSING);
5497 						}
5498 					} else if (!strcasecmp(var, "nonce-ttl") && !zstr(val)) {
5499 						profile->nonce_ttl = atoi(val);
5500 					} else if (!strcasecmp(var, "max-auth-validity") && !zstr(val)) {
5501 						profile->max_auth_validity = atoi(val);
5502 					} else if (!strcasecmp(var, "auth-require-user")) {
5503 						if (switch_true(val)) {
5504 							sofia_set_pflag(profile, PFLAG_AUTH_REQUIRE_USER);
5505 						} else {
5506 							sofia_clear_pflag(profile, PFLAG_AUTH_REQUIRE_USER);
5507 						}
5508 					} else if (!strcasecmp(var, "accept-blind-reg")) {
5509 						if (switch_true(val)) {
5510 							sofia_set_pflag(profile, PFLAG_BLIND_REG);
5511 						} else {
5512 							sofia_clear_pflag(profile, PFLAG_BLIND_REG);
5513 						}
5514 					} else if (!strcasecmp(var, "3pcc-reinvite-bridged-on-ack")) {
5515 						if (switch_true(val)) {
5516 							sofia_set_pflag(profile, PFLAG_3PCC_REINVITE_BRIDGED_ON_ACK);
5517 						} else {
5518 							sofia_clear_pflag(profile, PFLAG_3PCC_REINVITE_BRIDGED_ON_ACK);
5519 						}
5520 					} else if (!strcasecmp(var, "enable-3pcc")) {
5521 						if (switch_true(val)) {
5522 							sofia_set_pflag(profile, PFLAG_3PCC);
5523 						} else if (!strcasecmp(val, "proxy")) {
5524 							sofia_set_pflag(profile, PFLAG_3PCC_PROXY);
5525 						}
5526 					} else if (!strcasecmp(var, "accept-blind-auth")) {
5527 						if (switch_true(val)) {
5528 							sofia_set_pflag(profile, PFLAG_BLIND_AUTH);
5529 						} else {
5530 							sofia_clear_pflag(profile, PFLAG_BLIND_AUTH);
5531 						}
5532 					} else if (!strcasecmp(var, "auth-all-packets")) {
5533 						if (switch_true(val)) {
5534 							sofia_set_pflag(profile, PFLAG_AUTH_ALL);
5535 						} else {
5536 							sofia_clear_pflag(profile, PFLAG_AUTH_ALL);
5537 						}
5538 					} else if (!strcasecmp(var, "full-id-in-dialplan")) {
5539 						if (switch_true(val)) {
5540 							sofia_set_pflag(profile, PFLAG_FULL_ID);
5541 						} else {
5542 							sofia_clear_pflag(profile, PFLAG_FULL_ID);
5543 						}
5544 					} else if (!strcasecmp(var, "inbound-reg-force-matching-username")) {
5545 						if (switch_true(val)) {
5546 							sofia_set_pflag(profile, PFLAG_CHECKUSER);
5547 						} else {
5548 							sofia_clear_pflag(profile, PFLAG_CHECKUSER);
5549 						}
5550 					} else if (!strcasecmp(var, "enable-timer")) {
5551 						if (!switch_true(val)) {
5552 							sofia_set_pflag(profile, PFLAG_DISABLE_TIMER);
5553 						} else {
5554 							sofia_clear_pflag(profile, PFLAG_DISABLE_TIMER);
5555 						}
5556 					} else if (!strcasecmp(var, "enable-rfc-5626")) {
5557 						if (switch_true(val)) {
5558 							sofia_set_pflag(profile, PFLAG_ENABLE_RFC5626);
5559 						} else {
5560 							sofia_clear_pflag(profile, PFLAG_ENABLE_RFC5626);
5561 						}
5562 					} else if (!strcasecmp(var, "minimum-session-expires") && !zstr(val)) {
5563 						profile->minimum_session_expires = atoi(val);
5564 						/* per RFC 4028: minimum_session_expires must be > 90 */
5565 						if (profile->minimum_session_expires < 90) {
5566 							profile->minimum_session_expires = 90;
5567 						}
5568 					} else if (!strcasecmp(var, "enable-100rel")) {
5569 						if (switch_true(val)) {
5570 							sofia_clear_pflag(profile, PFLAG_DISABLE_100REL);
5571 						} else {
5572 							sofia_set_pflag(profile, PFLAG_DISABLE_100REL);
5573 						}
5574 					} else if (!strcasecmp(var, "enable-compact-headers")) {
5575 						if (switch_true(val)) {
5576 							sofia_set_pflag(profile, PFLAG_SIPCOMPACT);
5577 						} else {
5578 							sofia_clear_pflag(profile, PFLAG_SIPCOMPACT);
5579 						}
5580 					} else if (!strcasecmp(var, "pass-callee-id")) {
5581 						if (switch_true(val)) {
5582 							sofia_set_pflag(profile, PFLAG_PASS_CALLEE_ID);
5583 						} else {
5584 							sofia_clear_pflag(profile, PFLAG_PASS_CALLEE_ID);
5585 						}
5586 					} else if (!strcasecmp(var, "enable-soa")) {
5587 						if (switch_true(val)) {
5588 							sofia_set_flag(profile, TFLAG_ENABLE_SOA);
5589 						} else {
5590 							sofia_clear_flag(profile, TFLAG_ENABLE_SOA);
5591 						}
5592 					} else if (!strcasecmp(var, "parse-all-invite-headers")) {
5593 						if (switch_true(val)) {
5594 							sofia_set_pflag(profile, PFLAG_PARSE_ALL_INVITE_HEADERS);
5595 						} else {
5596 							sofia_clear_pflag(profile, PFLAG_PARSE_ALL_INVITE_HEADERS);
5597 						}
5598 					} else if (!strcasecmp(var, "bitpacking")) {
5599 						if (val && !strcasecmp(val, "aal2")) {
5600 							profile->codec_flags = SWITCH_CODEC_FLAG_AAL2;
5601 						} else {
5602 							profile->codec_flags = 0;
5603 						}
5604 					} else if (!strcasecmp(var, "username")) {
5605 						profile->sdp_username = switch_core_strdup(profile->pool, val);
5606 					} else if (!strcasecmp(var, "context")) {
5607 						profile->context = switch_core_strdup(profile->pool, val);
5608 					} else if (!strcasecmp(var, "apply-nat-acl") && !zstr(val)) {
5609 						if (!strcasecmp(val,"none")) {
5610 							profile->nat_acl_count = 0;
5611 						} else if (profile->nat_acl_count < SOFIA_MAX_ACL) {
5612 							if (!profile->extsipip && profile->sipip && switch_check_network_list_ip(profile->sipip, val)) {
5613 								switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Not adding acl %s because it's the local network\n", val);
5614 							} else {
5615 								profile->nat_acl[profile->nat_acl_count++] = switch_core_strdup(profile->pool, val);
5616 							}
5617 						} else {
5618 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Max acl records of %d reached\n", SOFIA_MAX_ACL);
5619 						}
5620 					} else if (!strcasecmp(var, "apply-inbound-acl") && !zstr(val)) {
5621 						if (!strcasecmp(val,"none")) {
5622 							profile->acl_count = 0;
5623 						} else if (profile->acl_count < SOFIA_MAX_ACL) {
5624 							char *list, *pass = NULL, *fail = NULL;
5625 
5626 							list = switch_core_strdup(profile->pool, val);
5627 
5628 							if ((pass = strchr(list, ':'))) {
5629 								*pass++ = '\0';
5630 								if ((fail = strchr(pass, ':'))) {
5631 									*fail++ = '\0';
5632 								}
5633 
5634 								if (zstr(pass)) pass = NULL;
5635 								if (zstr(fail)) fail = NULL;
5636 
5637 								profile->acl_pass_context[profile->acl_count] = pass;
5638 								profile->acl_fail_context[profile->acl_count] = fail;
5639 							}
5640 
5641 							profile->acl[profile->acl_count++] = list;
5642 
5643 						} else {
5644 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Max acl records of %d reached\n", SOFIA_MAX_ACL);
5645 						}
5646 					} else if (!strcasecmp(var, "apply-proxy-acl") && !zstr(val)) {
5647 						if (!strcasecmp(val,"none")) {
5648 							profile->proxy_acl_count = 0;
5649 						} else if (profile->proxy_acl_count < SOFIA_MAX_ACL) {
5650 							profile->proxy_acl[profile->proxy_acl_count++] = switch_core_strdup(profile->pool, val);
5651 						} else {
5652 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Max acl records of %d reached\n", SOFIA_MAX_ACL);
5653 						}
5654 					} else if (!strcasecmp(var, "apply-register-acl") && !zstr(val)) {
5655 						if (!strcasecmp(val,"none")) {
5656 							profile->reg_acl_count = 0;
5657 						} else if (profile->reg_acl_count < SOFIA_MAX_ACL) {
5658 							profile->reg_acl[profile->reg_acl_count++] = switch_core_strdup(profile->pool, val);
5659 						} else {
5660 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Max acl records of %d reached\n", SOFIA_MAX_ACL);
5661 						}
5662 
5663 					} else if (!strcasecmp(var, "apply-candidate-acl") && !zstr(val)) {
5664 						if (!strcasecmp(val,"none")) {
5665 							profile->cand_acl_count = 0;
5666 						} else if (profile->cand_acl_count < SWITCH_MAX_CAND_ACL) {
5667 							profile->cand_acl[profile->cand_acl_count++] = switch_core_strdup(profile->pool, val);
5668 						} else {
5669 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Max acl records of %d reached\n", SWITCH_MAX_CAND_ACL);
5670 						}
5671 					} else if (!strcasecmp(var, "alias")) {
5672 						sip_alias_node_t *node;
5673 						if (zstr(val)) {
5674 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Alias Param has no data...\n");
5675 						} else {
5676 							if ((node = switch_core_alloc(profile->pool, sizeof(*node)))) {
5677 								if ((node->url = switch_core_strdup(profile->pool, val))) {
5678 									node->next = profile->aliases;
5679 									profile->aliases = node;
5680 								}
5681 							}
5682 						}
5683 					} else if (!strcasecmp(var, "dialplan")) {
5684 						profile->dialplan = switch_core_strdup(profile->pool, val);
5685 					} else if (!strcasecmp(var, "max-calls") && !zstr(val)) {
5686 						profile->max_calls = atoi(val);
5687 					} else if (!strcasecmp(var, "codec-prefs")) {
5688 						profile->inbound_codec_string = switch_core_strdup(profile->pool, val);
5689 						profile->outbound_codec_string = switch_core_strdup(profile->pool, val);
5690 					} else if (!strcasecmp(var, "inbound-codec-prefs")) {
5691 						profile->inbound_codec_string = switch_core_strdup(profile->pool, val);
5692 					} else if (!strcasecmp(var, "outbound-codec-prefs")) {
5693 						profile->outbound_codec_string = switch_core_strdup(profile->pool, val);
5694 					} else if (!strcasecmp(var, "challenge-realm")) {
5695 						profile->challenge_realm = switch_core_strdup(profile->pool, val);
5696 					} else if (!strcasecmp(var, "dtmf-duration") && !zstr(val)) {
5697 						uint32_t dur = atoi(val);
5698 						if (dur >= switch_core_min_dtmf_duration(0) && dur <= switch_core_max_dtmf_duration(0)) {
5699 							profile->dtmf_duration = dur;
5700 						} else {
5701 							profile->dtmf_duration = SWITCH_DEFAULT_DTMF_DURATION;
5702 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Duration out of bounds, using default of %d!\n",
5703 											  SWITCH_DEFAULT_DTMF_DURATION);
5704 						}
5705 
5706 					} else if (!strcasecmp(var, "ws-binding") && !zstr(val)) {
5707 						int tmp;
5708 						char *p;
5709 
5710 						profile->ws_ip = switch_core_strdup(profile->pool, val);
5711 						if ((p = strrchr(profile->ws_ip, ':'))) {
5712 							*p++ = '\0';
5713 
5714 							if ((tmp = atol(p)) && tmp > 0) {
5715 								profile->ws_port = (switch_port_t) tmp;
5716 							}
5717 						}
5718 
5719 					} else if (!strcasecmp(var, "wss-binding") && !zstr(val)) {
5720 						int tmp;
5721 						char *p;
5722 
5723 						profile->wss_ip = switch_core_strdup(profile->pool, val);
5724 						if ((p = strrchr(profile->wss_ip, ':'))) {
5725 							*p++ = '\0';
5726 
5727 							if ((tmp = atol(p)) && tmp > 0) {
5728 								profile->wss_port = (switch_port_t) tmp;
5729 							}
5730 						}
5731 
5732 						/*
5733 						 * handle TLS params #1
5734 						 */
5735 					} else if (!strcasecmp(var, "tls")) {
5736 						if (switch_true(val)) {
5737 							sofia_set_pflag(profile, PFLAG_TLS);
5738 							if (profile->tls_bind_params) {
5739 								if (!switch_stristr("transport=tls", profile->tls_bind_params)) {
5740 									profile->tls_bind_params = switch_core_sprintf(profile->pool, "%s;transport=tls", profile->tls_bind_params);
5741 								}
5742 							} else {
5743 								profile->tls_bind_params = switch_core_strdup(profile->pool, "transport=tls");
5744 							}
5745 						} else {
5746 							sofia_clear_pflag(profile, PFLAG_TLS);
5747 						}
5748 					} else if (!strcasecmp(var, "tls-bind-params")) {
5749 						if (val && switch_stristr("transport=tls", val)) {
5750 							profile->tls_bind_params = switch_core_strdup(profile->pool, val);
5751 						} else {
5752 							profile->tls_bind_params = switch_core_sprintf(profile->pool, "%s;transport=tls", val);
5753 						}
5754 					} else if (!strcasecmp(var, "tls-only")) {
5755 						profile->tls_only = switch_true(val);
5756 					} else if (!strcasecmp(var, "tls-verify-date")) {
5757 						profile->tls_verify_date = switch_true(val);
5758 					} else if (!strcasecmp(var, "tls-verify-depth") && !zstr(val)) {
5759 						profile->tls_verify_depth = atoi(val);
5760 					} else if (!strcasecmp(var, "tls-verify-policy")) {
5761 						profile->tls_verify_policy = sofia_glue_str2tls_verify_policy(val);
5762 					} else if (!strcasecmp(var, "tls-sip-port") && !zstr(val)) {
5763 						if (!strcasecmp(val, "auto")) {
5764 							sofia_set_pflag(profile, PFLAG_AUTO_ASSIGN_TLS_PORT);
5765 						} else {
5766 							sofia_clear_pflag(profile, PFLAG_AUTO_ASSIGN_TLS_PORT);
5767 							profile->tls_sip_port = (switch_port_t) atoi(val);
5768 						}
5769 					} else if (!strcasecmp(var, "tls-cert-dir") && !zstr(val)) {
5770 						profile->tls_cert_dir = switch_core_strdup(profile->pool, val);
5771 					} else if (!strcasecmp(var, "tls-passphrase") && !zstr(val)) {
5772 						profile->tls_passphrase = switch_core_strdup(profile->pool, val);
5773 					} else if (!strcasecmp(var, "tls-verify-in-subjects") && !zstr(val)) {
5774 						profile->tls_verify_in_subjects_str = switch_core_strdup(profile->pool, val);
5775 					} else if (!strcasecmp(var, "tls-ciphers") && !zstr(val)) {
5776 						profile->tls_ciphers = switch_core_strdup(profile->pool, val);
5777 					} else if (!strcasecmp(var, "tls-version") && !zstr(val)) {
5778 						char *ps = val, *pe = val;
5779 						profile->tls_version = 0;
5780 						while (ps && *pe) {
5781 							int n;
5782 							pe = strchr(ps,',');
5783 							if (!pe && !(pe = memchr(ps,0,1024))) break;
5784 							n = (int)(pe-ps);
5785 							if (n==5 && !strncasecmp(ps, "sslv2", n))
5786 								profile->tls_version |= SOFIA_TLS_VERSION_SSLv2;
5787 							if (n==5 && !strncasecmp(ps, "sslv3", n))
5788 								profile->tls_version |= SOFIA_TLS_VERSION_SSLv3;
5789 							if (n==6 && !strncasecmp(ps, "sslv23", n))
5790 								profile->tls_version |= SOFIA_TLS_VERSION_SSLv2 | SOFIA_TLS_VERSION_SSLv3;
5791 							if (n==5 && !strncasecmp(ps, "tlsv1", n))
5792 								profile->tls_version |= SOFIA_TLS_VERSION_TLSv1;
5793 							if (n==7 && !strncasecmp(ps, "tlsv1.1", n))
5794 								profile->tls_version |= SOFIA_TLS_VERSION_TLSv1_1;
5795 							if (n==7 && !strncasecmp(ps, "tlsv1.2", n))
5796 								profile->tls_version |= SOFIA_TLS_VERSION_TLSv1_2;
5797 							ps=pe+1;
5798 						}
5799 					} else if (!strcasecmp(var, "tls-timeout") && !zstr(val)) {
5800 						int v = atoi(val);
5801 						profile->tls_timeout = v > 0 ? (unsigned int)v : 300;
5802 					} else if (!strcasecmp(var, "timer-T1") && !zstr(val)) {
5803 						int v = atoi(val);
5804 						if (v > 0) {
5805 							profile->timer_t1 = v;
5806 						} else {
5807 							profile->timer_t1 = 500;
5808 						}
5809 					} else if (!strcasecmp(var, "timer-T1X64") && !zstr(val)) {
5810 						int v = atoi(val);
5811 						if (v > 0) {
5812 							profile->timer_t1x64 = v;
5813 						} else {
5814 							profile->timer_t1x64 = 32000;
5815 						}
5816 					} else if (!strcasecmp(var, "timer-T2") && !zstr(val)) {
5817 						int v = atoi(val);
5818 						if (v > 0) {
5819 							profile->timer_t2 = v;
5820 						} else {
5821 							profile->timer_t2 = 4000;
5822 						}
5823 					} else if (!strcasecmp(var, "timer-T4") && !zstr(val)) {
5824 						int v = atoi(val);
5825 						if (v > 0) {
5826 							profile->timer_t4 = v;
5827 						} else {
5828 							profile->timer_t4 = 4000;
5829 						}
5830 					} else if (!strcasecmp(var, "sip-options-respond-503-on-busy")) {
5831 						if (switch_true(val)) {
5832 							sofia_set_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY);
5833 						} else {
5834 							sofia_clear_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY);
5835 						}
5836 					} else if (!strcasecmp(var, "sip-expires-late-margin") && !zstr(val)) {
5837 						int32_t sip_expires_late_margin = atoi(val);
5838 						if (sip_expires_late_margin >= 0) {
5839 							profile->sip_expires_late_margin = sip_expires_late_margin;
5840 						} else {
5841 							profile->sip_expires_late_margin = 60;
5842 						}
5843 					} else if (!strcasecmp(var, "sip-force-expires-min") && !zstr(val)) {
5844 						int32_t sip_force_expires_min = atoi(val);
5845 						if (sip_force_expires_min >= 0) {
5846 							profile->sip_force_expires_min = sip_force_expires_min;
5847 						} else {
5848 							profile->sip_force_expires_min = 0;
5849 						}
5850 					} else if (!strcasecmp(var, "sip-force-expires-max") && !zstr(val)) {
5851 						int32_t sip_force_expires_max = atoi(val);
5852 						if (sip_force_expires_max >= 0) {
5853 							profile->sip_force_expires_max = sip_force_expires_max;
5854 						} else {
5855 							profile->sip_force_expires_max = 0;
5856 						}
5857 					} else if (!strcasecmp(var, "sip-force-expires") && !zstr(val)) {
5858 						int32_t sip_force_expires = atoi(val);
5859 						if (sip_force_expires >= 0) {
5860 							profile->sip_force_expires = sip_force_expires;
5861 						} else {
5862 							profile->sip_force_expires = 0;
5863 						}
5864 					} else if (!strcasecmp(var, "sip-expires-max-deviation") && !zstr(val)) {
5865 						int32_t sip_expires_max_deviation = atoi(val);
5866 						if (sip_expires_max_deviation >= 0) {
5867 							profile->sip_expires_max_deviation = sip_expires_max_deviation;
5868 						} else {
5869 							profile->sip_expires_max_deviation = 0;
5870 						}
5871 					} else if (!strcasecmp(var, "sip-subscription-max-deviation") && !zstr(val)) {
5872 						int32_t sip_subscription_max_deviation = atoi(val);
5873 						if (sip_subscription_max_deviation >= 0) {
5874 							profile->sip_subscription_max_deviation = sip_subscription_max_deviation;
5875 						} else {
5876 							profile->sip_subscription_max_deviation = 0;
5877 						}
5878 					} else if (!strcasecmp(var, "reuse-connections")) {
5879 						switch_bool_t value = switch_true(val);
5880 						if (!value) {
5881 							sofia_set_pflag(profile, PFLAG_NO_CONNECTION_REUSE);
5882 						} else {
5883 							sofia_clear_pflag(profile, PFLAG_NO_CONNECTION_REUSE);
5884 						}
5885 					} else if (!strcasecmp(var, "p-asserted-id-parse")) {
5886 						if (!val) {
5887 							profile->paid_type = PAID_DEFAULT;
5888 						} else 	if (!strncasecmp(val, "default", 7)) {
5889 							profile->paid_type = PAID_DEFAULT;
5890 						} else if (!strncasecmp(val, "user-only", 9)) {
5891 							profile->paid_type = PAID_USER;
5892 						} else if (!strncasecmp(val, "user-domain", 11)) {
5893 							profile->paid_type = PAID_USER_DOMAIN;
5894 						} else if (!strncasecmp(val, "verbatim", 8)) {
5895 							profile->paid_type = PAID_VERBATIM;
5896 						} else {
5897 							profile->paid_type = PAID_DEFAULT;
5898 						}
5899 					} else if (!strcasecmp(var, "channel-xml-fetch-on-nightmare-transfer")) {
5900 						if(switch_true(val)) {
5901 							sofia_set_pflag(profile, PFLAG_CHANNEL_XML_FETCH_ON_NIGHTMARE_TRANSFER);
5902 						}  else {
5903 							sofia_clear_pflag(profile, PFLAG_CHANNEL_XML_FETCH_ON_NIGHTMARE_TRANSFER);
5904 						}
5905 					} else if (!strcasecmp(var, "make-every-transfer-a-nightmare")) {
5906 						if(switch_true(val)) {
5907 							sofia_set_pflag(profile, PFLAG_MAKE_EVERY_TRANSFER_A_NIGHTMARE);
5908 						}  else {
5909 							sofia_clear_pflag(profile, PFLAG_MAKE_EVERY_TRANSFER_A_NIGHTMARE);
5910 						}
5911 					} else if (!strcasecmp(var, "fire-transfer-events")) {
5912 						if(switch_true(val)) {
5913 							sofia_set_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS);
5914 						}  else {
5915 							sofia_clear_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS);
5916 						}
5917 					} else if (!strcasecmp(var, "enforce-blind-auth-result")) {
5918 						if(switch_true(val)) {
5919 							sofia_set_pflag(profile, PFLAG_BLIND_AUTH_ENFORCE_RESULT);
5920 						}  else {
5921 							sofia_clear_pflag(profile, PFLAG_BLIND_AUTH_ENFORCE_RESULT);
5922 						}
5923 					} else if (!strcasecmp(var, "blind-auth-reply-403")) {
5924 						if(switch_true(val)) {
5925 							sofia_set_pflag(profile, PFLAG_BLIND_AUTH_REPLY_403);
5926 						}  else {
5927 							sofia_clear_pflag(profile, PFLAG_BLIND_AUTH_REPLY_403);
5928 						}
5929 					} else if (!strcasecmp(var, "auth-calls-acl-only")) {
5930 						if(switch_true(val)) {
5931 							sofia_set_pflag(profile, PFLAG_AUTH_CALLS_ACL_ONLY);
5932 						}  else {
5933 							sofia_clear_pflag(profile, PFLAG_AUTH_CALLS_ACL_ONLY);
5934 						}
5935 					} else if (!strcasecmp(var, "use-port-for-acl-check")) {
5936 						if(switch_true(val)) {
5937 							sofia_set_pflag(profile, PFLAG_USE_PORT_FOR_ACL_CHECK);
5938 						}  else {
5939 							sofia_clear_pflag(profile, PFLAG_USE_PORT_FOR_ACL_CHECK);
5940 						}
5941 					} else if (!strcasecmp(var, "apply-inbound-acl-x-token")) {
5942 						profile->acl_inbound_x_token_header = switch_core_strdup(profile->pool, val);
5943 					} else if (!strcasecmp(var, "apply-proxy-acl-x-token")) {
5944 						profile->acl_proxy_x_token_header = switch_core_strdup(profile->pool, val);
5945 					} else if (!strcasecmp(var, "proxy-hold")) {
5946 						if(switch_true(val)) {
5947 							sofia_set_pflag(profile, PFLAG_PROXY_HOLD);
5948 						}  else {
5949 							sofia_clear_pflag(profile, PFLAG_PROXY_HOLD);
5950 						}
5951 					} else if (!strcasecmp(var, "proxy-info")) {
5952 						if(switch_true(val)) {
5953 							sofia_set_pflag(profile, PFLAG_PROXY_INFO);
5954 						}  else {
5955 							sofia_clear_pflag(profile, PFLAG_PROXY_INFO);
5956 						}
5957 					} else if (!strcasecmp(var, "proxy-message")) {
5958 						if(switch_true(val)) {
5959 							sofia_set_pflag(profile, PFLAG_PROXY_MESSAGE);
5960 						}  else {
5961 							sofia_clear_pflag(profile, PFLAG_PROXY_MESSAGE);
5962 						}
5963 					} else if (!strcasecmp(var, "proxy-notify-events")) {
5964 						profile->proxy_notify_events = switch_core_strdup(profile->pool, val);
5965 					} else if (!strcasecmp(var, "proxy-info-content-types")) {
5966 						profile->proxy_info_content_types = switch_core_strdup(profile->pool, val);
5967 					}
5968 				}
5969 
5970 				if (sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU) && !sofia_test_flag(profile, TFLAG_LATE_NEGOTIATION)) {
5971 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "ZRTP passthrough implictly enables inbound-late-negotiation\n");
5972 					sofia_set_flag(profile, TFLAG_LATE_NEGOTIATION);
5973 				}
5974 
5975 				if (sofia_test_flag(profile, TFLAG_INB_NOMEDIA) && !sofia_test_flag(profile, TFLAG_LATE_NEGOTIATION)) {
5976 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "inbound-bypass-media  implictly enables inbound-late-negotiation\n");
5977 					sofia_set_flag(profile, TFLAG_LATE_NEGOTIATION);
5978 				}
5979 
5980 				if (sofia_test_pflag(profile, PFLAG_SEND_DISPLAY_UPDATE) && !sofia_test_pflag(profile, PFLAG_ALLOW_UPDATE)) {
5981 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "send-display-update=true is set, but we can't comply because allow-update=false\n");
5982 					sofia_clear_pflag(profile, PFLAG_SEND_DISPLAY_UPDATE);
5983 				}
5984 				if (sofia_test_pflag(profile, PFLAG_PROXY_HOLD)) {
5985 					if (profile->media_options & MEDIA_OPT_MEDIA_ON_HOLD) {
5986 						profile->media_options &= ~MEDIA_OPT_MEDIA_ON_HOLD;
5987 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "proxy-hold=true is set, incompatible with media-option=resume-media-on-hold\n");
5988 					}
5989 					if (profile->media_options & MEDIA_OPT_BYPASS_AFTER_HOLD) {
5990 						profile->media_options &= ~MEDIA_OPT_BYPASS_AFTER_HOLD;
5991 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "proxy-hold=true is set, incompatible with media-option=bypass-media-after-hold\n");
5992 					}
5993 				}
5994 
5995 				if ((!profile->cng_pt) && (!sofia_test_media_flag(profile, SCMF_SUPPRESS_CNG))) {
5996 					profile->cng_pt = SWITCH_RTP_CNG_PAYLOAD;
5997 				}
5998 
5999 				if (!profile->sipip) {
6000 					profile->sipip = switch_core_strdup(profile->pool, mod_sofia_globals.guess_ip);
6001 				}
6002 
6003 				if (!profile->rtpip[0] && !profile->rtpip6[0]) {
6004 					profile->rtpip[profile->rtpip_index++] = switch_core_strdup(profile->pool, mod_sofia_globals.guess_ip);
6005 				}
6006 
6007 				if (switch_nat_get_type()) {
6008 					char *ip = switch_core_get_variable_dup("nat_public_addr");
6009 					if (ip && !strchr(profile->sipip, ':')) {
6010 						if (!profile->extrtpip) {
6011 							profile->extrtpip = switch_core_strdup(profile->pool, ip);
6012 						}
6013 						if (!profile->extsipip) {
6014 							profile->extsipip = switch_core_strdup(profile->pool, ip);
6015 						}
6016 						sofia_set_pflag(profile, PFLAG_AUTO_NAT);
6017 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "NAT detected setting external ip to %s\n", ip);
6018 					}
6019 					switch_safe_free(ip);
6020 				}
6021 
6022 				if (profile->nonce_ttl < 60) {
6023 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting nonce TTL to 60 seconds\n");
6024 					profile->nonce_ttl = 60;
6025 				}
6026 
6027 				if (!profile->max_auth_validity) {
6028 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Setting MAX Auth Validity to 0 Attempts\n");
6029 					profile->max_auth_validity = 0;
6030 				}
6031 
6032 				if (!profile->sdp_username) {
6033 					profile->sdp_username = switch_core_strdup(profile->pool, "FreeSWITCH");
6034 				}
6035 
6036 				if (!profile->rtpip[0] && !profile->rtpip6[0]) {
6037 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Setting ip to '127.0.0.1'\n");
6038 					profile->rtpip[profile->rtpip_index++] = switch_core_strdup(profile->pool, "127.0.0.1");
6039 				}
6040 
6041 				if (!profile->sip_port && !sofia_test_pflag(profile, PFLAG_AUTO_ASSIGN_PORT)) {
6042 					profile->sip_port = (switch_port_t) atoi(SOFIA_DEFAULT_PORT);
6043 					if (!profile->extsipport) profile->extsipport = profile->sip_port;
6044 				}
6045 
6046 				if (!profile->dialplan) {
6047 					profile->dialplan = switch_core_strdup(profile->pool, "XML");
6048 				}
6049 
6050 				if (!profile->context) {
6051 					profile->context = switch_core_strdup(profile->pool, "default");
6052 				}
6053 
6054 				if (!profile->sipdomain) {
6055 					profile->sipdomain = switch_core_strdup(profile->pool, profile->sipip);
6056 				}
6057 
6058 				if (profile->pres_type == PRES_TYPE_PNP) {
6059 					if (!profile->pnp_prov_url) {
6060 						profile->pnp_prov_url = switch_core_sprintf(profile->pool, "http://%s/provision/", mod_sofia_globals.guess_ip);
6061 					}
6062 
6063 					if (!profile->pnp_notify_profile) {
6064 						profile->pnp_notify_profile = switch_core_strdup(profile->pool, mod_sofia_globals.guess_ip);
6065 					}
6066 
6067 					if (!profile->extsipip) {
6068 						profile->extsipip = switch_core_strdup(profile->pool, mod_sofia_globals.guess_ip);
6069 					}
6070 
6071 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "we're configured to provision to [%s] on profile [%s]\n",
6072 									  profile->pnp_prov_url, profile->pnp_notify_profile);
6073 				}
6074 
6075 				config_sofia_profile_urls(profile);
6076 
6077 				if (profile->tls_cert_dir) {
6078 					if (profile->wss_ip) {
6079 						char *key, *cert;
6080 						key  = switch_core_sprintf(profile->pool, "%s/%s", profile->tls_cert_dir, "wss.key");
6081 						if (switch_file_exists(key, profile->pool) != SWITCH_STATUS_SUCCESS) key = NULL;
6082 						cert = switch_core_sprintf(profile->pool, "%s/%s", profile->tls_cert_dir, "wss.crt");
6083 						if (switch_file_exists(cert, profile->pool) != SWITCH_STATUS_SUCCESS) cert = NULL;
6084 						if ( !key || !cert) {
6085 							key  = switch_core_sprintf(profile->pool, "%s/%s", profile->tls_cert_dir, "wss.pem");
6086 							if ( switch_file_exists(key, profile->pool) != SWITCH_STATUS_SUCCESS ) {
6087 								switch_core_gen_certs(key);
6088 							}
6089 						}
6090 					}
6091 					if (sofia_test_pflag(profile, PFLAG_TLS)) {
6092 						char *key = switch_core_sprintf(profile->pool, "%s/%s", profile->tls_cert_dir, "agent.pem");
6093 						char *ca  =  switch_core_sprintf(profile->pool, "%s/%s", profile->tls_cert_dir, "cafile.pem");;
6094 						if (switch_file_exists(key, profile->pool) != SWITCH_STATUS_SUCCESS) key = NULL;
6095 						if (switch_file_exists(ca, profile->pool) != SWITCH_STATUS_SUCCESS) ca = NULL;
6096 						if ( !key || !ca ) {
6097 							key  = switch_core_sprintf(profile->pool, "%s/%s", profile->tls_cert_dir, "tls.pem");
6098 							if ( switch_file_exists(key, profile->pool) != SWITCH_STATUS_SUCCESS ) {
6099 								switch_core_gen_certs(key);
6100 							}
6101 						}
6102 					}
6103 				}
6104 			}
6105 
6106 			if (profile) {
6107 				if (profile_already_started) {
6108 					switch_xml_t gateways_tag, domain_tag, domains_tag, aliases_tag, alias_tag;
6109 
6110 					if (sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU)) {
6111 						sofia_set_flag(profile, TFLAG_LATE_NEGOTIATION);
6112 					}
6113 
6114 					if ((gateways_tag = switch_xml_child(xprofile, "gateways"))) {
6115 						parse_gateways(profile, gateways_tag, NULL);
6116 					}
6117 
6118 					status = SWITCH_STATUS_SUCCESS;
6119 
6120 					if ((domains_tag = switch_xml_child(xprofile, "domains"))) {
6121 						switch_event_t *xml_params;
6122 						switch_event_create(&xml_params, SWITCH_EVENT_REQUEST_PARAMS);
6123 						switch_assert(xml_params);
6124 						switch_event_add_header_string(xml_params, SWITCH_STACK_BOTTOM, "purpose", "gateways");
6125 						switch_event_add_header_string(xml_params, SWITCH_STACK_BOTTOM, "profile", profile->name);
6126 
6127 						for (domain_tag = switch_xml_child(domains_tag, "domain"); domain_tag; domain_tag = domain_tag->next) {
6128 							switch_xml_t droot, x_domain_tag;
6129 							const char *dname = switch_xml_attr_soft(domain_tag, "name");
6130 							const char *parse = switch_xml_attr_soft(domain_tag, "parse");
6131 							const char *alias = switch_xml_attr_soft(domain_tag, "alias");
6132 
6133 							if (!zstr(dname)) {
6134 								if (!strcasecmp(dname, "all")) {
6135 									switch_xml_t xml_root, x_domains;
6136 									if (switch_xml_locate("directory", NULL, NULL, NULL, &xml_root, &x_domains, xml_params, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
6137 										for (x_domain_tag = switch_xml_child(x_domains, "domain"); x_domain_tag; x_domain_tag = x_domain_tag->next) {
6138 											dname = switch_xml_attr_soft(x_domain_tag, "name");
6139 											parse_domain_tag(profile, x_domain_tag, dname, parse, alias);
6140 										}
6141 										switch_xml_free(xml_root);
6142 									}
6143 								} else if (switch_xml_locate_domain(dname, xml_params, &droot, &x_domain_tag) == SWITCH_STATUS_SUCCESS) {
6144 									parse_domain_tag(profile, x_domain_tag, dname, parse, alias);
6145 									switch_xml_free(droot);
6146 								}
6147 							}
6148 						}
6149 
6150 						switch_event_destroy(&xml_params);
6151 					}
6152 
6153 					if ((aliases_tag = switch_xml_child(xprofile, "aliases"))) {
6154 						for (alias_tag = switch_xml_child(aliases_tag, "alias"); alias_tag; alias_tag = alias_tag->next) {
6155 							char *aname = (char *) switch_xml_attr_soft(alias_tag, "name");
6156 							if (!zstr(aname)) {
6157 
6158 								if (sofia_glue_add_profile(switch_core_strdup(profile->pool, aname), profile) == SWITCH_STATUS_SUCCESS) {
6159 									switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Alias [%s] for profile [%s]\n", aname, profile->name);
6160 								} else {
6161 									switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Alias [%s] for profile [%s] (already exists)\n",
6162 													  aname, profile->name);
6163 								}
6164 							}
6165 						}
6166 					}
6167 
6168 				} else {
6169 					switch_xml_t aliases_tag, alias_tag;
6170 
6171 					if ((aliases_tag = switch_xml_child(xprofile, "aliases"))) {
6172 						for (alias_tag = switch_xml_child(aliases_tag, "alias"); alias_tag; alias_tag = alias_tag->next) {
6173 							char *aname = (char *) switch_xml_attr_soft(alias_tag, "name");
6174 							if (!zstr(aname)) {
6175 
6176 								if (sofia_glue_add_profile(switch_core_strdup(profile->pool, aname), profile) == SWITCH_STATUS_SUCCESS) {
6177 									switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Adding Alias [%s] for profile [%s]\n", aname, profile->name);
6178 								} else {
6179 									switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Adding Alias [%s] for profile [%s] (name in use)\n",
6180 													  aname, profile->name);
6181 								}
6182 							}
6183 						}
6184 					}
6185 
6186 					if (profile->sipip) {
6187 						switch_event_t *s_event;
6188 						if (!profile->extsipport) profile->extsipport = profile->sip_port;
6189 
6190 						launch_sofia_profile_thread(profile);
6191 						if (profile->odbc_dsn) {
6192 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Connecting ODBC Profile %s [%s]\n", profile->name, url);
6193 							switch_yield(1000000);
6194 						} else {
6195 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Started Profile %s [%s]\n", profile->name, url);
6196 						}
6197 						if ((switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_PROFILE_START) == SWITCH_STATUS_SUCCESS)) {
6198 							switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "module_name", "mod_sofia");
6199 							switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile_name", profile->name);
6200 							switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile_uri", profile->url);
6201 							switch_event_fire(&s_event);
6202 						}
6203 					} else {
6204 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Unable to start Profile %s due to no configured sip-ip\n", profile->name);
6205 						sofia_profile_start_failure(profile, profile->name);
6206 					}
6207 					profile = NULL;
6208 				}
6209 				if (profile_found) {
6210 					break;
6211 				}
6212 			}
6213 		}
6214 	}
6215   done:
6216 
6217 	if (profile_already_started) {
6218 		sofia_glue_release_profile(profile_already_started);
6219 	}
6220 
6221 	switch_event_destroy(&params);
6222 
6223 	if (xml) {
6224 		switch_xml_free(xml);
6225 	}
6226 
6227 	if (profile_name && !profile_found) {
6228 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No Such Profile '%s'\n", profile_name);
6229 		status = SWITCH_STATUS_FALSE;
6230 	}
6231 
6232 	return status;
6233 }
6234 
sofia_gateway_status_name(sofia_gateway_status_t status)6235 const char *sofia_gateway_status_name(sofia_gateway_status_t status)
6236 {
6237 	static const char *status_names[] = { "DOWN", "UP", NULL };
6238 
6239 	if (status < SOFIA_GATEWAY_INVALID) {
6240 		return status_names[status];
6241 	} else {
6242 		return "INVALID";
6243 	}
6244 }
6245 
sofia_sip_user_status_name(sofia_sip_user_status_t status)6246 const char *sofia_sip_user_status_name(sofia_sip_user_status_t status)
6247 {
6248 	static const char *status_names[] = { "UNREACHABLE", "REACHABLE", NULL };
6249 
6250 	if (status < SOFIA_REG_INVALID) {
6251 		return status_names[status];
6252 	} else {
6253 		return "INVALID";
6254 	}
6255 }
6256 
6257 struct cb_helper_sip_user_status {
6258 	char *status;
6259 	size_t status_len;
6260 
6261 	char *contact;
6262 	size_t contact_len;
6263 
6264 	int count;
6265 };
6266 
sofia_sip_user_status_callback(void * pArg,int argc,char ** argv,char ** columnNames)6267 int sofia_sip_user_status_callback(void *pArg, int argc, char **argv, char **columnNames)
6268 {
6269 	struct cb_helper_sip_user_status *cbt = (struct cb_helper_sip_user_status *) pArg;
6270 
6271 	if (argc != 3) {
6272 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "expected 3 arguments from query, instead got %d\n", argc);
6273 		return 0;
6274 	}
6275 
6276 	switch_copy_string(cbt->status, argv[0], cbt->status_len);
6277 	cbt->count = (argv[1] && switch_is_number(argv[1])) ? atoi(argv[1]) : 0;
6278 
6279 	switch_copy_string(cbt->contact, argv[2], cbt->contact_len);
6280 
6281 	return 1;
6282 }
6283 
sofia_handle_sip_r_options(switch_core_session_t * session,int status,char const * phrase,nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,sofia_private_t * sofia_private,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])6284 static void sofia_handle_sip_r_options(switch_core_session_t *session, int status,
6285 									   char const *phrase,
6286 									   nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
6287 								sofia_dispatch_event_t *de,
6288 									   tagi_t tags[])
6289 {
6290 	sofia_gateway_t *gateway = NULL;
6291 	switch_bool_t do_fire_gateway_state_event = SWITCH_FALSE;
6292 
6293 	if (sofia_private && !zstr(sofia_private->gateway_name)) {
6294 		gateway = sofia_reg_find_gateway(sofia_private->gateway_name);
6295 		sofia_private->destroy_me = 1;
6296 	}
6297 
6298 	if (gateway) {
6299 		if (status >= 200 && status < 600 && status != 408 && status != 503) {
6300 			if (gateway->state == REG_STATE_FAILED) {
6301 				gateway->state = REG_STATE_UNREGED;
6302 			}
6303 
6304 			if (gateway->ping_count < 0) {
6305 				gateway->ping_count = 0;
6306 			}
6307 
6308 			if (gateway->ping_count < gateway->ping_max) {
6309 				gateway->ping_count++;
6310 
6311 				if (gateway->ping_count >= gateway->ping_min && gateway->status != SOFIA_GATEWAY_UP) {
6312 					gateway->status = SOFIA_GATEWAY_UP;
6313 					gateway->uptime = switch_time_now();
6314 					do_fire_gateway_state_event = SWITCH_TRUE;
6315 				}
6316 
6317 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
6318 								  "Ping succeeded %s with code %d - count %d/%d/%d, state %s\n",
6319 								  gateway->name, status, gateway->ping_min, gateway->ping_count, gateway->ping_max, sofia_gateway_status_name(gateway->status));
6320 			}
6321 			if (gateway->ping_sent) {
6322 				gateway->ping_time = (float)(switch_time_now() - gateway->ping_sent) / 1000;
6323 				gateway->ping_sent = 0;
6324 			}
6325 		} else {
6326 			if (gateway->state == REG_STATE_REGED) {
6327 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Unregister %s\n", gateway->name);
6328 				gateway->state = REG_STATE_FAILED;
6329 				gateway->ping_time = 0;
6330 			}
6331 
6332 			if (gateway->ping_count > 0) {
6333 				gateway->ping_count--;
6334 			}
6335 
6336 			if (gateway->ping_count < gateway->ping_min && gateway->status != SOFIA_GATEWAY_DOWN) {
6337 				gateway->status = SOFIA_GATEWAY_DOWN;
6338 				do_fire_gateway_state_event = SWITCH_TRUE;
6339 				gateway->ping_time = 0;
6340 			}
6341 
6342 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
6343 							  "Ping failed %s with code %d - count %d/%d/%d, state %s\n",
6344 							  gateway->name, status, gateway->ping_min, gateway->ping_count, gateway->ping_max, sofia_gateway_status_name(gateway->status));
6345 		}
6346 		if (gateway->ping_monitoring || do_fire_gateway_state_event) {
6347 			sofia_reg_fire_custom_gateway_state_event(gateway, status, phrase);
6348 		}
6349 
6350 		gateway->ping = switch_epoch_time_now(NULL) + gateway->ping_freq;
6351 		sofia_reg_release_gateway(gateway);
6352 		gateway->pinging = 0;
6353 	} else if (sip && sip->sip_to && sip->sip_call_id && sip->sip_call_id->i_id && strchr(sip->sip_call_id->i_id, '_')) {
6354 		const char *call_id = strchr(sip->sip_call_id->i_id, '_') + 1;
6355 		char *sql;
6356 		struct cb_helper_sip_user_status sip_user_status;
6357 		char ping_status[255] = "";
6358 		char sip_contact[1024] = "";
6359 		int sip_user_ping_min = profile->sip_user_ping_min;
6360 		int sip_user_ping_max = profile->sip_user_ping_max;
6361 
6362 		char *sip_user = switch_mprintf("%s@%s", sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host);
6363 		int ping_time = 0;
6364 
6365 		if (sofia_private && sofia_private->ping_sent) {
6366 			ping_time = (int)(switch_time_now() - sofia_private->ping_sent);
6367 		}
6368 
6369 		sip_user_status.status = ping_status;
6370 		sip_user_status.status_len = sizeof(ping_status);
6371 		sip_user_status.contact = sip_contact;
6372 		sip_user_status.contact_len = sizeof(sip_contact);
6373 		sql = switch_mprintf("select ping_status, ping_count, contact from sip_registrations where sip_user='%q' and sip_host='%q' and call_id='%q'",
6374 				     sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, call_id);
6375 		sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_sip_user_status_callback, &sip_user_status);
6376 		switch_safe_free(sql);
6377 
6378 		if (status != 200 && status != 486) {
6379 			sip_user_status.count--;
6380 			if (sip_user_status.count >= 0) {
6381 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Ping to sip user '%s@%s' failed with code %d - count %d, state %s\n",
6382 						  sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, status, sip_user_status.count, sip_user_status.status);
6383 				sql = switch_mprintf("update sip_registrations set ping_count=%d, ping_time=%d where sip_user='%q' and sip_host='%q' and call_id='%q'",
6384 									 sip_user_status.count, ping_time, sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, call_id);
6385 				sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
6386 				switch_safe_free(sql);
6387 			}
6388 			if (sip_user_status.count < sip_user_ping_min) {
6389 				if (strcmp(sip_user_status.status, "Unreachable")) {
6390 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Sip user '%s@%s' is now Unreachable\n",
6391 							  sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host);
6392 					sql = switch_mprintf("update sip_registrations set ping_status='Unreachable', ping_time=%d where sip_user='%q' and sip_host='%q' and call_id='%q'",
6393 										 ping_time, sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, call_id);
6394 					sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
6395 					switch_safe_free(sql);
6396 					sofia_reg_fire_custom_sip_user_state_event(profile, sip_user, sip_user_status.contact, sip->sip_to->a_url->url_user,
6397 															   sip->sip_to->a_url->url_host, call_id, SOFIA_REG_REACHABLE, status, phrase);
6398 
6399 					if (sofia_test_pflag(profile, PFLAG_UNREG_OPTIONS_FAIL)) {
6400 						time_t now = switch_epoch_time_now(NULL);
6401 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Expire sip user '%s@%s' due to options failure\n",
6402 								  sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host);
6403 
6404 						sql = switch_mprintf("update sip_registrations set expires=%ld, ping_time=%d where sip_user='%q' and sip_host='%q' and call_id='%q'",
6405 											 (long) now, ping_time, sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, call_id);
6406 						sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
6407 						switch_safe_free(sql);
6408 					}
6409 				}
6410 			}
6411 		} else {
6412 			sip_user_status.count++;
6413 			if (sip_user_status.count <= sip_user_ping_max) {
6414 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Ping to sip user '%s@%s' succeeded with code %d - count %d, state %s\n",
6415 						  sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, status, sip_user_status.count, sip_user_status.status);
6416 				sql = switch_mprintf("update sip_registrations set ping_count=%d, ping_time=%d where sip_user='%q' and sip_host='%q' and call_id='%q'",
6417 									 sip_user_status.count, ping_time, sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, call_id);
6418 				sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
6419 				switch_safe_free(sql);
6420 			}
6421 			if (sip_user_status.count >= sip_user_ping_min) {
6422 				if (strcmp(sip_user_status.status, "Reachable")) {
6423 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Sip user '%s@%s' is now Reachable\n",
6424 							  sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host);
6425 					sql = switch_mprintf("update sip_registrations set ping_status='Reachable' where sip_user='%q' and sip_host='%q' and call_id='%q'",
6426 							     sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host, call_id);
6427 					sofia_glue_execute_sql(profile, &sql, SWITCH_TRUE);
6428 					switch_safe_free(sql);
6429 					sofia_reg_fire_custom_sip_user_state_event(profile, sip_user, sip_user_status.contact, sip->sip_to->a_url->url_user,
6430 															   sip->sip_to->a_url->url_host, call_id, SOFIA_REG_UNREACHABLE, status, phrase);
6431 				}
6432 			}
6433 		}
6434 
6435 		switch_safe_free(sip_user);
6436 
6437 	}
6438 }
6439 
sofia_handle_sip_r_invite(switch_core_session_t * session,int status,char const * phrase,nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,sofia_private_t * sofia_private,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])6440 static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status,
6441 									  char const *phrase,
6442 									  nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
6443 								sofia_dispatch_event_t *de,
6444 									  tagi_t tags[])
6445 {
6446 	char *call_info = NULL;
6447 	if (sip && session) {
6448 		switch_channel_t *channel = switch_core_session_get_channel(session);
6449 		const char *uuid;
6450 		switch_core_session_t *other_session;
6451 		private_object_t *tech_pvt = switch_core_session_get_private(session);
6452 		char network_ip[80];
6453 		int network_port = 0;
6454 		switch_caller_profile_t *caller_profile = NULL;
6455 		int has_t38 = 0;
6456 
6457 		switch_channel_clear_flag(channel, CF_REQ_MEDIA);
6458 
6459 		if (status < 200) {
6460 			if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
6461 				if(switch_core_session_compare(session, other_session)) {
6462 					private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
6463 					if (sofia_test_flag(other_tech_pvt, TFLAG_3PCC)) {
6464 						sofia_set_flag_locked(tech_pvt, TFLAG_SKIP_EARLY);
6465 					}
6466 				}
6467 				switch_core_session_rwunlock(other_session);
6468 			}
6469 
6470 			if (sofia_test_flag(tech_pvt, TFLAG_SKIP_EARLY)) {
6471 				return;
6472 			}
6473 		}
6474 
6475 		if (status >= 900) {
6476 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s status %d received.\n",
6477 							  switch_channel_get_name(channel), status);
6478 			return;
6479 		}
6480 
6481 		if (status > 299) {
6482 			switch_channel_set_variable(channel, "sip_hangup_disposition", "recv_refuse");
6483 		}
6484 
6485 		if (status >= 400) {
6486 			char status_str[5];
6487 			switch_snprintf(status_str, sizeof(status_str), "%d", status);
6488 			switch_channel_set_variable(channel, "sip_invite_failure_status", status_str);
6489 			switch_channel_set_variable(channel, "sip_invite_failure_phrase", phrase);
6490 			switch_channel_set_variable_partner(channel, "sip_invite_failure_status", status_str);
6491 			switch_channel_set_variable_partner(channel, "sip_invite_failure_phrase", phrase);
6492 		} else {
6493 			switch_channel_set_variable_partner(channel, "sip_invite_failure_status", NULL);
6494 			switch_channel_set_variable_partner(channel, "sip_invite_failure_phrase", NULL);
6495 		}
6496 
6497 		if (status >= 400 && sip->sip_reason && sip->sip_reason->re_protocol && (!strcasecmp(sip->sip_reason->re_protocol, "Q.850")
6498 				|| !strcasecmp(sip->sip_reason->re_protocol, "FreeSWITCH")
6499 				|| !strcasecmp(sip->sip_reason->re_protocol, profile->sdp_username)) && sip->sip_reason->re_cause) {
6500 				tech_pvt->q850_cause = atoi(sip->sip_reason->re_cause);
6501 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote Reason: %d\n", tech_pvt->q850_cause);
6502 		}
6503 
6504 		sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
6505 
6506 		switch_channel_set_variable_printf(channel, "sip_local_network_addr", "%s", profile->extsipip ? profile->extsipip : profile->sipip);
6507 		switch_channel_set_variable(channel, "sip_reply_host", network_ip);
6508 		switch_channel_set_variable_printf(channel, "sip_reply_port", "%d", network_port);
6509 
6510 		switch_channel_set_variable_printf(channel, "sip_network_ip", "%s", network_ip);
6511 		switch_channel_set_variable_printf(channel, "sip_network_port", "%d", network_port);
6512 
6513 		if ((caller_profile = switch_channel_get_caller_profile(channel)) && !zstr(network_ip) &&
6514 			(zstr(caller_profile->network_addr) || strcmp(caller_profile->network_addr, network_ip))) {
6515 			caller_profile->network_addr = switch_core_strdup(caller_profile->pool, network_ip);
6516 		}
6517 
6518 		if (tech_pvt->mparams.last_sdp_response) {
6519 			tech_pvt->mparams.prev_sdp_response = tech_pvt->mparams.last_sdp_response;
6520 		}
6521 		tech_pvt->mparams.last_sdp_response = NULL;
6522 
6523 		if (sip->sip_payload && sip->sip_payload->pl_data) {
6524 			switch_core_media_set_sdp_codec_string(session, sip->sip_payload->pl_data, SDP_TYPE_RESPONSE);
6525 
6526 			if (!zstr(tech_pvt->mparams.prev_sdp_response) && !strcmp(tech_pvt->mparams.prev_sdp_response, sip->sip_payload->pl_data)) {
6527 				tech_pvt->mparams.last_sdp_response = tech_pvt->mparams.prev_sdp_response;
6528 			} else {
6529 				tech_pvt->mparams.last_sdp_response = switch_core_session_strdup(session, sip->sip_payload->pl_data);
6530 			}
6531 		}
6532 
6533 		if (status > 299 && switch_channel_test_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_REQ)) {
6534 			switch_channel_set_private(channel, "t38_options", NULL);
6535 			switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38);
6536 			switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_REQ);
6537 			switch_channel_set_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_FAIL);
6538 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 invite failed\n", switch_channel_get_name(tech_pvt->channel));
6539 		}
6540 
6541 
6542 		if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
6543 			if (channel && sip->sip_call_info) {
6544 				char *p;
6545 				call_info = sip_header_as_string(nua_handle_home(nh), (void *) sip->sip_call_info);
6546 
6547 				if (switch_stristr("appearance", call_info)) {
6548 					switch_channel_set_variable(channel, "presence_call_info_full", call_info);
6549 					if ((p = strchr(call_info, ';'))) {
6550 						switch_channel_set_variable(channel, "presence_call_info", p + 1);
6551 					}
6552 				}
6553 			} else if ((status == 180 || status == 183 || status == 200)) {
6554 				char buf[128] = "";
6555 				char *sql;
6556 				char *state = "active";
6557 
6558 				if (status != 200) {
6559 					state = "progressing";
6560 				}
6561 
6562 				if (sip->sip_from && sip->sip_from->a_url->url_user && sip->sip_from->a_url->url_host &&
6563 					sip->sip_to && sip->sip_to->a_url->url_user && sip->sip_to->a_url->url_host) {
6564 					sql =
6565 						switch_mprintf("select 'appearance-index=1' from sip_subscriptions where expires > -1 and hostname='%q' and event='call-info' and "
6566 									   "sub_to_user='%q' and sub_to_host='%q'", mod_sofia_globals.hostname, sip->sip_to->a_url->url_user,
6567 									   sip->sip_from->a_url->url_host);
6568 					sofia_glue_execute_sql2str(profile, profile->dbh_mutex, sql, buf, sizeof(buf));
6569 
6570 					if (mod_sofia_globals.debug_sla > 1) {
6571 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "QUERY SQL %s [%s]\n", sql, buf);
6572 					}
6573 					free(sql);
6574 
6575 					if (!zstr(buf)) {
6576 						sql = switch_mprintf("update sip_dialogs set call_info='%q',call_info_state='%q' "
6577 											 "where uuid='%q'", buf, state, switch_core_session_get_uuid(session));
6578 
6579 						if (mod_sofia_globals.debug_sla > 1) {
6580 							switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "QUERY SQL %s\n", sql);
6581 						}
6582 
6583 						sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
6584 
6585 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Auto-Fixing Broken SLA [<sip:%s>;%s]\n",
6586 										  sip->sip_from->a_url->url_host, buf);
6587 						switch_channel_set_variable_printf(channel, "presence_call_info_full", "<sip:%s>;%s", sip->sip_from->a_url->url_host, buf);
6588 						switch_channel_set_variable(channel, "presence_call_info", buf);
6589 					}
6590 				}
6591 			}
6592 		}
6593 
6594 		if ((status == 180 || status == 183 || status > 199)) {
6595 			const char *vval;
6596 
6597 			sofia_set_accept_language_channel_variable(channel, sip);
6598 
6599 			if (status > 199) {
6600 				sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_RESPONSE_HEADER_PREFIX);
6601 			} else {
6602 				sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_PROGRESS_HEADER_PREFIX);
6603 			}
6604 
6605 
6606 			if (!(vval = switch_channel_get_variable(channel, "sip_copy_custom_headers")) || switch_true(vval)) {
6607 				switch_core_session_t *other_session;
6608 
6609 				if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
6610 					if (status > 199) {
6611 						switch_ivr_transfer_variable(session, other_session, SOFIA_SIP_RESPONSE_HEADER_PREFIX_T);
6612 					} else {
6613 						switch_ivr_transfer_variable(session, other_session, SOFIA_SIP_PROGRESS_HEADER_PREFIX_T);
6614 					}
6615 					switch_core_session_rwunlock(other_session);
6616 				}
6617 			}
6618 		}
6619 
6620 		if ((status == 180 || status == 183 || status == 200)) {
6621 			const char *x_freeswitch_support;
6622 
6623 			switch_channel_set_flag(channel, CF_MEDIA_ACK);
6624 
6625 			sofia_glue_store_session_id(session, profile, sip, 1);
6626 
6627 			if ((x_freeswitch_support = sofia_glue_get_unknown_header(sip, "X-FS-Support"))) {
6628 				tech_pvt->x_freeswitch_support_remote = switch_core_session_strdup(session, x_freeswitch_support);
6629 			}
6630 
6631 			if (sip->sip_user_agent && sip->sip_user_agent->g_string) {
6632 				switch_channel_set_variable(channel, "sip_user_agent", sip->sip_user_agent->g_string);
6633 			} else if (sip->sip_server && sip->sip_server->g_string) {
6634 				switch_channel_set_variable(channel, "sip_user_agent", sip->sip_server->g_string);
6635 			}
6636 
6637 			sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_allow, "sip_allow");
6638 
6639 			sofia_update_callee_id(session, profile, sip, SWITCH_FALSE);
6640 
6641 			if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING)) {
6642 				switch_core_media_reset_autofix(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
6643 			}
6644 
6645 		}
6646 
6647 		if (channel && (status == 300 || status == 301 || status == 302 || status == 305) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
6648 			sip_contact_t *p_contact = sip->sip_contact;
6649 			int i = 0;
6650 			char var_name[80];
6651 			const char *diversion_header;
6652 			char *full_contact = NULL;
6653 			char *invite_contact;
6654 			const char *br;
6655 			const char *v;
6656 
6657 			if ((v = switch_channel_get_variable(channel, "outbound_redirect_fatal")) && switch_true(v)) {
6658 				su_home_t *home = su_home_new(sizeof(*home));
6659 				switch_assert(home != NULL);
6660 
6661 				for (p_contact = sip->sip_contact; p_contact; p_contact = p_contact->m_next) {
6662 					full_contact = sip_header_as_string(home, (void *) p_contact);
6663 					invite_contact = sofia_glue_strip_uri(full_contact);
6664 
6665 					switch_snprintf(var_name, sizeof(var_name), "sip_redirect_contact_%d", i);
6666 					switch_channel_set_variable(channel, var_name, full_contact);
6667 
6668 					if (i == 0) {
6669 							switch_channel_set_variable(channel, "sip_redirected_to", full_contact);
6670 					}
6671 
6672 					if (p_contact->m_url->url_user) {
6673 						switch_snprintf(var_name, sizeof(var_name), "sip_redirect_contact_user_%d", i);
6674 						switch_channel_set_variable(channel, var_name, p_contact->m_url->url_user);
6675 					}
6676 					if (p_contact->m_url->url_host) {
6677 						switch_snprintf(var_name, sizeof(var_name), "sip_redirect_contact_host_%d", i);
6678 						switch_channel_set_variable(channel, var_name, p_contact->m_url->url_host);
6679 					}
6680 					if (p_contact->m_url->url_params) {
6681 						switch_snprintf(var_name, sizeof(var_name), "sip_redirect_contact_params_%d", i);
6682 						switch_channel_set_variable(channel, var_name, p_contact->m_url->url_params);
6683 					}
6684 
6685 					free(invite_contact);
6686 					i++;
6687 				}
6688 				su_home_unref(home);
6689 				home = NULL;
6690 				switch_snprintf(var_name, sizeof(var_name), "sip:%d", status);
6691 				switch_channel_set_variable(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, var_name);
6692 				switch_channel_hangup(channel, SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL);
6693 				goto end;
6694 			}
6695 
6696 			if (!p_contact) {
6697 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Missing contact header in redirect request\n");
6698 				goto end;
6699 			}
6700 
6701 			if ((br = switch_channel_get_partner_uuid(channel))) {
6702 				switch_xml_t root = NULL, domain = NULL;
6703 				switch_core_session_t *a_session;
6704 				switch_channel_t *a_channel;
6705 
6706 				const char *sip_redirect_profile, *sip_redirect_context, *sip_redirect_dialplan, *sip_redirect_fork;
6707 
6708 				if ((a_session = switch_core_session_locate(br)) && (a_channel = switch_core_session_get_channel(a_session))) {
6709 					switch_stream_handle_t stream = { 0 };
6710 					char separator[2] = "|";
6711 					char *redirect_dialstring;
6712 					su_home_t *home = su_home_new(sizeof(*home));
6713 					switch_assert(home != NULL);
6714 
6715 					SWITCH_STANDARD_STREAM(stream);
6716 
6717 					if (!(sip_redirect_profile = switch_channel_get_variable(channel, "sip_redirect_profile"))) {
6718 						sip_redirect_profile = profile->name;
6719 					}
6720 					if (!(sip_redirect_context = switch_channel_get_variable(channel, "sip_redirect_context"))) {
6721 						sip_redirect_context = "redirected";
6722 					}
6723 					if (!(sip_redirect_dialplan = switch_channel_get_variable(channel, "sip_redirect_dialplan"))) {
6724 						sip_redirect_dialplan = "XML";
6725 					}
6726 
6727 					sip_redirect_fork = switch_channel_get_variable(channel, "sip_redirect_fork");
6728 
6729 					if (switch_true(sip_redirect_fork)) {
6730 						*separator = ',';
6731 					}
6732 
6733 					for (p_contact = sip->sip_contact; p_contact; p_contact = p_contact->m_next) {
6734 						full_contact = sip_header_as_string(home, (void *) p_contact);
6735 						invite_contact = sofia_glue_strip_uri(full_contact);
6736 
6737 						switch_snprintf(var_name, sizeof(var_name), "sip_redirect_contact_%d", i);
6738 						switch_channel_set_variable(a_channel, var_name, full_contact);
6739 
6740 						if (i == 0) {
6741 							switch_channel_set_variable(channel, "sip_redirected_to", full_contact);
6742 							switch_channel_set_variable(a_channel, "sip_redirected_to", full_contact);
6743 						}
6744 
6745 						if (p_contact->m_url->url_user) {
6746 							switch_snprintf(var_name, sizeof(var_name), "sip_redirect_contact_user_%d", i);
6747 							switch_channel_set_variable(channel, var_name, p_contact->m_url->url_user);
6748 							switch_channel_set_variable(a_channel, var_name, p_contact->m_url->url_user);
6749 						}
6750 						if (p_contact->m_url->url_host) {
6751 							switch_snprintf(var_name, sizeof(var_name), "sip_redirect_contact_host_%d", i);
6752 							switch_channel_set_variable(channel, var_name, p_contact->m_url->url_host);
6753 							switch_channel_set_variable(a_channel, var_name, p_contact->m_url->url_host);
6754 						}
6755 						if (p_contact->m_url->url_params) {
6756 							switch_snprintf(var_name, sizeof(var_name), "sip_redirect_contact_params_%d", i);
6757 							switch_channel_set_variable(channel, var_name, p_contact->m_url->url_params);
6758 							switch_channel_set_variable(a_channel, var_name, p_contact->m_url->url_params);
6759 						}
6760 
6761 						switch_snprintf(var_name, sizeof(var_name), "sip_redirect_dialstring_%d", i);
6762 						switch_channel_set_variable_printf(channel, var_name, "sofia/%s/%s", sip_redirect_profile, invite_contact);
6763 						switch_channel_set_variable_printf(a_channel, var_name, "sofia/%s/%s", sip_redirect_profile, invite_contact);
6764 						stream.write_function(&stream, "%ssofia/%s/%s", i ? separator : "", sip_redirect_profile, invite_contact);
6765 						free(invite_contact);
6766 						i++;
6767 					}
6768 
6769 					redirect_dialstring = stream.data;
6770 
6771 					switch_channel_set_variable_printf(channel, "sip_redirect_count", "%d", i);
6772 					switch_channel_set_variable(channel, "sip_redirect_dialstring", redirect_dialstring);
6773 					switch_channel_set_variable(a_channel, "sip_redirect_dialstring", redirect_dialstring);
6774 
6775 					p_contact = sip->sip_contact;
6776 					full_contact = sip_header_as_string(home, (void *) sip->sip_contact);
6777 
6778 					if ((diversion_header = sofia_glue_get_unknown_header(sip, "diversion"))) {
6779 						switch_channel_set_variable(channel, "sip_redirected_by", diversion_header);
6780 						switch_channel_set_variable(a_channel, "sip_redirected_by", diversion_header);
6781 					}
6782 
6783 					if (sofia_test_pflag(profile, PFLAG_MANUAL_REDIRECT)) {
6784 						if (!(v = switch_channel_get_variable(channel, "outbound_redirect_info"))) {
6785 							switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Redirect: Transfering to %s %s %s\n",
6786 											  p_contact->m_url->url_user, sip_redirect_dialplan, sip_redirect_context);
6787 
6788 							if (switch_true(switch_channel_get_variable(channel, "recording_follow_transfer"))) {
6789 								switch_ivr_transfer_recordings(session, a_session);
6790 							}
6791 
6792 							switch_ivr_session_transfer(a_session, p_contact->m_url->url_user, sip_redirect_dialplan, sip_redirect_context);
6793 						}
6794 						switch_channel_hangup(channel, SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION);
6795 					} else if( !p_contact->m_url->url_host ) {
6796 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Received redirect with invalid URI\n");
6797 						switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "REDIRECT_ERROR");
6798 						switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
6799 					} else if ((!strcmp(profile->sipip, p_contact->m_url->url_host))
6800 							   || (profile->extsipip && !strcmp(profile->extsipip, p_contact->m_url->url_host))
6801 							   || (switch_xml_locate_domain(p_contact->m_url->url_host, NULL, &root, &domain) == SWITCH_STATUS_SUCCESS)) {
6802 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Redirect: Transfering to %s\n",
6803 										  p_contact->m_url->url_user);
6804 
6805 						if (switch_true(switch_channel_get_variable(channel, "recording_follow_transfer"))) {
6806 							switch_ivr_transfer_recordings(session, a_session);
6807 						}
6808 
6809 						switch_ivr_session_transfer(a_session, p_contact->m_url->url_user, NULL, NULL);
6810 						switch_channel_hangup(channel, SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION);
6811 						switch_xml_free(root);
6812 					} else {
6813 						invite_contact = sofia_glue_strip_uri(full_contact);
6814 						tech_pvt->redirected = switch_core_session_strdup(session, invite_contact);
6815 						free(invite_contact);
6816 					}
6817 
6818 					su_home_unref(home);
6819 					home = NULL;
6820 
6821 					free(stream.data);
6822 
6823 					switch_core_session_rwunlock(a_session);
6824 				}
6825 			} else {
6826 				su_home_t *home = su_home_new(sizeof(*home));
6827 				switch_assert(home != NULL);
6828 				full_contact = sip_header_as_string(home, (void *) sip->sip_contact);
6829 				invite_contact = sofia_glue_strip_uri(full_contact);
6830 
6831 				switch_channel_set_variable(channel, "sip_redirected_to", invite_contact);
6832 				tech_pvt->redirected = switch_core_session_strdup(session, invite_contact);
6833 
6834 				free(invite_contact);
6835 				su_home_unref(home);
6836 				home = NULL;
6837 			}
6838 		}
6839 
6840 
6841 		if (sip->sip_payload && sip->sip_payload->pl_data && switch_stristr("m=image", sip->sip_payload->pl_data)) {
6842 			has_t38 = 1;
6843 		}
6844 
6845 		if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
6846 			switch_channel_clear_flag(channel, CF_T38_PASSTHRU);
6847 			has_t38 = 0;
6848 		}
6849 
6850 		if (switch_channel_test_flag(channel, CF_PROXY_MEDIA) && has_t38) {
6851 			if (switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
6852 				switch_core_media_udptl_mode(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
6853 
6854 				if ((uuid = switch_channel_get_partner_uuid(channel)) && (other_session = switch_core_session_locate(uuid))) {
6855 					if (switch_core_session_compare(session, other_session)) {
6856 						private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
6857 						if (switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
6858 							switch_core_media_udptl_mode(other_tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
6859 						}
6860 					}
6861 					switch_core_session_rwunlock(other_session);
6862 				}
6863 			}
6864 
6865 			has_t38 = 0;
6866 		}
6867 
6868 		if (status > 199 && (switch_channel_test_flag(channel, CF_PROXY_MODE) ||
6869 							 switch_channel_test_flag(channel, CF_PROXY_MEDIA) ||
6870 							 (switch_channel_test_flag(tech_pvt->channel, CF_T38_PASSTHRU) && (has_t38 || status > 299)))) {
6871 
6872 			if (sofia_test_flag(tech_pvt, TFLAG_SENT_UPDATE)) {
6873 				sofia_clear_flag_locked(tech_pvt, TFLAG_SENT_UPDATE);
6874 
6875 				if ((uuid = switch_channel_get_partner_uuid(channel)) && (other_session = switch_core_session_locate(uuid))) {
6876 					const char *r_sdp = NULL;
6877 					switch_core_session_message_t *msg;
6878 					private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
6879 					//switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
6880 
6881 					if (sip->sip_payload && sip->sip_payload->pl_data &&
6882 						sip->sip_content_type && sip->sip_content_type->c_subtype && switch_stristr("sdp", sip->sip_content_type->c_subtype)) {
6883 						tech_pvt->mparams.remote_sdp_str = switch_core_session_strdup(tech_pvt->session, sip->sip_payload->pl_data);
6884 						r_sdp = tech_pvt->mparams.remote_sdp_str;
6885 						switch_core_media_proxy_remote_addr(session, NULL);
6886 					}
6887 
6888 					if (status == 415) {
6889 						int new_status = 488;
6890 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Overriding %d %s with %d\n", status, phrase, new_status);
6891 						status = new_status;
6892 					}
6893 
6894 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing %d %s to other leg\n%s\n", status, phrase, switch_str_nil(r_sdp));
6895 
6896 					if (switch_core_session_compare(session, other_session)) {
6897 						private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
6898 						sofia_set_flag(other_tech_pvt, TFLAG_PASS_ACK);
6899 					}
6900 
6901 
6902 					if (status == 491 && (switch_channel_test_flag(tech_pvt->channel, CF_T38_PASSTHRU) ||
6903 										  switch_channel_test_flag(channel, CF_PROXY_MODE))) {
6904 						nua_respond(other_tech_pvt->nh, SIP_491_REQUEST_PENDING, TAG_END());
6905 						switch_core_session_rwunlock(other_session);
6906 						goto end;
6907 					} else if (status > 299) {
6908 						switch_core_media_reset_t38(session);
6909 						switch_core_media_reset_t38(other_session);
6910 					} else if (status == 200 && switch_channel_test_flag(channel, CF_T38_PASSTHRU) &&
6911 							   has_t38 && sip->sip_payload && sip->sip_payload->pl_data) {
6912 						switch_t38_options_t *t38_options = switch_core_media_extract_t38_options(session, sip->sip_payload->pl_data);
6913 
6914 						if (!t38_options) {
6915 							switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Could not parse T.38 options from sdp.\n");
6916 							switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "T.38 NEGOTIATION ERROR");
6917 							switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
6918 							switch_core_session_rwunlock(other_session);
6919 							goto end;
6920 						} else {
6921 							switch_core_media_process_t38_passthru(session, other_session, t38_options);
6922 						}
6923 					}
6924 
6925 
6926 					msg = switch_core_session_alloc(other_session, sizeof(*msg));
6927 					msg->message_id = SWITCH_MESSAGE_INDICATE_RESPOND;
6928 					msg->from = __FILE__;
6929 					msg->numeric_arg = status;
6930 					msg->string_arg = switch_core_session_strdup(other_session, phrase);
6931 
6932 					if (status == 200 && switch_channel_test_flag(tech_pvt->channel, CF_T38_PASSTHRU) && has_t38) {
6933 						msg->pointer_arg = switch_core_session_strdup(other_session, "t38");
6934 					} else if (r_sdp) {
6935 						msg->pointer_arg = switch_core_session_strdup(other_session, r_sdp);
6936 						msg->pointer_arg_size = strlen(r_sdp);
6937 					}
6938 
6939 					if (status == 200 && switch_channel_test_flag(channel, CF_T38_PASSTHRU) && has_t38) {
6940 						if (switch_core_media_ready(session, SWITCH_MEDIA_TYPE_AUDIO) &&
6941 							switch_core_media_ready(other_session, SWITCH_MEDIA_TYPE_AUDIO)) {
6942 							switch_channel_clear_flag(channel, CF_NOTIMER_DURING_BRIDGE);
6943 							switch_core_media_udptl_mode(session, SWITCH_MEDIA_TYPE_AUDIO);
6944 							switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Activating T38 Passthru\n");
6945 						}
6946 					}
6947 
6948 					switch_core_session_queue_message(other_session, msg);
6949 
6950 					switch_core_session_rwunlock(other_session);
6951 				}
6952 				goto end;
6953 			}
6954 		}
6955 
6956 		if ((status == 180 || status == 183 || status == 200)) {
6957 			const char *astate = "early";
6958 			url_t *from = NULL, *to = NULL, *contact = NULL;
6959 
6960 			if (sip->sip_to) {
6961 				to = sip->sip_to->a_url;
6962 			}
6963 			if (sip->sip_from) {
6964 				from = sip->sip_from->a_url;
6965 			}
6966 			if (sip->sip_contact) {
6967 				contact = sip->sip_contact->m_url;
6968 			}
6969 
6970 			if (status == 200) {
6971 				astate = "confirmed";
6972 			}
6973 
6974 			if ((!switch_channel_test_flag(channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(channel, CF_ANSWERED) &&
6975 				 !switch_channel_test_flag(channel, CF_RING_READY)) || switch_channel_test_flag(channel, CF_RECOVERING)) {
6976 				const char *from_user = "", *from_host = "", *to_user = "", *to_host = "", *contact_user = "", *contact_host = "";
6977 				const char *user_agent = "", *call_id = "";
6978 				const char *to_tag = "";
6979 				const char *from_tag = "";
6980 				char *sql = NULL;
6981 
6982 				if (sip->sip_user_agent) {
6983 					user_agent = switch_str_nil(sip->sip_user_agent->g_string);
6984 				}
6985 
6986 				if (sip->sip_call_id) {
6987 					call_id = switch_str_nil(sip->sip_call_id->i_id);
6988 				}
6989 
6990 				if (to) {
6991 					from_user = switch_str_nil(to->url_user);
6992 					from_tag = switch_str_nil(sip->sip_to->a_tag);
6993 				}
6994 
6995 				if (from) {
6996 					from_host = switch_str_nil(from->url_host);
6997 					to_user = switch_str_nil(from->url_user);
6998 					to_host = switch_str_nil(from->url_host);
6999 					to_tag = switch_str_nil(sip->sip_from->a_tag);
7000 				}
7001 
7002 				if (contact) {
7003 					contact_user = switch_str_nil(contact->url_user);
7004 					contact_host = switch_str_nil(contact->url_host);
7005 				}
7006 
7007 				if (profile->pres_type) {
7008 					const char *presence_data = switch_channel_get_variable(channel, "presence_data");
7009 					const char *presence_id = switch_channel_get_variable(channel, "presence_id");
7010 					char *full_contact = NULL;
7011 					char *p = NULL;
7012 					time_t now;
7013 
7014 					if (sip->sip_contact) {
7015 						full_contact = sip_header_as_string(nua_handle_home(tech_pvt->nh), (void *) sip->sip_contact);
7016 					}
7017 
7018 					if (call_info && (p = strchr(call_info, ';'))) {
7019 						p++;
7020 					}
7021 
7022 					now = switch_epoch_time_now(NULL);
7023 
7024 					sql = switch_mprintf("insert into sip_dialogs "
7025 										 "(call_id,uuid,sip_to_user,sip_to_host,sip_to_tag,sip_from_user,sip_from_host,sip_from_tag,contact_user,"
7026 										 "contact_host,state,direction,user_agent,profile_name,hostname,contact,presence_id,presence_data,"
7027 										 "call_info,rcd,call_info_state) "
7028 										 "values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld,'')",
7029 										 call_id,
7030 										 switch_core_session_get_uuid(session),
7031 										 to_user, to_host, to_tag, from_user, from_host, from_tag, contact_user,
7032 										 contact_host, astate, "outbound", user_agent,
7033 										 profile->name, mod_sofia_globals.hostname, switch_str_nil(full_contact),
7034 										 switch_str_nil(presence_id), switch_str_nil(presence_data), switch_str_nil(p), (long) now);
7035 					switch_assert(sql);
7036 
7037 					sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
7038 
7039 					if ( full_contact ) {
7040 						su_free(nua_handle_home(tech_pvt->nh), full_contact);
7041 					}
7042 				}
7043 			} else if (status == 200 && (profile->pres_type)) {
7044 				char *sql = NULL;
7045 				const char *presence_data = switch_channel_get_variable(channel, "presence_data");
7046 				const char *presence_id = switch_channel_get_variable(channel, "presence_id");
7047 
7048 				sql = switch_mprintf("update sip_dialogs set state='%q',presence_id='%q',presence_data='%q' "
7049 									 "where uuid='%q';\n", astate, switch_str_nil(presence_id), switch_str_nil(presence_data),
7050 									 switch_core_session_get_uuid(session));
7051 				switch_assert(sql);
7052 				sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
7053 			}
7054 
7055 			extract_header_vars(profile, sip, session, nh);
7056 			extract_vars(profile, sip, session);
7057 			switch_channel_clear_flag(tech_pvt->channel, CF_RECOVERING);
7058 		}
7059 
7060 	}
7061 
7062   end:
7063 
7064 	if (call_info) {
7065 		su_free(nua_handle_home(nh), call_info);
7066 	}
7067 
7068 	if (!session && (status == 180 || status == 183 || status == 200)) {
7069 		/* nevermind */
7070 		nua_handle_bind(nh, NULL);
7071 		nua_handle_destroy(nh);
7072 	}
7073 }
7074 
7075 /* Pure black magic, if you can't understand this code you are lucky.........*/
media_on_hold_thread_run(switch_thread_t * thread,void * obj)7076 void *SWITCH_THREAD_FUNC media_on_hold_thread_run(switch_thread_t *thread, void *obj)
7077 {
7078 	switch_core_session_t *other_session = NULL, *session = (switch_core_session_t *) obj;
7079 	const char *uuid;
7080 
7081 	if (switch_core_session_read_lock(session) == SWITCH_STATUS_SUCCESS) {
7082 		switch_channel_t *channel = switch_core_session_get_channel(session);
7083 		private_object_t *tech_pvt = switch_core_session_get_private(session);
7084 
7085 		if ((uuid = switch_channel_get_partner_uuid(channel)) && (other_session = switch_core_session_locate(uuid))) {
7086 			if (switch_core_session_compare(session, other_session)) {
7087 				switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
7088 				sofia_set_flag_locked(tech_pvt, TFLAG_HOLD_LOCK);
7089 
7090 				switch_yield(250000);
7091 				switch_channel_wait_for_flag(channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
7092 				switch_channel_wait_for_flag(other_channel, CF_MEDIA_ACK, SWITCH_TRUE, 10000, NULL);
7093 
7094 				if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
7095 					switch_ivr_3p_media(switch_core_session_get_uuid(other_session), SMF_REBRIDGE|SMF_REPLYONLY_B);
7096 				} else {
7097 					switch_ivr_3p_media(switch_core_session_get_uuid(other_session), SMF_REBRIDGE);
7098 				}
7099 
7100 
7101 				switch_core_media_clear_rtp_flag(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_RTP_FLAG_AUTOADJ);
7102 				switch_core_media_clear_rtp_flag(other_session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_RTP_FLAG_AUTOADJ);
7103 
7104 
7105 				switch_core_media_toggle_hold(session, 1);
7106 			}
7107 			switch_core_session_rwunlock(other_session);
7108 		}
7109 
7110 		switch_core_session_rwunlock(session);
7111 	}
7112 
7113 	return NULL;
7114 }
7115 
launch_media_on_hold(switch_core_session_t * session)7116 static void launch_media_on_hold(switch_core_session_t *session)
7117 {
7118 	switch_thread_t *thread;
7119 	switch_threadattr_t *thd_attr = NULL;
7120 
7121 	switch_threadattr_create(&thd_attr, switch_core_session_get_pool(session));
7122 	switch_threadattr_detach_set(thd_attr, 1);
7123 	switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
7124 	switch_thread_create(&thread, thd_attr, media_on_hold_thread_run, session, switch_core_session_get_pool(session));
7125 }
7126 
7127 
7128 
mark_transfer_record(switch_core_session_t * session,const char * br_a,const char * br_b)7129 static void mark_transfer_record(switch_core_session_t *session, const char *br_a, const char *br_b)
7130 {
7131 	switch_core_session_t *br_b_session, *br_a_session;
7132 	switch_channel_t *channel;
7133 	const char *uvar1, *dvar1, *uvar2, *dvar2;
7134 
7135 	channel = switch_core_session_get_channel(session);
7136 
7137 	if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
7138 		uvar1 = "sip_from_user";
7139 		dvar1 = "sip_from_host";
7140 	} else {
7141 		uvar1 = "sip_to_user";
7142 		dvar1 = "sip_to_host";
7143 	}
7144 
7145 
7146 	if ((br_b_session = switch_core_session_locate(br_b)) ) {
7147 		switch_channel_t *br_b_channel = switch_core_session_get_channel(br_b_session);
7148 		switch_caller_profile_t *cp = switch_channel_get_caller_profile(br_b_channel);
7149 
7150 		if (switch_channel_direction(br_b_channel) == SWITCH_CALL_DIRECTION_INBOUND) {
7151 			uvar2 = "sip_from_user";
7152 			dvar2 = "sip_from_host";
7153 		} else {
7154 			uvar2 = "sip_to_user";
7155 			dvar2 = "sip_to_host";
7156 		}
7157 
7158 		cp->transfer_source = switch_core_sprintf(cp->pool,
7159 												  "%ld:%s:att_xfer:%s@%s/%s@%s",
7160 												  (long) switch_epoch_time_now(NULL),
7161 												  cp->uuid_str,
7162 												  switch_channel_get_variable(channel, uvar1),
7163 												  switch_channel_get_variable(channel, dvar1),
7164 												  switch_channel_get_variable(br_b_channel, uvar2),
7165 												  switch_channel_get_variable(br_b_channel, dvar2));
7166 
7167 		switch_channel_add_variable_var_check(br_b_channel, SWITCH_TRANSFER_HISTORY_VARIABLE, cp->transfer_source, SWITCH_FALSE, SWITCH_STACK_PUSH);
7168 		switch_channel_set_variable(br_b_channel, SWITCH_TRANSFER_SOURCE_VARIABLE, cp->transfer_source);
7169 
7170 		switch_core_session_rwunlock(br_b_session);
7171 	}
7172 
7173 
7174 
7175 	if ((br_a_session = switch_core_session_locate(br_a)) ) {
7176 		switch_channel_t *br_a_channel = switch_core_session_get_channel(br_a_session);
7177 		switch_caller_profile_t *cp = switch_channel_get_caller_profile(br_a_channel);
7178 
7179 		if (switch_channel_direction(br_a_channel) == SWITCH_CALL_DIRECTION_INBOUND) {
7180 			uvar2 = "sip_from_user";
7181 			dvar2 = "sip_from_host";
7182 		} else {
7183 			uvar2 = "sip_to_user";
7184 			dvar2 = "sip_to_host";
7185 		}
7186 
7187 		cp->transfer_source = switch_core_sprintf(cp->pool,
7188 												  "%ld:%s:att_xfer:%s@%s/%s@%s",
7189 												  (long) switch_epoch_time_now(NULL),
7190 												  cp->uuid_str,
7191 												  switch_channel_get_variable(channel, uvar1),
7192 												  switch_channel_get_variable(channel, dvar1),
7193 												  switch_channel_get_variable(br_a_channel, uvar2),
7194 												  switch_channel_get_variable(br_a_channel, dvar2));
7195 
7196 		switch_channel_add_variable_var_check(br_a_channel, SWITCH_TRANSFER_HISTORY_VARIABLE, cp->transfer_source, SWITCH_FALSE, SWITCH_STACK_PUSH);
7197 		switch_channel_set_variable(br_a_channel, SWITCH_TRANSFER_SOURCE_VARIABLE, cp->transfer_source);
7198 
7199 		switch_core_session_rwunlock(br_a_session);
7200 	}
7201 
7202 
7203 }
7204 
7205 
sofia_handle_sip_i_state(switch_core_session_t * session,int status,char const * phrase,nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,sofia_private_t * sofia_private,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])7206 static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
7207 									 char const *phrase,
7208 									 nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
7209 								sofia_dispatch_event_t *de,
7210 									 tagi_t tags[])
7211 {
7212 	const char *l_sdp = NULL, *r_sdp = NULL;
7213 	int offer_recv = 0, answer_recv = 0, offer_sent = 0, answer_sent = 0;
7214 	int ss_state = nua_callstate_init;
7215 	switch_channel_t *channel = NULL;
7216 	private_object_t *tech_pvt = NULL;
7217 	const char *replaces_str = NULL;
7218 	switch_core_session_t *other_session = NULL;
7219 	switch_channel_t *other_channel = NULL;
7220 	//private_object_t *other_tech_pvt = NULL;
7221 	char st[80] = "";
7222 	int is_dup_sdp = 0;
7223 	switch_event_t *s_event = NULL;
7224 	char *p;
7225 	char *patched_sdp = NULL;
7226 	const char *session_id_header = sofia_glue_session_id_header(session, profile);
7227 
7228 	tl_gets(tags,
7229 			NUTAG_CALLSTATE_REF(ss_state),
7230 			NUTAG_OFFER_RECV_REF(offer_recv),
7231 			NUTAG_ANSWER_RECV_REF(answer_recv),
7232 			NUTAG_OFFER_SENT_REF(offer_sent),
7233 			NUTAG_ANSWER_SENT_REF(answer_sent),
7234 			SIPTAG_REPLACES_STR_REF(replaces_str), SOATAG_LOCAL_SDP_STR_REF(l_sdp), SOATAG_REMOTE_SDP_STR_REF(r_sdp), TAG_END());
7235 
7236 	if (session) {
7237 		channel = switch_core_session_get_channel(session);
7238 		tech_pvt = switch_core_session_get_private(session);
7239 
7240 		if (!tech_pvt || !tech_pvt->nh) {
7241 			goto done;
7242 		}
7243 
7244 		if (!r_sdp && (status == 100 || status == 200)) {
7245 			if (ss_state == nua_callstate_completing) {
7246 				if (tech_pvt->mparams.last_sdp_response) {
7247 					r_sdp = tech_pvt->mparams.last_sdp_response;
7248 				}
7249 			} else if (ss_state == nua_callstate_received || ss_state == nua_callstate_ready) {
7250 				if (tech_pvt->mparams.last_sdp_str) {
7251 					r_sdp = tech_pvt->mparams.last_sdp_str;
7252 				}
7253 			}
7254 		}
7255 
7256 		if (tech_pvt->mparams.last_sdp_str) {
7257 			tech_pvt->mparams.prev_sdp_str = tech_pvt->mparams.last_sdp_str;
7258 		}
7259 
7260 		if (tech_pvt->mparams.last_sdp_response) {
7261 			tech_pvt->mparams.prev_sdp_response = tech_pvt->mparams.last_sdp_response;
7262 		}
7263 
7264 		tech_pvt->mparams.last_sdp_str = NULL;
7265 		tech_pvt->mparams.last_sdp_response = NULL;
7266 
7267 		if (r_sdp && (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA))) {
7268 			const char *var;
7269 
7270 			if ((var = switch_channel_get_variable(channel, "bypass_media_sdp_filter"))) {
7271 				if ((patched_sdp = switch_core_media_process_sdp_filter(r_sdp, var, session))) {
7272 					r_sdp = patched_sdp;
7273 				}
7274 			}
7275 		}
7276 
7277 		if ((switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) ||
7278 			(sofia_test_flag(profile, TFLAG_INB_NOMEDIA) || sofia_test_flag(profile, TFLAG_PROXY_MEDIA))) {
7279 
7280 			/* This marr in our code brought to you by people who can't read........ */
7281 			if (profile->ndlb & SM_NDLB_ALLOW_BAD_IANANAME && r_sdp && (p = (char *) switch_stristr("g729a/8000", r_sdp))) {
7282 				p += 4;
7283 				*p++ = '/';
7284 				*p++ = '8';
7285 				*p++ = '0';
7286 				*p++ = '0';
7287 				*p++ = '0';
7288 				*p++ = ' ';
7289 			}
7290 		}
7291 	}
7292 
7293 
7294 	if (ss_state == nua_callstate_terminated) {
7295 
7296 		if ((status == 300 || status == 301 || status == 302 || status == 305) && session) {
7297 			channel = switch_core_session_get_channel(session);
7298 			tech_pvt = switch_core_session_get_private(session);
7299 
7300 			if (!tech_pvt || !tech_pvt->nh) {
7301 				goto done;
7302 			}
7303 
7304 
7305 			if (tech_pvt->redirected) {
7306 				sofia_glue_do_invite(session);
7307 				goto done;
7308 			}
7309 		}
7310 
7311 		if (sofia_private) {
7312 			sofia_private->destroy_me = 1;
7313 		}
7314 	}
7315 
7316 	if (session) {
7317 		if ((switch_channel_test_flag(channel, CF_ANSWERED) && (status == 180 || status == 183) && !r_sdp) || (ss_state == nua_callstate_ready && status >= 300)) {
7318 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Channel %s skipping state [%s][%d]\n",
7319 							  switch_channel_get_name(channel), nua_callstate_name(ss_state), status);
7320 			goto done;
7321 		} else if (switch_channel_test_flag(channel, CF_EARLY_MEDIA) && (status == 180 || status == 183) && r_sdp) {
7322 			switch_channel_set_flag(tech_pvt->channel, CF_REINVITE);
7323 		}
7324 
7325 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Channel %s entering state [%s][%d]\n",
7326 						  switch_channel_get_name(channel), nua_callstate_name(ss_state), status);
7327 
7328 		if (r_sdp) {
7329 			switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, r_sdp);
7330 
7331 			if (!(profile->mndlb & SM_NDLB_ALLOW_NONDUP_SDP) || (!zstr(tech_pvt->mparams.remote_sdp_str) && !strcmp(tech_pvt->mparams.remote_sdp_str, r_sdp))) {
7332 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Duplicate SDP\n%s\n", r_sdp);
7333 				is_dup_sdp = 1;
7334 			} else {
7335 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Remote SDP:\n%s\n", r_sdp);
7336 				tech_pvt->mparams.remote_sdp_str = switch_core_session_strdup(session, r_sdp);
7337 				if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && status < 200) {
7338 					switch_channel_mark_pre_answered(channel);
7339 				}
7340                 //if ((sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) || switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND)) {
7341 				//	switch_core_media_set_sdp_codec_string(session, r_sdp, status < 200 ? SDP_TYPE_REQUEST : SDP_TYPE_RESPONSE);
7342 				//}
7343 				switch_core_media_set_sdp_codec_string(session, r_sdp, SDP_TYPE_REQUEST);
7344 				sofia_glue_pass_sdp(tech_pvt, (char *) r_sdp);
7345 				sofia_set_flag(tech_pvt, TFLAG_NEW_SDP);
7346 
7347 			}
7348 		}
7349 	}
7350 
7351 	if (status == 988) {
7352 		goto done;
7353 	}
7354 
7355 	if (status == 183 && !r_sdp) {
7356 		if ((channel && switch_true(switch_channel_get_variable(channel, "sip_ignore_183nosdp"))) || sofia_test_pflag(profile, PFLAG_IGNORE_183NOSDP)) {
7357 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Ignoring 183 w/o sdp\n", channel ? switch_channel_get_name(channel) : "None");
7358 			goto done;
7359 		}
7360 		status = 180;
7361 	}
7362 
7363 	if (status == 180 && r_sdp) {
7364 		status = 183;
7365 	}
7366 
7367 	if (channel && profile->pres_type && ss_state == nua_callstate_ready && status == 200) {
7368 		const char* to_tag = "";
7369 		char *sql = NULL;
7370 		to_tag = switch_str_nil(switch_channel_get_variable(channel, "sip_to_tag"));
7371 		sql = switch_mprintf("update sip_dialogs set sip_to_tag='%q' "
7372 				"where uuid='%q' and sip_to_tag = ''", to_tag, switch_core_session_get_uuid(session));
7373 
7374 		if (mod_sofia_globals.debug_presence > 1) {
7375 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "QUERY SQL %s\n", sql);
7376 		}
7377 		sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
7378 	}
7379 
7380 	if (channel && (status == 180 || status == 183) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
7381 		const char *full_to = NULL;
7382 		const char *var;
7383 		if ((var = switch_channel_get_variable(channel, "sip_auto_answer")) && switch_true(var) &&
7384                     !((var = switch_channel_get_variable(channel, "sip_auto_answer_suppress_notify")) && switch_true(var))) {
7385 			full_to = switch_str_nil(switch_channel_get_variable(channel, "sip_full_to"));
7386 
7387 			nua_notify(nh,
7388 					   NUTAG_NEWSUB(1),
7389 					   NUTAG_WITH_THIS_MSG(de->data->e_msg),
7390 					   NUTAG_SUBSTATE(nua_substate_terminated),
7391 					   TAG_IF((full_to), SIPTAG_TO_STR(full_to)),
7392 					   SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
7393 					   SIPTAG_EVENT_STR("talk"),
7394 					   TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
7395 					   TAG_END());
7396 		}
7397 	}
7398 
7399 
7400 
7401   state_process:
7402 
7403 	switch ((enum nua_callstate) ss_state) {
7404 	case nua_callstate_terminated:
7405 	case nua_callstate_terminating:
7406 	case nua_callstate_ready:
7407 	case nua_callstate_completed:
7408 	case nua_callstate_received:
7409 	case nua_callstate_proceeding:
7410 	case nua_callstate_completing:
7411 	case nua_callstate_calling:
7412 		if (!(session && channel && tech_pvt))
7413 			goto done;
7414 	default:
7415 		break;
7416 	}
7417 
7418 	switch ((enum nua_callstate) ss_state) {
7419 	case nua_callstate_init:
7420 		break;
7421 	case nua_callstate_authenticating:
7422 		break;
7423 	case nua_callstate_calling:
7424 		tech_pvt->sent_last_invite = 1;
7425 		tech_pvt->sent_invites++;
7426 		break;
7427 	case nua_callstate_proceeding:
7428 
7429 		if (sofia_test_flag(tech_pvt, TFLAG_SKIP_EARLY)) {
7430 			sofia_clear_flag_locked(tech_pvt, TFLAG_SKIP_EARLY);
7431 			goto done;
7432 		}
7433 
7434 		switch (status) {
7435 		case 180:
7436 			switch_channel_mark_ring_ready(channel);
7437 			break;
7438 		case 182:
7439 			switch_channel_mark_ring_ready_value(channel, SWITCH_RING_READY_QUEUED);
7440 			break;
7441 		default:
7442 			break;
7443 		}
7444 
7445 		if (r_sdp) {
7446 			if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
7447 				char ibuf[35] = "", pbuf[35] = "";
7448 				const char *ptr;
7449 
7450 				if ((ptr = switch_stristr("c=IN IP4", r_sdp))) {
7451 					int i = 0;
7452 
7453 					ptr += 8;
7454 
7455 					while(*ptr == ' ') {
7456 						ptr++;
7457 					}
7458 					while(*ptr && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') {
7459 						ibuf[i++] = *ptr++;
7460 					}
7461 
7462 					switch_channel_set_variable(channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, ibuf);
7463 				}
7464 
7465 				if ((ptr = switch_stristr("m=audio", r_sdp))) {
7466 					int i = 0;
7467 
7468 					ptr += 7;
7469 
7470 					while(*ptr == ' ') {
7471 						ptr++;
7472 					}
7473 					while(*ptr && *ptr != ' ' && *ptr != '\r' && *ptr != '\n') {
7474 						pbuf[i++] = *ptr++;
7475 					}
7476 
7477 					switch_channel_set_variable(channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, pbuf);
7478 				}
7479 
7480 				if (switch_channel_test_flag(channel, CF_PROXY_MEDIA) &&  switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
7481 					switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "PROXY MEDIA");
7482 				}
7483 				sofia_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
7484 				switch_channel_mark_pre_answered(channel);
7485 				sofia_set_flag(tech_pvt, TFLAG_SDP);
7486 				if (switch_channel_test_flag(channel, CF_PROXY_MEDIA) || switch_channel_test_flag(channel, CF_REINVITE)) {
7487 					if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
7488 						goto done;
7489 					}
7490 				}
7491 				if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
7492 					other_channel = switch_core_session_get_channel(other_session);
7493 					switch_channel_pass_sdp(channel, other_channel, r_sdp);
7494 
7495 					//switch_channel_pre_answer(other_channel);
7496 					switch_core_session_queue_indication(other_session, SWITCH_MESSAGE_INDICATE_PROGRESS);
7497 					switch_core_session_rwunlock(other_session);
7498 				}
7499 				goto done;
7500 			} else {
7501 				if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) &&  switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
7502 					switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "DELAYED NEGOTIATION");
7503 				} else if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
7504 					switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "PROXY MEDIA");
7505 					switch_core_media_patch_sdp(tech_pvt->session);
7506 					if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
7507 						nua_respond(nh, SIP_488_NOT_ACCEPTABLE,
7508 								TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
7509 						switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
7510 					} else{
7511 						switch_channel_mark_pre_answered(channel);
7512 					}
7513 
7514 				} else {
7515 					if (sofia_media_tech_media(tech_pvt, (char *) r_sdp, SDP_TYPE_REQUEST) != SWITCH_STATUS_SUCCESS) {
7516 						switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR");
7517 						nua_respond(nh, SIP_488_NOT_ACCEPTABLE,
7518 								TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),TAG_END());
7519 						switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
7520 					}
7521 				}
7522 				goto done;
7523 			}
7524 		}
7525 		break;
7526 	case nua_callstate_completing:
7527 		{
7528 			int send_ack = 1;
7529 
7530 			if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
7531 				const char *wait_for_ack = switch_channel_get_variable(channel, "sip_wait_for_aleg_ack");
7532 
7533 				if (switch_true(wait_for_ack)) {
7534 					switch_core_session_t *other_session;
7535 
7536 					if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
7537 						if (switch_core_session_compare(session, other_session)) {
7538 							private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
7539 
7540 							if (!sofia_test_flag(tech_pvt, TFLAG_3PCC) && !sofia_test_flag(other_tech_pvt, TFLAG_3PCC)) {
7541 								sofia_set_flag(other_tech_pvt, TFLAG_PASS_ACK);
7542 								send_ack = 0;
7543 							}
7544 						}
7545 						switch_core_session_rwunlock(other_session);
7546 					}
7547 				}
7548 			}
7549 
7550 			if (switch_channel_test_flag(channel, CF_3P_NOMEDIA_REQUESTED)) {
7551 				if (switch_channel_test_flag(channel, CF_3P_NOMEDIA_REQUESTED_BLEG)) {
7552 					switch_core_session_t *other_session;
7553 
7554 					switch_channel_clear_flag(channel, CF_3P_NOMEDIA_REQUESTED_BLEG);
7555 
7556 					if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
7557 						if (switch_core_session_compare(session, other_session)) {
7558 							//switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
7559 							private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
7560 
7561 							sofia_glue_clear_soa(other_session, SWITCH_TRUE);
7562 
7563 							if (sofia_use_soa(other_tech_pvt)) {
7564 								nua_ack(other_tech_pvt->nh,
7565 										TAG_IF(!zstr(other_tech_pvt->user_via), SIPTAG_VIA_STR(other_tech_pvt->user_via)),
7566 										SIPTAG_CONTACT_STR(other_tech_pvt->reply_contact),
7567 										SOATAG_USER_SDP_STR(r_sdp),
7568 										SOATAG_REUSE_REJECTED(1),
7569 										SOATAG_RTP_SELECT(1),
7570 										SOATAG_AUDIO_AUX("cn telephone-event"),
7571 										TAG_IF(sofia_test_pflag(other_tech_pvt->profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
7572 										TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
7573 										TAG_END());
7574 							} else {
7575 								nua_ack(other_tech_pvt->nh,
7576 										NUTAG_MEDIA_ENABLE(0),
7577 										TAG_IF(!zstr(other_tech_pvt->user_via), SIPTAG_VIA_STR(other_tech_pvt->user_via)),
7578 										SIPTAG_CONTACT_STR(other_tech_pvt->reply_contact),
7579 										TAG_IF(r_sdp, SIPTAG_CONTENT_TYPE_STR("application/sdp")),
7580 										TAG_IF(r_sdp, SIPTAG_PAYLOAD_STR(r_sdp)),
7581 										SOATAG_AUDIO_AUX("cn telephone-event"),
7582 										TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
7583 										TAG_END());
7584 							}
7585 
7586 							nua_ack(tech_pvt->nh,
7587 									TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
7588 									SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
7589 									TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
7590 									TAG_END());
7591 
7592 						}
7593 						switch_core_session_rwunlock(other_session);
7594 					}
7595 				} else {
7596 					switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, r_sdp);
7597 				}
7598 
7599 				switch_channel_clear_flag(channel, CF_3P_NOMEDIA_REQUESTED);
7600 				goto done;
7601 
7602 			} else if (switch_channel_test_flag(channel, CF_3P_MEDIA_REQUESTED)) {
7603 				uint8_t match = 0;
7604 
7605 				switch_channel_clear_flag(channel, CF_PROXY_MODE);
7606 
7607 				switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
7608 				switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_FALSE);
7609 
7610 				if (tech_pvt->mparams.num_codecs) {
7611 					match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_REQUEST);
7612 				}
7613 
7614 				if (!match) {
7615 					if (switch_channel_get_state(channel) != CS_NEW) {
7616 						nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE,
7617 								TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),TAG_END());
7618 					}
7619 				} else {
7620 					switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
7621 					switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED");
7622 					sofia_set_flag_locked(tech_pvt, TFLAG_READY);
7623 
7624 					sofia_set_flag(tech_pvt, TFLAG_SDP);
7625 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "RESTABLISH MEDIA SDP:\n%s\n", tech_pvt->mparams.local_sdp_str);
7626 
7627 					switch_channel_set_flag(channel, CF_REQ_MEDIA);
7628 					switch_channel_set_flag(channel, CF_MEDIA_ACK);
7629 					switch_channel_set_flag(channel, CF_MEDIA_SET);
7630 
7631 					switch_core_media_activate_rtp(session);
7632 
7633 
7634 					if (sofia_use_soa(tech_pvt)) {
7635 						nua_ack(tech_pvt->nh,
7636 								TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
7637 								SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
7638 								SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
7639 								SOATAG_REUSE_REJECTED(1),
7640 								SOATAG_RTP_SELECT(1),
7641 								SOATAG_AUDIO_AUX("cn telephone-event"),
7642 								TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
7643 								TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
7644 								TAG_END());
7645 					} else {
7646 						nua_ack(tech_pvt->nh,
7647 								NUTAG_MEDIA_ENABLE(0),
7648 								TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
7649 								SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
7650 								TAG_IF(tech_pvt->mparams.local_sdp_str, SIPTAG_CONTENT_TYPE_STR("application/sdp")),
7651 								TAG_IF(tech_pvt->mparams.local_sdp_str, SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str)),
7652 								SOATAG_AUDIO_AUX("cn telephone-event"),
7653 								TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
7654 								TAG_END());
7655 					}
7656 
7657 					switch_channel_clear_flag(channel, CF_3P_MEDIA_REQUESTED);
7658 					goto done;
7659 				}
7660 
7661 				switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "NO CODECS");
7662 				switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
7663 
7664 				switch_channel_clear_flag(channel, CF_3P_MEDIA_REQUESTED);
7665 				goto done;
7666 				//ss_state = nua_callstate_ready;
7667 				//goto state_process;
7668 			}
7669 
7670 			if (r_sdp && sofia_test_flag(tech_pvt, TFLAG_3PCC_INVITE) && !sofia_test_flag(tech_pvt, TFLAG_SDP)) {
7671 				sofia_set_flag(tech_pvt, TFLAG_SDP);
7672 				if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
7673 					other_channel = switch_core_session_get_channel(other_session);
7674 					//other_tech_pvt = switch_core_session_get_private(other_session);
7675 
7676 					switch_channel_pass_sdp(channel, other_channel, r_sdp);
7677 					switch_core_session_queue_indication(other_session, SWITCH_MESSAGE_INDICATE_ANSWER);
7678 					switch_core_session_rwunlock(other_session);
7679 				}
7680 				goto done;
7681 
7682 			}
7683 
7684 			if (send_ack) {
7685 				tech_send_ack(nh, tech_pvt, NULL);
7686 			} else {
7687 				ss_state = nua_callstate_ready;
7688 				goto state_process;
7689 			}
7690 
7691 		}
7692 		goto done;
7693 	case nua_callstate_received:
7694 		tech_pvt->recv_invites++;
7695 		tech_pvt->sent_last_invite = 0;
7696 
7697 		if (!sofia_test_flag(tech_pvt, TFLAG_SDP)) {
7698 			if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
7699 				private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
7700 				int r = sofia_test_flag(other_tech_pvt, TFLAG_REINVITED);
7701 				switch_core_session_rwunlock(other_session);
7702 
7703 				if (r) {
7704 					/* Due to a race between simultaneous reinvites to both legs of a bridge,
7705 					  an earlier call to nua_invite silently failed.
7706 					  So we reject the incoming invite with a 491 and redo the failed outgoing invite. */
7707 
7708 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
7709 									  "Other leg already handling a reinvite, so responding with 491\n");
7710 
7711 					nua_respond(tech_pvt->nh, SIP_491_REQUEST_PENDING,
7712 							TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
7713 					sofia_glue_do_invite(session);
7714 					goto done;
7715 				}
7716 			}
7717 
7718 
7719 			if (r_sdp && !sofia_test_flag(tech_pvt, TFLAG_SDP)) {
7720 				if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
7721 					switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED_NOMEDIA");
7722 					sofia_set_flag_locked(tech_pvt, TFLAG_READY);
7723 					if (switch_channel_get_state(channel) == CS_NEW) {
7724 						switch_channel_set_state(channel, CS_INIT);
7725 					}
7726 					sofia_set_flag(tech_pvt, TFLAG_SDP);
7727 					goto done;
7728 				} else if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
7729 					switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "PROXY MEDIA");
7730 					sofia_set_flag_locked(tech_pvt, TFLAG_READY);
7731 					if (switch_channel_get_state(channel) == CS_NEW) {
7732 						switch_channel_set_state(channel, CS_INIT);
7733 					}
7734 				} else if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION)) {
7735 					switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "DELAYED NEGOTIATION");
7736 					sofia_set_flag_locked(tech_pvt, TFLAG_READY);
7737 					if (switch_channel_get_state(channel) == CS_NEW) {
7738 						switch_channel_set_state(channel, CS_INIT);
7739 					}
7740 				} else {
7741 					uint8_t match = 0;
7742 
7743 					if (tech_pvt->mparams.num_codecs) {
7744 						match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_REQUEST);
7745 					}
7746 
7747 					if (!match) {
7748 						if (switch_channel_get_state(channel) != CS_NEW) {
7749 							nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
7750 						}
7751 					} else {
7752 						nua_handle_t *bnh;
7753 						sip_replaces_t *replaces;
7754 						su_home_t *home = NULL;
7755 						switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED");
7756 						sofia_set_flag_locked(tech_pvt, TFLAG_READY);
7757 
7758 						if (switch_channel_get_state(channel) == CS_NEW) {
7759 							switch_channel_set_state(channel, CS_INIT);
7760 						} else {
7761 							nua_respond(tech_pvt->nh, SIP_200_OK, TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
7762 						}
7763 						sofia_set_flag(tech_pvt, TFLAG_SDP);
7764 						if (replaces_str) {
7765 							home = su_home_new(sizeof(*home));
7766 							switch_assert(home != NULL);
7767 							if ((replaces = sip_replaces_make(home, replaces_str))
7768 								&& (bnh = nua_handle_by_replaces(nua, replaces))) {
7769 								sofia_private_t *b_private;
7770 
7771 								switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Processing Replaces Attended Transfer\n");
7772 								while (switch_channel_get_state(channel) < CS_EXECUTE) {
7773 									switch_yield(10000);
7774 								}
7775 
7776 								if ((b_private = nua_handle_magic(bnh))) {
7777 									const char *br_b = switch_channel_get_partner_uuid(channel);
7778 									char *br_a = b_private->uuid;
7779 
7780 
7781 									if (br_b) {
7782 										switch_core_session_t *tmp;
7783 
7784 										if (switch_true(switch_channel_get_variable(channel, "recording_follow_transfer")) &&
7785 											(tmp = switch_core_session_locate(br_a))) {
7786 											switch_ivr_transfer_recordings(session, tmp);
7787 											switch_core_session_rwunlock(tmp);
7788 										}
7789 
7790 										switch_channel_set_variable_printf(channel, "transfer_to", "att:%s", br_b);
7791 
7792 										mark_transfer_record(session, br_a, br_b);
7793 										switch_ivr_uuid_bridge(br_a, br_b);
7794 										switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER");
7795 										sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
7796 										switch_channel_clear_flag(channel, CF_LEG_HOLDING);
7797 										sofia_clear_flag_locked(tech_pvt, TFLAG_HOLD_LOCK);
7798 										switch_channel_hangup(channel, SWITCH_CAUSE_ATTENDED_TRANSFER);
7799 									} else {
7800 										switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER_ERROR");
7801 										switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
7802 									}
7803 								} else {
7804 									switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER_ERROR");
7805 									switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
7806 								}
7807 								nua_handle_unref(bnh);
7808 							}
7809 							su_home_unref(home);
7810 							home = NULL;
7811 						}
7812 
7813 						goto done;
7814 					}
7815 
7816 					switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "NO CODECS");
7817 					switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
7818 				}
7819 			} else {
7820 				if (sofia_test_pflag(profile, PFLAG_3PCC)) {
7821 					if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
7822 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "No SDP in INVITE and 3pcc=yes cannot work with bypass or proxy media, hanging up.\n");
7823 						switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "3PCC DISABLED");
7824 						switch_channel_hangup(channel, SWITCH_CAUSE_MANDATORY_IE_MISSING);
7825 					} else {
7826 						switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED_NOSDP");
7827 						switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
7828 						switch_core_media_prepare_codecs(session, 1);
7829 						switch_channel_set_state(channel, CS_HIBERNATE);
7830 						switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 0);
7831 						sofia_set_flag_locked(tech_pvt, TFLAG_3PCC);
7832 
7833 						if (sofia_use_soa(tech_pvt)) {
7834 							nua_respond(tech_pvt->nh, SIP_200_OK,
7835 										SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
7836 										SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
7837 										SOATAG_REUSE_REJECTED(1),
7838 										SOATAG_AUDIO_AUX("cn telephone-event"),
7839 										TAG_IF(sofia_test_pflag(profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
7840 										TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
7841 										TAG_END());
7842 						} else {
7843 							nua_respond(tech_pvt->nh, SIP_200_OK,
7844 										NUTAG_MEDIA_ENABLE(0),
7845 										SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
7846 										SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str),
7847 										TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
7848 										TAG_END());
7849 						}
7850 					}
7851 				} else if (sofia_test_pflag(profile, PFLAG_3PCC_PROXY)) {
7852 					//3PCC proxy mode delays the 200 OK until the call is answered
7853 					// so can be made to work with bypass media as we have time to find out what the other end thinks codec offer should be...
7854 					switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RECEIVED_NOSDP");
7855 					sofia_set_flag_locked(tech_pvt, TFLAG_3PCC);
7856 					//switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
7857 					//switch_core_media_gen_local_sdp(session, NULL, 0, NULL, 0);
7858 					sofia_set_flag(tech_pvt, TFLAG_LATE_NEGOTIATION);
7859 					//Moves into CS_INIT so call moves forward into the dialplan
7860 					switch_channel_set_state(channel, CS_INIT);
7861 				} else {
7862 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "No SDP in INVITE and 3pcc not enabled, hanging up.\n");
7863 					switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "3PCC DISABLED");
7864 					switch_channel_hangup(channel, SWITCH_CAUSE_MANDATORY_IE_MISSING);
7865 				}
7866 				goto done;
7867 			}
7868 
7869 		} else if (tech_pvt && sofia_test_flag(tech_pvt, TFLAG_SDP) && !r_sdp) {
7870 			sofia_set_flag_locked(tech_pvt, TFLAG_NOSDP_REINVITE);
7871 			if ((switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) && sofia_test_pflag(profile, PFLAG_3PCC_PROXY)) {
7872 				sofia_set_flag_locked(tech_pvt, TFLAG_3PCC);
7873 				sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA);
7874 
7875 				if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
7876 					switch_core_session_message_t *msg;
7877 					if (switch_core_session_compare(session, other_session)) {
7878 						private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
7879 						sofia_clear_flag(other_tech_pvt, TFLAG_ENABLE_SOA);
7880 					}
7881 
7882 					msg = switch_core_session_alloc(other_session, sizeof(*msg));
7883 					msg->message_id = SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT;
7884 					msg->from = __FILE__;
7885 					msg->string_arg = NULL;
7886 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing NOSDP to other leg.\n");
7887 					switch_core_session_queue_message(other_session, msg);
7888 					switch_core_session_rwunlock(other_session);
7889 				} else {
7890 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
7891 						  "NOSDP Re-INVITE to a proxy mode channel that is not in a bridge.\n");
7892 					switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
7893 				}
7894 				goto done;
7895 			}
7896 
7897 			if (switch_channel_var_true(channel, "sip_unhold_nosdp")) {
7898 				switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, "sendrecv",
7899 												zstr(tech_pvt->mparams.local_sdp_str) || !switch_channel_test_flag(channel, CF_PROXY_MODE));
7900 			} else {
7901 				switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL,
7902 											zstr(tech_pvt->mparams.local_sdp_str) || !switch_channel_test_flag(channel, CF_PROXY_MODE));
7903 			}
7904 
7905 			if (zstr(tech_pvt->mparams.local_sdp_str)) {
7906 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Cannot find a SDP\n");
7907 				switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
7908 			} else {
7909 				if (sofia_use_soa(tech_pvt)) {
7910 					nua_respond(tech_pvt->nh, SIP_200_OK,
7911 								SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
7912 								SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
7913 								SOATAG_REUSE_REJECTED(1),
7914 								SOATAG_AUDIO_AUX("cn telephone-event"),
7915 								TAG_IF(sofia_test_pflag(profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
7916 								TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
7917 								TAG_END());
7918 				} else {
7919 					nua_respond(tech_pvt->nh, SIP_200_OK,
7920 								NUTAG_MEDIA_ENABLE(0),
7921 								SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
7922 								SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str),
7923 								TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
7924 								TAG_END());
7925 				}
7926 			}
7927 
7928 			goto done;
7929 
7930 		} else {
7931 			ss_state = nua_callstate_completed;
7932 			goto state_process;
7933 		}
7934 
7935 		break;
7936 	case nua_callstate_early:
7937 		if (answer_recv) {
7938 			uint8_t match = 0;
7939 			switch_assert(tech_pvt);
7940 			sofia_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
7941 			switch_channel_mark_pre_answered(channel);
7942 			sofia_set_flag(tech_pvt, TFLAG_SDP);
7943 
7944 
7945 			match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_RESPONSE);
7946 			if (match) {
7947 				if (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) != SWITCH_STATUS_SUCCESS) {
7948 					goto done;
7949 				}
7950 
7951 				switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
7952 
7953 				if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
7954 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Early Media RTP Error!\n");
7955 					switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
7956 				}
7957 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Processing updated SDP\n");
7958 			} else {
7959 				switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
7960 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Early Media Codec Error!\n");
7961 			}
7962 		}
7963 		break;
7964 	case nua_callstate_completed:
7965 		if (r_sdp) {
7966 			const char *var;
7967 			uint8_t match = 0, is_ok = 1, is_t38 = 0;
7968 
7969 			tech_pvt->mparams.hold_laps = 0;
7970 
7971 				if ((var = switch_channel_get_variable(channel, "sip_ignore_reinvites")) && switch_true(var)) {
7972 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Ignoring Re-invite\n");
7973 					nua_respond(tech_pvt->nh, SIP_200_OK, TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
7974 					goto done;
7975 				}
7976 
7977 				if (switch_stristr("m=image", r_sdp)) {
7978 					is_t38 = 1;
7979 				}
7980 
7981 
7982 				if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
7983 					if ((sofia_test_media_flag(profile, SCMF_DISABLE_HOLD)
7984 						 || ((var = switch_channel_get_variable(channel, "rtp_disable_hold")) && switch_true(var)))
7985 						&& ((switch_stristr("sendonly", r_sdp) || switch_stristr("0.0.0.0", r_sdp) || switch_stristr("inactive", r_sdp)) || tech_pvt->mparams.hold_laps)) {
7986 						nua_respond(tech_pvt->nh, SIP_200_OK, TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
7987 
7988 						if (tech_pvt->mparams.hold_laps) {
7989 							tech_pvt->mparams.hold_laps = 0;
7990 						} else {
7991 							tech_pvt->mparams.hold_laps = 1;
7992 						}
7993 
7994 						goto done;
7995 					}
7996 
7997 					if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
7998 						switch_core_session_message_t *msg;
7999 						private_object_t *other_tech_pvt;
8000 						int media_on_hold = switch_true(switch_channel_get_variable_dup(channel, "bypass_media_resume_on_hold", SWITCH_FALSE, -1));
8001 
8002 						switch_core_media_clear_rtp_flag(other_session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_RTP_FLAG_AUTOADJ);
8003 
8004 
8005 						if (switch_channel_test_flag(channel, CF_PROXY_MODE) && !is_t38 &&
8006 							((profile->media_options & MEDIA_OPT_MEDIA_ON_HOLD) || media_on_hold)) {
8007 							if (switch_stristr("sendonly", r_sdp) || switch_stristr("0.0.0.0", r_sdp) || switch_stristr("inactive", r_sdp)) {
8008 								tech_pvt->mparams.hold_laps = 1;
8009 								switch_channel_set_variable(channel, SWITCH_R_SDP_VARIABLE, r_sdp);
8010 								switch_channel_clear_flag(channel, CF_PROXY_MODE);
8011 								switch_core_media_set_local_sdp(tech_pvt->session, NULL, SWITCH_FALSE);
8012 								switch_core_media_clear_rtp_flag(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, SWITCH_RTP_FLAG_AUTOADJ);
8013 
8014 								if (!switch_channel_media_ready(channel)) {
8015 									//if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
8016 										//const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
8017 
8018 
8019 										switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
8020 										if (sofia_media_tech_media(tech_pvt, r_sdp, SDP_TYPE_REQUEST) != SWITCH_STATUS_SUCCESS) {
8021 											switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR");
8022 											switch_core_session_rwunlock(other_session);
8023 											switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
8024 											goto done;
8025 										}
8026 										//}
8027 								}
8028 
8029 
8030 								if (!switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
8031 									switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_FALSE);
8032 									if (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) != SWITCH_STATUS_SUCCESS) {
8033 										switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
8034 										switch_core_session_rwunlock(other_session);
8035 										goto done;
8036 									}
8037 								}
8038 
8039 								switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 1);
8040 
8041 								if (sofia_use_soa(tech_pvt)) {
8042 									nua_respond(tech_pvt->nh, SIP_200_OK,
8043 												SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
8044 												SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
8045 												SOATAG_REUSE_REJECTED(1),
8046 												SOATAG_AUDIO_AUX("cn telephone-event"),
8047 												TAG_IF(sofia_test_pflag(profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
8048 												TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
8049 												TAG_END());
8050 								} else {
8051 									nua_respond(tech_pvt->nh, SIP_200_OK,
8052 												NUTAG_MEDIA_ENABLE(0),
8053 												SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
8054 												SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str),
8055 												TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
8056 												TAG_END());
8057 								}
8058 
8059 								switch_channel_set_flag(channel, CF_PROXY_MODE);
8060 								switch_yield(250000);
8061 								launch_media_on_hold(session);
8062 
8063 								switch_core_session_rwunlock(other_session);
8064 								goto done;
8065 							}
8066 						}
8067 
8068 						if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
8069 							sofia_media_activate_rtp(tech_pvt);
8070 							switch_core_media_proxy_remote_addr(session, r_sdp);
8071 
8072 							if ((tech_pvt->profile->mndlb & SM_NDLB_NEVER_PATCH_REINVITE)) {
8073 								nua_respond(tech_pvt->nh, SIP_200_OK, TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
8074 								switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "NOT proxying re-invite.\n");
8075 								switch_core_session_rwunlock(other_session);
8076 								goto done;
8077 							}
8078 						}
8079 
8080 						other_tech_pvt = switch_core_session_get_private(other_session);
8081 
8082 						if (sofia_test_flag(other_tech_pvt, TFLAG_REINVITED)) {
8083 							/* The other leg won the reinvite race */
8084 							switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Other leg already handling reinvite, so responding with 491\n");
8085 							nua_respond(tech_pvt->nh, SIP_491_REQUEST_PENDING,
8086 									TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
8087 							switch_core_session_rwunlock(other_session);
8088 							goto done;
8089 						}
8090 						sofia_set_flag(tech_pvt, TFLAG_REINVITED);
8091 
8092 						msg = switch_core_session_alloc(other_session, sizeof(*msg));
8093 						msg->message_id = SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT;
8094 						msg->from = __FILE__;
8095 						msg->string_arg = switch_core_session_strdup(other_session, r_sdp);
8096 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Passing SDP to other leg.\n%s\n", r_sdp);
8097 
8098 						if (sofia_test_flag(tech_pvt, TFLAG_SIP_HOLD)) {
8099 							if (!switch_stristr("sendonly", r_sdp) && !switch_stristr("inactive", r_sdp)) {
8100 								sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
8101 								switch_channel_clear_flag(channel, CF_LEG_HOLDING);
8102 								switch_channel_presence(tech_pvt->channel, "unknown", "unhold", NULL);
8103 							}
8104 						} else if (switch_stristr("sendonly", r_sdp) && !switch_stristr("inactive", r_sdp)) {
8105 							const char *msg = "hold";
8106 
8107 							if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
8108 								const char *info = switch_channel_get_variable(channel, "presence_call_info");
8109 								if (info) {
8110 									if (switch_stristr("private", info)) {
8111 										msg = "hold-private";
8112 									}
8113 								}
8114 							}
8115 
8116 							sofia_set_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
8117 							switch_channel_set_flag(channel, CF_LEG_HOLDING);
8118 							switch_channel_presence(tech_pvt->channel, "unknown", msg, NULL);
8119 						}
8120 
8121 						switch_core_session_queue_message(other_session, msg);
8122 
8123 						switch_core_session_rwunlock(other_session);
8124 					} else {
8125 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
8126 										  "Re-INVITE to a no-media channel that is not in a bridge.\n");
8127 						switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
8128 					}
8129 					goto done;
8130 				} else {
8131 					int hold_related = 0;
8132 
8133 					if (sofia_test_flag(tech_pvt, TFLAG_SIP_HOLD)) {
8134 						hold_related = 2;
8135 					} else if (switch_stristr("sendonly", r_sdp) || switch_stristr("0.0.0.0", r_sdp) || switch_stristr("inactive", r_sdp)) {
8136 						hold_related = 1;
8137 					}
8138 
8139 					if (!is_t38 && hold_related && switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
8140 						if (switch_core_session_compare(session, other_session)) {
8141 							switch_core_session_message_t *msg;
8142 							const char *hold_msg = "hold";
8143 							private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
8144 
8145 							if (sofia_test_pflag(profile, PFLAG_PROXY_HOLD)) {
8146 								switch_channel_set_flag(tech_pvt->channel, CF_REINVITE);
8147 
8148 								if (tech_pvt->mparams.num_codecs){
8149 									match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_REQUEST);
8150 								}
8151 
8152 								if (!match) {
8153 									switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Reinvite Codec Error!\n");
8154 									nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE,
8155 												TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
8156 												TAG_END());
8157 									switch_core_session_rwunlock(other_session);
8158 									goto done;
8159 								}
8160 
8161 								msg = switch_core_session_alloc(other_session, sizeof(*msg));
8162 
8163 								if (switch_stristr("inactive", r_sdp)) {
8164 									sofia_set_flag_locked(other_tech_pvt, TFLAG_SIP_HOLD_INACTIVE);
8165 									//switch_channel_set_variable(channel, "sofia_hold_inactive", "true");
8166 								} else {
8167 									sofia_clear_flag_locked(other_tech_pvt, TFLAG_SIP_HOLD_INACTIVE);
8168 								}
8169 
8170 								if (hold_related == 1) {
8171 									msg->message_id = SWITCH_MESSAGE_INDICATE_HOLD;
8172 									if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
8173 										const char *info = switch_channel_get_variable(channel, "presence_call_info");
8174 
8175 										if (info) {
8176 											if (switch_stristr("private", info)) {
8177 												hold_msg = "hold-private";
8178 											}
8179 										}
8180 									}
8181 									sofia_set_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
8182 									switch_channel_set_flag(channel, CF_LEG_HOLDING);
8183 									switch_channel_presence(tech_pvt->channel, "unknown", hold_msg, NULL);
8184 								} else {
8185 									hold_msg = "unhold";
8186 									msg->message_id = SWITCH_MESSAGE_INDICATE_UNHOLD;
8187 									sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
8188 									switch_channel_clear_flag(channel, CF_LEG_HOLDING);
8189 									switch_channel_presence(tech_pvt->channel, "unknown", hold_msg, NULL);
8190 								}
8191 								msg->from = __FILE__;
8192 								switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Indicating %s to other leg.\n%s\n", hold_msg, r_sdp);
8193 
8194 								switch_core_session_queue_message(other_session, msg);
8195 
8196 
8197 
8198 								switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
8199 								if (sofia_use_soa(tech_pvt)){
8200 									nua_respond(tech_pvt->nh, SIP_200_OK,
8201 												SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
8202 												SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
8203 												SOATAG_REUSE_REJECTED(1),
8204 												SOATAG_AUDIO_AUX("cn telephone-event"),
8205 												TAG_IF(sofia_test_pflag(profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
8206 												TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
8207 												TAG_END());
8208 								} else {
8209 									nua_respond(tech_pvt->nh, SIP_200_OK,
8210 												NUTAG_MEDIA_ENABLE(0),
8211 												SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
8212 												SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str),
8213 												TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
8214 												TAG_END());
8215 								}
8216 								switch_core_session_rwunlock(other_session);
8217 								goto done;
8218 							}
8219 						}
8220 
8221 						switch_core_session_rwunlock(other_session);
8222 					}
8223 
8224 					if (switch_channel_test_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_NEGOTIATED)) {
8225 						if (sofia_use_soa(tech_pvt)) {
8226 							nua_respond(tech_pvt->nh, SIP_200_OK,
8227 										SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
8228 										SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
8229 										SOATAG_REUSE_REJECTED(1),
8230 										SOATAG_AUDIO_AUX("cn telephone-event"),
8231 										TAG_IF(sofia_test_pflag(profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
8232 										TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
8233 										TAG_END());
8234 						} else {
8235 							nua_respond(tech_pvt->nh, SIP_200_OK,
8236 										NUTAG_MEDIA_ENABLE(0),
8237 										SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
8238 										SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str),
8239 										TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
8240 										TAG_END());
8241 						}
8242 						goto done;
8243 					}
8244 
8245 					switch_channel_set_flag(tech_pvt->channel, CF_REINVITE);
8246 
8247 					if (tech_pvt->mparams.num_codecs) {
8248 						match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_REQUEST);
8249 					}
8250 
8251 
8252 					if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
8253 						nua_respond(tech_pvt->nh, SIP_200_OK, TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
8254 						goto done;
8255 					}
8256 
8257 					if (match && sofia_test_flag(tech_pvt, TFLAG_NOREPLY)) {
8258 						sofia_clear_flag(tech_pvt, TFLAG_NOREPLY);
8259 						goto done;
8260 					}
8261 
8262 					if (match) {
8263 						if (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) != SWITCH_STATUS_SUCCESS) {
8264 							goto done;
8265 						}
8266 
8267 						switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
8268 
8269 						if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
8270 							switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Reinvite RTP Error!\n");
8271 							is_ok = 0;
8272 							switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
8273 						}
8274 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Processing updated SDP\n");
8275 					} else {
8276 						if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
8277 							nua_respond(tech_pvt->nh, SIP_200_OK, TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
8278 							goto done;
8279 						}
8280 
8281 						switch_channel_clear_flag(tech_pvt->channel, CF_REINVITE);
8282 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Reinvite resulted in codec negotiation failure.\n");
8283 						is_ok = 0;
8284 					}
8285 				}
8286 
8287 
8288 				if (is_ok) {
8289 
8290 					if (switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
8291 						switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
8292 					}
8293 
8294 					if (!switch_channel_test_flag(tech_pvt->channel, CF_AWAITING_STREAM_CHANGE)) {
8295 						if (sofia_use_soa(tech_pvt)) {
8296 							nua_respond(tech_pvt->nh, SIP_200_OK,
8297 										SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
8298 										SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
8299 										SOATAG_REUSE_REJECTED(1),
8300 										SOATAG_AUDIO_AUX("cn telephone-event"),
8301 										TAG_IF(sofia_test_pflag(profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1)),
8302 										TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
8303 										TAG_END());
8304 						} else {
8305 							nua_respond(tech_pvt->nh, SIP_200_OK,
8306 										NUTAG_MEDIA_ENABLE(0),
8307 										SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
8308 										SIPTAG_CONTENT_TYPE_STR("application/sdp"), SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str),
8309 										TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
8310 										TAG_END());
8311 						}
8312 					}
8313 
8314 					if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_REINVITE) == SWITCH_STATUS_SUCCESS) {
8315 						switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(session));
8316 						switch_event_fire(&s_event);
8317 					}
8318 				} else {
8319 					nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE,
8320 								TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
8321 								TAG_END());
8322 				}
8323 			}
8324 		break;
8325 	case nua_callstate_ready:
8326 		if (!switch_channel_test_flag(channel, CF_PROXY_MODE) && !switch_channel_test_flag(channel, CF_PROXY_MEDIA) &&
8327 			r_sdp && (!is_dup_sdp || sofia_test_flag(tech_pvt, TFLAG_NEW_SDP)) && switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO) && !sofia_test_flag(tech_pvt, TFLAG_NOSDP_REINVITE)) {
8328 			/* sdp changed since 18X w sdp, we're supposed to ignore it but we, of course, were pressured into supporting it */
8329 			uint8_t match = 0;
8330 
8331 			sofia_clear_flag(tech_pvt, TFLAG_NEW_SDP);
8332 			switch_channel_set_flag(tech_pvt->channel, CF_REINVITE);
8333 
8334 
8335 			if (tech_pvt->mparams.num_codecs) {
8336 				match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_RESPONSE);
8337 			}
8338 			if (match) {
8339 				if (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) != SWITCH_STATUS_SUCCESS) {
8340 					goto done;
8341 				}
8342 				switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL, 0, NULL, 0);
8343 
8344 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Processing updated SDP\n");
8345 				switch_channel_set_flag(tech_pvt->channel, CF_REINVITE);
8346 
8347 				if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
8348 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "RTP Error!\n");
8349 					switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
8350 					goto done;
8351 				}
8352 			} else {
8353 				switch_channel_clear_flag(tech_pvt->channel, CF_REINVITE);
8354 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error! %s\n", r_sdp);
8355 				goto done;
8356 
8357 			}
8358 		}
8359 
8360 		if (r_sdp && sofia_test_flag(tech_pvt, TFLAG_NOSDP_REINVITE)) {
8361 			sofia_clear_flag_locked(tech_pvt, TFLAG_NOSDP_REINVITE);
8362 			if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
8363 				if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
8364 					if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
8365 						goto done;
8366 					}
8367 				}
8368 
8369 				if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
8370 					other_channel = switch_core_session_get_channel(other_session);
8371 					switch_channel_pass_sdp(channel, other_channel, r_sdp);
8372 
8373 					if (sofia_test_flag(tech_pvt, TFLAG_3PCC) && sofia_test_pflag(profile, PFLAG_3PCC_PROXY)) {
8374 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Got my ACK\n");
8375 						sofia_set_flag(tech_pvt, TFLAG_3PCC_HAS_ACK);
8376 					} else {
8377 						switch_core_session_message_t *msg;
8378 
8379 						if (sofia_test_pflag(profile, PFLAG_3PCC_REINVITE_BRIDGED_ON_ACK)) {
8380 							msg = switch_core_session_alloc(other_session, sizeof(*msg));
8381 							msg->message_id = SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT;
8382 							msg->from = __FILE__;
8383 							msg->string_arg = switch_core_session_strdup(other_session, r_sdp);
8384 							switch_core_session_queue_message(other_session, msg);
8385 						}
8386 
8387 						switch_core_session_queue_indication(other_session, SWITCH_MESSAGE_INDICATE_ANSWER);
8388 					}
8389 
8390 					switch_core_session_rwunlock(other_session);
8391 				}
8392 			} else {
8393 				uint8_t match = 0;
8394 				int is_ok = 1;
8395 
8396 				if (!tech_pvt) goto done;
8397 
8398 				if (tech_pvt->mparams.num_codecs) {
8399 					match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_RESPONSE);
8400 				}
8401 
8402 				if (match) {
8403 					switch_channel_set_flag(tech_pvt->channel, CF_REINVITE);
8404 					if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
8405 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "RTP Error!\n");
8406 						switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "RTP ERROR");
8407 						is_ok = 0;
8408 					}
8409 					switch_channel_clear_flag(tech_pvt->channel, CF_REINVITE);
8410 				} else {
8411 					switch_channel_set_variable(tech_pvt->channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR");
8412 					is_ok = 0;
8413 				}
8414 
8415 				if (!is_ok) {
8416 					nua_respond(nh, SIP_488_NOT_ACCEPTABLE, TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
8417 					switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
8418 				}
8419 			}
8420 			goto done;
8421 		}
8422 
8423 		if (channel) {
8424 			switch_channel_clear_flag(channel, CF_REQ_MEDIA);
8425 		}
8426 		if (tech_pvt && nh == tech_pvt->nh2) {
8427 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Cheater Reinvite!\n");
8428 			switch_channel_set_flag(tech_pvt->channel, CF_REINVITE);
8429 			tech_pvt->nh = tech_pvt->nh2;
8430 			tech_pvt->nh2 = NULL;
8431 			if (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) == SWITCH_STATUS_SUCCESS) {
8432 				if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
8433 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cheater Reinvite RTP Error!\n");
8434 					switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
8435 				}
8436 			}
8437 			goto done;
8438 		}
8439 
8440 		if (channel) {
8441 			if (sofia_test_flag(tech_pvt, TFLAG_EARLY_MEDIA) && !sofia_test_flag(tech_pvt, TFLAG_ANS)) {
8442 				sofia_set_flag_locked(tech_pvt, TFLAG_ANS);
8443 				sofia_set_flag(tech_pvt, TFLAG_SDP);
8444 				switch_channel_mark_answered(channel);
8445 
8446 				if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
8447 					if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
8448 						//other_channel = switch_core_session_get_channel(other_session);
8449 						//switch_channel_answer(other_channel);
8450 						switch_core_session_queue_indication(other_session, SWITCH_MESSAGE_INDICATE_ANSWER);
8451 						switch_core_session_rwunlock(other_session);
8452 					}
8453 				}
8454 				goto done;
8455 			}
8456 
8457 			if (!r_sdp && !sofia_test_flag(tech_pvt, TFLAG_SDP)) {
8458 				r_sdp = (const char *) switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
8459 			}
8460 
8461 			if (r_sdp && !sofia_test_flag(tech_pvt, TFLAG_SDP)) {
8462 				if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
8463 					sofia_set_flag_locked(tech_pvt, TFLAG_ANS);
8464 					sofia_set_flag_locked(tech_pvt, TFLAG_SDP);
8465 					switch_channel_mark_answered(channel);
8466 
8467 					if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
8468 						if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
8469 							goto done;
8470 						}
8471 					}
8472 
8473 					if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
8474 						other_channel = switch_core_session_get_channel(other_session);
8475 						switch_channel_pass_sdp(channel, other_channel, r_sdp);
8476 
8477 						//switch_channel_answer(other_channel);
8478 						switch_core_session_queue_indication(other_session, SWITCH_MESSAGE_INDICATE_ANSWER);
8479 
8480 						switch_core_session_rwunlock(other_session);
8481 					}
8482 
8483 					if (sofia_test_flag(tech_pvt, TFLAG_3PCC) && sofia_test_pflag(profile, PFLAG_3PCC_PROXY)) {
8484 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Got my ACK\n");
8485 						sofia_set_flag(tech_pvt, TFLAG_3PCC_HAS_ACK);
8486 					}
8487 
8488 					goto done;
8489 				} else {
8490 					uint8_t match = 0;
8491 
8492 
8493 					match = sofia_media_negotiate_sdp(session, r_sdp, SDP_TYPE_RESPONSE);
8494 
8495 
8496 					sofia_set_flag_locked(tech_pvt, TFLAG_ANS);
8497 
8498 					if (match) {
8499 						switch_channel_check_zrtp(channel);
8500 
8501 						if (switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0) == SWITCH_STATUS_SUCCESS) {
8502 							if (sofia_media_activate_rtp(tech_pvt) == SWITCH_STATUS_SUCCESS) {
8503 								switch_channel_mark_answered(channel);
8504 							} else {
8505 								switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "RTP Error!\n");
8506 								switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
8507 							}
8508 
8509 							if (sofia_test_flag(tech_pvt, TFLAG_3PCC)) {
8510 								/* Check if we are in 3PCC proxy mode, if so then set the flag to indicate we received the ack */
8511 								if (sofia_test_pflag(profile, PFLAG_3PCC_PROXY)) {
8512 									switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "3PCC-PROXY, Got my ACK\n");
8513 									sofia_set_flag(tech_pvt, TFLAG_3PCC_HAS_ACK);
8514 								} else if (switch_channel_get_state(channel) == CS_HIBERNATE) {
8515 									sofia_set_flag_locked(tech_pvt, TFLAG_READY);
8516 									switch_channel_set_state(channel, CS_INIT);
8517 									sofia_set_flag(tech_pvt, TFLAG_SDP);
8518 								}
8519 							}
8520 							goto done;
8521 						}
8522 					}
8523 
8524 					switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "NO CODECS");
8525 					switch_channel_hangup(channel, SWITCH_CAUSE_INCOMPATIBLE_DESTINATION);
8526 				}
8527 			}
8528 		}
8529 
8530 		break;
8531 	case nua_callstate_terminating:
8532 		if (status == 488 || switch_channel_get_state(channel) == CS_HIBERNATE) {
8533 			tech_pvt->q850_cause = SWITCH_CAUSE_MANDATORY_IE_MISSING;
8534 		}
8535 	case nua_callstate_terminated:
8536 		sofia_set_flag_locked(tech_pvt, TFLAG_BYE);
8537 		if (sofia_test_flag(tech_pvt, TFLAG_NOHUP)) {
8538 			sofia_clear_flag_locked(tech_pvt, TFLAG_NOHUP);
8539 		} else if (switch_channel_up(channel)) {
8540 			int cause;
8541 			if (tech_pvt->q850_cause) {
8542 				cause = tech_pvt->q850_cause;
8543 			} else {
8544 				cause = sofia_glue_sip_cause_to_freeswitch(status);
8545 			}
8546 			if (status) {
8547 				switch_snprintf(st, sizeof(st), "%d", status);
8548 				switch_channel_set_variable(channel, "sip_term_status", st);
8549 				switch_snprintf(st, sizeof(st), "sip:%d", status);
8550 				switch_channel_set_variable(channel, SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE, st);
8551 				if (phrase) {
8552 					switch_channel_set_variable_partner(channel, "sip_hangup_phrase", phrase);
8553 				}
8554 				sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_BYE_HEADER_PREFIX);
8555 			}
8556 			switch_snprintf(st, sizeof(st), "%d", cause);
8557 			switch_channel_set_variable(channel, "sip_term_cause", st);
8558 			switch_channel_hangup(channel, cause);
8559 			ss_state = nua_callstate_terminated;
8560 		}
8561 
8562 		if (ss_state == nua_callstate_terminated) {
8563 			if (tech_pvt->sofia_private) {
8564 				tech_pvt->sofia_private = NULL;
8565 			}
8566 
8567 			tech_pvt->nh = NULL;
8568 
8569 			if (nh) {
8570 				nua_handle_bind(nh, NULL);
8571 				nua_handle_destroy(nh);
8572 			}
8573 		}
8574 
8575 		break;
8576 	}
8577 
8578   done:
8579 
8580 	switch_safe_free(patched_sdp);
8581 
8582 	if ((enum nua_callstate) ss_state == nua_callstate_ready && channel && session && tech_pvt) {
8583 		sofia_set_flag(tech_pvt, TFLAG_SIMPLIFY);
8584 	}
8585 
8586 
8587 	return;
8588 }
8589 
8590 typedef struct {
8591 	char *exten;
8592 	char *exten_with_params;
8593 	char *event;
8594 	char *reply_uuid;
8595 	char *bridge_to_uuid;
8596 	switch_event_t *vars;
8597 	switch_memory_pool_t *pool;
8598 	sofia_profile_t *profile;
8599 } nightmare_xfer_helper_t;
8600 
nightmare_xfer_thread_run(switch_thread_t * thread,void * obj)8601 void *SWITCH_THREAD_FUNC nightmare_xfer_thread_run(switch_thread_t *thread, void *obj)
8602 {
8603 	nightmare_xfer_helper_t *nhelper = (nightmare_xfer_helper_t *) obj;
8604 	switch_memory_pool_t *pool;
8605 	switch_status_t status = SWITCH_STATUS_FALSE;
8606 	switch_core_session_t *session, *a_session;
8607 
8608 	if ((a_session = switch_core_session_locate(nhelper->bridge_to_uuid))) {
8609 		switch_core_session_t *tsession = NULL;
8610 		switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
8611 		uint32_t timeout = 60;
8612 		char *tuuid_str;
8613 
8614 		if ((session = switch_core_session_locate(nhelper->reply_uuid))) {
8615 			private_object_t *tech_pvt = switch_core_session_get_private(session);
8616 			switch_channel_t *channel_a = switch_core_session_get_channel(session);
8617 			const char *session_id_header = sofia_glue_session_id_header(session, nhelper->profile);
8618 
8619 			if ((status = switch_ivr_originate(NULL, &tsession, &cause, nhelper->exten_with_params, timeout, NULL, NULL, NULL,
8620 											   switch_channel_get_caller_profile(channel_a), nhelper->vars, SOF_NONE, NULL, NULL)) == SWITCH_STATUS_SUCCESS) {
8621 				if (switch_channel_up(channel_a)) {
8622 
8623 					if (switch_true(switch_channel_get_variable(channel_a, "recording_follow_transfer"))) {
8624 						switch_ivr_transfer_recordings(session, a_session);
8625 					}
8626 
8627 
8628 					tuuid_str = switch_core_session_get_uuid(tsession);
8629 					switch_channel_set_variable_printf(channel_a, "transfer_to", "att:%s", tuuid_str);
8630 					mark_transfer_record(session, nhelper->bridge_to_uuid, tuuid_str);
8631 					switch_ivr_uuid_bridge(nhelper->bridge_to_uuid, tuuid_str);
8632 					switch_channel_set_variable(channel_a, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER");
8633 				} else {
8634 					switch_channel_hangup(switch_core_session_get_channel(tsession), SWITCH_CAUSE_ORIGINATOR_CANCEL);
8635 					status = SWITCH_STATUS_FALSE;
8636 				}
8637 				switch_core_session_rwunlock(tsession);
8638 			}
8639 
8640 			if (status == SWITCH_STATUS_SUCCESS) {
8641 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "The nightmare is over.....\n");
8642 			} else {
8643 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "1 .. 2 .. Freddie's commin' for you...\n");
8644 			}
8645 
8646 			nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag"),
8647 					   NUTAG_SUBSTATE(nua_substate_terminated),SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
8648 					   SIPTAG_PAYLOAD_STR(status == SWITCH_STATUS_SUCCESS ? "SIP/2.0 200 OK\r\n" :
8649 										  "SIP/2.0 403 Forbidden\r\n"), SIPTAG_EVENT_STR(nhelper->event),
8650 					   TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
8651 					   TAG_END());
8652 
8653 			switch_core_session_rwunlock(session);
8654 		}
8655 
8656 		switch_core_session_rwunlock(a_session);
8657 	}
8658 
8659 	switch_event_destroy(&nhelper->vars);
8660 
8661 	pool = nhelper->pool;
8662 	switch_core_destroy_memory_pool(&pool);
8663 
8664 	return NULL;
8665 }
8666 
launch_nightmare_xfer(nightmare_xfer_helper_t * nhelper)8667 static void launch_nightmare_xfer(nightmare_xfer_helper_t *nhelper)
8668 {
8669 	switch_thread_t *thread;
8670 	switch_threadattr_t *thd_attr = NULL;
8671 
8672 	switch_threadattr_create(&thd_attr, nhelper->pool);
8673 	switch_threadattr_detach_set(thd_attr, 1);
8674 	switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
8675 	switch_thread_create(&thread, thd_attr, nightmare_xfer_thread_run, nhelper, nhelper->pool);
8676 }
8677 
8678 /*---------------------------------------*/
8679 
xfer_hanguphook(switch_core_session_t * session)8680 static switch_status_t xfer_hanguphook(switch_core_session_t *session)
8681 {
8682 	switch_channel_t *channel = switch_core_session_get_channel(session);
8683 	switch_channel_state_t state = switch_channel_get_state(channel);
8684 
8685 	if (state == CS_HANGUP) {
8686 		switch_core_session_t *ksession;
8687 		const char *uuid = switch_channel_get_variable(channel, "att_xfer_kill_uuid");
8688 
8689 		if (uuid && (ksession = switch_core_session_force_locate(uuid))) {
8690 			switch_channel_t *kchannel = switch_core_session_get_channel(ksession);
8691 
8692 			switch_channel_clear_flag(kchannel, CF_XFER_ZOMBIE);
8693 			switch_channel_clear_flag(kchannel, CF_TRANSFER);
8694 			if (switch_channel_up(kchannel)) {
8695 				switch_channel_hangup(kchannel, SWITCH_CAUSE_NORMAL_CLEARING);
8696 			}
8697 
8698 			switch_core_session_rwunlock(ksession);
8699 		}
8700 
8701 		switch_core_event_hook_remove_state_change(session, xfer_hanguphook);
8702 
8703 	}
8704 
8705 	return SWITCH_STATUS_SUCCESS;
8706 }
8707 
sofia_global_nua_handle_by_replaces(sip_replaces_t * replaces)8708 nua_handle_t *sofia_global_nua_handle_by_replaces(sip_replaces_t *replaces)
8709 {
8710 	nua_handle_t *nh = NULL;
8711 	switch_hash_index_t *hi;
8712 	const void *var;
8713 	void *val;
8714 	sofia_profile_t *profile;
8715 
8716 	switch_mutex_lock(mod_sofia_globals.hash_mutex);
8717 	if (mod_sofia_globals.profile_hash) {
8718 		for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
8719 			switch_core_hash_this(hi, &var, NULL, &val);
8720 			if ((profile = (sofia_profile_t *) val)) {
8721 				if (!(nh = nua_handle_by_replaces(profile->nua, replaces))) {
8722 					nh = nua_handle_by_call_id(profile->nua, replaces->rp_call_id);
8723 				}
8724 				if (nh)
8725 					break;
8726 			}
8727 		}
8728 		switch_safe_free(hi);
8729 	}
8730 	switch_mutex_unlock(mod_sofia_globals.hash_mutex);
8731 
8732 	return nh;
8733 
8734 }
8735 
sofia_process_proxy_refer(switch_core_session_t * session,const char * refer_to)8736 static switch_status_t sofia_process_proxy_refer(switch_core_session_t *session, const char *refer_to)
8737 {
8738 	switch_core_session_t *other_session;
8739 	private_object_t *tech_pvt = switch_core_session_get_private(session);
8740 
8741 	if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
8742 		switch_core_session_message_t *msg;
8743 
8744 		tech_pvt->proxy_refer_uuid = switch_core_session_strdup(session, switch_core_session_get_uuid(other_session));
8745 		msg = switch_core_session_alloc(other_session, sizeof(*msg));
8746 		MESSAGE_STAMP_FFL(msg);
8747 		msg->message_id = SWITCH_MESSAGE_INDICATE_DEFLECT;
8748 		msg->string_arg = switch_core_session_strdup(other_session, refer_to);
8749 		msg->string_array_arg[0] = switch_core_session_strdup(other_session, switch_core_session_get_uuid(session));
8750 		msg->from = __FILE__;
8751 		switch_core_session_queue_message(other_session, msg);
8752 		switch_core_session_rwunlock(other_session);
8753 		return SWITCH_STATUS_SUCCESS;
8754 	}
8755 
8756 	return SWITCH_STATUS_FALSE;
8757 }
8758 
sofia_handle_sip_i_refer(nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,switch_core_session_t * session,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])8759 void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, switch_core_session_t *session, sip_t const *sip,
8760 								sofia_dispatch_event_t *de, tagi_t tags[])
8761 {
8762 	/* Incoming refer */
8763 	sip_from_t const *from;
8764 	//sip_to_t const *to;
8765 	sip_refer_to_t const *refer_to;
8766 	private_object_t *tech_pvt = switch_core_session_get_private(session);
8767 	char *etmp = NULL, *exten = NULL;
8768 	switch_channel_t *channel_a = switch_core_session_get_channel(session);
8769 	switch_channel_t *channel_b = NULL;
8770 	su_home_t *home = NULL;
8771 	char *full_ref_by = NULL;
8772 	char *full_ref_to = NULL;
8773 	nightmare_xfer_helper_t *nightmare_xfer_helper;
8774 	switch_memory_pool_t *npool;
8775 	switch_event_t *event = NULL;
8776 	const char *session_id_header = sofia_glue_session_id_header(session, profile);
8777 
8778 	if (!(profile->mflags & MFLAG_REFER)) {
8779 		nua_respond(nh, SIP_403_FORBIDDEN, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END());
8780 		goto done;
8781 	}
8782 
8783 	if (!sip->sip_cseq || !(etmp = switch_mprintf("refer;id=%u", sip->sip_cseq->cs_seq))) {
8784 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Memory Error!\n");
8785 		goto done;
8786 	}
8787 
8788 	home = su_home_new(sizeof(*home));
8789 	switch_assert(home != NULL);
8790 
8791 	if ((refer_to = sip->sip_refer_to)) {
8792 		full_ref_to = sip_header_as_string(home, (void *) sip->sip_refer_to);
8793 	}
8794 
8795 	if (full_ref_to && sofia_test_pflag(profile, PFLAG_PROXY_REFER)) {
8796 		if (sofia_process_proxy_refer(session, full_ref_to) == SWITCH_STATUS_SUCCESS) {
8797 			if (tech_pvt->proxy_refer_msg) {
8798 				msg_ref_destroy(tech_pvt->proxy_refer_msg);
8799 				tech_pvt->proxy_refer_msg = NULL;
8800 			}
8801 			tech_pvt->proxy_refer_msg = msg_ref_create(de->data->e_msg);
8802 			//nua_respond(nh, SIP_202_ACCEPTED, NUTAG_WITH_THIS_MSG(de->data->e_msg), SIPTAG_EXPIRES_STR("60"), TAG_END());
8803 			goto done;
8804 		}
8805 	}
8806 
8807 	from = sip->sip_from;
8808 	//to = sip->sip_to;
8809 
8810 	nua_respond(nh, SIP_202_ACCEPTED, NUTAG_WITH_THIS_MSG(de->data->e_msg), SIPTAG_EXPIRES_STR("60"),
8811 			TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
8812 
8813 
8814 	switch_channel_set_variable(tech_pvt->channel, SOFIA_REPLACES_HEADER, NULL);
8815 
8816 	if (sip->sip_referred_by) {
8817 		full_ref_by = sip_header_as_string(home, (void *) sip->sip_referred_by);
8818 	}
8819 
8820 	if (refer_to) {
8821 		char *rep = NULL;
8822 
8823 		if (sofia_test_pflag(profile, PFLAG_FULL_ID)) {
8824 			exten = switch_core_session_sprintf(session, "%s@%s", (char *) refer_to->r_url->url_user, (char *) refer_to->r_url->url_host);
8825 		} else {
8826 			exten = (char *) refer_to->r_url->url_user;
8827 		}
8828 
8829 		if (refer_to->r_url->url_params) {
8830 			switch_channel_set_variable(tech_pvt->channel, "sip_refer_to_params", refer_to->r_url->url_params);
8831 		}
8832 
8833 		switch_core_session_queue_indication(session, SWITCH_MESSAGE_REFER_EVENT);
8834 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Process REFER to [%s@%s]\n", exten, (char *) refer_to->r_url->url_host);
8835 
8836 		switch_channel_set_variable(tech_pvt->channel, "transfer_disposition", "recv_replace");
8837 
8838 
8839 		if (refer_to->r_url->url_headers) {
8840 			rep = (char *) switch_stristr("Replaces=", refer_to->r_url->url_headers);
8841 		}
8842 
8843 
8844 		if (rep) {
8845 			sip_replaces_t *replaces;
8846 			nua_handle_t *bnh = NULL;
8847 
8848 			const char *br_a = NULL, *br_b = NULL;
8849 			char *buf;
8850 			char *p;
8851 
8852 			rep = switch_core_session_strdup(session, rep + 9);
8853 
8854 			if ((buf = switch_core_session_alloc(session, strlen(rep) + 1))) {
8855 				rep = url_unescape(buf, (const char *) rep);
8856 				if ((p = strchr(rep, ';'))) {
8857 					*p = '\0';
8858 				}
8859 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Replaces: [%s]\n", rep);
8860 			} else {
8861 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Memory Error!\n");
8862 				goto done;
8863 			}
8864 
8865 			if ((replaces = sip_replaces_make(home, rep))) {
8866 				if (!(bnh = nua_handle_by_replaces(nua, replaces))) {
8867 					if (!(bnh = nua_handle_by_call_id(nua, replaces->rp_call_id))) {
8868 						bnh = sofia_global_nua_handle_by_replaces(replaces);
8869 					}
8870 				}
8871 			}
8872 
8873 			if (bnh && !sofia_test_pflag(profile, PFLAG_MAKE_EVERY_TRANSFER_A_NIGHTMARE)) {
8874 				sofia_private_t *b_private = NULL;
8875 				private_object_t *b_tech_pvt = NULL;
8876 				switch_core_session_t *b_session = NULL;
8877 
8878 
8879 				switch_channel_set_variable(channel_a, SOFIA_REPLACES_HEADER, rep);
8880 				if ((b_private = nua_handle_magic(bnh))) {
8881 					int deny_refer_requests = 0;
8882 
8883 					if (!(b_session = switch_core_session_locate(b_private->uuid))) {
8884 						goto done;
8885 					}
8886 					b_tech_pvt = (private_object_t *) switch_core_session_get_private(b_session);
8887 					channel_b = switch_core_session_get_channel(b_session);
8888 
8889 					switch_channel_set_variable(channel_a, "refer_uuid", b_private->uuid);
8890 					switch_channel_set_variable(channel_b, "transfer_disposition", "replaced");
8891 
8892 					br_a = switch_channel_get_partner_uuid(channel_a);
8893 					br_b = switch_channel_get_partner_uuid(channel_b);
8894 
8895 					if (!switch_ivr_uuid_exists(br_a)) {
8896 						br_a = NULL;
8897 					}
8898 
8899 					if (!switch_ivr_uuid_exists(br_b)) {
8900 						br_b = NULL;
8901 					}
8902 
8903 					if (channel_a && switch_true(switch_channel_get_variable(channel_a, "deny_refer_requests"))) {
8904 						deny_refer_requests = 1;
8905 					}
8906 
8907 					if (!deny_refer_requests && channel_b && switch_true(switch_channel_get_variable(channel_b, "deny_refer_requests"))) {
8908 						deny_refer_requests = 1;
8909 					}
8910 
8911 					if (!deny_refer_requests && br_a) {
8912 						switch_core_session_t *a_session;
8913 						if ((a_session = switch_core_session_locate(br_a))) {
8914 							switch_channel_t *a_channel = switch_core_session_get_channel(a_session);
8915 
8916 							if (a_channel && switch_true(switch_channel_get_variable(a_channel, "deny_refer_requests"))) {
8917 								deny_refer_requests = 1;
8918 							}
8919 							switch_core_session_rwunlock(a_session);
8920 						}
8921 					}
8922 
8923 					if (!deny_refer_requests && br_b) {
8924 						switch_core_session_t *b_session;
8925 						if ((b_session = switch_core_session_locate(br_b))) {
8926 							switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
8927 
8928 							if (b_channel && switch_true(switch_channel_get_variable(b_channel, "deny_refer_requests"))) {
8929 								deny_refer_requests = 1;
8930 							}
8931 							switch_core_session_rwunlock(b_session);
8932 						}
8933 					}
8934 
8935 					if (deny_refer_requests) {
8936 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Denying Attended Transfer, variable [deny_refer_requests] was set to true\n");
8937 
8938 						nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"),
8939 							NUTAG_SUBSTATE(nua_substate_terminated),SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
8940 							TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
8941 							SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden\r\n"), SIPTAG_EVENT_STR(etmp), TAG_END());
8942 
8943 					} else if (switch_channel_test_flag(channel_b, CF_ORIGINATOR)) {
8944 						switch_core_session_t *a_session;
8945 
8946 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE,
8947 										  "Attended Transfer on originating session %s\n", switch_core_session_get_uuid(b_session));
8948 
8949 
8950 
8951 						switch_channel_set_variable_printf(channel_b, "transfer_to", "satt:%s", br_a);
8952 
8953 						switch_channel_set_variable(channel_b, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER");
8954 
8955 
8956 						sofia_clear_flag_locked(b_tech_pvt, TFLAG_SIP_HOLD);
8957 						switch_channel_clear_flag(channel_b, CF_LEG_HOLDING);
8958 						sofia_clear_flag_locked(tech_pvt, TFLAG_HOLD_LOCK);
8959 
8960 						switch_channel_set_variable(channel_b, SWITCH_HOLDING_UUID_VARIABLE, br_a);
8961 						switch_channel_set_flag(channel_b, CF_XFER_ZOMBIE);
8962 						switch_channel_set_flag(channel_b, CF_TRANSFER);
8963 
8964 
8965 						if ((a_session = switch_core_session_locate(br_a))) {
8966 							const char *moh = profile->hold_music;
8967 							switch_core_session_t *tmpsess = NULL;
8968 							switch_channel_t *a_channel = switch_core_session_get_channel(a_session);
8969 							switch_caller_profile_t *prof = switch_channel_get_caller_profile(channel_b);
8970 							const char *tmp;
8971 
8972 							switch_core_event_hook_add_state_change(a_session, xfer_hanguphook);
8973 							switch_channel_set_variable(a_channel, "att_xfer_kill_uuid", switch_core_session_get_uuid(b_session));
8974 							switch_channel_set_variable(a_channel, "att_xfer_destination_number", prof->destination_number);
8975 							switch_channel_set_variable(a_channel, "att_xfer_callee_id_name", prof->callee_id_name);
8976 							switch_channel_set_variable(a_channel, "att_xfer_callee_id_number", prof->callee_id_number);
8977 
8978 							if (profile->media_options & MEDIA_OPT_BYPASS_AFTER_ATT_XFER) {
8979 								switch_channel_set_flag(a_channel, CF_BYPASS_MEDIA_AFTER_BRIDGE);
8980 							}
8981 
8982 
8983 							if ((tmp = switch_channel_get_hold_music(a_channel))) {
8984 								moh = tmp;
8985 							}
8986 
8987 							if (!zstr(moh) && !strcasecmp(moh, "silence")) {
8988 								moh = NULL;
8989 							}
8990 
8991 							if(sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)) {
8992 								if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_REPLACED) == SWITCH_STATUS_SUCCESS) {
8993 									switch_channel_event_set_data(channel_b, event);
8994 									switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_by", br_a);
8995 									switch_event_fire(&event);
8996 								}
8997 
8998 								if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEROR) == SWITCH_STATUS_SUCCESS) {
8999 									switch_channel_event_set_data(channel_a, event);
9000 									switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_original_call_id", br_a);
9001 									switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_destination_call_id", br_b);
9002 									switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_destination_peer_uuid", switch_core_session_get_uuid(b_session));
9003 									switch_event_fire(&event);
9004 								}
9005 
9006 								if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEREE) == SWITCH_STATUS_SUCCESS) {
9007 									switch_channel_event_set_data(a_channel, event);
9008 									switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_call_id", switch_core_session_get_uuid(b_session));
9009 									switch_event_fire(&event);
9010 								}
9011 							}
9012 
9013 							if (moh) {
9014 								char *xdest;
9015 								xdest = switch_core_session_sprintf(a_session, "m:\":endless_playback:%s\"park", moh);
9016 								switch_ivr_session_transfer(a_session, xdest, "inline", NULL);
9017 							} else {
9018 								switch_ivr_session_transfer(a_session, "park", "inline", NULL);
9019 							}
9020 							if (switch_true(switch_channel_get_variable(channel_a, "recording_follow_transfer"))) {
9021 								switch_ivr_transfer_recordings(session, a_session);
9022 							}
9023 							if (switch_true(switch_channel_get_variable(channel_b, "recording_follow_transfer")) && (tmpsess = switch_core_session_locate(br_a))) {
9024 								switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE,
9025 										  "Early transfer detected with no media, moving recording bug to other leg\n");
9026 								switch_ivr_transfer_recordings(b_session, tmpsess);
9027 								switch_core_session_rwunlock(tmpsess);
9028 							}
9029 
9030 							switch_core_session_rwunlock(a_session);
9031 
9032 							nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"),
9033 									   NUTAG_SUBSTATE(nua_substate_terminated),SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"), SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK\r\n"), SIPTAG_EVENT_STR(etmp),
9034 									   TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9035 									   TAG_END());
9036 
9037 							if (b_tech_pvt && !sofia_test_flag(b_tech_pvt, TFLAG_BYE)) {
9038 								char *q850 = NULL;
9039 								const char *val = NULL;
9040 
9041 								sofia_set_flag_locked(b_tech_pvt, TFLAG_BYE);
9042 								val = switch_channel_get_variable(tech_pvt->channel, "disable_q850_reason");
9043 								if (!val || switch_true(val)) {
9044 									q850 = switch_core_session_sprintf(a_session, "Q.850;cause=16;text=\"normal_clearing\"");
9045 								}
9046 								nua_bye(b_tech_pvt->nh,
9047 										SIPTAG_CONTACT(SIP_NONE),
9048 										TAG_IF(!zstr(q850), SIPTAG_REASON_STR(q850)),
9049 										TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
9050 										TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9051 										TAG_END());
9052 
9053 							}
9054 						} else {
9055 							nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"),
9056 									   NUTAG_SUBSTATE(nua_substate_terminated),SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
9057 									   SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden\r\n"), SIPTAG_EVENT_STR(etmp),
9058 									   TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9059 									   TAG_END());
9060 						}
9061 
9062 					} else if (br_a && br_b) {
9063 						switch_core_session_t *tmp = NULL;
9064 						switch_event_t *event = NULL;
9065 
9066 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Attended Transfer [%s][%s]\n",
9067 										  switch_str_nil(br_a), switch_str_nil(br_b));
9068 
9069 						if ((tmp = switch_core_session_locate(br_b))) {
9070 							switch_channel_t *tchannel = switch_core_session_get_channel(tmp);
9071 
9072 							if ((profile->media_options & MEDIA_OPT_BYPASS_AFTER_ATT_XFER)) {
9073 								switch_channel_set_flag(tchannel, CF_BYPASS_MEDIA_AFTER_BRIDGE);
9074 							}
9075 
9076 							switch_channel_set_variable(tchannel, "transfer_disposition", "bridge");
9077 
9078 							switch_channel_set_flag(tchannel, CF_ATTENDED_TRANSFER);
9079 							switch_core_session_rwunlock(tmp);
9080 						}
9081 
9082 						if ((profile->media_options & MEDIA_OPT_BYPASS_AFTER_ATT_XFER) && (tmp = switch_core_session_locate(br_a))) {
9083 							switch_channel_t *tchannel = switch_core_session_get_channel(tmp);
9084 							switch_channel_set_flag(tchannel, CF_BYPASS_MEDIA_AFTER_BRIDGE);
9085 							switch_core_session_rwunlock(tmp);
9086 						}
9087 
9088 
9089 						if (switch_true(switch_channel_get_variable(channel_a, "recording_follow_transfer")) &&
9090 							(tmp = switch_core_session_locate(br_a))) {
9091 							switch_channel_set_variable(switch_core_session_get_channel(tmp), "transfer_disposition", "bridge");
9092 							switch_ivr_transfer_recordings(session, tmp);
9093 							switch_core_session_rwunlock(tmp);
9094 						}
9095 
9096 
9097 						if (switch_true(switch_channel_get_variable(channel_b, "recording_follow_transfer")) &&
9098 							(tmp = switch_core_session_locate(br_b))) {
9099 							switch_ivr_transfer_recordings(b_session, tmp);
9100 							switch_core_session_rwunlock(tmp);
9101 						}
9102 
9103 						switch_channel_set_variable_printf(channel_a, "transfer_to", "att:%s", br_b);
9104 
9105 						mark_transfer_record(session, br_a, br_b);
9106 
9107 						if(sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)) {
9108 							if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_REPLACED) == SWITCH_STATUS_SUCCESS) {
9109 								switch_channel_event_set_data(channel_b, event);
9110 								switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_by", br_a);
9111 								switch_event_fire(&event);
9112 							}
9113 
9114 							if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEROR) == SWITCH_STATUS_SUCCESS) {
9115 								switch_channel_event_set_data(channel_a, event);
9116 								switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_original_call_id", br_a);
9117 								switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_destination_call_id", br_b);
9118 								switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_destination_peer_uuid", switch_core_session_get_uuid(b_session));
9119 								switch_event_fire(&event);
9120 							}
9121 
9122 							if ((tmp = switch_core_session_locate(br_a))) {
9123 								switch_channel_t *tchannel = switch_core_session_get_channel(tmp);
9124 
9125 								if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEREE) == SWITCH_STATUS_SUCCESS) {
9126 									switch_channel_event_set_data(tchannel, event);
9127 									switch_event_fire(&event);
9128 								}
9129 
9130 								switch_core_session_rwunlock(tmp);
9131 							}
9132 						}
9133 
9134 						switch_ivr_uuid_bridge(br_a, br_b);
9135 						switch_channel_set_variable(channel_b, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER");
9136 						nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"),
9137 								   NUTAG_SUBSTATE(nua_substate_terminated),SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"), SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK\r\n"), SIPTAG_EVENT_STR(etmp),
9138 								   TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9139 								   TAG_END());
9140 
9141 						sofia_clear_flag_locked(b_tech_pvt, TFLAG_SIP_HOLD);
9142 						switch_channel_clear_flag(channel_b, CF_LEG_HOLDING);
9143 						sofia_clear_flag_locked(tech_pvt, TFLAG_HOLD_LOCK);
9144 						switch_channel_set_variable(channel_b, "park_timeout", "2:attended_transfer");
9145 						switch_channel_set_state(channel_b, CS_PARK);
9146 						switch_channel_wait_for_state_timeout(channel_b, CS_PARK, 5000);
9147 
9148 					} else {
9149 						if (!br_a && !br_b) {
9150 							switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
9151 											  "Cannot transfer channels that are not in a bridge.\n");
9152 							nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"),
9153 									   NUTAG_SUBSTATE(nua_substate_terminated),SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"), SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden\r\n"),
9154 									   SIPTAG_EVENT_STR(etmp),
9155 									   TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9156 									   TAG_END());
9157 						} else {
9158 							switch_core_session_t *t_session, *hup_session;
9159 							switch_channel_t *hup_channel;
9160 							switch_event_t *event = NULL;
9161 							const char *ext;
9162 
9163 							if (br_a && !br_b) {
9164 								t_session = switch_core_session_locate(br_a);
9165 								hup_channel = channel_b;
9166 								hup_session = b_session;
9167 							} else {
9168 								private_object_t *h_tech_pvt = (private_object_t *) switch_core_session_get_private(b_session);
9169 								t_session = switch_core_session_locate(br_b);
9170 								hup_channel = channel_a;
9171 								hup_session = session;
9172 								sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD);
9173 								switch_channel_clear_flag(tech_pvt->channel, CF_LEG_HOLDING);
9174 								sofia_clear_flag_locked(h_tech_pvt, TFLAG_SIP_HOLD);
9175 								switch_channel_clear_flag(h_tech_pvt->channel, CF_LEG_HOLDING);
9176 								switch_channel_hangup(channel_b, SWITCH_CAUSE_ATTENDED_TRANSFER);
9177 							}
9178 
9179 							if (t_session) {
9180 								switch_channel_t *t_channel = switch_core_session_get_channel(t_session);
9181 								const char *idest = switch_channel_get_variable(hup_channel, "inline_destination");
9182 								ext = switch_channel_get_variable(hup_channel, "destination_number");
9183 
9184 								if (!zstr(full_ref_by)) {
9185 									switch_channel_set_variable(t_channel, SOFIA_SIP_HEADER_PREFIX "Referred-By", full_ref_by);
9186 								}
9187 
9188 								if (!zstr(full_ref_to)) {
9189 									switch_channel_set_variable(t_channel, SOFIA_REFER_TO_VARIABLE, full_ref_to);
9190 								}
9191 
9192 
9193 								if (switch_true(switch_channel_get_variable(hup_channel, "recording_follow_transfer"))) {
9194 									switch_ivr_transfer_recordings(hup_session, t_session);
9195 								}
9196 
9197 								if(sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)) {
9198 									if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEROR) == SWITCH_STATUS_SUCCESS) {
9199 										switch_channel_event_set_data(channel_a, event);
9200 										switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_original_call_id", switch_core_session_get_uuid(hup_session));
9201 										switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_destination_call_id", switch_core_session_get_uuid(t_session));
9202 										switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_destination_peer_uuid", switch_channel_get_partner_uuid(t_channel));
9203 										switch_event_fire(&event);
9204 									}
9205 
9206 									if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEREE) == SWITCH_STATUS_SUCCESS) {
9207 										switch_channel_event_set_data(t_channel, event);
9208 										switch_event_fire(&event);
9209 									}
9210 								}
9211 
9212 								if (idest) {
9213 									switch_ivr_session_transfer(t_session, idest, "inline", NULL);
9214 								} else {
9215 									switch_ivr_session_transfer(t_session, ext, NULL, NULL);
9216 								}
9217 
9218 								nua_notify(tech_pvt->nh,
9219 										   NUTAG_NEWSUB(1),
9220 										   SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"),
9221 										   NUTAG_SUBSTATE(nua_substate_terminated),SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
9222 										   SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK\r\n"), SIPTAG_EVENT_STR(etmp),
9223 										   TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9224 										   TAG_END());
9225 								switch_core_session_rwunlock(t_session);
9226 								switch_channel_hangup(hup_channel, SWITCH_CAUSE_ATTENDED_TRANSFER);
9227 							} else {
9228 								switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Session to transfer to not found.\n");
9229 								nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"),
9230 										   NUTAG_SUBSTATE(nua_substate_terminated),SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
9231 										   SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden\r\n"), SIPTAG_EVENT_STR(etmp),
9232 										   TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9233 										   TAG_END());
9234 							}
9235 						}
9236 					}
9237 					switch_core_session_rwunlock(b_session);
9238 				}
9239 				nua_handle_unref(bnh);
9240 			} else {		/* the other channel is on a different box, we have to go find them */
9241 				if (exten && (br_a = switch_channel_get_partner_uuid(channel_a))) {
9242 					switch_core_session_t *a_session;
9243 					switch_channel_t *channel;
9244 
9245 					if ((a_session = switch_core_session_locate(br_a))) {
9246 						const char *port = NULL;
9247 						const char *rep_h = NULL;
9248 
9249 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
9250 										  "REFER from %s replaces %s (%s@%s) with %s on another server\n",
9251 										  switch_core_session_get_uuid(session), rep, exten, (char *) refer_to->r_url->url_host, br_a);
9252 
9253 						if (refer_to->r_url->url_port) {
9254 							port = refer_to->r_url->url_port;
9255 						}
9256 
9257 						channel = switch_core_session_get_channel(a_session);
9258 
9259 						exten = NULL;
9260 
9261 						if (sofia_test_pflag(profile, PFLAG_CHANNEL_XML_FETCH_ON_NIGHTMARE_TRANSFER)) {
9262 							switch_xml_t xml_root = NULL, xml_channel = NULL;
9263 							switch_event_t *xml_params = NULL;
9264 							const char *xml_url = NULL, *use_profile = profile->name, *dial_prefix = NULL, *absolute_dial_string = NULL;
9265 							switch_xml_t params = NULL, param = NULL;
9266 
9267 							switch_event_create(&xml_params, SWITCH_EVENT_REQUEST_PARAMS);
9268 							switch_event_add_header_string(xml_params, SWITCH_STACK_BOTTOM, "purpose", "nightmare_xfer");
9269 							switch_event_add_header_string(xml_params, SWITCH_STACK_BOTTOM, "profile", profile->name);
9270 							switch_event_add_header_string(xml_params, SWITCH_STACK_BOTTOM, "refer-to-user", refer_to->r_url->url_user);
9271 							switch_event_add_header_string(xml_params, SWITCH_STACK_BOTTOM, "refer-to-host", refer_to->r_url->url_host);
9272 							switch_event_add_header_string(xml_params, SWITCH_STACK_BOTTOM, "refer-to-params", refer_to->r_url->url_params ? refer_to->r_url->url_params : "");
9273 							switch_event_add_header_string(xml_params, SWITCH_STACK_BOTTOM, "refer-to-headers", refer_to->r_url->url_headers ? refer_to->r_url->url_headers : "");
9274 							if (replaces) {
9275 								switch_event_add_header_string(xml_params, SWITCH_STACK_BOTTOM, "replaces-call-id", replaces->rp_call_id);
9276 							}
9277 							switch_event_add_header_string(xml_params, SWITCH_STACK_BOTTOM, "refer-from-channel-id", switch_core_session_get_uuid(session));
9278 							switch_event_add_header_string(xml_params, SWITCH_STACK_BOTTOM, "refer-for-channel-id", br_a);
9279 
9280 							if (switch_xml_locate("channels", NULL, NULL, NULL,
9281 												  &xml_root, &xml_channel, xml_params, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
9282 								if ((params = switch_xml_child(xml_channel, "params"))) {
9283 									for (param = switch_xml_child(params, "param"); param; param = param->next) {
9284 										const char *name = switch_xml_attr(param, "name");
9285 										const char *value = switch_xml_attr(param, "value");
9286 
9287 										if (!(name && value)) continue;
9288 
9289 										if (!strcasecmp(name, "sip-url")) {
9290 											xml_url = value;
9291 										} else if (!strcasecmp(name, "dial-prefix")) {
9292 											dial_prefix = value;
9293 										} else if (!strcasecmp(name, "absolute-dial-string")) {
9294 											absolute_dial_string = value;
9295 										} else if (!strcasecmp(name, "sip-profile")) {
9296 											use_profile = value;
9297 										}
9298 									}
9299 								}
9300 
9301 								if (absolute_dial_string) {
9302 									exten = switch_core_session_sprintf(session, "%s%s", dial_prefix, absolute_dial_string);
9303 								} else if (xml_url) {
9304 									exten = switch_core_session_sprintf(session, "%ssofia/%s/%s", dial_prefix, use_profile, xml_url);
9305 								}
9306 
9307 								switch_xml_free(xml_root);
9308 							}
9309 
9310 							switch_event_destroy(&xml_params);
9311 						}
9312 
9313 
9314 						if (zstr(exten)) {
9315 							exten = switch_core_session_sprintf(session, "sofia/%s/sip:%s@%s%s%s",
9316 																profile->name, refer_to->r_url->url_user,
9317 																refer_to->r_url->url_host, port ? ":" : "", port ? port : "");
9318 						}
9319 
9320 						switch_core_new_memory_pool(&npool);
9321 						nightmare_xfer_helper = switch_core_alloc(npool, sizeof(*nightmare_xfer_helper));
9322 						nightmare_xfer_helper->exten = switch_core_strdup(npool, exten);
9323 
9324 						if (refer_to->r_url->url_params || refer_to->r_url->url_headers) {
9325 							if (refer_to->r_url->url_headers) {
9326 								nightmare_xfer_helper->exten_with_params = switch_core_sprintf(npool,
9327 																							   "{sip_invite_params=%s?%s}%s",
9328 																							   refer_to->r_url->url_params ? refer_to->r_url->
9329 																							   url_params : "", refer_to->r_url->url_headers, exten);
9330 							} else {
9331 								nightmare_xfer_helper->exten_with_params = switch_core_sprintf(npool,
9332 																							   "{sip_invite_params=%s}%s", refer_to->r_url->url_params,
9333 																							   exten);
9334 							}
9335 						} else {
9336 							nightmare_xfer_helper->exten_with_params = nightmare_xfer_helper->exten;
9337 						}
9338 
9339 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Nightmare transfer to '%s'\n", nightmare_xfer_helper->exten_with_params);
9340 
9341 						nightmare_xfer_helper->event = switch_core_strdup(npool, etmp);
9342 						nightmare_xfer_helper->reply_uuid = switch_core_strdup(npool, switch_core_session_get_uuid(session));
9343 						nightmare_xfer_helper->bridge_to_uuid = switch_core_strdup(npool, br_a);
9344 						nightmare_xfer_helper->pool = npool;
9345 
9346 						if (refer_to->r_url->url_headers) {
9347 							char *h, *v, *hp;
9348 							p = switch_core_session_strdup(session, refer_to->r_url->url_headers);
9349 							while (p && *p) {
9350 								h = p;
9351 								if ((p = strchr(p, '='))) {
9352 									*p++ = '\0';
9353 									v = p;
9354 									if ((p = strchr(p, '&'))) {
9355 										*p++ = '\0';
9356 									}
9357 
9358 									url_unescape(h, (const char *) h);
9359 									url_unescape(v, (const char *) v);
9360 									if (strcasecmp("Replaces", h)) {
9361 										hp = switch_core_session_sprintf(session, "%s%s", SOFIA_SIP_HEADER_PREFIX, h);
9362 										switch_channel_set_variable(channel, hp, v);
9363 									} else {
9364 										// use this one instead of rep value from above to keep all parameters
9365 										switch_channel_set_variable(channel, SOFIA_REPLACES_HEADER, v);
9366 									}
9367 									switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Exporting replaces URL header [%s:%s]\n",
9368 													  h, v);
9369 								}
9370 							}
9371 						}
9372 
9373 
9374 						switch_event_create(&nightmare_xfer_helper->vars, SWITCH_EVENT_CHANNEL_DATA);
9375 
9376 						rep_h = switch_channel_get_variable(channel, SOFIA_REPLACES_HEADER);
9377 						if (rep_h) {
9378 							switch_event_add_header_string(nightmare_xfer_helper->vars, SWITCH_STACK_BOTTOM, SOFIA_REPLACES_HEADER, rep_h);
9379 						} else {
9380 							switch_event_add_header_string(nightmare_xfer_helper->vars, SWITCH_STACK_BOTTOM, SOFIA_REPLACES_HEADER, rep);
9381 						}
9382 
9383 
9384 						if (!zstr(full_ref_by)) {
9385 							switch_event_add_header_string(nightmare_xfer_helper->vars, SWITCH_STACK_BOTTOM, "Referred-By", full_ref_by);
9386 						}
9387 
9388 						if (!zstr(full_ref_to)) {
9389 							switch_event_add_header_string(nightmare_xfer_helper->vars, SWITCH_STACK_BOTTOM, SOFIA_REFER_TO_VARIABLE, full_ref_to);
9390 						}
9391 
9392 						if(sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)) {
9393 							if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEROR) == SWITCH_STATUS_SUCCESS) {
9394 								switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_original_call_id", br_a);
9395 								switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_destination_call_id", br_b);
9396 								switch_channel_event_set_data(channel_a, event);
9397 								switch_event_fire(&event);
9398 							}
9399 
9400 							if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEREE) == SWITCH_STATUS_SUCCESS) {
9401 								switch_channel_event_set_data(channel, event);
9402 								switch_event_fire(&event);
9403 							}
9404 						}
9405 
9406 						switch_event_add_header_string(nightmare_xfer_helper->vars, SWITCH_STACK_BOTTOM, "sip_h_X-FS-Refer-From", switch_core_session_get_uuid(session));
9407 						switch_event_add_header_string(nightmare_xfer_helper->vars, SWITCH_STACK_BOTTOM, "sip_h_X-FS-Refer-For", br_a);
9408 
9409 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Good Luck, you'll need it......\n");
9410 						nightmare_xfer_helper->profile = profile;
9411 						launch_nightmare_xfer(nightmare_xfer_helper);
9412 
9413 						switch_core_session_rwunlock(a_session);
9414 
9415 					} else {
9416 						goto error;
9417 					}
9418 
9419 				} else {
9420 				  error:
9421 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Transfer! [%s]\n", br_a);
9422 					switch_channel_set_variable(channel_a, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER_ERROR");
9423 					nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"),
9424 							   NUTAG_SUBSTATE(nua_substate_terminated),SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"), SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden\r\n"), SIPTAG_EVENT_STR(etmp),
9425 							   TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9426 							   TAG_END());
9427 				}
9428 			}
9429 			goto done;
9430 		}
9431 
9432 	} else {
9433 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Missing Refer-To\n");
9434 		goto done;
9435 	}
9436 
9437 	if (exten) {
9438 		switch_channel_t *channel = switch_core_session_get_channel(session);
9439 		const char *br = switch_channel_get_partner_uuid(channel);
9440 		switch_core_session_t *b_session;
9441 
9442 		switch_channel_set_variable_printf(channel, "transfer_to", "blind:%s", br ? br : exten);
9443 		switch_channel_set_variable_printf(channel, "transfer_destination", "blind:%s", exten);
9444 
9445 		if (!zstr(br) && (b_session = switch_core_session_locate(br))) {
9446 			const char *var;
9447 			switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
9448 			switch_event_t *event = NULL;
9449 
9450 			switch_channel_set_variable(channel, "transfer_fallback_extension", from->a_user);
9451 			if (!zstr(full_ref_by)) {
9452 				switch_channel_set_variable(b_channel, SOFIA_SIP_HEADER_PREFIX "Referred-By", full_ref_by);
9453 			}
9454 
9455 			if (!zstr(full_ref_to)) {
9456 				switch_channel_set_variable(b_channel, SOFIA_REFER_TO_VARIABLE, full_ref_to);
9457 			}
9458 
9459 			if (switch_true(switch_channel_get_variable(channel, "recording_follow_transfer"))) {
9460 				switch_ivr_transfer_recordings(session, b_session);
9461 			}
9462 
9463 			switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "BLIND_TRANSFER");
9464 
9465 			if (((var = switch_channel_get_variable(channel, "confirm_blind_transfer")) && switch_true(var)) ||
9466 				sofia_test_pflag(profile, PFLAG_CONFIRM_BLIND_TRANSFER)) {
9467 
9468 				switch_channel_set_state_flag(b_channel, CF_CONFIRM_BLIND_TRANSFER);
9469 				switch_channel_set_variable(channel, "sip_blind_transfer_event", etmp);
9470 				switch_channel_set_variable(b_channel, "blind_transfer_uuid", switch_core_session_get_uuid(session));
9471 				switch_channel_set_variable(channel, "blind_transfer_uuid", switch_core_session_get_uuid(b_session));
9472 
9473 				switch_channel_set_variable(channel, "park_timeout", "600:blind_transfer");
9474 				switch_channel_set_state(channel, CS_PARK);
9475 			} else {
9476 				nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"),
9477 						   NUTAG_SUBSTATE(nua_substate_terminated),
9478 						   SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
9479 						   SIPTAG_PAYLOAD_STR("SIP/2.0 200 OK\r\n"), SIPTAG_EVENT_STR(etmp),
9480 						   TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9481 						   TAG_END());
9482 			}
9483 
9484             if (refer_to->r_url->url_params) {
9485                 switch_channel_set_variable(b_channel, "sip_h_X-FS-Refer-Params", refer_to->r_url->url_params);
9486             }
9487 
9488             if(sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)) {
9489 	            if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEROR) == SWITCH_STATUS_SUCCESS) {
9490 	                switch_channel_event_set_data(channel_a, event);
9491 	                switch_event_fire(&event);
9492 	            }
9493 
9494 				if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_TRANSFEREE) == SWITCH_STATUS_SUCCESS) {
9495 	                switch_channel_event_set_data(b_channel, event);
9496 	                switch_event_fire(&event);
9497 	            }
9498             }
9499 
9500 			switch_ivr_session_transfer(b_session, exten, NULL, NULL);
9501 			switch_core_session_rwunlock(b_session);
9502 		} else {
9503 			switch_event_t *event;
9504 
9505 			if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_ERROR) == SWITCH_STATUS_SUCCESS) {
9506 				switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Error-Type", "blind_transfer");
9507 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Transfer-Exten", exten);
9508 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Full-Refer-To", full_ref_to);
9509 				switch_channel_event_set_data(channel, event);
9510 				switch_event_fire(&event);
9511 			}
9512 
9513 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Cannot Blind Transfer 1 Legged calls\n");
9514 			switch_channel_set_variable(channel_a, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "ATTENDED_TRANSFER_ERROR");
9515 			nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0"),
9516 					   NUTAG_SUBSTATE(nua_substate_terminated),
9517 					   SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
9518 					   SIPTAG_PAYLOAD_STR("SIP/2.0 403 Forbidden\r\n"), SIPTAG_EVENT_STR(etmp),
9519 					   TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9520 					   TAG_END());
9521 		}
9522 	}
9523 
9524   done:
9525 	if (home) {
9526 		su_home_unref(home);
9527 		home = NULL;
9528 	}
9529 
9530 	switch_safe_free(etmp);
9531 }
9532 
9533 
create_info_event(sip_t const * sip,nua_handle_t * nh,switch_event_t ** revent)9534 static switch_status_t create_info_event(sip_t const *sip,
9535 										 nua_handle_t *nh, switch_event_t **revent)
9536 {
9537 	sip_alert_info_t *alert_info = sip_alert_info(sip);
9538 	switch_event_t *event;
9539 
9540 	if (!(sip && switch_event_create(&event, SWITCH_EVENT_RECV_INFO) == SWITCH_STATUS_SUCCESS)) {
9541 		return SWITCH_STATUS_FALSE;
9542 	}
9543 
9544 	if (sip->sip_content_type) {
9545 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SIP-Content-Type", sip->sip_content_type->c_type);
9546 	}
9547 
9548 	if (sip->sip_from) {
9549 		if (sip->sip_from->a_url->url_user) {
9550 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SIP-From-User", sip->sip_from->a_url->url_user);
9551 		}
9552 
9553 		if (sip->sip_from->a_url->url_host) {
9554 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SIP-From-Host", sip->sip_from->a_url->url_host);
9555 		}
9556 	}
9557 
9558 	if (sip->sip_to) {
9559 		if (sip->sip_to->a_url->url_user) {
9560 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SIP-To-User", sip->sip_to->a_url->url_user);
9561 		}
9562 
9563 		if (sip->sip_to->a_url->url_host) {
9564 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SIP-To-Host", sip->sip_to->a_url->url_host);
9565 		}
9566 	}
9567 
9568 
9569 	if (sip->sip_contact) {
9570 		if (sip->sip_contact->m_url->url_user) {
9571 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SIP-Contact-User", sip->sip_contact->m_url->url_user);
9572 		}
9573 
9574 		if (sip->sip_contact->m_url->url_host) {
9575 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SIP-Contact-Host", sip->sip_contact->m_url->url_host);
9576 		}
9577 	}
9578 
9579 
9580 	if (sip->sip_call_info) {
9581 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Call-Info",
9582 									   sip_header_as_string(nua_handle_home(nh), (void *) sip->sip_call_info));
9583 	}
9584 
9585 	if (alert_info) {
9586 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Alert-Info", sip_header_as_string(nua_handle_home(nh), (void *) alert_info));
9587 	}
9588 
9589 
9590 	if (sip->sip_payload && sip->sip_payload->pl_data) {
9591 		switch_event_add_body(event, "%s", sip->sip_payload->pl_data);
9592 	}
9593 
9594 	*revent = event;
9595 
9596 	return SWITCH_STATUS_SUCCESS;
9597 }
9598 
sofia_proxy_sip_i_message(nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,switch_core_session_t * session,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])9599 switch_status_t sofia_proxy_sip_i_message(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, switch_core_session_t *session, sip_t const *sip,
9600 									   sofia_dispatch_event_t *de, tagi_t tags[])
9601 {
9602 	switch_core_session_t *other_session = NULL;
9603 	const char *session_id_header = sofia_glue_session_id_header(session, profile);
9604 
9605 	if (session && switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
9606 		if (switch_core_session_compare(session, other_session)) {
9607 			private_object_t *other_tech_pvt = NULL;
9608 			const char *ct = NULL;
9609 			char *pl = NULL;
9610 
9611 
9612 			if (sip && sip->sip_payload && sip->sip_payload->pl_data) {
9613 				pl = sip->sip_payload->pl_data;
9614 			}
9615 
9616 			other_tech_pvt = (private_object_t *) switch_core_session_get_private(other_session);
9617 
9618 			if (sip && sip->sip_content_type->c_type && sip->sip_content_type->c_subtype) {
9619 				ct = sip->sip_content_type->c_type;
9620 			}
9621 
9622 			nua_message(other_tech_pvt->nh,
9623 						TAG_IF(ct, SIPTAG_CONTENT_TYPE_STR(su_strdup(other_tech_pvt->nh->nh_home, ct))),
9624 						TAG_IF(!zstr(other_tech_pvt->user_via), SIPTAG_VIA_STR(other_tech_pvt->user_via)),
9625 						TAG_IF(pl, SIPTAG_PAYLOAD_STR(su_strdup(other_tech_pvt->nh->nh_home, pl))),
9626 						TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9627 						TAG_END());
9628 		}
9629 
9630 		switch_core_session_rwunlock(other_session);
9631 
9632 		nua_respond(nh, SIP_202_ACCEPTED, NUTAG_WITH_THIS_MSG(de->data->e_msg),
9633 					TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9634 					TAG_END());
9635 
9636 		return SWITCH_STATUS_SUCCESS;
9637 	}
9638 
9639 	return SWITCH_STATUS_FALSE;
9640 }
9641 
sofia_proxy_sip_i_info(nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,switch_core_session_t * session,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])9642 switch_status_t sofia_proxy_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, switch_core_session_t *session, sip_t const *sip,
9643 								sofia_dispatch_event_t *de, tagi_t tags[])
9644 {
9645 	switch_core_session_t *other_session = NULL;
9646 	const char *session_id_header = sofia_glue_session_id_header(session, profile);
9647 
9648 	if (session && switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
9649 		if (switch_core_session_compare(session, other_session)) {
9650 			private_object_t *other_tech_pvt = NULL;
9651 			const char *ct = NULL;
9652 			char *pl = NULL;
9653 			switch_channel_t *channel = switch_core_session_get_channel(session);
9654 
9655 			if (sip && sip->sip_payload && sip->sip_payload->pl_data) {
9656 				pl = sip->sip_payload->pl_data;
9657 			}
9658 
9659 			other_tech_pvt = (private_object_t *) switch_core_session_get_private(other_session);
9660 
9661 			if (sip && sip->sip_content_type->c_type && sip->sip_content_type->c_subtype) {
9662 				ct = sip->sip_content_type->c_type;
9663 			}
9664 
9665 			if (sip && sip->sip_content_type->c_type && !strncasecmp(sip->sip_content_type->c_type, "application", 11) && !strcasecmp(sip->sip_content_type->c_subtype, "media_control+xml")) {
9666 				if (switch_channel_test_flag(channel, CF_VIDEO)) {
9667 					switch_core_media_gen_key_frame(session);
9668 					switch_channel_set_flag(channel, CF_VIDEO_REFRESH_REQ);
9669 				}
9670 			}
9671 
9672 			nua_info(other_tech_pvt->nh,
9673 					 TAG_IF(ct, SIPTAG_CONTENT_TYPE_STR(su_strdup(other_tech_pvt->nh->nh_home, ct))),
9674 					 TAG_IF(!zstr(other_tech_pvt->user_via), SIPTAG_VIA_STR(other_tech_pvt->user_via)),
9675 					 TAG_IF(pl, SIPTAG_PAYLOAD_STR(su_strdup(other_tech_pvt->nh->nh_home, pl))),
9676 					 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9677 					 TAG_END());
9678 		}
9679 
9680 		switch_core_session_rwunlock(other_session);
9681 
9682 		nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
9683 
9684 		return SWITCH_STATUS_SUCCESS;
9685 	}
9686 
9687 	return SWITCH_STATUS_FALSE;
9688 }
9689 
9690 
sofia_handle_sip_i_info(nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,switch_core_session_t * session,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])9691 void sofia_handle_sip_i_info(nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, switch_core_session_t *session, sip_t const *sip,
9692 								sofia_dispatch_event_t *de, tagi_t tags[])
9693 {
9694 	/* placeholder for string searching */
9695 	const char *signal_ptr;
9696 	const char *rec_header;
9697 	const char *clientcode_header;
9698 	switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0), 0, SWITCH_DTMF_ENDPOINT };
9699 	switch_event_t *event;
9700 	private_object_t *tech_pvt = NULL;
9701 	switch_channel_t *channel = NULL;
9702 	const char *session_id_header = sofia_glue_session_id_header(session, profile);
9703 
9704 	if (session) {
9705 		tech_pvt = (private_object_t *) switch_core_session_get_private(session);
9706 		channel = switch_core_session_get_channel(session);
9707 	}
9708 
9709 	if (sofia_test_pflag(profile, PFLAG_EXTENDED_INFO_PARSING)) {
9710 		if (sip && sip->sip_content_type && sip->sip_content_type->c_type && sip->sip_content_type->c_subtype &&
9711 			sip->sip_payload && sip->sip_payload->pl_data) {
9712 
9713 			if (!strncasecmp(sip->sip_content_type->c_type, "freeswitch", 10)) {
9714 
9715 				if (!strcasecmp(sip->sip_content_type->c_subtype, "session-event")) {
9716 					if (session) {
9717 
9718 						if (create_info_event(sip, nh, &event) == SWITCH_STATUS_SUCCESS) {
9719 							if (switch_core_session_queue_event(session, &event) == SWITCH_STATUS_SUCCESS) {
9720 								switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "queued freeswitch event for INFO\n");
9721 								nua_respond(nh, SIP_200_OK, SIPTAG_CONTENT_TYPE_STR("freeswitch/session-event-response"),
9722 											SIPTAG_PAYLOAD_STR("+OK MESSAGE QUEUED"), NUTAG_WITH_THIS_MSG(de->data->e_msg),
9723 											TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9724 											TAG_END());
9725 							} else {
9726 								switch_event_destroy(&event);
9727 								nua_respond(nh, SIP_200_OK, SIPTAG_CONTENT_TYPE_STR("freeswitch/session-event-response"),
9728 											SIPTAG_PAYLOAD_STR("-ERR MESSAGE NOT QUEUED"), NUTAG_WITH_THIS_MSG(de->data->e_msg),
9729 											TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9730 											TAG_END());
9731 							}
9732 						}
9733 
9734 					} else {
9735 						nua_respond(nh, SIP_200_OK, SIPTAG_CONTENT_TYPE_STR("freeswitch/session-event-response"),
9736 									SIPTAG_PAYLOAD_STR("-ERR INVALID SESSION"), NUTAG_WITH_THIS_MSG(de->data->e_msg),
9737 									TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9738 									TAG_END());
9739 
9740 					}
9741 
9742 					return;
9743 
9744 				} else if (!strcasecmp(sip->sip_content_type->c_subtype, "api-request")) {
9745 					char *cmd = strdup(sip->sip_payload->pl_data);
9746 					char *arg;
9747 					switch_stream_handle_t stream = { 0 };
9748 					switch_status_t status;
9749 
9750 					switch_assert(cmd);
9751 					SWITCH_STANDARD_STREAM(stream);
9752 					switch_assert(stream.data);
9753 
9754 					if ((arg = strchr(cmd, ':'))) {
9755 						*arg++ = '\0';
9756 					}
9757 
9758 					if ((status = switch_api_execute(cmd, arg, NULL, &stream)) == SWITCH_STATUS_SUCCESS) {
9759 						nua_respond(nh, SIP_200_OK, SIPTAG_CONTENT_TYPE_STR("freeswitch/api-response"),
9760 									SIPTAG_PAYLOAD_STR(stream.data), NUTAG_WITH_THIS_MSG(de->data->e_msg),
9761 									TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9762 									TAG_END());
9763 					} else {
9764 
9765 						nua_respond(nh, SIP_200_OK, SIPTAG_CONTENT_TYPE_STR("freeswitch/api-response"),
9766 									SIPTAG_PAYLOAD_STR("-ERR INVALID COMMAND"), NUTAG_WITH_THIS_MSG(de->data->e_msg),
9767 									TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9768 									TAG_END());
9769 					}
9770 
9771 					switch_safe_free(stream.data);
9772 					switch_safe_free(cmd);
9773 					return;
9774 				}
9775 
9776 				nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg),
9777 						TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9778 						TAG_END());
9779 
9780 				return;
9781 			}
9782 		}
9783 	}
9784 
9785 	if (session) {
9786 		const char *vval;
9787 
9788 		/* Barf if we didn't get our private */
9789 		assert(switch_core_session_get_private(session));
9790 
9791 		sofia_glue_set_extra_headers(session, sip, SOFIA_SIP_INFO_HEADER_PREFIX);
9792 		if (!zstr(profile->proxy_info_content_types) && sip && sip->sip_content_type && sip->sip_content_type->c_type && sip->sip_content_type->c_subtype &&
9793 			(!strcasecmp(profile->proxy_info_content_types,"all") || strstr(profile->proxy_info_content_types,sip->sip_content_type->c_type))) {
9794 			switch_core_session_t *other_session;
9795 
9796 			if (switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
9797 				char *pl = NULL;
9798 				char *ct = NULL;
9799 				char *extra_headers = NULL;
9800 				char *unknown = NULL;
9801 				private_object_t *other_tech_pvt = switch_core_session_get_private(other_session);
9802 
9803 				ct = switch_core_session_strdup(other_session, (char*)sip->sip_content_type->c_type);
9804 				if (sip->sip_payload && sip->sip_payload->pl_data) {
9805 					pl = switch_core_session_strdup(other_session,(char*)sip->sip_payload->pl_data);
9806 				}
9807 				unknown = sofia_glue_get_non_extra_unknown_headers(sip);
9808 
9809                                 extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_INFO_HEADER_PREFIX);
9810 
9811 				nua_info(other_tech_pvt->nh,
9812 						SIPTAG_CONTENT_TYPE_STR(ct),
9813 						TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
9814 						TAG_IF(!zstr(unknown), SIPTAG_HEADER_STR(unknown)),
9815 						TAG_IF(!zstr(other_tech_pvt->user_via), SIPTAG_VIA_STR(other_tech_pvt->user_via)),
9816 						TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9817 						TAG_IF(!zstr(pl), SIPTAG_PAYLOAD_STR(pl)),
9818 						TAG_END());
9819 				switch_safe_free(extra_headers);
9820 				switch_safe_free(unknown);
9821 				switch_core_session_rwunlock(other_session);
9822 			}
9823 		}
9824 
9825 		if (sip && sip->sip_content_type && sip->sip_content_type->c_type && !strcasecmp(sip->sip_content_type->c_type, "freeswitch/data")) {
9826 			char *data = NULL;
9827 
9828 			if (sip->sip_payload && sip->sip_payload->pl_data) {
9829 				data = sip->sip_payload->pl_data;
9830 			}
9831 
9832 			if ((vval = switch_channel_get_variable(channel, "sip_copy_custom_headers")) && switch_true(vval)) {
9833 				switch_core_session_t *nsession = NULL;
9834 
9835 				switch_core_session_get_partner(session, &nsession);
9836 
9837 				if (nsession) {
9838 					switch_core_session_message_t *msg;
9839 
9840 					switch_ivr_transfer_variable(session, nsession, SOFIA_SIP_INFO_HEADER_PREFIX_T);
9841 					msg = switch_core_session_alloc(nsession, sizeof(*msg));
9842 					MESSAGE_STAMP_FFL(msg);
9843 					msg->message_id = SWITCH_MESSAGE_INDICATE_INFO;
9844 
9845 					msg->string_array_arg[2] = switch_core_session_strdup(nsession, data);
9846 
9847 					msg->from = __FILE__;
9848 					switch_core_session_queue_message(nsession, msg);
9849 
9850 					switch_core_session_rwunlock(nsession);
9851 				}
9852 			}
9853 		}
9854 
9855 		if (sip && sip->sip_content_type && sip->sip_content_type->c_subtype && sip->sip_content_type->c_type &&
9856 			!strncasecmp(sip->sip_content_type->c_type, "message", 7) &&
9857 			!strcasecmp(sip->sip_content_type->c_subtype, "update_display")) {
9858 			sofia_update_callee_id(session, profile, sip, SWITCH_TRUE);
9859 			goto end;
9860 		}
9861 
9862 		if (sip && sip->sip_content_type && sip->sip_content_type->c_type && sip->sip_content_type->c_subtype &&
9863 			sip->sip_payload && sip->sip_payload->pl_data) {
9864 			if (!strncasecmp(sip->sip_content_type->c_type, "application", 11) && !strcasecmp(sip->sip_content_type->c_subtype, "media_control+xml")) {
9865 
9866 				if (switch_channel_test_flag(channel, CF_VIDEO)) {
9867 					switch_core_media_gen_key_frame(session);
9868 					switch_channel_set_flag(channel, CF_VIDEO_REFRESH_REQ);
9869 				}
9870 
9871 			} else if (!strncasecmp(sip->sip_content_type->c_type, "application", 11) &&
9872 					   !strcasecmp(sip->sip_content_type->c_subtype, "vnd.nortelnetworks.digits")) {
9873 				int tmp;
9874 				if ((signal_ptr = switch_stristr("d=", sip->sip_payload->pl_data))) {
9875 					signal_ptr = signal_ptr + 2;
9876 
9877 					while (*signal_ptr && *signal_ptr == ' ') {
9878 						signal_ptr++;
9879 					}
9880 
9881 					if (*signal_ptr	&& (*signal_ptr == '*' || *signal_ptr == '#' || *signal_ptr == 'A' || *signal_ptr == 'B'
9882 										|| *signal_ptr == 'C' || *signal_ptr == 'D')) {
9883 						dtmf.digit = *signal_ptr;
9884 					} else {
9885 						tmp = atoi(signal_ptr);
9886 						dtmf.digit = switch_rfc2833_to_char(tmp);
9887 					}
9888 
9889 					dtmf.duration = 100;
9890 				} else {
9891 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Bad signal\n");
9892 					goto end;
9893 				}
9894 			} else if (!strncasecmp(sip->sip_content_type->c_type, "application", 11) && !strcasecmp(sip->sip_content_type->c_subtype, "dtmf-relay")) {
9895 				/* Try and find signal information in the payload */
9896 				if ((signal_ptr = switch_stristr("Signal=", sip->sip_payload->pl_data))) {
9897 					int tmp;
9898 					/* move signal_ptr where we need it (right past Signal=) */
9899 					signal_ptr = signal_ptr + 7;
9900 
9901 					/* handle broken devices with spaces after the = (cough) VegaStream (cough) */
9902 					while (*signal_ptr && *signal_ptr == ' ')
9903 						signal_ptr++;
9904 
9905 					if (*signal_ptr
9906 						&& (*signal_ptr == '*' || *signal_ptr == '#' || *signal_ptr == 'A' || *signal_ptr == 'B' || *signal_ptr == 'C'
9907 							|| *signal_ptr == 'D')) {
9908 						dtmf.digit = *signal_ptr;
9909 					} else {
9910 						tmp = atoi(signal_ptr);
9911 						dtmf.digit = switch_rfc2833_to_char(tmp);
9912 					}
9913 				} else {
9914 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Bad signal\n");
9915 					goto end;
9916 				}
9917 
9918 				if ((signal_ptr = switch_stristr("Duration=", sip->sip_payload->pl_data))) {
9919 					int tmp;
9920 					signal_ptr += 9;
9921 
9922 					/* handle broken devices with spaces after the = (cough) VegaStream (cough) */
9923 					while (*signal_ptr && *signal_ptr == ' ')
9924 						signal_ptr++;
9925 
9926 					if ((tmp = atoi(signal_ptr)) <= 0) {
9927 						tmp = switch_core_default_dtmf_duration(0);
9928 					}
9929 					dtmf.duration = tmp * 8;
9930 				}
9931 			} else if (!strncasecmp(sip->sip_content_type->c_type, "application", 11) && !strcasecmp(sip->sip_content_type->c_subtype, "dtmf")) {
9932 				int tmp = atoi(sip->sip_payload->pl_data);
9933 				dtmf.digit = switch_rfc2833_to_char(tmp);
9934 			}
9935 
9936 			if (dtmf.digit) {
9937 				if (tech_pvt->mparams.dtmf_type == DTMF_INFO ||
9938 						sofia_test_pflag(tech_pvt->profile, PFLAG_LIBERAL_DTMF) || switch_channel_test_flag(tech_pvt->channel, CF_LIBERAL_DTMF)) {
9939 					/* queue it up */
9940 					switch_channel_queue_dtmf(channel, &dtmf);
9941 
9942 					/* print debug info */
9943 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "INFO DTMF(%c)\n", dtmf.digit);
9944 
9945 					if (switch_channel_test_flag(channel, CF_PROXY_MODE)) {
9946 						const char *uuid;
9947 						switch_core_session_t *session_b;
9948 
9949 						if ((uuid = switch_channel_get_partner_uuid(channel)) && (session_b = switch_core_session_locate(uuid))) {
9950 							while (switch_channel_has_dtmf(channel)) {
9951 								switch_dtmf_t idtmf = { 0, 0 };
9952 								if (switch_channel_dequeue_dtmf(channel, &idtmf) == SWITCH_STATUS_SUCCESS) {
9953 									switch_core_session_send_dtmf(session_b, &idtmf);
9954 								}
9955 							}
9956 
9957 							switch_core_session_rwunlock(session_b);
9958 						}
9959 					}
9960 
9961 					/* Send 200 OK response */
9962 					nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg),
9963 							TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9964 							TAG_END());
9965 				} else {
9966 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
9967 									  "IGNORE INFO DTMF(%c) (This channel was not configured to use INFO DTMF!)\n", dtmf.digit);
9968 				}
9969 				goto end;
9970 			}
9971 		}
9972 
9973 		if ((clientcode_header = sofia_glue_get_unknown_header(sip, "x-clientcode"))) {
9974 			if (!zstr(clientcode_header)) {
9975 				switch_channel_set_variable(channel, "call_clientcode", clientcode_header);
9976 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Setting CMC to %s\n", clientcode_header);
9977 				nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg),
9978 						TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9979 						TAG_END());
9980 			}
9981 			goto end;
9982 		}
9983 
9984 		if ((rec_header = sofia_glue_get_unknown_header(sip, "record"))) {
9985 			if (zstr(profile->record_template)) {
9986 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Record attempted but no template defined.\n");
9987 				nua_respond(nh, 488, "Recording not enabled", NUTAG_WITH_THIS_MSG(de->data->e_msg),
9988 						TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
9989 						TAG_END());
9990 			} else {
9991 				if (!strcasecmp(rec_header, "on")) {
9992 					char *file = NULL, *tmp = NULL;
9993 
9994 					if (switch_true(switch_channel_get_variable(channel, "sip_disable_recording"))) {
9995 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Record attempted but is disabled by sip_disable_recording variable.\n");
9996 						nua_respond(nh, 488, "Recording disabled for this channel", NUTAG_WITH_THIS_MSG(de->data->e_msg),
9997 								TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
9998 					} else {
9999 
10000 						tmp = switch_mprintf("%s%s%s", profile->record_path ? profile->record_path : "${recordings_dir}",
10001 								SWITCH_PATH_SEPARATOR, profile->record_template);
10002 						file = switch_channel_expand_variables(channel, tmp);
10003 						switch_ivr_record_session(session, file, 0, NULL);
10004 						switch_channel_set_variable(channel, "sofia_record_file", file);
10005 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Recording %s to %s\n", switch_channel_get_name(channel),
10006 								file);
10007 						switch_safe_free(tmp);
10008 						nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg),
10009 								TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
10010 								TAG_END());
10011 						if (file != profile->record_template) {
10012 							free(file);
10013 							file = NULL;
10014 						}
10015 					}
10016 				} else {
10017 					const char *file;
10018 
10019 					if ((file = switch_channel_get_variable(channel, "sofia_record_file"))) {
10020 						switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Done recording %s to %s\n",
10021 										  switch_channel_get_name(channel), file);
10022 						switch_ivr_stop_record_session(session, file);
10023 						nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg),
10024 								TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
10025 								TAG_END());
10026 					} else {
10027 						nua_respond(nh, 488, "Nothing to stop", NUTAG_WITH_THIS_MSG(de->data->e_msg),
10028 								TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
10029 								TAG_END());
10030 					}
10031 				}
10032 			}
10033 		}
10034 	}
10035 
10036   end:
10037 
10038 	if (create_info_event(sip, nh, &event) == SWITCH_STATUS_SUCCESS) {
10039 		if (channel) {
10040 			switch_channel_event_set_data(channel, event);
10041 		}
10042 		switch_event_fire(&event);
10043 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "dispatched freeswitch event for INFO\n");
10044 	}
10045 
10046 	nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg),
10047 			TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
10048 			TAG_END());
10049 
10050 	return;
10051 
10052 }
10053 
sofia_handle_sip_i_reinvite(switch_core_session_t * session,nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,sofia_private_t * sofia_private,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])10054 void sofia_handle_sip_i_reinvite(switch_core_session_t *session,
10055 								 nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
10056 								sofia_dispatch_event_t *de,
10057 								 tagi_t tags[])
10058 {
10059 	char *call_info = NULL;
10060 	switch_channel_t *channel = NULL;
10061 	private_object_t *tech_pvt = NULL;
10062 
10063 	nua_respond(nh, SIP_100_TRYING, TAG_END());
10064 
10065 	if (session) {
10066 		channel = switch_core_session_get_channel(session);
10067 		tech_pvt = switch_core_session_get_private(session);
10068 
10069 
10070 		if (sip && sip->sip_payload && sip->sip_payload->pl_data) {
10071 			tech_pvt->mparams.last_sdp_str = switch_core_session_strdup(session, sip->sip_payload->pl_data);
10072 		}
10073 	}
10074 
10075 	if (session && profile && sip && sofia_test_pflag(profile, PFLAG_TRACK_CALLS)) {
10076 		switch_channel_t *channel = switch_core_session_get_channel(session);
10077 		private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session);
10078 		char network_ip[80];
10079 		int network_port = 0;
10080 		char via_space[2048];
10081 		char branch[16] = "";
10082 
10083 		sofia_glue_store_session_id(session, profile, sip, 0);
10084 
10085 		sofia_clear_flag(tech_pvt, TFLAG_GOT_ACK);
10086 
10087 		sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
10088 		switch_stun_random_string(branch, sizeof(branch) - 1, "0123456789abcdef");
10089 
10090 		switch_snprintf(via_space, sizeof(via_space), "SIP/2.0/UDP %s;rport=%d;branch=%s", network_ip, network_port, branch);
10091 		switch_channel_set_variable(channel, "sip_full_via", via_space);
10092 		switch_channel_set_variable_printf(channel, "sip_network_port", "%d", network_port);
10093 		switch_channel_set_variable_printf(channel, "sip_recieved_port", "%d", network_port);
10094 		switch_channel_set_variable_printf(channel, "sip_via_rport", "%d", network_port);
10095 
10096 		switch_core_recovery_track(session);
10097 	}
10098 
10099 	if (profile && sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
10100 		if (channel && sip && sip->sip_call_info) {
10101 			char *p;
10102 			if ((call_info = sip_header_as_string(nua_handle_home(nh), (void *) sip->sip_call_info))) {
10103 				if (switch_stristr("appearance", call_info)) {
10104 					switch_channel_set_variable(channel, "presence_call_info_full", call_info);
10105 					if ((p = strchr(call_info, ';'))) {
10106 						switch_channel_set_variable(channel, "presence_call_info", p + 1);
10107 					}
10108 				}
10109 				su_free(nua_handle_home(nh), call_info);
10110 			}
10111 		}
10112 	}
10113 
10114 	if (channel) {
10115 		if (tech_pvt->mparams.last_sdp_str) {
10116 			tech_pvt->mparams.prev_sdp_str = tech_pvt->mparams.last_sdp_str;
10117 		}
10118 		tech_pvt->mparams.last_sdp_str = NULL;
10119 
10120 		if (sip && sip->sip_payload && sip->sip_payload->pl_data) {
10121 			if (!zstr(tech_pvt->mparams.prev_sdp_str) && strcmp(tech_pvt->mparams.prev_sdp_str, sip->sip_payload->pl_data)) {
10122 				switch_channel_set_variable(channel, "sip_reinvite_sdp", sip->sip_payload->pl_data);
10123 				tech_pvt->mparams.last_sdp_str = switch_core_session_strdup(session, sip->sip_payload->pl_data);
10124 			} else {
10125 				tech_pvt->mparams.last_sdp_str = tech_pvt->mparams.prev_sdp_str;
10126 			}
10127 		}
10128 
10129 		switch_channel_execute_on(channel, "execute_on_sip_reinvite");
10130 	}
10131 
10132 }
10133 
sofia_locate_user(char * user,switch_core_session_t * session,sip_t const * sip,switch_xml_t * x_user)10134 switch_status_t sofia_locate_user(char* user, switch_core_session_t *session, sip_t const *sip, switch_xml_t* x_user)
10135 {
10136 	char *username, *domain;
10137 	switch_event_t *v_event = NULL;
10138 	switch_status_t result = SWITCH_STATUS_FALSE;
10139 
10140 	if (!session) {
10141 		return SWITCH_STATUS_FALSE;
10142 	}
10143 
10144 	if (zstr(user)) {
10145 		return SWITCH_STATUS_FALSE;
10146 	}
10147 
10148 	if (!(username = switch_core_session_strdup(session, user))) {
10149 		return SWITCH_STATUS_FALSE;
10150 	}
10151 
10152 	if (!(domain = strchr(username, '@'))) {
10153 		return SWITCH_STATUS_FALSE;
10154 	}
10155 
10156 	*domain++ = '\0';
10157 
10158 	if (switch_event_create(&v_event, SWITCH_EVENT_REQUEST_PARAMS) == SWITCH_STATUS_SUCCESS) {
10159 		sip_unknown_t *un;
10160 		for (un = sip->sip_unknown; un; un = un->un_next) {
10161 			switch_event_add_header_string(v_event, SWITCH_STACK_BOTTOM, un->un_name, un->un_value);
10162 		};
10163 		switch_channel_event_set_data(switch_core_session_get_channel(session), v_event);
10164 	}
10165 
10166 	result = switch_xml_locate_user_merged("id", username, domain, NULL, x_user, v_event);
10167 
10168 	if (v_event) {
10169 		switch_event_destroy(&v_event);
10170 	}
10171 
10172 	return result;
10173 }
10174 
sofia_handle_sip_i_invite(switch_core_session_t * session,nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,sofia_private_t * sofia_private,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])10175 void sofia_handle_sip_i_invite(switch_core_session_t *session, nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip, sofia_dispatch_event_t *de, tagi_t tags[])
10176 {
10177 	char key[128] = "";
10178 	sip_unknown_t *un;
10179 	sip_remote_party_id_t *rpid = NULL;
10180 	sip_p_asserted_identity_t *passerted = NULL;
10181 	sip_p_preferred_identity_t *ppreferred = NULL;
10182 	sip_privacy_t *privacy = NULL;
10183 	sip_alert_info_t *alert_info = NULL;
10184 	sip_call_info_t *call_info = NULL;
10185 	private_object_t *tech_pvt = NULL;
10186 	switch_channel_t *channel = NULL;
10187 	//const char *channel_name = NULL;
10188 	const char *displayname = NULL;
10189 	const char *destination_number = NULL;
10190 	const char *from_user = NULL, *from_host = NULL;
10191 	const char *referred_by_user = NULL;//, *referred_by_host = NULL;
10192 	const char *context = NULL;
10193 	const char *dialplan = NULL;
10194 	char network_ip[80];
10195 	char proxied_client_ip[80];
10196 	switch_event_t *v_event = NULL;
10197 	switch_xml_t x_user = NULL;
10198 	uint32_t sess_count = switch_core_session_count();
10199 	uint32_t sess_max = switch_core_session_limit(0);
10200 	int is_auth = 0, calling_myself = 0;
10201 	int network_port = 0;
10202 	char *is_nat = NULL;
10203 	char *aniii = NULL;
10204 	char acl_token[512] = "";
10205 	sofia_transport_t transport;
10206 	const char *gw_name = NULL;
10207 	const char *gw_param_name = NULL;
10208 	char *call_info_str = NULL;
10209 	nua_handle_t *bnh = NULL;
10210 	char sip_acl_authed_by[512] = "";
10211 	char sip_acl_token[512] = "";
10212 	const char *dialog_from_user = "", *dialog_from_host = "", *to_user = "", *to_host = "", *contact_user = "", *contact_host = "";
10213 	const char *user_agent = "", *call_id = "";
10214 	url_t *from = NULL, *to = NULL, *contact = NULL;
10215 	const char *to_tag = "";
10216 	const char *from_tag = "";
10217 	char *sql = NULL;
10218 	char *acl_context = NULL;
10219 	const char *r_sdp = NULL;
10220 	int is_tcp = 0, is_tls = 0;
10221 	const char *uparams = NULL;
10222 	char *name_params = NULL;
10223 	const char *req_uri = NULL;
10224 	char *req_user = NULL;
10225 	switch_time_t sip_invite_time;
10226 	const char *session_id_header;
10227 
10228 	sofia_glue_store_session_id(session, profile, sip, 0);
10229 	session_id_header = sofia_glue_session_id_header(session, profile);
10230 
10231 	if (sip && sip->sip_contact && sip->sip_contact->m_url->url_params) {
10232 		uparams = sip->sip_contact->m_url->url_params;
10233 	} else {
10234 		uparams = NULL;
10235 	}
10236 
10237 
10238 	if (uparams) {
10239 		if (switch_stristr("transport=tcp", uparams)) {
10240 			is_tcp = 1;
10241 		} else if (switch_stristr("transport=tls", uparams)) {
10242 			is_tls = 1;
10243 		}
10244 	}
10245 
10246 	profile->ib_calls++;
10247 
10248 	if (sip && sip->sip_payload && sip->sip_payload->pl_data) {
10249 		r_sdp = sip->sip_payload->pl_data;
10250 	}
10251 
10252 	if (!session || (sess_count >= sess_max || !sofia_test_pflag(profile, PFLAG_RUNNING))) {
10253 		nua_respond(nh, 503, "Maximum Calls In Progress", SIPTAG_RETRY_AFTER_STR("300"),
10254 					TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
10255 		goto fail;
10256 	}
10257 
10258 	tech_pvt = switch_core_session_get_private(session);
10259 
10260 	sip_invite_time = switch_micro_time_now();
10261 
10262 	if (!sip || !sip->sip_request || !sip->sip_request->rq_method_name) {
10263 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received an invalid packet!\n");
10264 		nua_respond(nh, SIP_503_SERVICE_UNAVAILABLE,
10265 					TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
10266 		goto fail;
10267 	}
10268 
10269 	if (!(sip->sip_contact)) {
10270 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NO CONTACT!\n");
10271 		nua_respond(nh, 400, "Missing Contact Header",
10272 					TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
10273 		goto fail;
10274 	}
10275 
10276 
10277 	sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port);
10278 
10279 	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "%s receiving invite from %s:%d version: %s\n",
10280 					  switch_channel_get_name(tech_pvt->channel), network_ip, network_port, switch_version_full_human());
10281 
10282 
10283 	if (sip->sip_via && sip->sip_via->v_protocol && switch_stristr("sip/2.0/ws", sip->sip_via->v_protocol)) {
10284 		is_nat = "websockets";
10285 	}
10286 
10287 
10288 	if (r_sdp) {
10289 		switch_core_media_set_sdp_codec_string(session, r_sdp, SDP_TYPE_REQUEST);
10290 	}
10291 
10292 
10293 	if (sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION) ||
10294 		(sofia_test_pflag(profile, PFLAG_TLS_ALWAYS_NAT) && (is_tcp || is_tls)) ||
10295 		(!is_tcp && !is_tls && (zstr(network_ip) || !switch_check_network_list_ip(network_ip, profile->local_network)) &&
10296 		 profile->server_rport_level >= 2 && sip->sip_user_agent &&
10297 		 sip->sip_user_agent->g_string &&
10298 		 (!strncasecmp(sip->sip_user_agent->g_string, "Polycom", 7) || !strncasecmp(sip->sip_user_agent->g_string, "KIRK Wireless Server", 20)))
10299 		) {
10300 		if (sip->sip_via) {
10301 			const char *port = sip->sip_via->v_port;
10302 			const char *host = sip->sip_via->v_host;
10303 
10304 			if (host && sip->sip_via->v_received) {
10305 				is_nat = "via received";
10306 			} else if (host && strcmp(network_ip, host)) {
10307 				is_nat = "via host";
10308 			} else if (port && atoi(port) != network_port) {
10309 				is_nat = "via port";
10310 			}
10311 		}
10312 	}
10313 
10314 	if (!is_nat && profile->nat_acl_count) {
10315 		uint32_t x = 0;
10316 		int contact_private_ip = 1;
10317 		int network_private_ip = 0;
10318 		char *last_acl = NULL;
10319 		const char *contact_host = NULL;
10320 
10321 		if (sip->sip_via && sip->sip_via->v_host) {
10322 			contact_host = sip->sip_via->v_host;
10323 		} else if (sip->sip_contact) {
10324 			contact_host = sip->sip_contact->m_url->url_host;
10325 		}
10326 
10327 		if (!zstr(contact_host)) {
10328 			/* NAT mode double check logic and examples.
10329 
10330 			   Example 1: the contact_host is 192.168.1.100 and the network_ip is also 192.168.1.100 the end point
10331 			   is most likely behind nat with us so we need to veto that decision to turn on nat processing.
10332 
10333 			   Example 2: the contact_host is 192.168.1.100 and the network_ip is 192.0.2.100 which is a public internet ip
10334 			   the remote endpoint is likely behind a remote nat traversing the public internet.
10335 
10336 			   This secondary check is here to double check the conclusion of nat settigs to ensure we don't set net
10337 			   in cases where we don't really need to be doing this.
10338 
10339 			   Why would you want to do this?  Well if your FreeSWITCH is behind nat and you want to talk to endpoints behind
10340 			   remote NAT over the public internet in addition to endpoints behind nat with you.  This simplifies that process.
10341 
10342 			*/
10343 
10344 			for (x = 0; x < profile->nat_acl_count; x++) {
10345 				last_acl = profile->nat_acl[x];
10346 				if ((contact_private_ip = switch_check_network_list_ip(contact_host, last_acl))) {
10347 					break;
10348 				}
10349 			}
10350 			if (contact_private_ip) {
10351 				for (x = 0; x < profile->nat_acl_count; x++) {
10352 					if ((network_private_ip = switch_check_network_list_ip(network_ip, profile->nat_acl[x]))) {
10353 						break;
10354 					}
10355 				}
10356 			}
10357 
10358 			if (contact_private_ip && !network_private_ip) {
10359 				is_nat = last_acl;
10360 			}
10361 		}
10362 	}
10363 
10364 	if (profile->acl_count) {
10365 		uint32_t x = 0;
10366 		int ok = 1;
10367 		char *last_acl = NULL;
10368 		const char *token = NULL;
10369 		int acl_port = sofia_test_pflag(profile, PFLAG_USE_PORT_FOR_ACL_CHECK) ? network_port : 0;
10370 
10371 		for (x = 0; x < profile->acl_count; x++) {
10372 			last_acl = profile->acl[x];
10373 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "verifying acl \"%s\" for ip/port %s:%i.\n",
10374 							  switch_str_nil(last_acl), network_ip, acl_port);
10375 			if ((ok = switch_check_network_list_ip_port_token(network_ip, acl_port, last_acl, &token))) {
10376 
10377 				if (profile->acl_pass_context[x]) {
10378 					acl_context = profile->acl_pass_context[x];
10379 				}
10380 				if(!token && profile->acl_inbound_x_token_header) {
10381 					const char * x_auth_token = sofia_glue_get_unknown_header(sip, profile->acl_inbound_x_token_header);
10382 					if (!zstr(x_auth_token)) {
10383 						token = x_auth_token;
10384 					}
10385 				}
10386 
10387 				break;
10388 			}
10389 
10390 			if (profile->acl_fail_context[x]) {
10391 				acl_context = profile->acl_fail_context[x];
10392 			} else {
10393 				acl_context = NULL;
10394 			}
10395 		}
10396 
10397 		if (ok) {
10398 			if (token) {
10399 				switch_set_string(acl_token, token);
10400 			}
10401 			if (sofia_test_pflag(profile, PFLAG_AUTH_CALLS)) {
10402 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IP %s Approved by acl \"%s[%s]\". Access Granted.\n",
10403 								  network_ip, switch_str_nil(last_acl), acl_token);
10404 				switch_set_string(sip_acl_authed_by, last_acl);
10405 				switch_set_string(sip_acl_token, acl_token);
10406 				is_auth = 1;
10407 			}
10408 		} else {
10409 			int network_ip_is_proxy = 0;
10410 			const char* x_auth_ip = network_ip;
10411 			/* Check if network_ip is a proxy allowed to send us calls */
10412 			if (profile->proxy_acl_count) {
10413 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%d acls to check for proxy\n", profile->proxy_acl_count);
10414 				for (x = 0; x < profile->proxy_acl_count; x++) {
10415 					last_acl = profile->proxy_acl[x];
10416 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "checking %s against acl %s\n", network_ip, last_acl);
10417 					if (switch_check_network_list_ip_port_token(network_ip, network_port, last_acl, &token)) {
10418 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s is a proxy according to the %s acl\n", network_ip, last_acl);
10419 						network_ip_is_proxy = 1;
10420 						break;
10421 					}
10422 				}
10423 			}
10424 
10425 			/*
10426 			 * if network_ip is a proxy allowed to send calls, check for auth
10427 			 * ip header and see if it matches against the inbound acl
10428 			 */
10429 			if (network_ip_is_proxy) {
10430 				const char * x_auth_port = sofia_glue_get_unknown_header(sip, "X-AUTH-PORT");
10431 				int x_auth_port_i = sofia_test_pflag(profile, PFLAG_USE_PORT_FOR_ACL_CHECK) ? zstr(x_auth_port) ? 0 : atoi(x_auth_port) : 0;
10432 
10433 				/*
10434 				 * if network_ip is a proxy allowed to send calls,
10435 				 * authorize call if proxy provided matched token header
10436 				 */
10437 				if (profile->acl_proxy_x_token_header) {
10438 					const char * x_auth_token = sofia_glue_get_unknown_header(sip, profile->acl_proxy_x_token_header);
10439 					if (!zstr(x_auth_token)) {
10440 						token = x_auth_token;
10441 						switch_copy_string(proxied_client_ip, x_auth_ip, sizeof(proxied_client_ip));
10442 						ok = 1;
10443 					}
10444 				}
10445 
10446 				if (!ok && (x_auth_ip = sofia_glue_get_unknown_header(sip, "X-AUTH-IP")) && !zstr(x_auth_ip)) {
10447 					for (x = 0; x < profile->acl_count; x++) {
10448 						last_acl = profile->acl[x];
10449 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "verifying acl \"%s\" from proxy for ip/port %s:%i.\n",
10450 										  switch_str_nil(last_acl), x_auth_ip, x_auth_port_i);
10451 						if ((ok = switch_check_network_list_ip_port_token(x_auth_ip, x_auth_port_i, last_acl, &token))) {
10452 
10453 							switch_copy_string(proxied_client_ip, x_auth_ip, sizeof(proxied_client_ip));
10454 
10455 							if (profile->acl_pass_context[x]) {
10456 								acl_context = profile->acl_pass_context[x];
10457 							}
10458 
10459 							break;
10460 						}
10461 
10462 						if (profile->acl_fail_context[x]) {
10463 							acl_context = profile->acl_fail_context[x];
10464 						} else {
10465 							acl_context = NULL;
10466 						}
10467 					}
10468 				} else {
10469 					x_auth_ip = network_ip;
10470 				}
10471 			}
10472 
10473 			if (ok) {
10474 				if (token) {
10475 					switch_set_string(acl_token, token);
10476 				}
10477 				if (sofia_test_pflag(profile, PFLAG_AUTH_CALLS)) {
10478 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IP %s Approved by acl \"%s[%s]\". Access Granted.\n",
10479 					                  x_auth_ip, switch_str_nil(last_acl), acl_token);
10480 					switch_set_string(sip_acl_authed_by, last_acl);
10481 					switch_set_string(sip_acl_token, acl_token);
10482 					is_auth = 1;
10483 				}
10484 			} else {
10485 				if (!sofia_test_pflag(profile, PFLAG_AUTH_CALLS)) {
10486 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "IP %s Rejected by acl \"%s\"\n", x_auth_ip, switch_str_nil(last_acl));
10487 					if (!acl_context) {
10488 						nua_respond(nh, SIP_403_FORBIDDEN,
10489 									TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
10490 						goto fail;
10491 					} else {
10492 						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IP %s Rejected by acl \"%s\". Falling back to Digest auth.\n",
10493 										  x_auth_ip, switch_str_nil(last_acl));
10494 					}
10495 				}
10496 			}
10497 		}
10498 	}
10499 
10500 
10501 	if (!is_auth && sofia_test_pflag(profile, PFLAG_AUTH_CALLS) && sofia_test_pflag(profile, PFLAG_AUTH_CALLS_ACL_ONLY)) {
10502 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IP/Port %s %i Rejected by acls and auth-calls-acl-only flag is set, rejecting call\n",
10503 						  network_ip, network_port);
10504 		nua_respond(nh, SIP_403_FORBIDDEN,
10505 					TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)), TAG_END());
10506 		goto fail;
10507 	}
10508 
10509 	if (!is_auth && sofia_test_pflag(profile, PFLAG_AUTH_CALLS) && sofia_test_pflag(profile, PFLAG_BLIND_AUTH)) {
10510 		char *user = NULL;
10511 		switch_status_t blind_result = SWITCH_STATUS_FALSE;
10512 
10513 		if (!strcmp(network_ip, profile->sipip) && network_port == profile->sip_port) {
10514 			calling_myself++;
10515 		}
10516 
10517 		if (sip->sip_from) {
10518 			user = switch_core_session_sprintf(session, "%s@%s", sip->sip_from->a_url->url_user, sip->sip_from->a_url->url_host);
10519 			blind_result = sofia_locate_user(user, session, sip, &x_user);
10520 		}
10521 		if (!sofia_test_pflag(profile, PFLAG_BLIND_AUTH_ENFORCE_RESULT) || blind_result == SWITCH_STATUS_SUCCESS) {
10522 			is_auth++;
10523 		} else if (sofia_test_pflag(profile, PFLAG_BLIND_AUTH_REPLY_403)) {
10524 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "blind auth enforce 403 enabled and couldn't find user %s, rejecting call\n", user);
10525 			nua_respond(nh, SIP_403_FORBIDDEN, TAG_END());
10526 			goto fail;
10527 		}
10528 	}
10529 
10530 
10531 	tech_pvt->from_user = switch_core_session_strdup(session, sip->sip_from->a_url->url_user);
10532 	tech_pvt->mparams.remote_ip = switch_core_session_strdup(session, network_ip);
10533 	tech_pvt->mparams.remote_port = network_port;
10534 
10535 	if (!is_auth &&
10536 		(sofia_test_pflag(profile, PFLAG_AUTH_CALLS)
10537 		 || (!sofia_test_pflag(profile, PFLAG_BLIND_AUTH) && (sip->sip_proxy_authorization || sip->sip_authorization)))) {
10538 		if (!strcmp(network_ip, profile->sipip) && network_port == profile->sip_port) {
10539 			calling_myself++;
10540 		} else {
10541 			switch_event_create(&v_event, SWITCH_EVENT_REQUEST_PARAMS);
10542 
10543 			if (sofia_reg_handle_register(nua, profile, nh, sip, de, REG_INVITE, key, sizeof(key), &v_event, NULL, NULL, &x_user)) {
10544 				if (v_event) {
10545 					switch_event_destroy(&v_event);
10546 				}
10547 				if (x_user) {
10548 					switch_xml_free(x_user);
10549 				}
10550 
10551 				if (sip->sip_authorization || sip->sip_proxy_authorization) {
10552 					goto fail;
10553 				}
10554 
10555 				return;
10556 			}
10557 		}
10558 		is_auth++;
10559 	}
10560 
10561 	channel = tech_pvt->channel = switch_core_session_get_channel(session);
10562 
10563 	switch_channel_set_variable_printf(channel, "sip_local_network_addr", "%s", profile->extsipip ? profile->extsipip : profile->sipip);
10564 	switch_channel_set_variable_printf(channel, "sip_network_ip", "%s", network_ip);
10565 	switch_channel_set_variable_printf(channel, "sip_network_port", "%d", network_port);
10566 	switch_channel_set_variable_printf(channel, "sip_invite_stamp", "%" SWITCH_TIME_T_FMT, sip_invite_time);
10567 
10568 	if (*acl_token) {
10569 		if (x_user) {
10570 			switch_xml_free(x_user);
10571 			x_user = NULL;
10572 		}
10573 		switch_channel_set_variable(channel, "acl_token", acl_token);
10574 		if (sofia_locate_user(acl_token, session, sip, &x_user) == SWITCH_STATUS_SUCCESS) {
10575 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Authenticating user %s\n", acl_token);
10576 		} else {
10577 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Error Authenticating user %s\n", acl_token);
10578 			if (sofia_test_pflag(profile, PFLAG_AUTH_REQUIRE_USER)) {
10579 				nua_respond(nh, SIP_480_TEMPORARILY_UNAVAILABLE, TAG_END());
10580 				if (v_event) {
10581 					switch_event_destroy(&v_event);
10582 				}
10583 				goto fail;
10584 			}
10585 		}
10586 	}
10587 
10588 	if (sip->sip_via) {
10589 		char tmp[35] = "";
10590 		const char *ipv6 = strchr(tech_pvt->mparams.remote_ip, ':');
10591 
10592 		transport = sofia_glue_via2transport(sip->sip_via);
10593 
10594 
10595 		tech_pvt->record_route =
10596 			switch_core_session_sprintf(session,
10597 										"sip:%s%s%s:%d;transport=%s",
10598 										ipv6 ? "[" : "", tech_pvt->mparams.remote_ip, ipv6 ? "]" : "",
10599 										tech_pvt->mparams.remote_port, sofia_glue_transport2str(transport));
10600 
10601 		switch_channel_set_variable(channel, "sip_received_ip", tech_pvt->mparams.remote_ip);
10602 		snprintf(tmp, sizeof(tmp), "%d", tech_pvt->mparams.remote_port);
10603 		switch_channel_set_variable(channel, "sip_received_port", tmp);
10604 		switch_channel_set_variable(channel, "sip_via_protocol", sofia_glue_transport2str(sofia_glue_via2transport(sip->sip_via)));
10605 	}
10606 
10607 	if (*key != '\0') {
10608 		tech_pvt->key = switch_core_session_strdup(session, key);
10609 	}
10610 
10611 
10612 	if (is_auth) {
10613 		switch_channel_set_variable(channel, "sip_authorized", "true");
10614 
10615 		if (!zstr(sip_acl_authed_by)) {
10616 			switch_channel_set_variable(channel, "sip_acl_authed_by", sip_acl_authed_by);
10617 		}
10618 
10619 		if (!zstr(sip_acl_token)) {
10620 			switch_channel_set_variable(channel, "sip_acl_token", sip_acl_token);
10621 		}
10622 
10623 	}
10624 
10625 	if (calling_myself) {
10626 		switch_channel_set_variable(channel, "sip_looped_call", "true");
10627 	}
10628 
10629 	tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
10630 														 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, MODNAME, NULL, NULL);
10631 	switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
10632 
10633 	if (x_user) {
10634 		const char *ruser = NULL, *rdomain = NULL, *user = switch_xml_attr(x_user, "id"), *domain = switch_xml_attr(x_user, "domain-name");
10635 
10636 		if (v_event) {
10637 			switch_event_header_t *hp;
10638 
10639 			for (hp = v_event->headers; hp; hp = hp->next) {
10640 				switch_channel_set_variable(channel, hp->name, hp->value);
10641 			}
10642 
10643 			ruser = switch_event_get_header(v_event, "user_name");
10644 			rdomain = switch_event_get_header(v_event, "domain_name");
10645 
10646 			switch_channel_set_variable(channel, "requested_user_name", ruser);
10647 			switch_channel_set_variable(channel, "requested_domain_name", rdomain);
10648 		}
10649 
10650 		if (!user) user = ruser;
10651 		if (!domain) domain = rdomain;
10652 
10653 		switch_ivr_set_user_xml(session, NULL, user, domain, x_user);
10654 		switch_xml_free(x_user);
10655 		x_user = NULL;
10656 	}
10657 
10658 	if (v_event) {
10659 		switch_event_destroy(&v_event);
10660 	}
10661 
10662 	if (sip->sip_from) {
10663 		from_user = sip->sip_from->a_url->url_user;
10664 		from_host = sip->sip_from->a_url->url_host;
10665 		//channel_name = url_set_chanvars(session, sip->sip_from->a_url, sip_from);
10666 
10667 		if (sip->sip_from->a_url->url_params) {
10668 			aniii = switch_find_parameter(sip->sip_from->a_url->url_params, "isup-oli", switch_core_session_get_pool(session));
10669 		}
10670 
10671 		if (!zstr(from_user)) {
10672 			if (*from_user == '+') {
10673 				switch_channel_set_variable(channel, "sip_from_user_stripped", (const char *) (from_user + 1));
10674 			} else {
10675 				switch_channel_set_variable(channel, "sip_from_user_stripped", from_user);
10676 			}
10677 		}
10678 
10679 		switch_channel_set_variable(channel, "sip_from_comment", sip->sip_from->a_comment);
10680 
10681 		if (sip->sip_from->a_params) {
10682 			set_variable_sip_param(channel, "from", sip->sip_from->a_params);
10683 		}
10684 
10685 		switch_channel_set_variable(channel, "sofia_profile_name", profile->name);
10686 		switch_channel_set_variable(channel, "sofia_profile_url", profile->url);
10687 		switch_channel_set_variable(channel, "recovery_profile_name", profile->name);
10688 		switch_channel_set_variable(channel, "sofia_profile_domain_name", profile->domain_name);
10689 
10690 		if (!zstr(sip->sip_from->a_display)) {
10691 			displayname = sip->sip_from->a_display;
10692 		} else {
10693 			displayname = zstr(from_user) ? "unknown" : from_user;
10694 		}
10695 	}
10696 
10697 	if ((rpid = sip_remote_party_id(sip))) {
10698 		if (rpid->rpid_url->url_user) {
10699 			char *full_rpid_header = sip_header_as_string(nh->nh_home, (void *) rpid);
10700 			from_user = rpid->rpid_url->url_user;
10701 			if (!zstr(full_rpid_header)) {
10702 				switch_channel_set_variable(channel, "sip_Remote-Party-ID", full_rpid_header);
10703 			}
10704 
10705 		}
10706 		if (!zstr(rpid->rpid_display)) {
10707 			displayname = rpid->rpid_display;
10708 		}
10709 		switch_channel_set_variable(channel, "sip_cid_type", "rpid");
10710 		tech_pvt->cid_type = CID_TYPE_RPID;
10711 	}
10712 
10713 	if ((passerted = sip_p_asserted_identity(sip))) {
10714 		if (passerted->paid_url->url_user) {
10715 			char *full_paid_header = sip_header_as_string(nh->nh_home, (void *) passerted);
10716 			//char *full_paid_header = (char *)(passerted->paid_common->h_data);
10717 			from_user = passerted->paid_url->url_user;
10718 			if (!zstr(full_paid_header)) {
10719 				if (profile->paid_type == PAID_DEFAULT || profile->paid_type == PAID_USER) {
10720 					switch_channel_set_variable(channel, "sip_P-Asserted-Identity", from_user);
10721 				} else if (profile->paid_type == PAID_USER_DOMAIN) {
10722 					switch_channel_set_variable(channel, "sip_P-Asserted-Identity",
10723 								switch_core_session_sprintf(session, "%s@%s", passerted->paid_url->url_user, passerted->paid_url->url_host));
10724 				} else if (profile->paid_type == PAID_VERBATIM) {
10725 					switch_channel_set_variable(channel, "sip_P-Asserted-Identity",  full_paid_header);
10726 				}
10727 			}
10728 		}
10729 		if (!zstr(passerted->paid_display)) {
10730 			displayname = passerted->paid_display;
10731 		}
10732 		switch_channel_set_variable(channel, "sip_cid_type", "pid");
10733 		tech_pvt->cid_type = CID_TYPE_PID;
10734 	}
10735 
10736 	if ((ppreferred = sip_p_preferred_identity(sip))) {
10737 		if (ppreferred->ppid_url->url_user) {
10738 			char *full_ppid_header = sip_header_as_string(nh->nh_home, (void *) ppreferred);
10739 			from_user = ppreferred->ppid_url->url_user;
10740 			if (!zstr(full_ppid_header)) {
10741 				switch_channel_set_variable(channel, "sip_P-Preferred-Identity", full_ppid_header);
10742 			}
10743 
10744 		}
10745 		if (!zstr(ppreferred->ppid_display)) {
10746 			displayname = ppreferred->ppid_display;
10747 		}
10748 		switch_channel_set_variable(channel, "sip_cid_type", "pid");
10749 		tech_pvt->cid_type = CID_TYPE_PID;
10750 	}
10751 
10752 	if (from_user) {
10753 		check_decode(from_user, session);
10754 
10755 		if ((name_params = strchr(from_user, ';'))) {
10756 			*name_params++ = '\0';
10757 			switch_channel_set_variable(channel, "sip_name_params", name_params);
10758 		}
10759 	}
10760 
10761 	extract_header_vars(profile, sip, session, nh);
10762 	sofia_add_invite_header_to_chanvars(channel, nh, sip->sip_allow, "sip_allow");
10763 
10764 	req_uri = url_set_chanvars(session, sip->sip_request->rq_url, sip_req);
10765 	if (sip->sip_request->rq_url->url_user) {
10766 
10767 		req_user = switch_core_session_strdup(session, sip->sip_request->rq_url->url_user);
10768 		if (profile->parse_invite_tel_params) {
10769 			if (strchr(req_user, ';')) {
10770 				int argc1, x1 = 0;
10771 				char *argv1[32] = { 0 };
10772 
10773 				if ((argc1 = switch_separate_string(req_user, ';', argv1, (sizeof(argv1) / sizeof(argv1[0]))))) {
10774 					for (x1 = 0; x1 < argc1; x1++) {
10775 						if (x1 == 0) {
10776 							switch_channel_set_variable(channel, "sip_req_user", argv1[0]);
10777 						} else {
10778 							int argc2 = 0;
10779 							char *argv2[2] = { 0 };
10780 							if ((argc2 = switch_separate_string(argv1[x1], '=', argv2, (sizeof(argv2) / sizeof(argv2[0])))) == 2) {
10781 								char *var_name = NULL;
10782 								var_name = switch_mprintf("sip_invite_%s", argv2[0]);
10783 								switch_channel_set_variable(channel, var_name, argv2[1]);
10784 								switch_safe_free( var_name );
10785 							} else {
10786 								char *var_name = NULL;
10787 								var_name = switch_mprintf("sip_invite_%s", argv1[x1]);
10788 								switch_channel_set_variable(channel, var_name, "true");
10789 								switch_safe_free( var_name );
10790 							}
10791 						}
10792 					}
10793 				}
10794 			}
10795 		}
10796 	}
10797 
10798 	if (sofia_test_pflag(profile, PFLAG_FULL_ID)) {
10799 		destination_number = req_uri;
10800 	} else {
10801 		destination_number = req_user;
10802 	}
10803 	if (sip->sip_request->rq_url->url_params && (sofia_glue_find_parameter(sip->sip_request->rq_url->url_params, "intercom=true"))) {
10804 		switch_channel_set_variable(channel, "sip_auto_answer_detected", "true");
10805 	}
10806 
10807 	if (!destination_number && sip->sip_to) {
10808 		destination_number = sip->sip_to->a_url->url_user;
10809 	}
10810 
10811 	/* The human network, OH THE HUMANITY!!! lets send invites with no number! */
10812 	if (!destination_number && sip->sip_from) {
10813 		destination_number = sip->sip_from->a_url->url_user;
10814 	}
10815 
10816 	if (destination_number) {
10817 		check_decode(destination_number, session);
10818 	} else {
10819 		destination_number = "service";
10820 	}
10821 
10822 	if (sip->sip_to) {
10823 		const char *host, *user;
10824 		int port, check_nat = 0;
10825 		url_t *transport_url;
10826 
10827 		if (sip->sip_record_route) {
10828 			transport_url = sip->sip_record_route->r_url;
10829 		} else {
10830 			transport_url = sip->sip_contact->m_url;
10831 		}
10832 
10833 		transport = sofia_glue_url2transport(transport_url);
10834 		tech_pvt->transport = transport;
10835 
10836 		url_set_chanvars(session, sip->sip_to->a_url, sip_to);
10837 		if (switch_channel_get_variable(channel, "sip_to_uri")) {
10838 			const char *ipv6;
10839 			const char *tmp, *at, *url = NULL;
10840 
10841 			host = switch_channel_get_variable(channel, "sip_to_host");
10842 			user = switch_channel_get_variable(channel, "sip_to_user");
10843 
10844 			switch_channel_set_variable(channel, "sip_to_comment", sip->sip_to->a_comment);
10845 
10846 			if (sip->sip_to->a_params) {
10847 				set_variable_sip_param(channel, "to", sip->sip_to->a_params);
10848 			}
10849 
10850 			if (sip->sip_contact->m_url->url_port) {
10851 				port = atoi(sip->sip_contact->m_url->url_port);
10852 			} else {
10853 				port = sofia_glue_transport_has_tls(transport) ? profile->tls_sip_port : profile->extsipport;
10854 			}
10855 
10856 			ipv6 = strchr(host, ':');
10857 			tech_pvt->to_uri =
10858 				switch_core_session_sprintf(session,
10859 											"sip:%s@%s%s%s:%d;transport=%s",
10860 											user, ipv6 ? "[" : "", host, ipv6 ? "]" : "", port, sofia_glue_transport2str(transport));
10861 
10862 			if (sofia_glue_check_nat(profile, tech_pvt->mparams.remote_ip)) {
10863 				check_nat = 1;
10864 			}
10865 			url = sofia_glue_get_profile_url(profile, tech_pvt->mparams.remote_ip, transport);
10866 
10867 			if (!url) {
10868 				if (check_nat) {
10869 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Nat detected but no external address configured.\n");
10870 				}
10871 				url = profile->url;
10872 			}
10873 
10874 			if (!url) {
10875 				switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
10876 			}
10877 
10878 			tmp = sofia_overcome_sip_uri_weakness(session, url, transport, SWITCH_TRUE, NULL, NULL);
10879 
10880 			if ((at = strchr(tmp, '@'))) {
10881 				url = switch_core_session_sprintf(session, "sip:%s%s", user, at);
10882 			}
10883 
10884 			if (url) {
10885 				const char *brackets = NULL;
10886 				const char *proto = NULL;
10887 
10888 				brackets = strchr(url, '>');
10889 				proto = switch_stristr("transport=", url);
10890 				tech_pvt->reply_contact = switch_core_session_sprintf(session, "%s%s%s%s%s",
10891 																	  brackets ? "" : "<", url,
10892 																	  proto ? "" : ";transport=",
10893 																	  proto ? "" : sofia_glue_transport2str(transport), brackets ? "" : ">");
10894 			} else {
10895 				switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
10896 			}
10897 
10898 		} else {
10899 			const char *url = NULL;
10900 			url = sofia_glue_get_profile_url(profile, tech_pvt->mparams.remote_ip, transport);
10901 
10902 			if (url) {
10903 				const char *brackets = NULL;
10904 				const char *proto = NULL;
10905 
10906 				brackets = strchr(url, '>');
10907 				proto = switch_stristr("transport=", url);
10908 				tech_pvt->reply_contact = switch_core_session_sprintf(session, "%s%s%s%s%s",
10909 																	  brackets ? "" : "<", url,
10910 																	  proto ? "" : ";transport=",
10911 																	  proto ? "" : sofia_glue_transport2str(transport), brackets ? "" : ">");
10912 			} else {
10913 				switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
10914 			}
10915 		}
10916 	}
10917 
10918 	if (sofia_glue_check_nat(profile, tech_pvt->mparams.remote_ip)) {
10919 		tech_pvt->user_via = sofia_glue_create_external_via(session, profile, tech_pvt->transport);
10920 		nua_set_hparams(nh, SIPTAG_VIA_STR(tech_pvt->user_via), TAG_END());
10921 	}
10922 
10923 	url_set_chanvars(session, sip->sip_contact->m_url, sip_contact);
10924 
10925 	if (sip->sip_referred_by) {
10926 		referred_by_user = sip->sip_referred_by->b_url->url_user;
10927 		//referred_by_host = sip->sip_referred_by->b_url->url_host;
10928 		//channel_name = url_set_chanvars(session, sip->sip_referred_by->b_url, sip_referred_by);
10929 
10930 		check_decode(referred_by_user, session);
10931 
10932 		if (!zstr(referred_by_user)) {
10933 			if (*referred_by_user == '+') {
10934 				switch_channel_set_variable(channel, "sip_referred_by_user_stripped", (const char *) (referred_by_user + 1));
10935 			} else {
10936 				switch_channel_set_variable(channel, "sip_referred_by_user_stripped", referred_by_user);
10937 			}
10938 		}
10939 
10940 		switch_channel_set_variable(channel, "sip_referred_by_cid", sip->sip_referred_by->b_cid);
10941 
10942 		if (sip->sip_referred_by->b_params) {
10943 			set_variable_sip_param(channel, "referred_by", sip->sip_referred_by->b_params);
10944 		}
10945 	}
10946 
10947 	//sofia_glue_set_name(tech_pvt, channel_name);
10948 	switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_FALSE);
10949 
10950 	switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "INBOUND CALL");
10951 
10952 	if (sofia_test_flag(tech_pvt, TFLAG_INB_NOMEDIA)) {
10953 		switch_channel_set_flag(channel, CF_PROXY_MODE);
10954 	}
10955 
10956 	if (profile->media_options & MEDIA_OPT_BYPASS_AFTER_HOLD) {
10957 		switch_channel_set_flag(channel, CF_BYPASS_MEDIA_AFTER_HOLD);
10958 	}
10959 
10960 	if (sofia_test_flag(tech_pvt, TFLAG_PROXY_MEDIA)) {
10961 		switch_channel_set_flag(channel, CF_PROXY_MEDIA);
10962 	}
10963 
10964 	if (sofia_test_flag(tech_pvt, TFLAG_ZRTP_PASSTHRU)) {
10965 		switch_channel_set_flag(channel, CF_ZRTP_PASSTHRU_REQ);
10966 	}
10967 
10968 	if (sip->sip_subject && sip->sip_subject->g_string) {
10969 		switch_channel_set_variable(channel, "sip_subject", sip->sip_subject->g_string);
10970 	}
10971 
10972 	if (sip->sip_user_agent && !zstr(sip->sip_user_agent->g_string)) {
10973 		switch_channel_set_variable(channel, "sip_user_agent", sip->sip_user_agent->g_string);
10974 	}
10975 
10976 	sofia_set_accept_language_channel_variable(channel, sip);
10977 
10978 	if (sip->sip_via) {
10979 		if (sip->sip_via->v_host) {
10980 			switch_channel_set_variable(channel, "sip_via_host", sip->sip_via->v_host);
10981 		}
10982 		if (sip->sip_via->v_port) {
10983 			switch_channel_set_variable(channel, "sip_via_port", sip->sip_via->v_port);
10984 		}
10985 		if (sip->sip_via->v_rport) {
10986 			switch_channel_set_variable(channel, "sip_via_rport", sip->sip_via->v_rport);
10987 		}
10988 	}
10989 
10990 
10991 	if (sip->sip_multipart) {
10992 		msg_multipart_t *mp;
10993 
10994 		for (mp = sip->sip_multipart; mp; mp = mp->mp_next) {
10995 			if (mp->mp_payload && mp->mp_payload->pl_data && mp->mp_content_type && mp->mp_content_type->c_type) {
10996 				char *val = switch_core_session_sprintf(session, "%s:%s", mp->mp_content_type->c_type, mp->mp_payload->pl_data);
10997 				switch_channel_add_variable_var_check(channel, "sip_multipart", val, SWITCH_FALSE, SWITCH_STACK_PUSH);
10998 			}
10999 		}
11000 	}
11001 
11002 	if (sip->sip_max_forwards) {
11003 		char max_forwards[32];
11004 		switch_snprintf(max_forwards, sizeof(max_forwards), "%lu", sip->sip_max_forwards->mf_count);
11005 		switch_channel_set_variable(channel, SWITCH_MAX_FORWARDS_VARIABLE, max_forwards);
11006 	}
11007 
11008 	if (acl_context) context = acl_context;
11009 
11010 	if (!context) {
11011 		context = switch_channel_get_variable(channel, "user_context");
11012 	}
11013 
11014 	if (!context) {
11015 		if (profile->context && !strcasecmp(profile->context, "_domain_")) {
11016 			context = from_host;
11017 		} else {
11018 			context = profile->context;
11019 		}
11020 	}
11021 
11022 	if (!(dialplan = switch_channel_get_variable(channel, "inbound_dialplan"))) {
11023 		dialplan = profile->dialplan;
11024 	}
11025 
11026 	if ((alert_info = sip_alert_info(sip))) {
11027 		char *tmp = sip_header_as_string(nh->nh_home, (void *) alert_info);
11028 		switch_channel_set_variable(channel, "alert_info", tmp);
11029 		su_free(nh->nh_home, tmp);
11030 	}
11031 
11032 	if ((call_info = sip_call_info(sip))) {
11033 		call_info_str = sip_header_as_string(nh->nh_home, (void *) call_info);
11034 
11035 		if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE) && switch_stristr("appearance", call_info_str)) {
11036 			char *p;
11037 
11038 			switch_channel_set_variable(channel, "presence_call_info_full", call_info_str);
11039 			if ((p = strchr(call_info_str, ';'))) {
11040 				p++;
11041 				switch_channel_set_variable(channel, "presence_call_info", p);
11042 			}
11043 		}
11044 
11045 		if (call_info->ci_params && (msg_params_find(call_info->ci_params, "answer-after=0"))) {
11046 			switch_channel_set_variable(channel, "sip_auto_answer_detected", "true");
11047 		}
11048 
11049 		switch_channel_set_variable(channel, "sip_call_info", call_info_str);
11050 
11051 		call_info = call_info->ci_next;
11052 
11053 		while (call_info) {
11054 			call_info_str = sip_header_as_string(nh->nh_home, (void *) call_info);
11055 			switch_channel_add_variable_var_check(channel, "sip_call_info", call_info_str, SWITCH_FALSE, SWITCH_STACK_PUSH);
11056 			call_info = call_info->ci_next;
11057 		}
11058 
11059 		call_info = sip_call_info(sip);
11060 
11061 	} else if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) {
11062 		char buf[128] = "";
11063 		char *sql;
11064 		char *state = "progressing";
11065 
11066 		if (sip->sip_from && sip->sip_from->a_url->url_user && sip->sip_from->a_url->url_host &&
11067 			sip->sip_to && sip->sip_to->a_url->url_user && sip->sip_to->a_url->url_host) {
11068 			sql =
11069 				switch_mprintf("select 'appearance-index=1' from sip_subscriptions where expires > -1 and hostname='%q' and event='call-info' and "
11070 							   "sub_to_user='%q' and sub_to_host='%q'", mod_sofia_globals.hostname, sip->sip_to->a_url->url_user,
11071 							   sip->sip_from->a_url->url_host);
11072 			sofia_glue_execute_sql2str(profile, profile->dbh_mutex, sql, buf, sizeof(buf));
11073 
11074 			if (mod_sofia_globals.debug_sla > 1) {
11075 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "QUERY SQL %s [%s]\n", sql, buf);
11076 			}
11077 			free(sql);
11078 
11079 			if (!zstr(buf)) {
11080 				sql = switch_mprintf("update sip_dialogs set call_info='%q',call_info_state='%q' "
11081 									 "where uuid='%q'", buf, state, switch_core_session_get_uuid(session));
11082 
11083 				if (mod_sofia_globals.debug_sla > 1) {
11084 					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "QUERY SQL %s\n", sql);
11085 				}
11086 
11087 				sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
11088 
11089 
11090 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Auto-Fixing Broken SLA [<sip:%s>;%s]\n",
11091 								  sip->sip_from->a_url->url_host, buf);
11092 
11093 				switch_channel_set_variable_printf(channel, "presence_call_info_full", "<sip:%s>;%s", sip->sip_from->a_url->url_host, buf);
11094 				switch_channel_set_variable(channel, "presence_call_info", buf);
11095 				call_info_str = switch_core_session_sprintf(session, "<sip:%s>;%s", sip->sip_from->a_url->url_host, buf);
11096 			}
11097 		}
11098 	}
11099 
11100 
11101 	if (profile->pres_type) {
11102 		const char *presence_id = switch_channel_get_variable(channel, "presence_id");
11103 		if (zstr(presence_id)) {
11104 			const char *user = switch_str_nil(sip->sip_from->a_url->url_user);
11105 			const char *host = switch_str_nil(sip->sip_from->a_url->url_host);
11106 			char *tmp = switch_mprintf("%s@%s", user, host);
11107 			switch_assert(tmp);
11108 			switch_channel_set_variable(channel, "presence_id", tmp);
11109 			free(tmp);
11110 		}
11111 	}
11112 
11113 
11114 	if (sip->sip_request->rq_url->url_params) {
11115 		gw_param_name = switch_find_parameter(sip->sip_request->rq_url->url_params, "gw", switch_core_session_get_pool(session));
11116 	}
11117 
11118 	if (strstr(destination_number, "gw+")) {
11119 		if (sofia_test_pflag(profile, PFLAG_FULL_ID)) {
11120 			char *tmp;
11121 			gw_name = switch_core_session_strdup(session, destination_number + 3);
11122 			if ((tmp = strchr(gw_name, '@'))) {
11123 				*tmp = '\0';
11124 			}
11125 		} else {
11126 			gw_name = destination_number + 3;
11127 		}
11128 	}
11129 
11130 	if (gw_name || gw_param_name) {
11131 		sofia_gateway_t *gateway = NULL;
11132 		char *extension = NULL;
11133 
11134 		if (gw_name && ((gateway = sofia_reg_find_gateway(gw_name)))) {
11135 			gw_param_name = NULL;
11136 			extension = gateway->extension;
11137 		}
11138 
11139 		if (!gateway && gw_param_name) {
11140 			if ((gateway = sofia_reg_find_gateway(gw_param_name))) {
11141 				extension = gateway->real_extension;
11142 			}
11143 		}
11144 
11145 		if (gateway) {
11146 			context = switch_core_session_strdup(session, gateway->register_context);
11147 			switch_channel_set_variable(channel, "sip_gateway", gateway->name);
11148 
11149 			if (!zstr(extension)) {
11150 				if (!strcasecmp(extension, "auto_to_user") && sip->sip_to) {
11151 					destination_number = sip->sip_to->a_url->url_user;
11152 				} else if (!strcasecmp(extension, "auto")) {
11153 					if (gw_name && sip->sip_to) {
11154 						destination_number = sip->sip_to->a_url->url_user;
11155 					}
11156 				} else {
11157 					destination_number = switch_core_session_strdup(session, extension);
11158 				}
11159 			} else if (!gw_param_name && sip->sip_to) {
11160 				destination_number = sip->sip_to->a_url->url_user;
11161 			}
11162 
11163 			gateway->ib_calls++;
11164 
11165 			if (gateway->ib_vars) {
11166 				switch_event_header_t *hp;
11167 				for (hp = gateway->ib_vars->headers; hp; hp = hp->next) {
11168 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s setting variable [%s]=[%s]\n",
11169 									  switch_channel_get_name(channel), hp->name, hp->value);
11170 					switch_channel_set_variable(channel, hp->name, hp->value);
11171 				}
11172 			}
11173 
11174 			sofia_reg_release_gateway(gateway);
11175 		}
11176 	}
11177 
11178 	if (call_info_str) {
11179 		char *sql;
11180 		char cid[512] = "";
11181 		char *str;
11182 		char *p = NULL;
11183 		const char *user = NULL, *host = NULL, *from_user = NULL, *from_host = NULL;
11184 
11185 		if (sip->sip_to) {
11186 			user = sip->sip_to->a_url->url_user;
11187 			host = sip->sip_to->a_url->url_host;
11188 		}
11189 
11190 		if (sip->sip_from) {
11191 			from_user = sip->sip_from->a_url->url_user;
11192 			from_host = sip->sip_from->a_url->url_host;
11193 		}
11194 
11195 		if (!user) user = from_user;
11196 		if (!host) user = from_host;
11197 
11198 		if (user && host && from_user && !strcmp(user, from_user)) {
11199 			if ((p = strchr(call_info_str, ';'))) {
11200 				p++;
11201 			}
11202 
11203 			sql = switch_mprintf(
11204 		      "select call_id from sip_dialogs where (call_info='%q' or call_info='%q;appearance-state=held') and "
11205 			  "((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q') and call_id is not null",
11206 				 switch_str_nil(p), switch_str_nil(p), user, host, user, host);
11207 
11208 			if ((str = sofia_glue_execute_sql2str(profile, profile->dbh_mutex, sql, cid, sizeof(cid)))) {
11209 				bnh = nua_handle_by_call_id(nua, str);
11210 			}
11211 
11212 			if (mod_sofia_globals.debug_sla > 1) {
11213 				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "PICK SQL %s [%s] [%s] %d\n", sql, str, cid, !!bnh);
11214 			}
11215 
11216 			free(sql);
11217 		}
11218 	}
11219 
11220 
11221 	check_decode(displayname, session);
11222 
11223 	profile_dup_clean(from_user, tech_pvt->caller_profile->username, tech_pvt->caller_profile->pool);
11224 	profile_dup_clean(dialplan, tech_pvt->caller_profile->dialplan, tech_pvt->caller_profile->pool);
11225 	profile_dup_clean(displayname, tech_pvt->caller_profile->caller_id_name, tech_pvt->caller_profile->pool);
11226 	profile_dup_clean(from_user, tech_pvt->caller_profile->caller_id_number, tech_pvt->caller_profile->pool);
11227 	profile_dup_clean(displayname, tech_pvt->caller_profile->orig_caller_id_name, tech_pvt->caller_profile->pool);
11228 	profile_dup_clean(from_user, tech_pvt->caller_profile->orig_caller_id_number, tech_pvt->caller_profile->pool);
11229 	profile_dup_clean(network_ip, tech_pvt->caller_profile->network_addr, tech_pvt->caller_profile->pool);
11230 	profile_dup_clean(from_user, tech_pvt->caller_profile->ani, tech_pvt->caller_profile->pool);
11231 	profile_dup_clean(aniii, tech_pvt->caller_profile->aniii, tech_pvt->caller_profile->pool);
11232 	profile_dup_clean(context, tech_pvt->caller_profile->context, tech_pvt->caller_profile->pool);
11233 	profile_dup_clean(destination_number, tech_pvt->caller_profile->destination_number, tech_pvt->caller_profile->pool);
11234 
11235 	if (!bnh && sip->sip_replaces) {
11236 		if (!(bnh = nua_handle_by_replaces(nua, sip->sip_replaces))) {
11237 			if (!(bnh = nua_handle_by_call_id(nua, sip->sip_replaces->rp_call_id))) {
11238 				bnh = sofia_global_nua_handle_by_replaces(sip->sip_replaces);
11239 			}
11240 		}
11241 	}
11242 
11243 	if (sip->sip_replaces) {
11244 		msg_common_t *rp_common = sip->sip_replaces->rp_common;
11245 		switch_channel_set_variable(channel, "sip_replaces_call_id", sip->sip_replaces->rp_call_id);
11246 		if (rp_common->h_class->hc_params) {
11247 			int i, n;
11248 			msg_param_t const *params = * (msg_param_t const **) ((char *)rp_common + rp_common->h_class->hc_params);
11249 			for (i = 0; params[i]; i++) {
11250 				msg_param_t param = params[i];
11251 				if (strchr(param, '=')) {
11252 					n = strcspn(param, "=");
11253 					switch_channel_set_variable_name_printf(channel, param + n + 1, "sip_replaces_%.*s", n, param);
11254 				} else {
11255 					switch_channel_set_variable_name_printf(channel, "true", "sip_replaces_%s", param);
11256 				}
11257 			}
11258 		}
11259 	}
11260 
11261 	if (bnh) {
11262 		sofia_private_t *b_private = NULL;
11263 		if ((b_private = nua_handle_magic(bnh))) {
11264 			switch_core_session_t *b_session = NULL;
11265 			if ((b_session = switch_core_session_locate(b_private->uuid))) {
11266 				switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
11267 				sofia_handle_sip_i_invite_replaces(session, channel, b_channel, b_private->uuid, tech_pvt, call_info, profile, is_nat, sip);
11268 				switch_core_session_rwunlock(b_session);
11269 			}
11270 		}
11271 		nua_handle_unref(bnh);
11272 	} else if (sip->sip_replaces && sip->sip_replaces->rp_call_id) {
11273 		switch_core_session_t *b_session = NULL;
11274 		if ((b_session = switch_core_session_locate((char*) sip->sip_replaces->rp_call_id))) {
11275 				switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
11276 				sofia_handle_sip_i_invite_replaces(session, channel, b_channel, (char*) sip->sip_replaces->rp_call_id, tech_pvt, call_info, profile, is_nat, sip);
11277 				switch_core_session_rwunlock(b_session);
11278 		}
11279 	}
11280 
11281 	if (tech_pvt->caller_profile) {
11282 
11283 		int first_history_info = 1;
11284 
11285 		if (rpid) {
11286 			if (rpid->rpid_privacy) {
11287 				if (!strcasecmp(rpid->rpid_privacy, "yes")) {
11288 					switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NAME | SWITCH_CPF_HIDE_NUMBER);
11289 				} else if (!strcasecmp(rpid->rpid_privacy, "full")) {
11290 					switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NAME | SWITCH_CPF_HIDE_NUMBER);
11291 				} else if (!strcasecmp(rpid->rpid_privacy, "name")) {
11292 					switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NAME);
11293 				} else if (!strcasecmp(rpid->rpid_privacy, "number")) {
11294 					switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NUMBER);
11295 				} else {
11296 					switch_clear_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NAME);
11297 					switch_clear_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NUMBER);
11298 				}
11299 			}
11300 
11301 			if (rpid->rpid_screen && !strcasecmp(rpid->rpid_screen, "no")) {
11302 				switch_clear_flag(tech_pvt->caller_profile, SWITCH_CPF_SCREEN);
11303 			}
11304 		}
11305 
11306 		if ((privacy = sip_privacy(sip))) {
11307 			char *full_priv_header = sip_header_as_string(nh->nh_home, (void *) privacy);
11308 			if (!zstr(full_priv_header)) {
11309 				switch_channel_set_variable(channel, "sip_Privacy", full_priv_header);
11310 			}
11311 			if (msg_params_find(privacy->priv_values, "id")) {
11312 				switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NAME | SWITCH_CPF_HIDE_NUMBER);
11313 			}
11314 		}
11315 
11316 		/* Loop thru unknown Headers Here so we can do something with them */
11317 		for (un = sip->sip_unknown; un; un = un->un_next) {
11318 			if (!strncasecmp(un->un_name, "Accept-Language", 15)) {
11319 				if (!zstr(un->un_value)) {
11320 					char *tmp_name;
11321 					if ((tmp_name = switch_mprintf("%s%s", SOFIA_SIP_HEADER_PREFIX, un->un_name))) {
11322 						switch_channel_set_variable(channel, tmp_name, un->un_value);
11323 						free(tmp_name);
11324 					}
11325 				}
11326 			} else if (!strncasecmp(un->un_name, "Diversion", 9)) {
11327 				/* Basic Diversion Support for Diversion Indication in SIP */
11328 				/* draft-levy-sip-diversion-08 */
11329 				if (!zstr(un->un_value)) {
11330 					char *tmp_name;
11331 					if ((tmp_name = switch_mprintf("%s%s", SOFIA_SIP_HEADER_PREFIX, un->un_name))) {
11332 						switch_channel_set_variable(channel, tmp_name, un->un_value);
11333 						free(tmp_name);
11334 					}
11335 				}
11336 			} else if (!strncasecmp(un->un_name, "History-Info", 12)) {
11337 				if (first_history_info) {
11338 					/* If the header exists first time, make sure to remove old info and re-set the variable */
11339 					switch_channel_set_variable(channel, "sip_history_info", un->un_value);
11340 					first_history_info = 0;
11341 				} else {
11342 					/* Append the History-Info into one long string */
11343 					const char *history_var = switch_channel_get_variable(channel, "sip_history_info");
11344 					if (!zstr(history_var)) {
11345 						char *tmp_str;
11346 						if ((tmp_str = switch_mprintf("%s, %s", history_var, un->un_value))) {
11347 							switch_channel_set_variable(channel, "sip_history_info", tmp_str);
11348 							free(tmp_str);
11349 						} else {
11350 							switch_channel_set_variable(channel, "sip_history_info", un->un_value);
11351 						}
11352 					} else {
11353 						switch_channel_set_variable(channel, "sip_history_info", un->un_value);
11354 					}
11355 				}
11356 			} else if (!strcasecmp(un->un_name, "X-FS-Channel-Name") && !zstr(un->un_value)) {
11357 				switch_channel_set_name(channel, un->un_value);
11358 				switch_channel_set_variable(channel, "push_channel_name", "true");
11359 			} else if (!strcasecmp(un->un_name, "X-FS-Support")) {
11360 				tech_pvt->x_freeswitch_support_remote = switch_core_session_strdup(session, un->un_value);
11361 			} else if (!strcasecmp(un->un_name, "Geolocation")) {
11362 				switch_channel_set_variable(channel, "sip_geolocation", un->un_value);
11363 			} else if (!strcasecmp(un->un_name, "Geolocation-Error")) {
11364 				switch_channel_set_variable(channel, "sip_geolocation_error", un->un_value);
11365 			} else if (!strcasecmp(un->un_name, "userLocation")) {
11366 				switch_channel_set_variable(channel, "sip_user_location", un->un_value);
11367 			} else if (!strncasecmp(un->un_name, "X-", 2) || !strncasecmp(un->un_name, "P-", 2) || !strcasecmp(un->un_name, "User-to-User") || !strncasecmp(un->un_name, "On", 2) || !strncasecmp(un->un_name, "K-", 2)) {
11368 				if (!zstr(un->un_value)) {
11369 					char new_name[512] = "";
11370 					int reps = 0;
11371 					for (;;) {
11372 						char postfix[25] = "";
11373 						if (reps > 0) {
11374 							switch_snprintf(postfix, sizeof(postfix), "-%d", reps);
11375 						}
11376 						reps++;
11377 						switch_snprintf(new_name, sizeof(new_name), "%s%s%s", SOFIA_SIP_HEADER_PREFIX, un->un_name, postfix);
11378 
11379 						if (switch_channel_get_variable(channel, new_name)) {
11380 							continue;
11381 						}
11382 
11383 						switch_channel_set_variable(channel, new_name, un->un_value);
11384 						break;
11385 					}
11386 				}
11387 			}
11388 		}
11389 
11390 	}
11391 
11392 	tech_pvt->sofia_private = sofia_private;
11393 	tech_pvt->nh = nh;
11394 
11395 	if (profile->pres_type && sofia_test_pflag(profile, PFLAG_IN_DIALOG_CHAT)) {
11396 		sofia_presence_set_chat_hash(tech_pvt, sip);
11397 	}
11398 
11399 	if (sofia_test_pflag(profile, PFLAG_PARSE_ALL_INVITE_HEADERS)) {
11400 		sofia_parse_all_invite_headers(sip, session, nh);
11401 	}
11402 
11403 	if (sip->sip_to) {
11404 		to = sip->sip_to->a_url;
11405 	}
11406 	if (sip->sip_from) {
11407 		from = sip->sip_from->a_url;
11408 	}
11409 	contact = sip->sip_contact->m_url;
11410 
11411 	if (sip->sip_user_agent) {
11412 		user_agent = switch_str_nil(sip->sip_user_agent->g_string);
11413 	}
11414 
11415 	if (sip->sip_call_id) {
11416 		call_id = switch_str_nil(sip->sip_call_id->i_id);
11417 	}
11418 
11419 	if (to) {
11420 		to_user = switch_str_nil(to->url_user);
11421 		to_host = switch_str_nil(to->url_host);
11422 		to_tag = switch_str_nil(sip->sip_to->a_tag);
11423 	}
11424 
11425 	if (from) {
11426 		dialog_from_user = switch_str_nil(from->url_user);
11427 		dialog_from_host = switch_str_nil(from->url_host);
11428 		from_tag = switch_str_nil(sip->sip_from->a_tag);
11429 	}
11430 
11431 	contact_user = switch_str_nil(contact->url_user);
11432 	contact_host = switch_str_nil(contact->url_host);
11433 
11434 	if (profile->pres_type) {
11435 		const char *presence_data = switch_channel_get_variable(channel, "presence_data");
11436 		const char *presence_id = switch_channel_get_variable(channel, "presence_id");
11437 		char *full_contact = "";
11438 		char *p = NULL;
11439 		time_t now;
11440 
11441 		full_contact = sip_header_as_string(nua_handle_home(tech_pvt->nh), (void *) sip->sip_contact);
11442 
11443 		if (call_info_str && switch_stristr("appearance", call_info_str)) {
11444 			switch_channel_set_variable(channel, "presence_call_info_full", call_info_str);
11445 			if ((p = strchr(call_info_str, ';'))) {
11446 				p++;
11447 				switch_channel_set_variable(channel, "presence_call_info", p);
11448 			}
11449 		}
11450 
11451 		now = switch_epoch_time_now(NULL);
11452 
11453 		sql = switch_mprintf("insert into sip_dialogs "
11454 							 "(call_id,uuid,sip_to_user,sip_to_host,sip_to_tag,sip_from_user,sip_from_host,sip_from_tag,contact_user,"
11455 							 "contact_host,state,direction,user_agent,profile_name,hostname,contact,presence_id,presence_data,"
11456 							 "call_info,rcd,call_info_state) "
11457 							 "values('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld,'')",
11458 							 call_id,
11459 							 tech_pvt->sofia_private->uuid,
11460 							 to_user, to_host, to_tag, dialog_from_user, dialog_from_host, from_tag,
11461 							 contact_user, contact_host, "confirmed", "inbound", user_agent,
11462 							 profile->name, mod_sofia_globals.hostname, switch_str_nil(full_contact),
11463 							 switch_str_nil(presence_id), switch_str_nil(presence_data), switch_str_nil(p), now);
11464 
11465 		switch_assert(sql);
11466 
11467 		sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
11468 
11469 		if ( full_contact ) {
11470 			su_free(nua_handle_home(tech_pvt->nh), full_contact);
11471 		}
11472 	}
11473 
11474 	if (is_nat) {
11475 		sofia_set_flag(tech_pvt, TFLAG_NAT);
11476 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setting NAT mode based on %s\n", is_nat);
11477 		switch_channel_set_variable(channel, "sip_nat_detected", "true");
11478 	}
11479 
11480 	return;
11481 
11482   fail:
11483 	profile->ib_failed_calls++;
11484 
11485 	return;
11486 
11487 }
11488 
sofia_handle_sip_i_invite_replaces(switch_core_session_t * session,switch_channel_t * channel,switch_channel_t * b_channel,char * uuid,private_object_t * tech_pvt,sip_call_info_t * call_info,sofia_profile_t * profile,char * is_nat,sip_t const * sip)11489 void sofia_handle_sip_i_invite_replaces(switch_core_session_t *session, switch_channel_t *channel, switch_channel_t *b_channel, char* uuid, private_object_t *tech_pvt, sip_call_info_t *call_info, sofia_profile_t *profile, char *is_nat, sip_t const *sip)
11490 {
11491 	const char *bridge_uuid;
11492 	switch_caller_profile_t *orig_cp, *cp;
11493 	//const char *sent_name, *sent_number;
11494 	orig_cp = switch_channel_get_caller_profile(b_channel);
11495 
11496 	if (orig_cp) {
11497 		tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_name);
11498 		tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_number);
11499 
11500 		if (!call_info) {
11501 			tech_pvt->caller_profile->caller_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_name);
11502 			tech_pvt->caller_profile->caller_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_number);
11503 		}
11504 
11505 		cp = switch_caller_profile_dup(tech_pvt->caller_profile->pool, orig_cp);
11506 		switch_channel_set_originator_caller_profile(channel, cp);
11507 	}
11508 
11509 #if 0
11510 	sent_name = switch_channel_get_variable(b_channel, "last_sent_callee_id_name");
11511 	sent_number = switch_channel_get_variable(b_channel, "last_sent_callee_id_number");
11512 
11513 	if (!zstr(sent_name) && !zstr(sent_number)) {
11514 		tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, sent_name);
11515 		tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, sent_number);
11516 	} else {
11517 		if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
11518 			tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_name);
11519 			tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_number);
11520 		} else {
11521 			tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_name);
11522 			tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_number);
11523 		}
11524 	}
11525 #endif
11526 
11527 	if (is_nat) {
11528 		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Setting NAT mode based on %s\n", is_nat);
11529 	}
11530 
11531 	tech_pvt->caller_profile->dialplan = "inline";
11532 
11533 	bridge_uuid = switch_channel_get_partner_uuid(b_channel);
11534 	if (bridge_uuid) {
11535 		switch_core_session_t *bridge_session = NULL;
11536 		if ((bridge_session = switch_core_session_locate(bridge_uuid))) {
11537 			switch_core_session_rwunlock(bridge_session);
11538 		} else {
11539 			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "could not locate partner_uuid %s, resetting\n", bridge_uuid);
11540 			bridge_uuid = NULL;
11541 		}
11542 	}
11543 
11544 	if (call_info) {
11545 		switch_event_t *event = NULL;
11546 
11547 		if (!zstr(bridge_uuid) && switch_channel_test_flag(b_channel, CF_LEG_HOLDING)) {
11548 			const char *b_call_id = switch_channel_get_variable(b_channel, "sip_call_id");
11549 
11550 			if (b_call_id) {
11551 				char *sql = switch_mprintf("update sip_dialogs set call_info_state='idle' where call_id='%q'", b_call_id);
11552 				if (mod_sofia_globals.debug_sla > 1) {
11553 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "QUERY SQL %s\n", sql);
11554 				}
11555 				sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
11556 
11557 				switch_channel_presence(b_channel, "unknown", "idle", NULL);
11558 			}
11559 			switch_channel_set_flag(tech_pvt->channel, CF_SLA_INTERCEPT);
11560 			tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool,
11561 																			   "answer,intercept:%s", bridge_uuid);
11562 
11563 			if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)
11564 				&& sip && sip->sip_call_id
11565 				&& switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_REPLACED) == SWITCH_STATUS_SUCCESS) {
11566 				switch_channel_event_set_data(b_channel, event);
11567 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_by", sip->sip_call_id->i_id);
11568 				switch_event_fire(&event);
11569 			}
11570 		} else {
11571 			switch_caller_profile_t *bcp = switch_channel_get_caller_profile(b_channel);
11572 
11573 			if (switch_channel_test_flag(b_channel, CF_BRIDGE_ORIGINATOR)) {
11574 				switch_channel_set_flag(tech_pvt->channel, CF_BRIDGE_ORIGINATOR);
11575 			}
11576 
11577 			if (!zstr(bcp->callee_id_name)) {
11578 				tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->callee_id_name);
11579 			}
11580 
11581 			if (!zstr(bcp->callee_id_number)) {
11582 				tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->callee_id_number);
11583 			}
11584 
11585 
11586 			if (!zstr(bcp->caller_id_name)) {
11587 				tech_pvt->caller_profile->caller_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->caller_id_name);
11588 			}
11589 
11590 			if (!zstr(bcp->caller_id_number)) {
11591 				tech_pvt->caller_profile->caller_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, bcp->caller_id_number);
11592 			}
11593 
11594 			if (bcp->originatee_caller_profile) {
11595 				switch_caller_profile_t *cp;
11596 
11597 				cp = switch_caller_profile_dup(tech_pvt->caller_profile->pool,
11598 											   bcp->originatee_caller_profile);
11599 
11600 				switch_channel_set_originatee_caller_profile(tech_pvt->channel, cp);
11601 			}
11602 
11603 			tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool,
11604 																			   "answer,sofia_sla:%s", uuid);
11605 		}
11606 	} else {
11607 		char const *nightmare_xfer_uuid = NULL;
11608 		switch_event_t *event = NULL;
11609 		if (switch_channel_var_true(channel, "sip_replaces_a-leg")) {
11610 			switch_channel_mark_hold(b_channel, SWITCH_FALSE);
11611 			if (sip) {
11612 				tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,intercept:%s", sip->sip_replaces->rp_call_id);
11613 				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call %s picked up on a-leg\n", sip->sip_replaces->rp_call_id);
11614 				if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)
11615 					&& sip->sip_call_id
11616 					&& switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_INTERCEPTED) == SWITCH_STATUS_SUCCESS) {
11617 					switch_channel_event_set_data(b_channel, event);
11618 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "intercepted_by", sip->sip_call_id->i_id);
11619 					switch_event_fire(&event);
11620 				}
11621 			}
11622 		} else {
11623 			if (sip) {
11624 				if ((nightmare_xfer_uuid = sofia_glue_get_unknown_header(sip, "X-FS-Refer-For"))) {
11625 					switch_channel_set_variable(b_channel, "transfer_refer_for", nightmare_xfer_uuid);
11626 				}
11627 				if ((nightmare_xfer_uuid = sofia_glue_get_unknown_header(sip, "X-FS-Refer-From"))) {
11628 					switch_channel_set_variable(b_channel, "transfer_refer_from", nightmare_xfer_uuid);
11629 				}
11630 			}
11631 
11632 			if (!zstr(bridge_uuid)) {
11633 				if (sip && sip->sip_replaces && sip->sip_replaces->rp_params && sip->sip_replaces->rp_call_id && switch_channel_test_flag(b_channel, CF_BRIDGED) &&
11634 					switch_true(switch_find_parameter(*(sip->sip_replaces->rp_params), "early-only", switch_core_session_get_pool(session)))) {
11635 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call %s intercept rejected\n", bridge_uuid);
11636 					tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "hangup:CALL_REJECTED");
11637 				} else {
11638 					switch_channel_mark_hold(b_channel, SWITCH_FALSE);
11639 					tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,intercept:%s", bridge_uuid);
11640 					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call %s intercepted\n", bridge_uuid);
11641 					if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)
11642 						&& sip && sip->sip_call_id
11643 						&& switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_INTERCEPTED) == SWITCH_STATUS_SUCCESS) {
11644 							switch_channel_event_set_data(b_channel, event);
11645 							switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "intercepted_by", sip->sip_call_id->i_id);
11646 							switch_event_fire(&event);
11647 					}
11648 				}
11649 			} else {
11650 				const char *b_app = switch_channel_get_variable(b_channel, SWITCH_CURRENT_APPLICATION_VARIABLE);
11651 				const char *b_data = switch_channel_get_variable(b_channel, SWITCH_CURRENT_APPLICATION_DATA_VARIABLE);
11652 				if (b_data && b_app) {
11653 					tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,%s:%s", b_app, b_data);
11654 				} else if (b_app) {
11655 					tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,%s", b_app);
11656 				}
11657 				if (sofia_test_pflag(profile, PFLAG_FIRE_TRANFER_EVENTS)
11658 					&& sip && sip->sip_call_id
11659 					&& switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_REPLACED) == SWITCH_STATUS_SUCCESS) {
11660 					switch_channel_event_set_data(b_channel, event);
11661 					switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_by", sip->sip_call_id->i_id);
11662 					switch_event_fire(&event);
11663 				}
11664 				switch_channel_hangup(b_channel, SWITCH_CAUSE_ATTENDED_TRANSFER);
11665 			}
11666 		}
11667 	}
11668 
11669 }
11670 
sofia_handle_sip_i_options(int status,char const * phrase,nua_t * nua,sofia_profile_t * profile,nua_handle_t * nh,sofia_private_t * sofia_private,sip_t const * sip,sofia_dispatch_event_t * de,tagi_t tags[])11671 void sofia_handle_sip_i_options(int status,
11672 								char const *phrase,
11673 								nua_t *nua, sofia_profile_t *profile, nua_handle_t *nh, sofia_private_t *sofia_private, sip_t const *sip,
11674 								sofia_dispatch_event_t *de,
11675 								tagi_t tags[])
11676 {
11677 	uint32_t sess_count = switch_core_session_count();
11678 	uint32_t sess_max = switch_core_session_limit(0);
11679 
11680 	if (sofia_test_pflag(profile, PFLAG_OPTIONS_RESPOND_503_ON_BUSY) &&
11681 			(sess_count >= sess_max || !sofia_test_pflag(profile, PFLAG_RUNNING) || !switch_core_ready_inbound())) {
11682 		nua_respond(nh, 503, "Maximum Calls In Progress", NUTAG_WITH_THIS_MSG(de->data->e_msg), SIPTAG_RETRY_AFTER_STR("300"), TAG_END());
11683 	} else {
11684 		switch_assert(sip);
11685 		nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg),
11686 					TAG_IF(sip->sip_record_route, SIPTAG_RECORD_ROUTE(sip->sip_record_route)), TAG_END());
11687 	}
11688 
11689 }
11690 
11691 /*
11692  * This subroutine will take the a_params of a sip_addr_s structure and spin through them.
11693  * Each param will be used to create a channel variable.
11694  * In the SIP RFC's, this data is called generic-param.
11695  * Note that the tag-param is also included in the a_params list.
11696  *
11697  * From: "John Doe" <sip:5551212@1.2.3.4>;tag=ed23266b52cbb17eo2;ref=101;mbid=201
11698  *
11699  * For example, the header above will produce an a_params list with three entries
11700  *    tag=ed23266b52cbb17eo2
11701  *    ref=101
11702  *    mbid=201
11703  *
11704  * The a_params list is parsed and the lvalue is used to create the channel variable name while the
11705  * rvalue is used to create the channel variable value.
11706  *
11707  * If no equal (=) sign is found during parsing, a channel variable name is created with the param and
11708  * the value is set to NULL.
11709  *
11710  * Pointers are used for copying the sip_header_name for performance reasons.  There are no calls to
11711  * any string functions and no memory is allocated/dealocated.  The only limiter is the size of the
11712  * sip_header_name array.
11713 */
set_variable_sip_param(switch_channel_t * channel,char * header_type,sip_param_t const * params)11714 static void set_variable_sip_param(switch_channel_t *channel, char *header_type, sip_param_t const *params)
11715 {
11716 	char sip_header_name[128] = "";
11717 	char var1[] = "sip_";
11718 	char *cp, *sh, *sh_end, *sh_save;
11719 
11720 	/* Build the static part of the sip_header_name variable from   */
11721 	/* the header_type. If the header type is "referred_by" then    */
11722 	/* sip_header_name = "sip_referred_by_".                        */
11723 	sh = sip_header_name;
11724 	sh_end = sh + sizeof(sip_header_name) - 1;
11725 	for (cp = var1; *cp; cp++, sh++) {
11726 		*sh = *cp;
11727 	}
11728 	*sh = '\0';
11729 
11730 	/* Copy the header_type to the sip_header_name. Before copying  */
11731 	/* each character, check that we aren't going to overflow the   */
11732 	/* the sip_header_name buffer.  We have to account for the      */
11733 	/* trailing underscore and NULL that will be added to the end.  */
11734 	for (cp = header_type; (*cp && (sh < (sh_end - 1))); cp++, sh++) {
11735 		*sh = *cp;
11736 	}
11737 	*sh++ = '_';
11738 	*sh = '\0';
11739 
11740 	/* sh now points to the NULL at the end of the partially built  */
11741 	/* sip_header_name variable.  This is also the start of the     */
11742 	/* variable part of the sip_header_name built from the lvalue   */
11743 	/* of the params data.                                          */
11744 	sh_save = sh;
11745 
11746 	while (params && params[0]) {
11747 
11748 		/* Copy the params data to the sip_header_name variable until   */
11749 		/* the end of the params string is reached, an '=' is detected  */
11750 		/* or until the sip_header_name buffer has been exhausted.      */
11751 		for (cp = (char *) (*params); ((*cp != '=') && *cp && (sh < sh_end)); cp++, sh++) {
11752 			*sh = *cp;
11753 		}
11754 
11755 		/* cp now points to either the end of the params data or the */
11756 		/* equal (=) sign separating the lvalue and rvalue.          */
11757 		if (*cp == '=')
11758 			cp++;
11759 		*sh = '\0';
11760 		switch_channel_set_variable(channel, sip_header_name, cp);
11761 
11762 		/* Bump pointer to next param in the list.  Also reset the      */
11763 		/* sip_header_name pointer to the beginning of the dynamic area */
11764 		params++;
11765 		sh = sh_save;
11766 	}
11767 }
11768 
11769 /* For Emacs:
11770  * Local Variables:
11771  * mode:c
11772  * indent-tabs-mode:t
11773  * tab-width:4
11774  * c-basic-offset:4
11775  * End:
11776  * For VIM:
11777  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
11778  */
11779