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 * Eliot Gable <egable AT.AT broadvox.com>
31 *
32 *
33 * sofia_glue.c -- SOFIA SIP Endpoint (code to tie sofia to freeswitch)
34 *
35 */
36 #include "mod_sofia.h"
37 #include <switch_stun.h>
38
39 switch_cache_db_handle_t *_sofia_glue_get_db_handle(sofia_profile_t *profile, const char *file, const char *func, int line);
40 #define sofia_glue_get_db_handle(_p) _sofia_glue_get_db_handle(_p, __FILE__, __SWITCH_FUNC__, __LINE__)
41
42
sofia_glue_check_nat(sofia_profile_t * profile,const char * network_ip)43 int sofia_glue_check_nat(sofia_profile_t *profile, const char *network_ip)
44 {
45 switch_assert(network_ip);
46
47 return (profile->extsipip &&
48 !switch_check_network_list_ip(network_ip, "loopback.auto") &&
49 !switch_check_network_list_ip(network_ip, profile->local_network));
50 }
51
sofia_glue_new_pvt(switch_core_session_t * session)52 private_object_t *sofia_glue_new_pvt(switch_core_session_t *session)
53 {
54 private_object_t *tech_pvt = (private_object_t *) switch_core_session_alloc(session, sizeof(private_object_t));
55 switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
56 switch_mutex_init(&tech_pvt->sofia_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
57 return tech_pvt;
58 }
59
sofia_glue_set_name(private_object_t * tech_pvt,const char * channame)60 void sofia_glue_set_name(private_object_t *tech_pvt, const char *channame)
61 {
62 char name[256];
63 char *p;
64
65 switch_snprintf(name, sizeof(name), "sofia/%s/%s", tech_pvt->profile->name, channame);
66 if ((p = strchr(name, ';'))) {
67 *p = '\0';
68 }
69 switch_channel_set_name(tech_pvt->channel, name);
70 }
71
sofia_glue_attach_private(switch_core_session_t * session,sofia_profile_t * profile,private_object_t * tech_pvt,const char * channame)72 void sofia_glue_attach_private(switch_core_session_t *session, sofia_profile_t *profile, private_object_t *tech_pvt, const char *channame)
73 {
74
75 unsigned int x, i;
76
77 switch_assert(session != NULL);
78 switch_assert(profile != NULL);
79 switch_assert(tech_pvt != NULL);
80
81 switch_core_session_add_stream(session, NULL);
82
83 switch_mutex_lock(tech_pvt->flag_mutex);
84 switch_mutex_lock(profile->flag_mutex);
85
86 /* copy flags from profile to the sofia private */
87 for (x = 0; x < TFLAG_MAX; x++) {
88 tech_pvt->flags[x] = profile->flags[x];
89 }
90
91 tech_pvt->x_freeswitch_support_local = FREESWITCH_SUPPORT;
92
93 tech_pvt->profile = profile;
94
95 if (!zstr(profile->rtpip[profile->rtpip_next])) {
96 tech_pvt->mparams.rtpip4 = switch_core_session_strdup(session, profile->rtpip[profile->rtpip_next++]);
97 tech_pvt->mparams.rtpip = tech_pvt->mparams.rtpip4;
98
99 if (profile->rtpip_next >= profile->rtpip_index) {
100 profile->rtpip_next = 0;
101 }
102 }
103
104 if (!zstr(profile->rtpip6[profile->rtpip_next6])) {
105 tech_pvt->mparams.rtpip6 = switch_core_session_strdup(session, profile->rtpip6[profile->rtpip_next6++]);
106
107 if (zstr(tech_pvt->mparams.rtpip)) {
108 tech_pvt->mparams.rtpip = tech_pvt->mparams.rtpip6;
109 }
110
111 if (profile->rtpip_next6 >= profile->rtpip_index6) {
112 profile->rtpip_next6 = 0;
113 }
114 }
115
116 profile->inuse++;
117 switch_mutex_unlock(profile->flag_mutex);
118 switch_mutex_unlock(tech_pvt->flag_mutex);
119
120 if (tech_pvt->bte) {
121 tech_pvt->recv_te = tech_pvt->te = tech_pvt->bte;
122 } else if (!tech_pvt->te) {
123 tech_pvt->mparams.recv_te = tech_pvt->mparams.te = profile->te;
124 }
125
126 tech_pvt->mparams.dtmf_type = tech_pvt->profile->dtmf_type;
127
128 if (!sofia_test_media_flag(tech_pvt->profile, SCMF_SUPPRESS_CNG)) {
129 if (tech_pvt->bcng_pt) {
130 tech_pvt->cng_pt = tech_pvt->bcng_pt;
131 } else if (!tech_pvt->cng_pt) {
132 tech_pvt->cng_pt = profile->cng_pt;
133 }
134 }
135
136 tech_pvt->session = session;
137 tech_pvt->channel = switch_core_session_get_channel(session);
138
139 if (sofia_test_pflag(profile, PFLAG_TRACK_CALLS)) {
140 switch_channel_set_flag(tech_pvt->channel, CF_TRACKABLE);
141 }
142
143
144 if (profile->flags[PFLAG_PASS_RFC2833]) {
145 switch_channel_set_flag(tech_pvt->channel, CF_PASS_RFC2833);
146 }
147
148 if (sofia_test_pflag(tech_pvt->profile, PFLAG_RTP_NOTIMER_DURING_BRIDGE)) {
149 switch_channel_set_flag(tech_pvt->channel, CF_RTP_NOTIMER_DURING_BRIDGE);
150 }
151
152 if (sofia_test_pflag(tech_pvt->profile, PFLAG_T38_PASSTHRU)) {
153 switch_channel_set_flag(tech_pvt->channel, CF_T38_PASSTHRU);
154 }
155
156 switch_channel_set_cap(tech_pvt->channel, CC_MEDIA_ACK);
157 switch_channel_set_cap(tech_pvt->channel, CC_BYPASS_MEDIA);
158 switch_channel_set_cap(tech_pvt->channel, CC_PROXY_MEDIA);
159 switch_channel_set_cap(tech_pvt->channel, CC_JITTERBUFFER);
160 switch_channel_set_cap(tech_pvt->channel, CC_FS_RTP);
161 switch_channel_set_cap(tech_pvt->channel, CC_RTP_RTT);
162 switch_channel_set_cap(tech_pvt->channel, CC_MSRP);
163 switch_channel_set_cap(tech_pvt->channel, CC_QUEUEABLE_DTMF_DELAY);
164
165
166
167 tech_pvt->mparams.ndlb = tech_pvt->profile->mndlb;
168 tech_pvt->mparams.inbound_codec_string = profile->inbound_codec_string;
169 tech_pvt->mparams.outbound_codec_string = profile->outbound_codec_string;
170 tech_pvt->mparams.auto_rtp_bugs = profile->auto_rtp_bugs;
171 tech_pvt->mparams.timer_name = profile->timer_name;
172 tech_pvt->mparams.vflags = profile->vflags;
173 tech_pvt->mparams.manual_rtp_bugs = profile->manual_rtp_bugs;
174 tech_pvt->mparams.manual_video_rtp_bugs = profile->manual_video_rtp_bugs;
175 tech_pvt->mparams.extsipip = profile->extsipip;
176 tech_pvt->mparams.extrtpip = profile->extrtpip;
177 tech_pvt->mparams.local_network = profile->local_network;
178 tech_pvt->mparams.sipip = profile->sipip;
179 tech_pvt->mparams.jb_msec = profile->jb_msec;
180 tech_pvt->mparams.rtcp_audio_interval_msec = profile->rtcp_audio_interval_msec;
181 tech_pvt->mparams.rtcp_video_interval_msec = profile->rtcp_video_interval_msec;
182 tech_pvt->mparams.sdp_username = profile->sdp_username;
183 tech_pvt->mparams.cng_pt = tech_pvt->cng_pt;
184 tech_pvt->mparams.rtp_timeout_sec = profile->rtp_timeout_sec;
185 tech_pvt->mparams.rtp_hold_timeout_sec = profile->rtp_hold_timeout_sec;
186
187 if (profile->rtp_digit_delay) {
188 tech_pvt->mparams.dtmf_delay = profile->rtp_digit_delay;
189 }
190
191 switch_media_handle_create(&tech_pvt->media_handle, session, &tech_pvt->mparams);
192 switch_media_handle_set_media_flags(tech_pvt->media_handle, tech_pvt->profile->media_flags);
193
194 switch_core_media_check_dtmf_type(session);
195
196 for(i = 0; i < profile->cand_acl_count; i++) {
197 switch_core_media_add_ice_acl(session, SWITCH_MEDIA_TYPE_AUDIO, profile->cand_acl[i]);
198 switch_core_media_add_ice_acl(session, SWITCH_MEDIA_TYPE_VIDEO, profile->cand_acl[i]);
199 }
200
201
202 switch_core_session_set_private(session, tech_pvt);
203
204 if (channame) {
205 sofia_glue_set_name(tech_pvt, channame);
206 }
207
208 }
209
210
211
212
sofia_glue_ext_address_lookup(sofia_profile_t * profile,char ** ip,switch_port_t * port,const char * sourceip,switch_memory_pool_t * pool)213 switch_status_t sofia_glue_ext_address_lookup(sofia_profile_t *profile, char **ip, switch_port_t *port,
214 const char *sourceip, switch_memory_pool_t *pool)
215 {
216 char *error = "";
217 switch_status_t status = SWITCH_STATUS_FALSE;
218 int x;
219 switch_port_t stun_port = SWITCH_STUN_DEFAULT_PORT;
220 char *stun_ip = NULL;
221
222 if (!sourceip) {
223 return status;
224 }
225
226 if (!strncasecmp(sourceip, "host:", 5)) {
227 status = (*ip = switch_stun_host_lookup(sourceip + 5, pool)) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
228 } else if (!strncasecmp(sourceip, "stun:", 5)) {
229 char *p;
230
231 stun_ip = strdup(sourceip + 5);
232
233 switch_assert(stun_ip);
234
235 if ((p = strchr(stun_ip, ':'))) {
236 int iport;
237 *p++ = '\0';
238 iport = atoi(p);
239 if (iport > 0 && iport < 0xFFFF) {
240 stun_port = (switch_port_t) iport;
241 }
242 }
243
244 if (zstr(stun_ip)) {
245 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! NO STUN SERVER\n");
246 goto out;
247 }
248
249
250 for (x = 0; x < 5; x++) {
251 if ((status = switch_stun_lookup(ip, port, stun_ip, stun_port, &error, pool)) != SWITCH_STATUS_SUCCESS) {
252 switch_yield(100000);
253 } else {
254 break;
255 }
256 }
257
258 if (!*ip) {
259 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "STUN Failed! No IP returned\n");
260 goto out;
261 }
262 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "STUN Success [%s]:[%d]\n", *ip, *port);
263 status = SWITCH_STATUS_SUCCESS;
264 } else {
265 *ip = (char *) sourceip;
266 status = SWITCH_STATUS_SUCCESS;
267 }
268
269 out:
270
271 switch_safe_free(stun_ip);
272
273 return status;
274 }
275
276
sofia_glue_get_unknown_header(sip_t const * sip,const char * name)277 const char *sofia_glue_get_unknown_header(sip_t const *sip, const char *name)
278 {
279 sip_unknown_t *un;
280 for (un = sip->sip_unknown; un; un = un->un_next) {
281 if (!strcasecmp(un->un_name, name)) {
282 if (!zstr(un->un_value)) {
283 return un->un_value;
284 }
285 }
286 }
287 return NULL;
288 }
289
sofia_glue_str2transport(const char * str)290 sofia_transport_t sofia_glue_str2transport(const char *str)
291 {
292 if (!strncasecmp(str, "udp", 3)) {
293 return SOFIA_TRANSPORT_UDP;
294 } else if (!strncasecmp(str, "tcp", 3)) {
295 return SOFIA_TRANSPORT_TCP;
296 } else if (!strncasecmp(str, "sctp", 4)) {
297 return SOFIA_TRANSPORT_SCTP;
298 } else if (!strncasecmp(str, "tls", 3)) {
299 return SOFIA_TRANSPORT_TCP_TLS;
300 }
301
302 return SOFIA_TRANSPORT_UNKNOWN;
303 }
304
sofia_glue_str2tls_verify_policy(const char * str)305 enum tport_tls_verify_policy sofia_glue_str2tls_verify_policy(const char * str){
306 char *ptr_next;
307 int len;
308 enum tport_tls_verify_policy ret;
309 char *ptr_cur = (char *) str;
310 ret = TPTLS_VERIFY_NONE;
311
312 while (ptr_cur) {
313 if ((ptr_next = strchr(ptr_cur, '|'))) {
314 len = (int)(ptr_next++ - ptr_cur);
315 } else {
316 len = (int)strlen(ptr_cur);
317 }
318 if (!strncasecmp(ptr_cur, "in",len)) {
319 ret |= TPTLS_VERIFY_IN;
320 } else if (!strncasecmp(ptr_cur, "none",len)) {
321 ret = TPTLS_VERIFY_NONE;
322 break;
323 } else if (!strncasecmp(ptr_cur, "out",len)) {
324 ret |= TPTLS_VERIFY_OUT;
325 } else if (!strncasecmp(ptr_cur, "all",len)) {
326 ret |= TPTLS_VERIFY_ALL;
327 } else if (!strncasecmp(ptr_cur, "subjects_in",len)) {
328 ret |= TPTLS_VERIFY_SUBJECTS_IN;
329 } else if (!strncasecmp(ptr_cur, "subjects_out",len)) {
330 ret |= TPTLS_VERIFY_SUBJECTS_OUT;
331 } else if (!strncasecmp(ptr_cur, "subjects_all",len)) {
332 ret |= TPTLS_VERIFY_SUBJECTS_ALL;
333 } else {
334 char el[32] = {0};
335 strncpy(el, ptr_cur, len < sizeof(el) ? len : sizeof(el) - 1);
336 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid tls-verify-policy value: %s\n", el);
337 }
338 ptr_cur = ptr_next;
339 }
340 return ret;
341 }
342
343 /* create "local-uuid" */
sofia_glue_is_valid_session_uuid(const char * session_uuid)344 int sofia_glue_is_valid_session_uuid(const char *session_uuid)
345 {
346 int i;
347 if (zstr(session_uuid) || strlen(session_uuid) != RFC7989_SESSION_UUID_LEN) {
348 return 0;
349 }
350 for (i = 0; i < RFC7989_SESSION_UUID_LEN; i++) {
351 char c = session_uuid[i];
352 if ((c < '0' || c > '9') && (c < 'a' || c > 'f')) {
353 return 0;
354 }
355 }
356 return 1;
357 }
358
359 /* NIL session-uuid: 00000000000000000000000000000000 */
sofia_glue_is_nil_session_uuid(const char * session_uuid)360 int sofia_glue_is_nil_session_uuid(const char *session_uuid)
361 {
362 if (zstr(session_uuid)) {
363 return 0;
364 }
365 if (!memcmp(session_uuid, RFC7989_SESSION_UUID_NULL, RFC7989_SESSION_UUID_LEN)) {
366 return 1;
367 }
368 return 0;
369 }
370
sofia_glue_uuid_to_session_uuid(switch_memory_pool_t * pool,const char * uuid)371 const char *sofia_glue_uuid_to_session_uuid(switch_memory_pool_t *pool, const char *uuid)
372 {
373 char *session_uuid = NULL; /*"local-uuid", per rfc7989*/
374 if (zstr(uuid) || strlen(uuid) != 36) return NULL;
375
376 session_uuid = switch_core_alloc(pool, RFC7989_SESSION_UUID_LEN + 1);
377 memcpy(session_uuid, uuid, 8);
378 memcpy(session_uuid + 8, uuid + 9, 4);
379 memcpy(session_uuid + 12, uuid + 14, 4);
380 memcpy(session_uuid + 16, uuid + 19, 4);
381 memcpy(session_uuid + 20, uuid + 24, 12);
382
383 if (!sofia_glue_is_valid_session_uuid(session_uuid)) return NULL;
384
385 return session_uuid;
386 }
387
388 /* rfc7989 generic params, return 0 if param is disabled from config or invalid. ALL params allowed by default. */
389 /* save updated generic params list in chan var. */
sofia_glue_check_filter_generic_params(switch_core_session_t * session,sofia_profile_t * profile,char * param)390 int sofia_glue_check_filter_generic_params(switch_core_session_t *session, sofia_profile_t *profile, char *param)
391 {
392
393 char *tmp = NULL;
394 switch_channel_t *channel = switch_core_session_get_channel(session);
395
396 if (zstr(param)) {
397 return 0;
398 }
399 if (profile->rfc7989_filter) {
400 char *found = NULL; char *end = NULL;
401 char *token_array[100] = { 0 };
402 int tokens = switch_separate_string(profile->rfc7989_filter, ',', token_array, (sizeof(token_array) / sizeof(token_array[0])));
403 tmp = switch_core_session_strdup(session, param);
404 if (tokens) {
405 int i;
406 for (i = 0; i < tokens && token_array[i]; i++) {
407 while ((found = strstr(tmp, token_array[i]))) {
408 end = strchr(found, ';');
409 if (!end) end = strchr(found, '\0');
410 *found = '\0';
411 strcat(tmp, found + (end - found));
412 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
413 "Session-ID: Dropped generic param: %s\n", token_array[i]);
414 }
415 }
416 }
417 }
418
419 if (tmp) {
420 switch_channel_set_variable(channel, SWITCH_RFC7989_GENERIC_PARAM_VARIABLE, tmp);
421 } else {
422 switch_channel_set_variable(channel, SWITCH_RFC7989_GENERIC_PARAM_VARIABLE, param);
423 }
424
425 return 1;
426 }
427 /* check and store Session-ID header. */
428 /* retrieve "local-uuid" and "remote-uuid" of the remote party. */
sofia_glue_store_session_id(switch_core_session_t * session,sofia_profile_t * profile,sip_t const * sip,switch_bool_t is_reply)429 void sofia_glue_store_session_id(switch_core_session_t *session, sofia_profile_t *profile, sip_t const *sip, switch_bool_t is_reply)
430 {
431 char *a_id, *b_id, *duped, *p, *remote_param;
432 const char *header = sofia_glue_get_unknown_header(sip, "Session-ID");
433 switch_channel_t *channel = switch_core_session_get_channel(session);
434
435 if (!sofia_test_pflag(profile, PFLAG_RFC7989_SESSION_ID)) return;
436
437 if (!header) {
438 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Session-ID: missing header.");
439 return;
440 }
441
442 duped = switch_core_session_strdup(session, header);
443
444 if (zstr(duped)) return;
445
446 a_id = switch_strip_whitespace(duped);
447
448 if (zstr(a_id)) return;
449
450 p = strchr(a_id, ';');
451 if (p) *p = '\0';
452
453 if (!sofia_glue_is_valid_session_uuid(a_id)) {
454 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Session-ID: Ignoring \"%s\" parsed as \"%s\"\n", header, a_id);
455 return;
456 }
457
458 /* RFC7329 compatibility */
459 if (is_reply) {
460 const char *temp_id = switch_channel_get_variable(channel, SWITCH_RFC7989_APP_SESSION_ID_VARIABLE);
461 if (!zstr(temp_id) && !memcmp(a_id, temp_id, RFC7989_SESSION_UUID_LEN) ) {
462 /* 'If a SIP response only contains the "local-uuid" that was sent
463 * originally, this comes from a pre-standard implementation and MUST
464 * NOT be discarded for removing the nil "remote-uuid". In this
465 * case, all future transactions within this dialog MUST contain only
466 * the UUID received in the first SIP response" */
467 switch_channel_set_flag(channel, CF_RFC7329_COMPAT);
468 switch_channel_set_flag_partner(channel, CF_RFC7329_COMPAT);
469 }
470 }
471
472 /* "local-uuid" field retrieved from remote party will become
473 * SWITCH_RFC7989_APP_SESSION_ID_VARIABLE in a b2bua role. */
474 if (!zstr(a_id)) {
475 struct private_object *tech_pvt = switch_core_session_get_private(session);
476 switch_channel_set_variable(channel, SWITCH_RFC7989_SESSION_ID_VARIABLE, a_id);
477 if (tech_pvt && tech_pvt->sofia_private && !tech_pvt->sofia_private->rfc7989_uuid) {
478 tech_pvt->sofia_private->rfc7989_uuid = su_strdup(tech_pvt->nh->nh_home, a_id);
479 }
480 }
481
482 if (!p) {
483 switch_channel_set_flag(channel, CF_RFC7329_COMPAT);
484 switch_channel_set_flag_partner(channel, CF_RFC7329_COMPAT);
485 return;
486 }
487 p++;
488 remote_param = strstr(p, "remote=");
489 if (!remote_param) {
490 switch_channel_set_flag(channel, CF_RFC7329_COMPAT);
491 switch_channel_set_flag_partner(channel, CF_RFC7329_COMPAT);
492 sofia_glue_check_filter_generic_params(session, profile, p);
493 return;
494 }
495 b_id = remote_param + 7;
496 if (!zstr(b_id) && strlen(b_id) == RFC7989_SESSION_UUID_LEN /*32*/) {
497 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Session-ID: Set remote-uuid: %s\n", b_id);
498 /*using chan var as placeholder only when UAS or when answer() was called in the dialplan */
499 switch_channel_set_variable(channel, SWITCH_RFC7989_REMOTE_SESSION_ID_VARIABLE, b_id);
500 switch_channel_set_variable_partner(channel, SWITCH_RFC7989_REMOTE_SESSION_ID_VARIABLE, b_id);
501
502 } else {
503 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Session-ID: invalid uuid, ignored.\n");
504 }
505 }
506
507 /* add "Session-ID:" header */
sofia_glue_session_id_header(switch_core_session_t * session,sofia_profile_t * profile)508 char *sofia_glue_session_id_header(switch_core_session_t *session, sofia_profile_t *profile)
509 {
510 switch_channel_t *channel;
511 const char *b_id = NULL;
512 const char *a_id = NULL;
513 const char *temp_id = NULL;
514 const char *generic = NULL;
515
516 if (!session) return NULL;
517
518 if (!profile) return NULL;
519
520 if (!sofia_test_pflag(profile, PFLAG_RFC7989_SESSION_ID)) return NULL;
521
522 channel = switch_core_session_get_channel(session);
523
524 a_id = switch_channel_get_variable_partner(channel, SWITCH_RFC7989_SESSION_ID_VARIABLE);
525
526 if (zstr(a_id)) {
527 a_id = switch_channel_get_variable(channel, SWITCH_RFC7989_APP_SESSION_ID_VARIABLE);
528 if (!zstr(a_id) && strlen(a_id) == 36) {
529 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Reformatting app Session-ID: %s\n", a_id);
530 a_id = sofia_glue_uuid_to_session_uuid(switch_core_session_get_pool(session), a_id);
531 if (!zstr(a_id)) {
532 struct private_object *tech_pvt = switch_core_session_get_private(session);
533 switch_channel_set_variable(channel, SWITCH_RFC7989_APP_SESSION_ID_VARIABLE, a_id);
534 if (tech_pvt && tech_pvt->sofia_private && !tech_pvt->sofia_private->rfc7989_uuid) {
535 tech_pvt->sofia_private->rfc7989_uuid = su_strdup(tech_pvt->nh->nh_home, a_id);
536 }
537 }
538 }
539 }
540
541 if (zstr(a_id)) {
542 const char *partner_uuid = switch_channel_get_partner_uuid(channel);
543 if (!zstr(partner_uuid)) {
544 const char *partner_session_id = sofia_glue_uuid_to_session_uuid(switch_core_session_get_pool(session), partner_uuid);
545 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Setting \"Session-ID: %s\" from partner leg\n", partner_session_id);
546 switch_channel_set_variable_partner(channel, SWITCH_RFC7989_SESSION_ID_VARIABLE, partner_session_id);
547 a_id = partner_session_id;
548 }
549 }
550
551 if (((switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) && zstr(a_id) &&
552 switch_channel_get_state(channel) == CS_INIT) && switch_channel_test_flag(channel, CF_ORIGINATING)) {
553 /*outbound initial request*/
554 char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
555
556 switch_uuid_str(uuid_str, sizeof(uuid_str));
557 a_id = sofia_glue_uuid_to_session_uuid(switch_core_session_get_pool(session), uuid_str);
558 if (!zstr(a_id)) {
559 struct private_object *tech_pvt = switch_core_session_get_private(session);
560 switch_channel_set_variable(channel, SWITCH_RFC7989_APP_SESSION_ID_VARIABLE, a_id);
561 if (tech_pvt && tech_pvt->sofia_private && !tech_pvt->sofia_private->rfc7989_uuid) {
562 tech_pvt->sofia_private->rfc7989_uuid = su_strdup(tech_pvt->nh->nh_home, a_id);
563 }
564 }
565 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
566 "Session-ID: Outbound initial request. local-uuid: %s", a_id);
567 if (sofia_test_pflag(profile, PFLAG_RFC7989_FORCE_OLD)) {
568 /*for old (and obsolete) Session-ID RFC7329 */
569 return switch_core_session_sprintf(session, "Session-ID: %s", a_id);
570 }
571
572 b_id = RFC7989_SESSION_UUID_NULL;
573 return switch_core_session_sprintf(session, "Session-ID: %s;remote=%s", a_id, b_id);
574 }
575
576 temp_id = switch_channel_get_variable(channel, SWITCH_RFC7989_REMOTE_SESSION_ID_VARIABLE);
577 if ((switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) &&
578 ((switch_channel_get_state(channel) == CS_INIT) || (switch_channel_get_state(channel) == CS_EXECUTE)) &&
579 zstr(temp_id)) {
580 /* fallback to RFC7329 - "old". */
581 /* inbound initial request, no "remote" param. section 11 of RFC7989. */
582 a_id = switch_channel_get_variable(channel, SWITCH_RFC7989_SESSION_ID_VARIABLE);
583 if (zstr(a_id)) {
584 a_id = RFC7989_SESSION_UUID_NULL;
585 } else {
586 switch_channel_set_variable(channel, SWITCH_RFC7989_APP_SESSION_ID_VARIABLE, a_id);
587 }
588 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Session-ID: Fallback to RFC7329");
589 switch_channel_set_flag(channel, CF_RFC7329_COMPAT);
590 return switch_core_session_sprintf(session, "Session-ID: %s", a_id);
591 }
592 if ((switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) &&
593 ((switch_channel_get_state(channel) == CS_INIT) || (switch_channel_get_state(channel) == CS_EXECUTE)) &&
594 sofia_glue_is_nil_session_uuid(temp_id)) {
595 /*inbound initial request*/
596 char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
597
598 switch_uuid_str(uuid_str, sizeof(uuid_str));
599 a_id = sofia_glue_uuid_to_session_uuid(switch_core_session_get_pool(session), uuid_str);
600 if (!zstr(a_id)) {
601 struct private_object *tech_pvt = switch_core_session_get_private(session);
602 switch_channel_set_variable(channel, SWITCH_RFC7989_APP_SESSION_ID_VARIABLE, a_id);
603 if (tech_pvt && tech_pvt->sofia_private) {
604 tech_pvt->sofia_private->rfc7989_uuid = su_strdup(tech_pvt->nh->nh_home, a_id);
605 }
606 }
607 b_id = switch_channel_get_variable(channel, SWITCH_RFC7989_SESSION_ID_VARIABLE);
608 if (zstr(b_id)) {
609 b_id = RFC7989_SESSION_UUID_NULL;
610 }
611 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
612 "Session-ID: Inbound initial request. local-uuid: %s", a_id);
613 return switch_core_session_sprintf(session, "Session-ID: %s;remote=%s", a_id, b_id);
614 }
615
616 if (zstr(a_id)) {
617 struct private_object *tech_pvt = switch_core_session_get_private(session);
618 /* setting NIL local-uuid should never happen,
619 * but in case we don't get to set it properly by here, just set it to NIL */
620 if (tech_pvt && tech_pvt->sofia_private && tech_pvt->sofia_private->rfc7989_uuid) {
621 /* handle BYE after REFER or other cases where the channel is destroyed already and we can't get the chan var */
622 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Session-ID: retrieved local-uuid ");
623 a_id = tech_pvt->sofia_private->rfc7989_uuid;
624 } else {
625 a_id = RFC7989_SESSION_UUID_NULL;
626 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Session-ID: NIL local-uuid ");
627 }
628 }
629
630 b_id = switch_channel_get_variable(channel, SWITCH_RFC7989_SESSION_ID_VARIABLE);
631
632 if (zstr(b_id) && switch_channel_test_flag(channel, CF_RFC7329_COMPAT)) {
633 /* fallback to RFC7329 , only one uuid*/
634 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING ,"Session-ID: Fallback to RFC7329, use one uuid");
635 return switch_core_session_sprintf(session, "Session-ID: %s", a_id);
636 } else if (zstr(b_id)) {
637 b_id = RFC7989_SESSION_UUID_NULL;
638 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Session-ID: set NIL remote-uuid");
639 }
640
641 /* B2B: handle generic params*/
642 generic = switch_channel_get_variable_partner(channel, SWITCH_RFC7989_GENERIC_PARAM_VARIABLE);
643 if (!zstr(generic)) {
644 /* copy generic param (name and val) */
645 return switch_core_session_sprintf(session, "Session-ID: %s;%s", a_id, generic);
646 }
647 if (switch_channel_test_flag(channel, CF_RFC7329_COMPAT)) {
648 return switch_core_session_sprintf(session, "Session-ID: %s", a_id);
649 }
650 return switch_core_session_sprintf(session, "Session-ID: %s;remote=%s", a_id, b_id);
651 }
652
sofia_glue_find_parameter_value(switch_core_session_t * session,const char * str,const char * param)653 char *sofia_glue_find_parameter_value(switch_core_session_t *session, const char *str, const char *param)
654 {
655 const char *param_ptr;
656 char *param_value;
657 char *tmp;
658 switch_size_t param_len;
659
660 if (zstr(str) || zstr(param) || !session) return NULL;
661
662 if (end_of(param) != '=') {
663 param = switch_core_session_sprintf(session, "%s=", param);
664 if (zstr(param)) return NULL;
665 }
666
667 param_len = strlen(param);
668 param_ptr = sofia_glue_find_parameter(str, param);
669
670 if (zstr(param_ptr)) return NULL;
671
672 param_value = switch_core_session_strdup(session, param_ptr + param_len);
673
674 if (zstr(param_value)) return NULL;
675
676 if ((tmp = strchr(param_value, ';'))) *tmp = '\0';
677
678 return param_value;
679 }
680
sofia_glue_find_parameter(const char * str,const char * param)681 char *sofia_glue_find_parameter(const char *str, const char *param)
682 {
683 char *ptr = NULL;
684
685 ptr = (char *) str;
686 while (ptr) {
687 if (!strncasecmp(ptr, param, strlen(param)))
688 return ptr;
689
690 if ((ptr = strchr(ptr, ';')))
691 ptr++;
692 }
693
694 return NULL;
695 }
696
sofia_glue_url2transport(const url_t * url)697 sofia_transport_t sofia_glue_url2transport(const url_t *url)
698 {
699 char *ptr = NULL;
700 int tls = 0;
701
702 if (!url)
703 return SOFIA_TRANSPORT_UNKNOWN;
704
705 if (url->url_scheme && !strcasecmp(url->url_scheme, "sips")) {
706 tls++;
707 }
708
709 if ((ptr = sofia_glue_find_parameter(url->url_params, "transport="))) {
710 return sofia_glue_str2transport(ptr + 10);
711 }
712
713 return (tls) ? SOFIA_TRANSPORT_TCP_TLS : SOFIA_TRANSPORT_UDP;
714 }
715
sofia_glue_via2transport(const sip_via_t * via)716 sofia_transport_t sofia_glue_via2transport(const sip_via_t * via)
717 {
718 char *ptr = NULL;
719
720 if (!via || !via->v_protocol)
721 return SOFIA_TRANSPORT_UNKNOWN;
722
723 if ((ptr = strrchr(via->v_protocol, '/'))) {
724 ptr++;
725
726 if (!strncasecmp(ptr, "udp", 3)) {
727 return SOFIA_TRANSPORT_UDP;
728 } else if (!strncasecmp(ptr, "tcp", 3)) {
729 return SOFIA_TRANSPORT_TCP;
730 } else if (!strncasecmp(ptr, "tls", 3)) {
731 return SOFIA_TRANSPORT_TCP_TLS;
732 } else if (!strncasecmp(ptr, "sctp", 4)) {
733 return SOFIA_TRANSPORT_SCTP;
734 } else if (!strncasecmp(ptr, "wss", 3)) {
735 return SOFIA_TRANSPORT_WSS;
736 } else if (!strncasecmp(ptr, "ws", 2)) {
737 return SOFIA_TRANSPORT_WS;
738 }
739 }
740
741 return SOFIA_TRANSPORT_UNKNOWN;
742 }
743
sofia_glue_transport2str(const sofia_transport_t tp)744 const char *sofia_glue_transport2str(const sofia_transport_t tp)
745 {
746 switch (tp) {
747 case SOFIA_TRANSPORT_TCP:
748 return "tcp";
749
750 case SOFIA_TRANSPORT_TCP_TLS:
751 return "tls";
752
753 case SOFIA_TRANSPORT_SCTP:
754 return "sctp";
755
756 case SOFIA_TRANSPORT_WS:
757 return "ws";
758
759 case SOFIA_TRANSPORT_WSS:
760 return "wss";
761
762 default:
763 return "udp";
764 }
765 }
766
sofia_glue_create_external_via(switch_core_session_t * session,sofia_profile_t * profile,sofia_transport_t transport)767 char *sofia_glue_create_external_via(switch_core_session_t *session, sofia_profile_t *profile, sofia_transport_t transport)
768 {
769 return sofia_glue_create_via(session, profile->extsipip, (sofia_glue_transport_has_tls(transport))
770 ? profile->tls_sip_port : profile->extsipport, transport);
771 }
772
sofia_glue_create_via(switch_core_session_t * session,const char * ip,switch_port_t port,sofia_transport_t transport)773 char *sofia_glue_create_via(switch_core_session_t *session, const char *ip, switch_port_t port, sofia_transport_t transport)
774 {
775 char *ipv6 = strchr(ip, ':');
776 if (port && port != 5060) {
777 if (session) {
778 return switch_core_session_sprintf(session, "SIP/2.0/%s %s%s%s:%d;rport", sofia_glue_transport2str(transport), ipv6 ? "[" : "", ip, ipv6 ? "]" : "", port);
779 } else {
780 return switch_mprintf("SIP/2.0/%s %s%s%s:%d;rport", sofia_glue_transport2str(transport), ipv6 ? "[" : "", ip, ipv6 ? "]" : "", port);
781 }
782 } else {
783 if (session) {
784 return switch_core_session_sprintf(session, "SIP/2.0/%s %s%s%s;rport", sofia_glue_transport2str(transport), ipv6 ? "[" : "", ip, ipv6 ? "]" : "");
785 } else {
786 return switch_mprintf("SIP/2.0/%s %s%s%s;rport", sofia_glue_transport2str(transport), ipv6 ? "[" : "", ip, ipv6 ? "]" : "");
787 }
788 }
789 }
790
sofia_glue_strip_uri(const char * str)791 char *sofia_glue_strip_uri(const char *str)
792 {
793 char *p;
794 char *r;
795
796 if ((p = strchr(str, '<'))) {
797 p++;
798 r = strdup(p);
799 switch_assert(r);
800 if ((p = strchr(r, '>'))) {
801 *p = '\0';
802 }
803 } else {
804 r = strdup(str);
805 switch_assert(r);
806 }
807
808 return r;
809 }
810
811
812
sofia_glue_transport_has_tls(const sofia_transport_t tp)813 int sofia_glue_transport_has_tls(const sofia_transport_t tp)
814 {
815 switch (tp) {
816 case SOFIA_TRANSPORT_TCP_TLS:
817 return 1;
818
819 default:
820 return 0;
821 }
822 }
823
sofia_glue_get_addr(msg_t * msg,char * buf,size_t buflen,int * port)824 void sofia_glue_get_addr(msg_t *msg, char *buf, size_t buflen, int *port)
825 {
826 su_addrinfo_t *addrinfo = msg_addrinfo(msg);
827 if (!addrinfo) {
828 return;
829 }
830
831 if (buf) {
832 get_addr(buf, buflen, addrinfo->ai_addr, (socklen_t)addrinfo->ai_addrlen);
833 }
834
835 if (port) {
836 *port = get_port(addrinfo->ai_addr);
837 }
838 }
839
sofia_overcome_sip_uri_weakness(switch_core_session_t * session,const char * uri,const sofia_transport_t transport,switch_bool_t uri_only,const char * params,const char * invite_tel_params)840 char *sofia_overcome_sip_uri_weakness(switch_core_session_t *session, const char *uri, const sofia_transport_t transport, switch_bool_t uri_only,
841 const char *params, const char *invite_tel_params)
842 {
843 char *stripped = switch_core_session_strdup(session, uri);
844 char *new_uri = NULL;
845 char *p;
846 const char *url_params = NULL;
847
848 if (!zstr(params) && *params == '~') {
849 url_params = params + 1;
850 params = NULL;
851 }
852
853 stripped = sofia_glue_get_url_from_contact(stripped, 0);
854
855 /* remove our params so we don't make any whiny moronic device piss its pants and forget who it is for a half-hour */
856 if ((p = (char *) switch_stristr(";fs_", stripped))) {
857 *p = '\0';
858 }
859
860 if (transport && transport != SOFIA_TRANSPORT_UDP) {
861
862 if (switch_stristr("port=", stripped)) {
863 new_uri = switch_core_session_sprintf(session, "%s%s%s", uri_only ? "" : "<", stripped, uri_only ? "" : ">");
864 } else {
865 if (params) {
866 new_uri = switch_core_session_sprintf(session, "%s%s;transport=%s;%s%s",
867 uri_only ? "" : "<", stripped, sofia_glue_transport2str(transport), params, uri_only ? "" : ">");
868 } else {
869 new_uri = switch_core_session_sprintf(session, "%s%s;transport=%s%s",
870 uri_only ? "" : "<", stripped, sofia_glue_transport2str(transport), uri_only ? "" : ">");
871 }
872 }
873 } else {
874 if (params) {
875 new_uri = switch_core_session_sprintf(session, "%s%s;%s%s", uri_only ? "" : "<", stripped, params, uri_only ? "" : ">");
876 } else {
877 if (uri_only) {
878 new_uri = stripped;
879 } else {
880 new_uri = switch_core_session_sprintf(session, "<%s>", stripped);
881 }
882 }
883 }
884
885 if (url_params && !uri_only) {
886 new_uri = switch_core_session_sprintf(session, "%s;%s", new_uri, url_params);
887 }
888
889 if (!zstr(invite_tel_params)) {
890 char *lhs, *rhs = strchr(new_uri, '@');
891
892 if (!zstr(rhs)) {
893 *rhs++ = '\0';
894 lhs = new_uri;
895 new_uri = switch_core_session_sprintf(session, "%s;%s@%s", lhs, invite_tel_params, rhs);
896 }
897 }
898
899 return new_uri;
900 }
901
sofia_glue_get_extra_headers(switch_channel_t * channel,const char * prefix)902 char *sofia_glue_get_extra_headers(switch_channel_t *channel, const char *prefix)
903 {
904 char *extra_headers = NULL;
905 switch_stream_handle_t stream = { 0 };
906 switch_event_header_t *hi = NULL;
907 const char *exclude_regex = NULL;
908 switch_regex_t *re = NULL;
909 int ovector[30] = {0};
910 int proceed;
911
912 exclude_regex = switch_channel_get_variable(channel, "exclude_outgoing_extra_header");
913 SWITCH_STANDARD_STREAM(stream);
914 if ((hi = switch_channel_variable_first(channel))) {
915 for (; hi; hi = hi->next) {
916 const char *name = (char *) hi->name;
917 char *value = (char *) hi->value;
918
919 if (!strcasecmp(name, "sip_geolocation")) {
920 stream.write_function(&stream, "Geolocation: %s\r\n", value);
921 }
922
923 if (!strncasecmp(name, prefix, strlen(prefix))) {
924 if ( !exclude_regex || !(proceed = switch_regex_perform(name, exclude_regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) {
925 const char *hname = name + strlen(prefix);
926 stream.write_function(&stream, "%s: %s\r\n", hname, value);
927 switch_regex_safe_free(re);
928 } else {
929 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Ignoring Extra Header [%s] , matches exclude_outgoing_extra_header [%s]\n", name, exclude_regex);
930 }
931 }
932 }
933 switch_channel_variable_last(channel);
934 }
935
936 if (!zstr((char *) stream.data)) {
937 extra_headers = stream.data;
938 } else {
939 switch_safe_free(stream.data);
940 }
941
942 return extra_headers;
943 }
944
sofia_glue_set_extra_headers(switch_core_session_t * session,sip_t const * sip,const char * prefix)945 void sofia_glue_set_extra_headers(switch_core_session_t *session, sip_t const *sip, const char *prefix)
946 {
947 sip_unknown_t *un;
948 char name[512] = "";
949 switch_channel_t *channel = switch_core_session_get_channel(session);
950 char pstr[32];
951
952
953 if (!sip || !channel) {
954 return;
955 }
956
957 for (un = sip->sip_unknown; un; un = un->un_next) {
958 if (sofia_test_extra_headers(un->un_name)) {
959 if (!zstr(un->un_value)) {
960 switch_snprintf(name, sizeof(name), "%s%s", prefix, un->un_name);
961 switch_channel_set_variable(channel, name, un->un_value);
962 }
963 }
964 }
965
966 switch_snprintf(pstr, sizeof(pstr), "execute_on_%sprefix", prefix);
967 switch_channel_execute_on(channel, pstr);
968 switch_channel_api_on(channel, pstr);
969
970 switch_channel_execute_on(channel, "execute_on_sip_extra_headers");
971 switch_channel_api_on(channel, "api_on_sip_extra_headers");
972 }
973
sofia_glue_get_extra_headers_from_event(switch_event_t * event,const char * prefix)974 char *sofia_glue_get_extra_headers_from_event(switch_event_t *event, const char *prefix)
975 {
976 char *extra_headers = NULL;
977 switch_stream_handle_t stream = { 0 };
978 switch_event_header_t *hp;
979
980 SWITCH_STANDARD_STREAM(stream);
981 for (hp = event->headers; hp; hp = hp->next) {
982 if (!zstr(hp->name) && !zstr(hp->value) && !strncasecmp(hp->name, prefix, strlen(prefix))) {
983 char *name = strdup(hp->name);
984 const char *hname;
985 switch_assert(name);
986 hname = name + strlen(prefix);
987 stream.write_function(&stream, "%s: %s\r\n", hname, (char *)hp->value);
988 free(name);
989 }
990 }
991
992 if (!zstr((char *) stream.data)) {
993 extra_headers = stream.data;
994 } else {
995 switch_safe_free(stream.data);
996 }
997
998 return extra_headers;
999 }
1000
sofia_glue_get_non_extra_unknown_headers(sip_t const * sip)1001 char *sofia_glue_get_non_extra_unknown_headers(sip_t const *sip)
1002 {
1003 char *unknown = NULL;
1004 switch_stream_handle_t stream = { 0 };
1005 sip_unknown_t *un;
1006
1007 if (!sip) {
1008 return NULL;
1009 }
1010
1011 SWITCH_STANDARD_STREAM(stream);
1012 for (un = sip->sip_unknown; un; un = un->un_next) {
1013 if (!sofia_test_extra_headers(un->un_name)) {
1014 if (!zstr(un->un_value)) {
1015 stream.write_function(&stream, "%s: %s\r\n",un->un_name,un->un_value);
1016 }
1017 }
1018 }
1019 if (!zstr((char *) stream.data)) {
1020 unknown = stream.data;
1021 } else {
1022 switch_safe_free(stream.data);
1023 }
1024
1025 return unknown;
1026 }
1027
sofia_glue_do_invite(switch_core_session_t * session)1028 switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
1029 {
1030 char *alert_info = NULL;
1031 const char *max_forwards = NULL;
1032 const char *alertbuf;
1033 private_object_t *tech_pvt = switch_core_session_get_private(session);
1034 switch_channel_t *channel = switch_core_session_get_channel(session);
1035 switch_caller_profile_t *caller_profile;
1036 const char *cid_name, *cid_num;
1037 char *e_dest = NULL;
1038 const char *holdstr = "";
1039 char *extra_headers = NULL;
1040 switch_status_t status = SWITCH_STATUS_FALSE;
1041 uint32_t session_timeout = tech_pvt->profile->session_timeout;
1042 const char *val;
1043 const char *rep;
1044 const char *call_id = NULL;
1045 char *route = NULL;
1046 char *route_uri = NULL;
1047 sofia_destination_t *dst = NULL;
1048 sofia_cid_type_t cid_type = tech_pvt->profile->cid_type;
1049 sip_cseq_t *cseq = NULL;
1050 const char *invite_record_route = switch_channel_get_variable(tech_pvt->channel, "sip_invite_record_route");
1051 const char *invite_route_uri = switch_channel_get_variable(tech_pvt->channel, "sip_invite_route_uri");
1052 const char *invite_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_from");
1053 const char *invite_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_to");
1054 const char *handle_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_handle_full_from");
1055 const char *handle_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_handle_full_to");
1056 const char *force_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_force_full_from");
1057 const char *force_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_force_full_to");
1058 const char *content_encoding = switch_channel_get_variable(tech_pvt->channel, "sip_content_encoding");
1059 char *mp = NULL, *mp_type = NULL;
1060 char *record_route = NULL;
1061 const char *recover_via = NULL;
1062 int require_timer = 1;
1063 uint8_t is_t38 = 0;
1064 const char *hold_char = "*";
1065 const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
1066
1067
1068 if (sofia_test_flag(tech_pvt, TFLAG_SIP_HOLD_INACTIVE) ||
1069 switch_true(switch_channel_get_variable_dup(tech_pvt->channel, "sofia_hold_inactive", SWITCH_FALSE, -1))) {
1070 hold_char = "#";
1071 }
1072
1073 if (switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING)) {
1074 const char *recover_contact = switch_channel_get_variable(tech_pvt->channel, "sip_recover_contact");
1075 recover_via = switch_channel_get_variable(tech_pvt->channel, "sip_recover_via");
1076
1077 if (!zstr(invite_record_route)) {
1078 record_route = switch_core_session_sprintf(session, "Record-Route: %s", invite_record_route);
1079 }
1080
1081 if (recover_contact) {
1082 char *tmp = switch_core_session_strdup(session, recover_contact);
1083 tech_pvt->redirected = sofia_glue_get_url_from_contact(tmp, 0);
1084 }
1085 }
1086
1087
1088 if ((rep = switch_channel_get_variable(channel, SOFIA_REPLACES_HEADER))) {
1089 switch_channel_set_variable(channel, SOFIA_REPLACES_HEADER, NULL);
1090 }
1091
1092 switch_assert(tech_pvt != NULL);
1093
1094 sofia_clear_flag_locked(tech_pvt, TFLAG_SDP);
1095
1096 caller_profile = switch_channel_get_caller_profile(channel);
1097
1098 if (!caller_profile) {
1099 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
1100 switch_goto_status(SWITCH_STATUS_FALSE, end);
1101 }
1102
1103
1104 if ((val = switch_channel_get_variable_dup(channel, "sip_require_timer", SWITCH_FALSE, -1)) && switch_false(val)) {
1105 require_timer = 0;
1106 }
1107
1108
1109 cid_name = caller_profile->caller_id_name;
1110 cid_num = caller_profile->caller_id_number;
1111
1112 if (!tech_pvt->sent_invites && !switch_channel_test_flag(channel, CF_ANSWERED)) {
1113 switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_FALSE);
1114 switch_core_media_check_video_codecs(tech_pvt->session);
1115 }
1116
1117 check_decode(cid_name, session);
1118 check_decode(cid_num, session);
1119
1120
1121 if ((alertbuf = switch_channel_get_variable(channel, "alert_info"))) {
1122 alert_info = switch_core_session_sprintf(tech_pvt->session, "Alert-Info: %s", alertbuf);
1123 }
1124
1125 max_forwards = switch_channel_get_variable(channel, SWITCH_MAX_FORWARDS_VARIABLE);
1126
1127 if ((status = switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0)) != SWITCH_STATUS_SUCCESS) {
1128 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Port Error!\n");
1129 goto end;
1130 }
1131
1132 if (!switch_channel_get_private(tech_pvt->channel, "t38_options") || zstr(tech_pvt->mparams.local_sdp_str)) {
1133 switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL, 0, NULL, 0);
1134 }
1135
1136 sofia_set_flag_locked(tech_pvt, TFLAG_READY);
1137
1138 if (!tech_pvt->nh) {
1139 char *d_url = NULL, *url = NULL, *url_str = NULL;
1140 sofia_private_t *sofia_private;
1141 char *invite_contact = NULL, *to_str, *use_from_str, *from_str;
1142 const char *t_var;
1143 char *rpid_domain = NULL, *p;
1144 const char *priv = "off";
1145 const char *screen = "no";
1146 const char *invite_params = switch_channel_get_variable(tech_pvt->channel, "sip_invite_params");
1147 const char *invite_to_params = switch_channel_get_variable(tech_pvt->channel, "sip_invite_to_params");
1148 const char *invite_tel_params = switch_channel_get_variable(switch_core_session_get_channel(session), "sip_invite_tel_params");
1149 const char *invite_to_uri = switch_channel_get_variable(tech_pvt->channel, "sip_invite_to_uri");
1150 const char *invite_from_uri = switch_channel_get_variable(tech_pvt->channel, "sip_invite_from_uri");
1151 const char *invite_contact_params = switch_channel_get_variable(tech_pvt->channel, "sip_invite_contact_params");
1152 const char *invite_from_params = switch_channel_get_variable(tech_pvt->channel, "sip_invite_from_params");
1153 const char *invite_pid_params = switch_channel_get_variable(tech_pvt->channel, "sip_invite_pid_params");
1154 const char *from_var = switch_channel_get_variable(tech_pvt->channel, "sip_from_uri");
1155 const char *from_display = switch_channel_get_variable(tech_pvt->channel, "sip_from_display");
1156 const char *invite_req_uri = switch_channel_get_variable(tech_pvt->channel, "sip_invite_req_uri");
1157 const char *invite_domain = switch_channel_get_variable(tech_pvt->channel, "sip_invite_domain");
1158
1159 const char *use_name, *use_number;
1160
1161 if (zstr(tech_pvt->dest)) {
1162 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "URL Error!\n");
1163 switch_goto_status(SWITCH_STATUS_FALSE, end);
1164 }
1165
1166 if ((d_url = sofia_glue_get_url_from_contact(tech_pvt->dest, 1))) {
1167 url = d_url;
1168 } else {
1169 url = tech_pvt->dest;
1170 }
1171
1172 if (!tech_pvt->from_str) {
1173 const char *sipip;
1174 const char *format;
1175 char *use_cid_num = switch_core_session_url_encode(tech_pvt->session, cid_num);
1176
1177 sipip = tech_pvt->profile->sipip;
1178
1179 if (!zstr(tech_pvt->mparams.remote_ip) && sofia_glue_check_nat(tech_pvt->profile, tech_pvt->mparams.remote_ip)) {
1180 sipip = tech_pvt->profile->extsipip;
1181 }
1182
1183 if (!zstr(invite_domain)) {
1184 sipip = invite_domain;
1185 }
1186
1187 format = strchr(sipip, ':') ? "\"%s\" <sip:%s%s[%s]>" : "\"%s\" <sip:%s%s%s>";
1188
1189 tech_pvt->from_str = switch_core_session_sprintf(tech_pvt->session, format, cid_name, use_cid_num, !zstr(cid_num) ? "@" : "", sipip);
1190 }
1191
1192 if (from_var) {
1193 if (strncasecmp(from_var, "sip:", 4) || strncasecmp(from_var, "sips:", 5)) {
1194 use_from_str = switch_core_session_strdup(tech_pvt->session, from_var);
1195 } else {
1196 use_from_str = switch_core_session_sprintf(tech_pvt->session, "sip:%s", from_var);
1197 }
1198 } else if (!zstr(tech_pvt->gateway_from_str)) {
1199 use_from_str = tech_pvt->gateway_from_str;
1200 } else {
1201 use_from_str = tech_pvt->from_str;
1202 }
1203
1204 if (!zstr(tech_pvt->gateway_from_str)) {
1205 rpid_domain = switch_core_session_strdup(session, tech_pvt->gateway_from_str);
1206 } else if (!zstr(tech_pvt->from_str)) {
1207 rpid_domain = switch_core_session_strdup(session, use_from_str);
1208 }
1209
1210 sofia_glue_get_url_from_contact(rpid_domain, 0);
1211 if ((rpid_domain = strrchr(rpid_domain, '@'))) {
1212 rpid_domain++;
1213 if ((p = strchr(rpid_domain, ';'))) {
1214 *p = '\0';
1215 }
1216 }
1217
1218 if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTO_NAT)) {
1219 if (!zstr(tech_pvt->mparams.remote_ip) && !zstr(tech_pvt->profile->extsipip) && sofia_glue_check_nat(tech_pvt->profile, tech_pvt->mparams.remote_ip)) {
1220 rpid_domain = tech_pvt->profile->extsipip;
1221 } else {
1222 rpid_domain = tech_pvt->profile->sipip;
1223 }
1224 }
1225
1226 if (!zstr(invite_domain)) {
1227 rpid_domain = (char *)invite_domain;
1228 }
1229
1230 if (zstr(rpid_domain)) {
1231 rpid_domain = "cluecon.com";
1232 }
1233
1234 if (!zstr(tech_pvt->dest)) {
1235 dst = sofia_glue_get_destination(tech_pvt->dest);
1236 }
1237
1238 /*
1239 * Ignore transport chanvar and uri parameter for gateway connections
1240 * since all of them have been already taken care of in mod_sofia.c:sofia_outgoing_channel()
1241 */
1242 if (tech_pvt->transport == SOFIA_TRANSPORT_UNKNOWN && zstr(tech_pvt->gateway_name)) {
1243 if (dst && dst->route_uri) {
1244 p = dst->route_uri;
1245 } else {
1246 p = url;
1247 }
1248 if ((p = (char *) switch_stristr("port=", p))) {
1249 p += 5;
1250 tech_pvt->transport = sofia_glue_str2transport(p);
1251 } else {
1252 if ((t_var = switch_channel_get_variable(channel, "sip_transport"))) {
1253 tech_pvt->transport = sofia_glue_str2transport(t_var);
1254 }
1255 }
1256
1257 if (tech_pvt->transport == SOFIA_TRANSPORT_UNKNOWN) {
1258 tech_pvt->transport = SOFIA_TRANSPORT_UDP;
1259 }
1260 }
1261
1262 if (!zstr(tech_pvt->mparams.remote_ip) && sofia_glue_check_nat(tech_pvt->profile, tech_pvt->mparams.remote_ip)) {
1263 tech_pvt->user_via = sofia_glue_create_external_via(session, tech_pvt->profile, tech_pvt->transport);
1264 }
1265
1266 if (!sofia_test_pflag(tech_pvt->profile, PFLAG_TLS) && sofia_glue_transport_has_tls(tech_pvt->transport)) {
1267 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "TLS not supported by profile\n");
1268 switch_goto_status(SWITCH_STATUS_FALSE, end);
1269 }
1270
1271 if (zstr(tech_pvt->invite_contact)) {
1272 const char *contact;
1273 if ((contact = switch_channel_get_variable(channel, "sip_contact_user"))) {
1274 char *ip_addr = tech_pvt->profile->sipip;
1275 char *ipv6;
1276
1277 if ( !zstr(tech_pvt->mparams.remote_ip) && sofia_glue_check_nat(tech_pvt->profile, tech_pvt->mparams.remote_ip ) ) {
1278 ip_addr = tech_pvt->profile->extsipip;
1279 }
1280
1281 ipv6 = strchr(ip_addr, ':');
1282
1283 if (sofia_glue_transport_has_tls(tech_pvt->transport)) {
1284 tech_pvt->invite_contact = switch_core_session_sprintf(session, "sip:%s@%s%s%s:%d", contact,
1285 ipv6 ? "[" : "", ip_addr, ipv6 ? "]" : "", tech_pvt->profile->tls_sip_port);
1286 } else {
1287 tech_pvt->invite_contact = switch_core_session_sprintf(session, "sip:%s@%s%s%s:%d", contact,
1288 ipv6 ? "[" : "", ip_addr, ipv6 ? "]" : "", tech_pvt->profile->extsipport);
1289 }
1290 } else {
1291 tech_pvt->invite_contact = sofia_glue_get_profile_url(tech_pvt->profile, tech_pvt->mparams.remote_ip, tech_pvt->transport);
1292 }
1293 }
1294
1295 url_str = sofia_overcome_sip_uri_weakness(session, url, tech_pvt->transport, SWITCH_TRUE, invite_params, invite_tel_params);
1296 invite_contact = sofia_overcome_sip_uri_weakness(session, tech_pvt->invite_contact, tech_pvt->transport, SWITCH_FALSE, invite_contact_params, NULL);
1297 from_str = sofia_overcome_sip_uri_weakness(session, invite_from_uri ? invite_from_uri : use_from_str, 0, SWITCH_TRUE, invite_from_params, NULL);
1298 to_str = sofia_overcome_sip_uri_weakness(session, invite_to_uri ? invite_to_uri : tech_pvt->dest_to, 0, SWITCH_FALSE, invite_to_params, NULL);
1299
1300 switch_channel_set_variable(channel, "sip_outgoing_contact_uri", invite_contact);
1301
1302 /*
1303 Does the "genius" who wanted SIP to be "text-based" so it was "easier to read" even use it now,
1304 or did he just suggest it to make our lives miserable?
1305 */
1306 use_from_str = from_str;
1307
1308 if (!switch_stristr("sip:", use_from_str)) {
1309 use_from_str = switch_core_session_sprintf(session, "sip:%s", use_from_str);
1310 }
1311
1312 if (!from_display && (!strcasecmp(tech_pvt->caller_profile->caller_id_name, "_undef_") || zstr(tech_pvt->caller_profile->caller_id_name))) {
1313 from_str = switch_core_session_sprintf(session, "<%s>", use_from_str);
1314 } else {
1315 char *name = switch_core_session_strdup(session, from_display ? from_display : tech_pvt->caller_profile->caller_id_name);
1316 check_decode(name, session);
1317 from_str = switch_core_session_sprintf(session, "\"%s\" <%s>", name, use_from_str);
1318 }
1319
1320 if (!(call_id = switch_channel_get_variable(channel, "sip_invite_call_id"))) {
1321 if (sofia_test_pflag(tech_pvt->profile, PFLAG_UUID_AS_CALLID)) {
1322 call_id = switch_core_session_get_uuid(session);
1323 }
1324 }
1325
1326 if (handle_full_from) {
1327 from_str = (char *) handle_full_from;
1328 }
1329
1330 if (handle_full_to) {
1331 to_str = (char *) handle_full_to;
1332 }
1333
1334
1335 if (force_full_from) {
1336 from_str = (char *) force_full_from;
1337 }
1338
1339 if (force_full_to) {
1340 to_str = (char *) force_full_to;
1341 }
1342
1343
1344 if (invite_req_uri) {
1345 url_str = (char *) invite_req_uri;
1346 }
1347
1348 if (url_str) {
1349 char *s = NULL;
1350 if (!strncasecmp(url_str, "sip:", 4)) {
1351 s = url_str + 4;
1352 }
1353 if (!strncasecmp(url_str, "sips:", 5)) {
1354 s = url_str + 5;
1355 }
1356
1357 /* tel: patch from jaybinks, added by MC
1358 It compiles but I don't have a way to test it
1359 */
1360 if (!strncasecmp(url_str, "tel:", 4)) {
1361 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
1362 SWITCH_LOG_ERROR, "URL Error! tel: uri's not supported at this time\n");
1363 switch_goto_status(SWITCH_STATUS_FALSE, end);
1364 }
1365 if (!s) {
1366 s = url_str;
1367 }
1368 switch_channel_set_variable(channel, "sip_req_uri", s);
1369 }
1370
1371 switch_channel_set_variable(channel, "sip_to_host", sofia_glue_get_host(to_str, switch_core_session_get_pool(session)));
1372 switch_channel_set_variable(channel, "sip_from_host", sofia_glue_get_host(from_str, switch_core_session_get_pool(session)));
1373
1374 if (!(tech_pvt->nh = nua_handle(tech_pvt->profile->nua, NULL,
1375 NUTAG_URL(url_str),
1376 TAG_IF(call_id, SIPTAG_CALL_ID_STR(call_id)),
1377 TAG_IF(!zstr(record_route), SIPTAG_HEADER_STR(record_route)),
1378 SIPTAG_TO_STR(to_str), SIPTAG_FROM_STR(from_str), SIPTAG_CONTACT_STR(invite_contact), TAG_END()))) {
1379
1380 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT,
1381 "Error creating HANDLE!\nurl_str=[%s]\ncall_id=[%s]\nto_str=[%s]\nfrom_str=[%s]\ninvite_contact=[%s]\n",
1382 url_str,
1383 call_id ? call_id : "N/A",
1384 to_str,
1385 from_str,
1386 invite_contact);
1387
1388 switch_safe_free(d_url);
1389 switch_goto_status(SWITCH_STATUS_FALSE, end);
1390 }
1391
1392 if (tech_pvt->dest && (strstr(tech_pvt->dest, ";fs_nat") || strstr(tech_pvt->dest, ";received")
1393 || ((val = switch_channel_get_variable(channel, "sip_sticky_contact")) && switch_true(val)))) {
1394 sofia_set_flag(tech_pvt, TFLAG_NAT);
1395 tech_pvt->record_route = switch_core_session_strdup(tech_pvt->session, url_str);
1396 if (!dst || !dst->route_uri) {
1397 route_uri = tech_pvt->record_route;
1398 }
1399 session_timeout = SOFIA_NAT_SESSION_TIMEOUT;
1400 switch_channel_set_variable(channel, "sip_nat_detected", "true");
1401 }
1402
1403 if ((val = switch_channel_get_variable(channel, "sip_cid_type"))) {
1404 cid_type = sofia_cid_name2type(val);
1405 }
1406
1407 if (switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING) && switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
1408 if (zstr((use_name = switch_channel_get_variable(tech_pvt->channel, "effective_callee_id_name"))) &&
1409 zstr((use_name = switch_channel_get_variable(tech_pvt->channel, "sip_callee_id_name")))) {
1410 if (!(use_name = switch_channel_get_variable(tech_pvt->channel, "sip_to_display"))) {
1411 use_name = switch_channel_get_variable(tech_pvt->channel, "sip_to_user");
1412 }
1413 }
1414
1415 if (zstr((use_number = switch_channel_get_variable(tech_pvt->channel, "effective_callee_id_number"))) &&
1416 zstr((use_number = switch_channel_get_variable(tech_pvt->channel, "sip_callee_id_number")))) {
1417 use_number = switch_channel_get_variable(tech_pvt->channel, "sip_to_user");
1418 }
1419
1420 if (zstr(use_name) && zstr(use_name = tech_pvt->caller_profile->callee_id_name)) {
1421 use_name = tech_pvt->caller_profile->caller_id_name;
1422 }
1423
1424 if (zstr(use_number) && zstr(use_number = tech_pvt->caller_profile->callee_id_number)) {
1425 use_number = tech_pvt->caller_profile->caller_id_number;
1426 }
1427 } else {
1428 use_name = tech_pvt->caller_profile->caller_id_name;
1429 use_number = tech_pvt->caller_profile->caller_id_number;
1430 }
1431
1432 check_decode(use_name, session);
1433
1434 switch (cid_type) {
1435 case CID_TYPE_PID:
1436 if (switch_test_flag(caller_profile, SWITCH_CPF_SCREEN)) {
1437 if (zstr(tech_pvt->caller_profile->caller_id_name) || !strcasecmp(tech_pvt->caller_profile->caller_id_name, "_undef_")) {
1438 tech_pvt->asserted_id = switch_core_session_sprintf(tech_pvt->session, "<sip:%s@%s%s%s>",
1439 use_number, rpid_domain,
1440 invite_pid_params ? ";" : "",
1441 invite_pid_params ? invite_pid_params : "");
1442 } else {
1443 tech_pvt->asserted_id = switch_core_session_sprintf(tech_pvt->session, "\"%s\" <sip:%s@%s%s%s>",
1444 use_name, use_number, rpid_domain,
1445 invite_pid_params ? ";" : "",
1446 invite_pid_params ? invite_pid_params : "");
1447 }
1448 } else {
1449 if (zstr(tech_pvt->caller_profile->caller_id_name) || !strcasecmp(tech_pvt->caller_profile->caller_id_name, "_undef_")) {
1450 tech_pvt->preferred_id = switch_core_session_sprintf(tech_pvt->session, "<sip:%s@%s%s%s>",
1451 tech_pvt->caller_profile->caller_id_number, rpid_domain,
1452 invite_pid_params ? ";" : "",
1453 invite_pid_params ? invite_pid_params : "");
1454 } else {
1455 tech_pvt->preferred_id = switch_core_session_sprintf(tech_pvt->session, "\"%s\" <sip:%s@%s%s%s>",
1456 tech_pvt->caller_profile->caller_id_name,
1457 tech_pvt->caller_profile->caller_id_number, rpid_domain,
1458 invite_pid_params ? ";" : "",
1459 invite_pid_params ? invite_pid_params : "");
1460 }
1461 }
1462
1463 if (switch_test_flag(caller_profile, SWITCH_CPF_HIDE_NUMBER)) {
1464 tech_pvt->privacy = "id";
1465 } else {
1466 if (!(val = switch_channel_get_variable(channel, "sip_cid_suppress_privacy_none")) || !switch_true(val)) {
1467 tech_pvt->privacy = "none";
1468 }
1469 }
1470
1471 break;
1472 case CID_TYPE_RPID:
1473 {
1474 if (switch_test_flag(caller_profile, SWITCH_CPF_HIDE_NAME)) {
1475 priv = "name";
1476 if (switch_test_flag(caller_profile, SWITCH_CPF_HIDE_NUMBER)) {
1477 priv = "full";
1478 }
1479 } else if (switch_test_flag(caller_profile, SWITCH_CPF_HIDE_NUMBER)) {
1480 priv = "full";
1481 }
1482
1483 if (switch_test_flag(caller_profile, SWITCH_CPF_SCREEN)) {
1484 screen = "yes";
1485 }
1486
1487 if (zstr(tech_pvt->caller_profile->caller_id_name) || !strcasecmp(tech_pvt->caller_profile->caller_id_name, "_undef_")) {
1488 tech_pvt->rpid = switch_core_session_sprintf(tech_pvt->session, "<sip:%s@%s>;party=calling;screen=%s;privacy=%s",
1489 use_number, rpid_domain, screen, priv);
1490 } else {
1491 tech_pvt->rpid = switch_core_session_sprintf(tech_pvt->session, "\"%s\"<sip:%s@%s>;party=calling;screen=%s;privacy=%s",
1492 use_name, use_number, rpid_domain, screen, priv);
1493 }
1494 }
1495 break;
1496 default:
1497 break;
1498 }
1499
1500
1501 switch_safe_free(d_url);
1502
1503 if (!(sofia_private = su_alloc(tech_pvt->nh->nh_home, sizeof(*sofia_private)))) {
1504 abort();
1505 }
1506
1507 memset(sofia_private, 0, sizeof(*sofia_private));
1508 sofia_private->is_call = 2;
1509 sofia_private->is_static++;
1510
1511 if (switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING)) {
1512 sofia_private->is_call++;
1513 }
1514
1515 tech_pvt->sofia_private = sofia_private;
1516 switch_copy_string(tech_pvt->sofia_private->uuid_str, switch_core_session_get_uuid(session), sizeof(tech_pvt->sofia_private->uuid_str));
1517 tech_pvt->sofia_private->uuid = tech_pvt->sofia_private->uuid_str;
1518 nua_handle_bind(tech_pvt->nh, tech_pvt->sofia_private);
1519 }
1520
1521 if (tech_pvt->e_dest && sofia_test_pflag(tech_pvt->profile, PFLAG_IN_DIALOG_CHAT)) {
1522 char *user = NULL, *host = NULL;
1523 char hash_key[256] = "";
1524
1525 e_dest = strdup(tech_pvt->e_dest);
1526 switch_assert(e_dest != NULL);
1527 user = e_dest;
1528
1529 if ((host = strchr(user, '@'))) {
1530 *host++ = '\0';
1531 }
1532 switch_snprintf(hash_key, sizeof(hash_key), "%s%s%s", user, host, cid_num);
1533
1534 tech_pvt->chat_from = tech_pvt->from_str;
1535 tech_pvt->chat_to = tech_pvt->dest;
1536 if (tech_pvt->profile->pres_type) {
1537 tech_pvt->hash_key = switch_core_session_strdup(tech_pvt->session, hash_key);
1538 switch_mutex_lock(tech_pvt->profile->flag_mutex);
1539 switch_core_hash_insert(tech_pvt->profile->chat_hash, tech_pvt->hash_key, tech_pvt);
1540 switch_mutex_unlock(tech_pvt->profile->flag_mutex);
1541 }
1542 free(e_dest);
1543 }
1544
1545 holdstr = sofia_test_flag(tech_pvt, TFLAG_SIP_HOLD) ? hold_char : "";
1546
1547 if (!switch_channel_get_variable(channel, "sofia_profile_name")) {
1548 switch_channel_set_variable(channel, "sofia_profile_name", tech_pvt->profile->name);
1549 switch_channel_set_variable(channel, "recovery_profile_name", tech_pvt->profile->name);
1550 switch_channel_set_variable(channel, "sofia_profile_url", tech_pvt->profile->url);
1551 }
1552
1553 extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_HEADER_PREFIX);
1554
1555 if ((val = switch_channel_get_variable(channel, SOFIA_SESSION_TIMEOUT))) {
1556 int v_session_timeout = atoi(val);
1557 if (v_session_timeout >= 0) {
1558 session_timeout = v_session_timeout;
1559 }
1560 }
1561
1562 if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
1563 switch_core_media_proxy_remote_addr(session, NULL);
1564 switch_core_media_patch_sdp(tech_pvt->session);
1565 }
1566
1567 if (!zstr(tech_pvt->dest)) {
1568 if (!dst) {
1569 dst = sofia_glue_get_destination(tech_pvt->dest);
1570 }
1571
1572 if (dst->route_uri) {
1573 route_uri = sofia_overcome_sip_uri_weakness(tech_pvt->session, dst->route_uri, tech_pvt->transport, SWITCH_TRUE, NULL, NULL);
1574 }
1575
1576 if (dst->route) {
1577 route = dst->route;
1578 }
1579 }
1580
1581 if ((val = switch_channel_get_variable(channel, "sip_route_uri"))) {
1582 route_uri = switch_core_session_strdup(session, val);
1583 route = NULL;
1584 }
1585
1586 if (route_uri) {
1587 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "%s Setting proxy route to %s\n", route_uri,
1588 switch_channel_get_name(channel));
1589 tech_pvt->route_uri = switch_core_session_strdup(tech_pvt->session, route_uri);
1590 }
1591
1592
1593 if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_invite_cseq"))) {
1594 uint32_t callsequence = (uint32_t) strtoul(val, NULL, 10);
1595 cseq = sip_cseq_create(tech_pvt->nh->nh_home, callsequence, SIP_METHOD_INVITE);
1596 }
1597
1598
1599 switch_channel_clear_flag(channel, CF_MEDIA_ACK);
1600
1601 if (handle_full_from) {
1602 tech_pvt->nh->nh_has_invite = 1;
1603 }
1604
1605 if ((mp = sofia_media_get_multipart(session, "sip_multipart", tech_pvt->mparams.local_sdp_str, &mp_type))) {
1606 sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA);
1607 }
1608
1609 if ((tech_pvt->session_timeout = session_timeout)) {
1610 tech_pvt->session_refresher = switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? nua_local_refresher : nua_remote_refresher;
1611 if (sofia_test_pflag(tech_pvt->profile, PFLAG_UPDATE_REFRESHER) || switch_channel_var_true(tech_pvt->channel, "sip_update_refresher")) {
1612 tech_pvt->update_refresher = 1;
1613 }
1614 } else {
1615 tech_pvt->session_refresher = nua_no_refresher;
1616 }
1617
1618 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "%s sending invite version: %s\nLocal SDP:\n%s\n",
1619 switch_channel_get_name(tech_pvt->channel), switch_version_full_human(),
1620 tech_pvt->mparams.local_sdp_str ? tech_pvt->mparams.local_sdp_str : "NO SDP PRESENT\n");
1621
1622
1623
1624 if ((switch_channel_get_private(tech_pvt->channel, "t38_options")) ||
1625 ((switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) ||
1626 switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA) )
1627 && switch_stristr("m=image", tech_pvt->mparams.local_sdp_str))) {
1628 sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA);
1629 is_t38 = 1;
1630 }
1631
1632
1633 if (sofia_use_soa(tech_pvt)) {
1634 nua_invite(tech_pvt->nh,
1635 NUTAG_AUTOANSWER(0),
1636 //TAG_IF(zstr(tech_pvt->mparams.local_sdp_str), NUTAG_AUTOACK(0)),
1637 //TAG_IF(!zstr(tech_pvt->mparams.local_sdp_str), NUTAG_AUTOACK(1)),
1638 // The code above is breaking things...... grrr WE need this because we handle our own acks and there are 3pcc cases in there too
1639 NUTAG_AUTOACK(0),
1640 NUTAG_SESSION_TIMER(tech_pvt->session_timeout),
1641 NUTAG_SESSION_REFRESHER(tech_pvt->session_refresher),
1642 NUTAG_UPDATE_REFRESH(tech_pvt->update_refresher),
1643 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
1644 TAG_IF(sofia_test_flag(tech_pvt, TFLAG_RECOVERED), NUTAG_INVITE_TIMER(UINT_MAX)),
1645 TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)),
1646 TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
1647 TAG_IF(tech_pvt->redirected, NUTAG_URL(tech_pvt->redirected)),
1648 TAG_IF(!zstr(recover_via), SIPTAG_VIA_STR(recover_via)),
1649 TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
1650 TAG_IF(!zstr(tech_pvt->rpid), SIPTAG_REMOTE_PARTY_ID_STR(tech_pvt->rpid)),
1651 TAG_IF(!zstr(tech_pvt->preferred_id), SIPTAG_P_PREFERRED_IDENTITY_STR(tech_pvt->preferred_id)),
1652 TAG_IF(!zstr(tech_pvt->asserted_id), SIPTAG_P_ASSERTED_IDENTITY_STR(tech_pvt->asserted_id)),
1653 TAG_IF(!zstr(tech_pvt->privacy), SIPTAG_PRIVACY_STR(tech_pvt->privacy)),
1654 TAG_IF(!zstr(alert_info), SIPTAG_HEADER_STR(alert_info)),
1655 TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
1656 TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_PASS_CALLEE_ID), SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)),
1657 TAG_IF(!zstr(max_forwards), SIPTAG_MAX_FORWARDS_STR(max_forwards)),
1658 TAG_IF(!zstr(route_uri), NUTAG_PROXY(route_uri)),
1659 TAG_IF(!zstr(invite_route_uri), NUTAG_INITIAL_ROUTE_STR(invite_route_uri)),
1660 TAG_IF(!zstr(route), SIPTAG_ROUTE_STR(route)),
1661 TAG_IF(tech_pvt->profile->minimum_session_expires, NUTAG_MIN_SE(tech_pvt->profile->minimum_session_expires)),
1662 TAG_IF(cseq, SIPTAG_CSEQ(cseq)),
1663 TAG_IF(content_encoding, SIPTAG_CONTENT_ENCODING_STR(content_encoding)),
1664 TAG_IF(zstr(tech_pvt->mparams.local_sdp_str), SIPTAG_PAYLOAD_STR("")),
1665 TAG_IF(!zstr(tech_pvt->mparams.local_sdp_str), SOATAG_ADDRESS(tech_pvt->mparams.adv_sdp_audio_ip)),
1666 TAG_IF(!zstr(tech_pvt->mparams.local_sdp_str), SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str)),
1667 TAG_IF(!zstr(tech_pvt->mparams.local_sdp_str), SOATAG_REUSE_REJECTED(1)),
1668 TAG_IF(is_t38, SOATAG_ORDERED_USER(1)),
1669 TAG_IF(!zstr(tech_pvt->mparams.local_sdp_str), SOATAG_RTP_SORT(SOA_RTP_SORT_REMOTE)),
1670 TAG_IF(!zstr(tech_pvt->mparams.local_sdp_str), SOATAG_RTP_SELECT(SOA_RTP_SELECT_ALL)),
1671 TAG_IF(rep, SIPTAG_REPLACES_STR(rep)),
1672 TAG_IF(!require_timer, NUTAG_TIMER_AUTOREQUIRE(0)),
1673 TAG_IF(!zstr(tech_pvt->mparams.local_sdp_str), SOATAG_HOLD(holdstr)), TAG_END());
1674 } else {
1675 nua_invite(tech_pvt->nh,
1676 NUTAG_AUTOANSWER(0),
1677 NUTAG_AUTOACK(0),
1678 NUTAG_SESSION_TIMER(tech_pvt->session_timeout),
1679 NUTAG_SESSION_REFRESHER(tech_pvt->session_refresher),
1680 NUTAG_UPDATE_REFRESH(tech_pvt->update_refresher),
1681 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header)),
1682 TAG_IF(sofia_test_flag(tech_pvt, TFLAG_RECOVERED), NUTAG_INVITE_TIMER(UINT_MAX)),
1683 TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)),
1684 TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
1685 TAG_IF(tech_pvt->redirected, NUTAG_URL(tech_pvt->redirected)),
1686 TAG_IF(!zstr(recover_via), SIPTAG_VIA_STR(recover_via)),
1687 TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
1688 TAG_IF(!zstr(tech_pvt->rpid), SIPTAG_REMOTE_PARTY_ID_STR(tech_pvt->rpid)),
1689 TAG_IF(!zstr(tech_pvt->preferred_id), SIPTAG_P_PREFERRED_IDENTITY_STR(tech_pvt->preferred_id)),
1690 TAG_IF(!zstr(tech_pvt->asserted_id), SIPTAG_P_ASSERTED_IDENTITY_STR(tech_pvt->asserted_id)),
1691 TAG_IF(!zstr(tech_pvt->privacy), SIPTAG_PRIVACY_STR(tech_pvt->privacy)),
1692 TAG_IF(!zstr(alert_info), SIPTAG_HEADER_STR(alert_info)),
1693 TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers)),
1694 TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_PASS_CALLEE_ID), SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT)),
1695 TAG_IF(!zstr(max_forwards), SIPTAG_MAX_FORWARDS_STR(max_forwards)),
1696 TAG_IF(!zstr(route_uri), NUTAG_PROXY(route_uri)),
1697 TAG_IF(!zstr(route), SIPTAG_ROUTE_STR(route)),
1698 TAG_IF(!zstr(invite_route_uri), NUTAG_INITIAL_ROUTE_STR(invite_route_uri)),
1699 TAG_IF(tech_pvt->profile->minimum_session_expires, NUTAG_MIN_SE(tech_pvt->profile->minimum_session_expires)),
1700 TAG_IF(!require_timer, NUTAG_TIMER_AUTOREQUIRE(0)),
1701 TAG_IF(cseq, SIPTAG_CSEQ(cseq)),
1702 TAG_IF(content_encoding, SIPTAG_CONTENT_ENCODING_STR(content_encoding)),
1703 NUTAG_MEDIA_ENABLE(0),
1704 SIPTAG_CONTENT_TYPE_STR(mp_type ? mp_type : "application/sdp"),
1705 SIPTAG_PAYLOAD_STR(mp ? mp : tech_pvt->mparams.local_sdp_str), TAG_IF(rep, SIPTAG_REPLACES_STR(rep)), SOATAG_HOLD(holdstr), TAG_END());
1706 }
1707
1708 switch_safe_free(extra_headers);
1709 switch_safe_free(mp);
1710 tech_pvt->redirected = NULL;
1711
1712 status = SWITCH_STATUS_SUCCESS;
1713
1714 end:
1715
1716 if (dst) {
1717 sofia_glue_free_destination(dst);
1718 }
1719
1720 return status;
1721 }
1722
sofia_glue_do_xfer_invite(switch_core_session_t * session)1723 void sofia_glue_do_xfer_invite(switch_core_session_t *session)
1724 {
1725 private_object_t *tech_pvt = switch_core_session_get_private(session);
1726 switch_channel_t *channel = switch_core_session_get_channel(session);
1727 switch_caller_profile_t *caller_profile;
1728 const char *sipip, *format, *contact_url;
1729
1730 switch_assert(tech_pvt != NULL);
1731 switch_mutex_lock(tech_pvt->sofia_mutex);
1732 caller_profile = switch_channel_get_caller_profile(channel);
1733
1734 if (!zstr(tech_pvt->mparams.remote_ip) && sofia_glue_check_nat(tech_pvt->profile, tech_pvt->mparams.remote_ip)) {
1735 sipip = tech_pvt->profile->extsipip;
1736 contact_url = tech_pvt->profile->public_url;
1737 } else {
1738 sipip = tech_pvt->profile->extsipip ? tech_pvt->profile->extsipip : tech_pvt->profile->sipip;
1739 contact_url = tech_pvt->profile->url;
1740 }
1741
1742 format = strchr(sipip, ':') ? "\"%s\" <sip:%s@[%s]>" : "\"%s\" <sip:%s@%s>";
1743
1744 if ((tech_pvt->from_str = switch_core_session_sprintf(session, format, caller_profile->caller_id_name, caller_profile->caller_id_number, sipip))) {
1745
1746 const char *rep = switch_channel_get_variable(channel, SOFIA_REPLACES_HEADER);
1747
1748 tech_pvt->nh2 = nua_handle(tech_pvt->profile->nua, NULL,
1749 SIPTAG_TO_STR(tech_pvt->dest), SIPTAG_FROM_STR(tech_pvt->from_str), SIPTAG_CONTACT_STR(contact_url), TAG_END());
1750
1751 nua_handle_bind(tech_pvt->nh2, tech_pvt->sofia_private);
1752
1753 nua_invite(tech_pvt->nh2,
1754 SIPTAG_CONTACT_STR(contact_url),
1755 TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)),
1756 SOATAG_ADDRESS(tech_pvt->mparams.adv_sdp_audio_ip),
1757 SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str),
1758 SOATAG_REUSE_REJECTED(1),
1759 SOATAG_RTP_SORT(SOA_RTP_SORT_REMOTE), SOATAG_RTP_SELECT(SOA_RTP_SELECT_ALL), TAG_IF(rep, SIPTAG_REPLACES_STR(rep)), TAG_END());
1760 } else {
1761 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Memory Error!\n");
1762 }
1763 switch_mutex_unlock(tech_pvt->sofia_mutex);
1764 }
1765
1766
1767 /* map sip responses to QSIG cause codes ala RFC4497 section 8.4.4 */
sofia_glue_sip_cause_to_freeswitch(int status)1768 switch_call_cause_t sofia_glue_sip_cause_to_freeswitch(int status)
1769 {
1770 switch (status) {
1771 case 200:
1772 return SWITCH_CAUSE_NORMAL_CLEARING;
1773 case 401:
1774 case 402:
1775 case 403:
1776 case 407:
1777 case 603:
1778 case 607:
1779 return SWITCH_CAUSE_CALL_REJECTED;
1780 case 404:
1781 return SWITCH_CAUSE_UNALLOCATED_NUMBER;
1782 case 485:
1783 case 604:
1784 return SWITCH_CAUSE_NO_ROUTE_DESTINATION;
1785 case 408:
1786 case 504:
1787 return SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE;
1788 case 410:
1789 return SWITCH_CAUSE_NUMBER_CHANGED;
1790 case 413:
1791 case 414:
1792 case 416:
1793 case 420:
1794 case 421:
1795 case 423:
1796 case 505:
1797 case 513:
1798 return SWITCH_CAUSE_INTERWORKING;
1799 case 480:
1800 return SWITCH_CAUSE_NO_USER_RESPONSE;
1801 case 400:
1802 case 481:
1803 case 500:
1804 case 503:
1805 return SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE;
1806 case 486:
1807 case 600:
1808 return SWITCH_CAUSE_USER_BUSY;
1809 case 484:
1810 return SWITCH_CAUSE_INVALID_NUMBER_FORMAT;
1811 case 488:
1812 case 606:
1813 return SWITCH_CAUSE_INCOMPATIBLE_DESTINATION;
1814 case 502:
1815 return SWITCH_CAUSE_NETWORK_OUT_OF_ORDER;
1816 case 405:
1817 return SWITCH_CAUSE_SERVICE_UNAVAILABLE;
1818 case 406:
1819 case 415:
1820 case 501:
1821 return SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED;
1822 case 482:
1823 case 483:
1824 return SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR;
1825 case 487:
1826 return SWITCH_CAUSE_ORIGINATOR_CANCEL;
1827 default:
1828 return SWITCH_CAUSE_NORMAL_UNSPECIFIED;
1829 }
1830 }
1831
sofia_glue_pass_sdp(private_object_t * tech_pvt,char * sdp)1832 void sofia_glue_pass_sdp(private_object_t *tech_pvt, char *sdp)
1833 {
1834 const char *val;
1835 switch_core_session_t *other_session;
1836 switch_channel_t *other_channel;
1837
1838 if ((val = switch_channel_get_partner_uuid(tech_pvt->channel))
1839 && (other_session = switch_core_session_locate(val))) {
1840 other_channel = switch_core_session_get_channel(other_session);
1841 switch_channel_set_variable(other_channel, SWITCH_B_SDP_VARIABLE, sdp);
1842
1843 #if 0
1844 if (!sofia_test_flag(tech_pvt, TFLAG_CHANGE_MEDIA) && !switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING) &&
1845 (switch_channel_direction(other_channel) == SWITCH_CALL_DIRECTION_OUTBOUND &&
1846 switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_OUTBOUND && switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE))) {
1847 switch_ivr_nomedia(val, SMF_FORCE);
1848 sofia_set_flag_locked(tech_pvt, TFLAG_CHANGE_MEDIA);
1849 }
1850 #endif
1851
1852 switch_core_session_rwunlock(other_session);
1853 }
1854 }
1855
sofia_glue_get_path_from_contact(char * buf)1856 char *sofia_glue_get_path_from_contact(char *buf)
1857 {
1858 char *p, *e, *path = NULL, *contact = NULL;
1859
1860 if (!buf) return NULL;
1861
1862 contact = sofia_glue_get_url_from_contact(buf, SWITCH_TRUE);
1863
1864 if (!contact) return NULL;
1865
1866 if ((p = strstr(contact, "fs_path="))) {
1867 p += 8;
1868
1869 if (!zstr(p)) {
1870 path = strdup(p);
1871 }
1872 }
1873
1874 if (!path) {
1875 free(contact);
1876 return NULL;
1877 }
1878
1879 if ((e = strrchr(path, ';'))) {
1880 *e = '\0';
1881 }
1882
1883 switch_url_decode(path);
1884
1885 free(contact);
1886
1887 return path;
1888 }
1889
sofia_glue_get_url_from_contact(char * buf,uint8_t to_dup)1890 char *sofia_glue_get_url_from_contact(char *buf, uint8_t to_dup)
1891 {
1892 char *url = NULL, *e;
1893
1894 switch_assert(buf);
1895
1896 while(*buf == ' ') {
1897 buf++;
1898 }
1899
1900 if (*buf == '"') {
1901 buf++;
1902 if((e = strchr(buf, '"'))) {
1903 buf = e+1;
1904 }
1905 }
1906
1907 while(*buf == ' ') {
1908 buf++;
1909 }
1910
1911 url = strchr(buf, '<');
1912
1913 if (url && (e = switch_find_end_paren(url, '<', '>'))) {
1914 url++;
1915 if (to_dup) {
1916 url = strdup(url);
1917 switch_assert(url);
1918 e = strchr(url, '>');
1919 }
1920
1921 *e = '\0';
1922 } else {
1923 if (url) buf++;
1924
1925 if (to_dup) {
1926 url = strdup(buf);
1927 } else {
1928 url = buf;
1929 }
1930 }
1931 return url;
1932 }
1933
sofia_glue_profile_rdlock__(const char * file,const char * func,int line,sofia_profile_t * profile)1934 switch_status_t sofia_glue_profile_rdlock__(const char *file, const char *func, int line, sofia_profile_t *profile)
1935 {
1936 switch_status_t status = switch_thread_rwlock_tryrdlock(profile->rwlock);
1937 if (status != SWITCH_STATUS_SUCCESS) {
1938 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "Profile %s is locked\n", profile->name);
1939 return status;
1940 }
1941 #ifdef SOFIA_DEBUG_RWLOCKS
1942 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "XXXXXXXXXXXXXX LOCK %s\n", profile->name);
1943 #endif
1944 return status;
1945 }
1946
sofia_glue_profile_exists(const char * key)1947 switch_bool_t sofia_glue_profile_exists(const char *key)
1948 {
1949 switch_bool_t tf = SWITCH_FALSE;
1950
1951 switch_mutex_lock(mod_sofia_globals.hash_mutex);
1952 if (switch_core_hash_find(mod_sofia_globals.profile_hash, key)) {
1953 tf = SWITCH_TRUE;
1954 }
1955 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
1956
1957 return tf;
1958 }
1959
sofia_glue_find_profile__(const char * file,const char * func,int line,const char * key)1960 sofia_profile_t *sofia_glue_find_profile__(const char *file, const char *func, int line, const char *key)
1961 {
1962 sofia_profile_t *profile;
1963
1964 switch_mutex_lock(mod_sofia_globals.hash_mutex);
1965 if ((profile = (sofia_profile_t *) switch_core_hash_find(mod_sofia_globals.profile_hash, key))) {
1966 if (!sofia_test_pflag(profile, PFLAG_RUNNING)) {
1967 #ifdef SOFIA_DEBUG_RWLOCKS
1968 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "Profile %s is not running\n", profile->name);
1969 #endif
1970 profile = NULL;
1971 goto done;
1972 }
1973 if (sofia_glue_profile_rdlock__(file, func, line, profile) != SWITCH_STATUS_SUCCESS) {
1974 profile = NULL;
1975 }
1976 } else {
1977 #ifdef SOFIA_DEBUG_RWLOCKS
1978 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "Profile %s is not in the hash\n", key);
1979 #endif
1980 }
1981
1982 done:
1983 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
1984
1985 return profile;
1986 }
1987
sofia_glue_release_profile__(const char * file,const char * func,int line,sofia_profile_t * profile)1988 void sofia_glue_release_profile__(const char *file, const char *func, int line, sofia_profile_t *profile)
1989 {
1990 if (profile) {
1991 #ifdef SOFIA_DEBUG_RWLOCKS
1992 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "XXXXXXXXXXXXXX UNLOCK %s\n", profile->name);
1993 #endif
1994 switch_thread_rwlock_unlock(profile->rwlock);
1995 }
1996 }
1997
sofia_glue_add_profile(char * key,sofia_profile_t * profile)1998 switch_status_t sofia_glue_add_profile(char *key, sofia_profile_t *profile)
1999 {
2000 switch_status_t status = SWITCH_STATUS_FALSE;
2001
2002 switch_mutex_lock(mod_sofia_globals.hash_mutex);
2003 if (!switch_core_hash_find(mod_sofia_globals.profile_hash, key)) {
2004 status = switch_core_hash_insert(mod_sofia_globals.profile_hash, key, profile);
2005 }
2006 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
2007
2008 return status;
2009 }
2010
2011
sofia_glue_del_every_gateway(sofia_profile_t * profile)2012 void sofia_glue_del_every_gateway(sofia_profile_t *profile)
2013 {
2014 sofia_gateway_t *gp = NULL;
2015
2016 switch_mutex_lock(mod_sofia_globals.hash_mutex);
2017 for (gp = profile->gateways; gp; gp = gp->next) {
2018 sofia_glue_del_gateway(gp);
2019 }
2020 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
2021 }
2022
2023
sofia_glue_gateway_list(sofia_profile_t * profile,switch_stream_handle_t * stream,int up)2024 void sofia_glue_gateway_list(sofia_profile_t *profile, switch_stream_handle_t *stream, int up)
2025 {
2026 sofia_gateway_t *gp = NULL;
2027
2028 switch_mutex_lock(mod_sofia_globals.hash_mutex);
2029 for (gp = profile->gateways; gp; gp = gp->next) {
2030 int reged = (gp->status == SOFIA_GATEWAY_UP);
2031
2032 if (up ? reged : !reged) {
2033 stream->write_function(stream, "%s ", gp->name);
2034 }
2035 }
2036
2037 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
2038 }
2039
2040
sofia_glue_del_gateway(sofia_gateway_t * gp)2041 void sofia_glue_del_gateway(sofia_gateway_t *gp)
2042 {
2043 if (!gp->deleted) {
2044 if (gp->state != REG_STATE_NOREG) {
2045 gp->retry = 0;
2046 gp->state = REG_STATE_UNREGISTER;
2047 }
2048
2049 gp->deleted = 1;
2050 }
2051 }
2052
sofia_glue_restart_all_profiles(void)2053 void sofia_glue_restart_all_profiles(void)
2054 {
2055 switch_hash_index_t *hi;
2056 const void *var;
2057 void *val;
2058 sofia_profile_t *pptr;
2059 switch_xml_t xml_root;
2060 const char *err;
2061
2062 if ((xml_root = switch_xml_open_root(1, &err))) {
2063 switch_xml_free(xml_root);
2064 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Reload XML [%s]\n", err);
2065 }
2066
2067 switch_mutex_lock(mod_sofia_globals.hash_mutex);
2068 if (mod_sofia_globals.profile_hash) {
2069 for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
2070 switch_core_hash_this(hi, &var, NULL, &val);
2071 if ((pptr = (sofia_profile_t *) val)) {
2072 int rsec = 10;
2073 int diff = (int) (switch_epoch_time_now(NULL) - pptr->started);
2074 int remain = rsec - diff;
2075 if (sofia_test_pflag(pptr, PFLAG_RESPAWN) || !sofia_test_pflag(pptr, PFLAG_RUNNING)) {
2076 continue;
2077 }
2078
2079 if (diff < rsec) {
2080 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
2081 "Profile %s must be up for at least %d seconds to stop/restart.\nPlease wait %d second%s\n",
2082 pptr->name, rsec, remain, remain == 1 ? "" : "s");
2083 continue;
2084 }
2085 sofia_set_pflag_locked(pptr, PFLAG_RESPAWN);
2086 sofia_clear_pflag_locked(pptr, PFLAG_RUNNING);
2087 }
2088 }
2089 }
2090 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
2091
2092 }
2093
2094
sofia_glue_global_siptrace(switch_bool_t on)2095 void sofia_glue_global_siptrace(switch_bool_t on)
2096 {
2097 switch_hash_index_t *hi;
2098 const void *var;
2099 void *val;
2100 sofia_profile_t *pptr;
2101
2102 switch_mutex_lock(mod_sofia_globals.hash_mutex);
2103 if (mod_sofia_globals.profile_hash) {
2104 for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
2105 switch_core_hash_this(hi, &var, NULL, &val);
2106 if ((pptr = (sofia_profile_t *) val)) {
2107 nua_set_params(pptr->nua, TPTAG_LOG(on), TAG_END());
2108 }
2109 }
2110 }
2111 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
2112
2113 }
2114
sofia_glue_global_standby(switch_bool_t on)2115 void sofia_glue_global_standby(switch_bool_t on)
2116 {
2117 switch_hash_index_t *hi;
2118 const void *var;
2119 void *val;
2120 sofia_profile_t *pptr;
2121
2122 switch_mutex_lock(mod_sofia_globals.hash_mutex);
2123 if (mod_sofia_globals.profile_hash) {
2124 for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
2125 switch_core_hash_this(hi, &var, NULL, &val);
2126 if ((pptr = (sofia_profile_t *) val)) {
2127 if (on) {
2128 sofia_set_pflag_locked(pptr, PFLAG_STANDBY);
2129 } else {
2130 sofia_clear_pflag_locked(pptr, PFLAG_STANDBY);
2131 }
2132 }
2133 }
2134 }
2135 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
2136
2137 }
2138
sofia_glue_global_capture(switch_bool_t on)2139 void sofia_glue_global_capture(switch_bool_t on)
2140 {
2141 switch_hash_index_t *hi;
2142 const void *var;
2143 void *val;
2144 sofia_profile_t *pptr;
2145
2146 switch_mutex_lock(mod_sofia_globals.hash_mutex);
2147 if (mod_sofia_globals.profile_hash) {
2148 for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
2149 switch_core_hash_this(hi, &var, NULL, &val);
2150 if ((pptr = (sofia_profile_t *) val)) {
2151 nua_set_params(pptr->nua, TPTAG_CAPT(on ? mod_sofia_globals.capture_server : NULL), TAG_END());
2152 }
2153 }
2154 }
2155 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
2156
2157 }
2158
2159
sofia_glue_global_watchdog(switch_bool_t on)2160 void sofia_glue_global_watchdog(switch_bool_t on)
2161 {
2162 switch_hash_index_t *hi;
2163 const void *var;
2164 void *val;
2165 sofia_profile_t *pptr;
2166
2167 switch_mutex_lock(mod_sofia_globals.hash_mutex);
2168 if (mod_sofia_globals.profile_hash) {
2169 for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
2170 switch_core_hash_this(hi, &var, NULL, &val);
2171 if ((pptr = (sofia_profile_t *) val)) {
2172 pptr->watchdog_enabled = (on ? 1 : 0);
2173 }
2174 }
2175 }
2176 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
2177
2178 }
2179
sofia_glue_del_profile(sofia_profile_t * profile)2180 void sofia_glue_del_profile(sofia_profile_t *profile)
2181 {
2182 sofia_gateway_t *gp;
2183 char *aliases[512];
2184 int i = 0, j = 0;
2185 switch_hash_index_t *hi;
2186 const void *var;
2187 void *val;
2188 sofia_profile_t *pptr;
2189
2190 switch_mutex_lock(mod_sofia_globals.hash_mutex);
2191 if (mod_sofia_globals.profile_hash) {
2192 for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash); hi; hi = switch_core_hash_next(&hi)) {
2193 switch_core_hash_this(hi, &var, NULL, &val);
2194 if ((pptr = (sofia_profile_t *) val) && pptr == profile) {
2195 aliases[i++] = strdup((char *) var);
2196 if (i == 512) {
2197 abort();
2198 }
2199 }
2200 }
2201
2202 for (j = 0; j < i && j < 512; j++) {
2203 switch_core_hash_delete(mod_sofia_globals.profile_hash, aliases[j]);
2204 free(aliases[j]);
2205 }
2206
2207 for (gp = profile->gateways; gp; gp = gp->next) {
2208 char *pkey = switch_mprintf("%s::%s", profile->name, gp->name);
2209
2210 switch_core_hash_delete(mod_sofia_globals.gateway_hash, gp->name);
2211 switch_core_hash_delete(mod_sofia_globals.gateway_hash, pkey);
2212 switch_safe_free(pkey);
2213 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "deleted gateway %s from profile %s\n", gp->name, profile->name);
2214 }
2215 profile->gateways = NULL;
2216 }
2217 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
2218 }
2219
sofia_recover_callback(switch_core_session_t * session)2220 int sofia_recover_callback(switch_core_session_t *session)
2221 {
2222
2223 switch_channel_t *channel = switch_core_session_get_channel(session);
2224 private_object_t *tech_pvt = NULL;
2225 sofia_profile_t *profile = NULL;
2226 const char *tmp;
2227 const char *rr;
2228 int r = 0;
2229 const char *profile_name = switch_channel_get_variable_dup(channel, "recovery_profile_name", SWITCH_FALSE, -1);
2230
2231
2232 if (zstr(profile_name)) {
2233 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Missing profile\n");
2234 return 0;
2235 }
2236
2237 if (!(profile = sofia_glue_find_profile(profile_name))) {
2238 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Invalid profile %s\n", profile_name);
2239 return 0;
2240 }
2241
2242
2243 tech_pvt = (private_object_t *) switch_core_session_alloc(session, sizeof(private_object_t));
2244 tech_pvt->channel = channel;
2245
2246 switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
2247 switch_mutex_init(&tech_pvt->sofia_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
2248
2249 tech_pvt->mparams.remote_ip = (char *) switch_channel_get_variable(channel, "sip_network_ip");
2250 tech_pvt->mparams.remote_port = atoi(switch_str_nil(switch_channel_get_variable(channel, "sip_network_port")));
2251 tech_pvt->caller_profile = switch_channel_get_caller_profile(channel);
2252
2253 if ((tmp = switch_channel_get_variable(tech_pvt->channel, "rtp_2833_send_payload"))) {
2254 int te = atoi(tmp);
2255 if (te > 64) {
2256 tech_pvt->te = (switch_payload_t)te;
2257 }
2258 }
2259
2260 if ((tmp = switch_channel_get_variable(tech_pvt->channel, "rtp_2833_recv_payload"))) {
2261 int te = atoi(tmp);
2262 if (te > 64) {
2263 tech_pvt->recv_te = (switch_payload_t)te;
2264 }
2265 }
2266
2267 rr = switch_channel_get_variable(channel, "sip_invite_record_route");
2268
2269 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
2270 int break_rfc = switch_true(switch_channel_get_variable(channel, "sip_recovery_break_rfc"));
2271 tech_pvt->dest = switch_core_session_sprintf(session, "sip:%s", switch_channel_get_variable(channel, "sip_req_uri"));
2272 switch_channel_set_variable(channel, "sip_handle_full_from", switch_channel_get_variable(channel, break_rfc ? "sip_full_to" : "sip_full_from"));
2273 switch_channel_set_variable(channel, "sip_handle_full_to", switch_channel_get_variable(channel, break_rfc ? "sip_full_from" : "sip_full_to"));
2274 } else {
2275 const char *contact_params = switch_channel_get_variable(channel, "sip_contact_params");
2276 const char *contact_uri = switch_channel_get_variable(channel, "sip_contact_uri");
2277 tech_pvt->redirected = switch_core_session_sprintf(session, "sip:%s%s%s", contact_uri, contact_params ? ";" : "", switch_str_nil(contact_params));
2278
2279 if (zstr(rr)) {
2280 switch_channel_set_variable_printf(channel, "sip_invite_route_uri", "<sip:%s@%s:%s;transport=%s>",
2281 switch_channel_get_variable(channel, "sip_from_user"),
2282 switch_channel_get_variable(channel, "sip_network_ip"),
2283 switch_channel_get_variable(channel, "sip_network_port"),
2284 switch_channel_get_variable(channel,"sip_via_protocol")
2285 );
2286
2287 }
2288
2289 tech_pvt->dest = switch_core_session_sprintf(session, "sip:%s", switch_channel_get_variable(channel, "sip_from_uri"));
2290
2291 if (!switch_channel_get_variable_dup(channel, "sip_handle_full_from", SWITCH_FALSE, -1)) {
2292 switch_channel_set_variable(channel, "sip_handle_full_from", switch_channel_get_variable(channel, "sip_full_to"));
2293 }
2294
2295 if (!switch_channel_get_variable_dup(channel, "sip_handle_full_to", SWITCH_FALSE, -1)) {
2296 switch_channel_set_variable(channel, "sip_handle_full_to", switch_channel_get_variable(channel, "sip_full_from"));
2297 }
2298 }
2299
2300 if (rr && !switch_channel_get_variable(channel, "sip_invite_route_uri")) {
2301 switch_channel_set_variable(channel, "sip_invite_route_uri", rr);
2302 }
2303
2304 tech_pvt->dest_to = tech_pvt->dest;
2305
2306 sofia_glue_attach_private(session, profile, tech_pvt, NULL);
2307 switch_channel_set_name(tech_pvt->channel, switch_channel_get_variable(channel, "channel_name"));
2308
2309
2310 switch_channel_set_variable(channel, "sip_invite_call_id", switch_channel_get_variable(channel, "sip_call_id"));
2311
2312 if (switch_true(switch_channel_get_variable(channel, "sip_nat_detected"))) {
2313 switch_channel_set_variable_printf(channel, "sip_route_uri", "sip:%s@%s:%s",
2314 switch_channel_get_variable(channel, "sip_req_user"),
2315 switch_channel_get_variable(channel, "sip_network_ip"), switch_channel_get_variable(channel, "sip_network_port")
2316 );
2317 }
2318
2319 if (session) {
2320 const char *use_uuid;
2321
2322 if ((use_uuid = switch_channel_get_variable(channel, "origination_uuid"))) {
2323 if (switch_core_session_set_uuid(session, use_uuid) == SWITCH_STATUS_SUCCESS) {
2324 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s set UUID=%s\n", switch_channel_get_name(channel),
2325 use_uuid);
2326 } else {
2327 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "%s set UUID=%s FAILED\n",
2328 switch_channel_get_name(channel), use_uuid);
2329 }
2330 }
2331 }
2332
2333 r++;
2334
2335 sofia_glue_release_profile(profile);
2336
2337
2338 return r;
2339
2340 }
2341
2342
2343
sofia_glue_recover(switch_bool_t flush)2344 int sofia_glue_recover(switch_bool_t flush)
2345 {
2346 sofia_profile_t *profile;
2347 int r = 0;
2348 switch_console_callback_match_t *matches;
2349
2350
2351 if (list_profiles_full(NULL, NULL, &matches, SWITCH_FALSE) == SWITCH_STATUS_SUCCESS) {
2352 switch_console_callback_match_node_t *m;
2353 for (m = matches->head; m; m = m->next) {
2354 if ((profile = sofia_glue_find_profile(m->val))) {
2355 r += sofia_glue_profile_recover(profile, flush);
2356 sofia_glue_release_profile(profile);
2357 }
2358 }
2359 switch_console_free_matches(&matches);
2360 }
2361 return r;
2362 }
2363
sofia_glue_profile_recover(sofia_profile_t * profile,switch_bool_t flush)2364 int sofia_glue_profile_recover(sofia_profile_t *profile, switch_bool_t flush)
2365 {
2366 int r = 0;
2367
2368 if (profile) {
2369 sofia_clear_pflag_locked(profile, PFLAG_STANDBY);
2370
2371 if (flush) {
2372 switch_core_recovery_flush(SOFIA_RECOVER, profile->name);
2373 } else {
2374 r = switch_core_recovery_recover(SOFIA_RECOVER, profile->name);
2375 }
2376 }
2377
2378 return r;
2379 }
2380
2381
sofia_glue_init_sql(sofia_profile_t * profile)2382 int sofia_glue_init_sql(sofia_profile_t *profile)
2383 {
2384 char *test_sql = NULL;
2385
2386 char reg_sql[] =
2387 "CREATE TABLE sip_registrations (\n"
2388 " call_id VARCHAR(255),\n"
2389 " sip_user VARCHAR(255),\n"
2390 " sip_host VARCHAR(255),\n"
2391 " presence_hosts VARCHAR(255),\n"
2392 " contact VARCHAR(1024),\n"
2393 " status VARCHAR(255),\n"
2394 " ping_status VARCHAR(255),\n"
2395 " ping_count INTEGER,\n"
2396 " ping_time BIGINT,\n"
2397 " force_ping INTEGER,\n"
2398 " rpid VARCHAR(255),\n"
2399 " expires BIGINT,\n"
2400 " ping_expires INTEGER not null default 0,\n"
2401 " user_agent VARCHAR(255),\n"
2402 " server_user VARCHAR(255),\n"
2403 " server_host VARCHAR(255),\n"
2404 " profile_name VARCHAR(255),\n"
2405 " hostname VARCHAR(255),\n"
2406 " network_ip VARCHAR(255),\n"
2407 " network_port VARCHAR(6),\n"
2408 " sip_username VARCHAR(255),\n"
2409 " sip_realm VARCHAR(255),\n"
2410 " mwi_user VARCHAR(255),\n"
2411 " mwi_host VARCHAR(255),\n"
2412 " orig_server_host VARCHAR(255),\n"
2413 " orig_hostname VARCHAR(255),\n"
2414 " sub_host VARCHAR(255)\n"
2415 ");\n";
2416
2417 char pres_sql[] =
2418 "CREATE TABLE sip_presence (\n"
2419 " sip_user VARCHAR(255),\n"
2420 " sip_host VARCHAR(255),\n"
2421 " status VARCHAR(255),\n"
2422 " rpid VARCHAR(255),\n"
2423 " expires BIGINT,\n"
2424 " user_agent VARCHAR(255),\n"
2425 " profile_name VARCHAR(255),\n"
2426 " hostname VARCHAR(255),\n"
2427 " network_ip VARCHAR(255),\n"
2428 " network_port VARCHAR(6),\n"
2429 " open_closed VARCHAR(255)\n"
2430 ");\n";
2431
2432 char dialog_sql[] =
2433 "CREATE TABLE sip_dialogs (\n"
2434 " call_id VARCHAR(255),\n"
2435 " uuid VARCHAR(255),\n"
2436 " sip_to_user VARCHAR(255),\n"
2437 " sip_to_host VARCHAR(255),\n"
2438 " sip_from_user VARCHAR(255),\n"
2439 " sip_from_host VARCHAR(255),\n"
2440 " contact_user VARCHAR(255),\n"
2441 " contact_host VARCHAR(255),\n"
2442 " state VARCHAR(255),\n"
2443 " direction VARCHAR(255),\n"
2444 " user_agent VARCHAR(255),\n"
2445 " profile_name VARCHAR(255),\n"
2446 " hostname VARCHAR(255),\n"
2447 " contact VARCHAR(255),\n"
2448 " presence_id VARCHAR(255),\n"
2449 " presence_data VARCHAR(255),\n"
2450 " call_info VARCHAR(255),\n"
2451 " call_info_state VARCHAR(255) default '',\n"
2452 " expires BIGINT default 0,\n"
2453 " status VARCHAR(255),\n"
2454 " rpid VARCHAR(255),\n"
2455 " sip_to_tag VARCHAR(255),\n"
2456 " sip_from_tag VARCHAR(255),\n"
2457 " rcd INTEGER not null default 0\n"
2458 ");\n";
2459
2460 char sub_sql[] =
2461 "CREATE TABLE sip_subscriptions (\n"
2462 " proto VARCHAR(255),\n"
2463 " sip_user VARCHAR(255),\n"
2464 " sip_host VARCHAR(255),\n"
2465 " sub_to_user VARCHAR(255),\n"
2466 " sub_to_host VARCHAR(255),\n"
2467 " presence_hosts VARCHAR(255),\n"
2468 " event VARCHAR(255),\n"
2469 " contact VARCHAR(1024),\n"
2470 " call_id VARCHAR(255),\n"
2471 " full_from VARCHAR(255),\n"
2472 " full_via VARCHAR(255),\n"
2473 " expires BIGINT,\n"
2474 " user_agent VARCHAR(255),\n"
2475 " accept VARCHAR(255),\n"
2476 " profile_name VARCHAR(255),\n"
2477 " hostname VARCHAR(255),\n"
2478 " network_port VARCHAR(6),\n"
2479 " network_ip VARCHAR(255),\n"
2480 " version INTEGER DEFAULT 0 NOT NULL,\n"
2481 " orig_proto VARCHAR(255),\n"
2482 " full_to VARCHAR(255)\n"
2483 ");\n";
2484
2485 char auth_sql[] =
2486 "CREATE TABLE sip_authentication (\n"
2487 " nonce VARCHAR(255),\n"
2488 " expires BIGINT,"
2489 " profile_name VARCHAR(255),\n"
2490 " hostname VARCHAR(255),\n"
2491 " last_nc INTEGER\n"
2492 ");\n";
2493
2494 /* should we move this glue to sofia_sla or keep it here where all db init happens? XXX MTK */
2495 char shared_appearance_sql[] =
2496 "CREATE TABLE sip_shared_appearance_subscriptions (\n"
2497 " subscriber VARCHAR(255),\n"
2498 " call_id VARCHAR(255),\n"
2499 " aor VARCHAR(255),\n"
2500 " profile_name VARCHAR(255),\n"
2501 " hostname VARCHAR(255),\n"
2502 " contact_str VARCHAR(255),\n"
2503 " network_ip VARCHAR(255)\n"
2504 ");\n";
2505
2506 char shared_appearance_dialogs_sql[] =
2507 "CREATE TABLE sip_shared_appearance_dialogs (\n"
2508 " profile_name VARCHAR(255),\n"
2509 " hostname VARCHAR(255),\n"
2510 " contact_str VARCHAR(255),\n"
2511 " call_id VARCHAR(255),\n"
2512 " network_ip VARCHAR(255),\n"
2513 " expires BIGINT\n"
2514 ");\n";
2515
2516
2517 int x;
2518 char *indexes[] = {
2519 "create index sr_call_id on sip_registrations (call_id)",
2520 "create index sr_sip_user on sip_registrations (sip_user)",
2521 "create index sr_sip_host on sip_registrations (sip_host)",
2522 "create index sr_sub_host on sip_registrations (sub_host)",
2523 "create index sr_mwi_user on sip_registrations (mwi_user)",
2524 "create index sr_mwi_host on sip_registrations (mwi_host)",
2525 "create index sr_profile_name on sip_registrations (profile_name)",
2526 "create index sr_presence_hosts on sip_registrations (presence_hosts)",
2527 "create index sr_contact on sip_registrations (contact)",
2528 "create index sr_expires on sip_registrations (expires)",
2529 "create index sr_ping_expires on sip_registrations (ping_expires)",
2530 "create index sr_hostname on sip_registrations (hostname)",
2531 "create index sr_status on sip_registrations (status)",
2532 "create index sr_ping_status on sip_registrations (ping_status)",
2533 "create index sr_network_ip on sip_registrations (network_ip)",
2534 "create index sr_network_port on sip_registrations (network_port)",
2535 "create index sr_sip_username on sip_registrations (sip_username)",
2536 "create index sr_sip_realm on sip_registrations (sip_realm)",
2537 "create index sr_orig_server_host on sip_registrations (orig_server_host)",
2538 "create index sr_orig_hostname on sip_registrations (orig_hostname)",
2539 "create index ss_call_id on sip_subscriptions (call_id)",
2540 "create index ss_multi on sip_subscriptions (call_id, profile_name, hostname)",
2541 "create index ss_hostname on sip_subscriptions (hostname)",
2542 "create index ss_network_ip on sip_subscriptions (network_ip)",
2543 "create index ss_sip_user on sip_subscriptions (sip_user)",
2544 "create index ss_sip_host on sip_subscriptions (sip_host)",
2545 "create index ss_presence_hosts on sip_subscriptions (presence_hosts)",
2546 "create index ss_event on sip_subscriptions (event)",
2547 "create index ss_proto on sip_subscriptions (proto)",
2548 "create index ss_sub_to_user on sip_subscriptions (sub_to_user)",
2549 "create index ss_sub_to_host on sip_subscriptions (sub_to_host)",
2550 "create index ss_expires on sip_subscriptions (expires)",
2551 "create index ss_orig_proto on sip_subscriptions (orig_proto)",
2552 "create index ss_network_port on sip_subscriptions (network_port)",
2553 "create index ss_profile_name on sip_subscriptions (profile_name)",
2554 "create index ss_version on sip_subscriptions (version)",
2555 "create index ss_full_from on sip_subscriptions (full_from)",
2556 "create index ss_contact on sip_subscriptions (contact)",
2557 "create index sd_uuid on sip_dialogs (uuid)",
2558 "create index sd_hostname on sip_dialogs (hostname)",
2559 "create index sd_presence_data on sip_dialogs (presence_data)",
2560 "create index sd_call_info on sip_dialogs (call_info)",
2561 "create index sd_call_info_state on sip_dialogs (call_info_state)",
2562 "create index sd_expires on sip_dialogs (expires)",
2563 "create index sd_rcd on sip_dialogs (rcd)",
2564 "create index sd_sip_to_tag on sip_dialogs (sip_to_tag)",
2565 "create index sd_sip_from_user on sip_dialogs (sip_from_user)",
2566 "create index sd_sip_from_host on sip_dialogs (sip_from_host)",
2567 "create index sd_sip_to_host on sip_dialogs (sip_to_host)",
2568 "create index sd_presence_id on sip_dialogs (presence_id)",
2569 "create index sd_call_id on sip_dialogs (call_id)",
2570 "create index sd_sip_from_tag on sip_dialogs (sip_from_tag)",
2571 "create index sp_hostname on sip_presence (hostname)",
2572 "create index sp_open_closed on sip_presence (open_closed)",
2573 "create index sp_sip_user on sip_presence (sip_user)",
2574 "create index sp_sip_host on sip_presence (sip_host)",
2575 "create index sp_profile_name on sip_presence (profile_name)",
2576 "create index sp_expires on sip_presence (expires)",
2577 "create index sa_nonce on sip_authentication (nonce)",
2578 "create index sa_hostname on sip_authentication (hostname)",
2579 "create index sa_expires on sip_authentication (expires)",
2580 "create index sa_last_nc on sip_authentication (last_nc)",
2581 "create index ssa_hostname on sip_shared_appearance_subscriptions (hostname)",
2582 "create index ssa_network_ip on sip_shared_appearance_subscriptions (network_ip)",
2583 "create index ssa_subscriber on sip_shared_appearance_subscriptions (subscriber)",
2584 "create index ssa_profile_name on sip_shared_appearance_subscriptions (profile_name)",
2585 "create index ssa_aor on sip_shared_appearance_subscriptions (aor)",
2586 "create index ssd_profile_name on sip_shared_appearance_dialogs (profile_name)",
2587 "create index ssd_hostname on sip_shared_appearance_dialogs (hostname)",
2588 "create index ssd_contact_str on sip_shared_appearance_dialogs (contact_str)",
2589 "create index ssd_call_id on sip_shared_appearance_dialogs (call_id)",
2590 "create index ssd_expires on sip_shared_appearance_dialogs (expires)",
2591 NULL
2592 };
2593
2594 switch_cache_db_handle_t *dbh = sofia_glue_get_db_handle(profile);
2595 char *test2;
2596 char *err;
2597
2598 if (!dbh) {
2599 return 0;
2600 }
2601
2602
2603 test_sql = switch_mprintf("delete from sip_registrations where sub_host is null "
2604 "and hostname='%q' "
2605 "and network_ip like '%%' and network_port like '%%' and sip_username "
2606 "like '%%' and mwi_user like '%%' and mwi_host like '%%' "
2607 "and orig_server_host like '%%' and orig_hostname like '%%'", mod_sofia_globals.hostname);
2608
2609
2610 switch_cache_db_test_reactive(dbh, test_sql, "drop table sip_registrations", reg_sql);
2611
2612 switch_cache_db_test_reactive(dbh, "select ping_count from sip_registrations", NULL, "alter table sip_registrations add column ping_count INTEGER default 0");
2613 switch_cache_db_test_reactive(dbh, "select ping_status from sip_registrations", NULL, "alter table sip_registrations add column ping_status VARCHAR(255) default 'Reachable'");
2614 switch_cache_db_test_reactive(dbh, "select ping_expires from sip_registrations", NULL, "alter table sip_registrations add column ping_expires INTEGER not null default 0");
2615 switch_cache_db_test_reactive(dbh, "select ping_time from sip_registrations", NULL, "alter table sip_registrations add column ping_time BIGINT not null default 0");
2616 switch_cache_db_test_reactive(dbh, "select force_ping from sip_registrations", NULL, "alter table sip_registrations add column force_ping INTEGER not null default 0");
2617
2618 test2 = switch_mprintf("%s;%s", test_sql, test_sql);
2619
2620 if (switch_cache_db_execute_sql(dbh, test2, &err) != SWITCH_STATUS_SUCCESS) {
2621
2622 if (switch_stristr("read-only", err)) {
2623 free(err);
2624 } else {
2625 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "GREAT SCOTT!!! Cannot execute batched statements! [%s]\n"
2626 "If you are using mysql, make sure you are using MYODBC 3.51.18 or higher and enable FLAG_MULTI_STATEMENTS\n", err);
2627
2628 switch_cache_db_release_db_handle(&dbh);
2629 free(test2);
2630 free(test_sql);
2631 free(err);
2632 return 0;
2633 }
2634 }
2635
2636 free(test2);
2637
2638
2639 free(test_sql);
2640
2641 test_sql = switch_mprintf("delete from sip_subscriptions where hostname='%q' and full_to='XXX'", mod_sofia_globals.hostname);
2642
2643 switch_cache_db_test_reactive(dbh, test_sql, "DROP TABLE sip_subscriptions", sub_sql);
2644
2645 free(test_sql);
2646 test_sql = switch_mprintf("delete from sip_dialogs where hostname='%q' and (expires <> -9999 or rpid='' or sip_from_tag='' or rcd > 0)",
2647 mod_sofia_globals.hostname);
2648
2649
2650 switch_cache_db_test_reactive(dbh, test_sql, "DROP TABLE sip_dialogs", dialog_sql);
2651
2652 free(test_sql);
2653 test_sql = switch_mprintf("delete from sip_presence where hostname='%q' or open_closed=''", mod_sofia_globals.hostname);
2654
2655 switch_cache_db_test_reactive(dbh, test_sql, "DROP TABLE sip_presence", pres_sql);
2656
2657 free(test_sql);
2658 test_sql = switch_mprintf("delete from sip_authentication where hostname='%q' or last_nc >= 0", mod_sofia_globals.hostname);
2659
2660 switch_cache_db_test_reactive(dbh, test_sql, "DROP TABLE sip_authentication", auth_sql);
2661
2662 free(test_sql);
2663 test_sql = switch_mprintf("delete from sip_shared_appearance_subscriptions where contact_str='' or hostname='%q' and network_ip like '%%'",
2664 mod_sofia_globals.hostname);
2665
2666 switch_cache_db_test_reactive(dbh, test_sql, "DROP TABLE sip_shared_appearance_subscriptions", shared_appearance_sql);
2667
2668 free(test_sql);
2669 test_sql = switch_mprintf("delete from sip_shared_appearance_dialogs where contact_str='' or hostname='%q' and network_ip like '%%'",
2670 mod_sofia_globals.hostname);
2671
2672 switch_cache_db_test_reactive(dbh, test_sql, "DROP TABLE sip_shared_appearance_dialogs", shared_appearance_dialogs_sql);
2673
2674 free(test_sql);
2675
2676 for (x = 0; indexes[x]; x++) {
2677 switch_cache_db_create_schema(dbh, indexes[x], NULL);
2678 }
2679
2680 switch_cache_db_release_db_handle(&dbh);
2681
2682 return 1;
2683
2684 }
2685
sofia_glue_execute_sql(sofia_profile_t * profile,char ** sqlp,switch_bool_t sql_already_dynamic)2686 void sofia_glue_execute_sql(sofia_profile_t *profile, char **sqlp, switch_bool_t sql_already_dynamic)
2687 {
2688 char *sql;
2689
2690 switch_assert(sqlp && *sqlp);
2691 sql = *sqlp;
2692
2693 switch_sql_queue_manager_push(profile->qm, sql, 1, !sql_already_dynamic);
2694
2695 if (sql_already_dynamic) {
2696 *sqlp = NULL;
2697 }
2698 }
2699
2700
sofia_glue_execute_sql_now(sofia_profile_t * profile,char ** sqlp,switch_bool_t sql_already_dynamic)2701 void sofia_glue_execute_sql_now(sofia_profile_t *profile, char **sqlp, switch_bool_t sql_already_dynamic)
2702 {
2703 char *sql;
2704
2705 switch_assert(sqlp && *sqlp);
2706 sql = *sqlp;
2707
2708 switch_mutex_lock(profile->dbh_mutex);
2709 switch_sql_queue_manager_push_confirm(profile->qm, sql, 0, !sql_already_dynamic);
2710 switch_mutex_unlock(profile->dbh_mutex);
2711
2712 if (sql_already_dynamic) {
2713 *sqlp = NULL;
2714 }
2715 }
2716
sofia_glue_execute_sql_soon(sofia_profile_t * profile,char ** sqlp,switch_bool_t sql_already_dynamic)2717 void sofia_glue_execute_sql_soon(sofia_profile_t *profile, char **sqlp, switch_bool_t sql_already_dynamic)
2718 {
2719 char *sql;
2720
2721 switch_assert(sqlp && *sqlp);
2722 sql = *sqlp;
2723
2724 switch_sql_queue_manager_push(profile->qm, sql, 0, !sql_already_dynamic);
2725
2726 if (sql_already_dynamic) {
2727 *sqlp = NULL;
2728 }
2729 }
2730
2731
_sofia_glue_get_db_handle(sofia_profile_t * profile,const char * file,const char * func,int line)2732 switch_cache_db_handle_t *_sofia_glue_get_db_handle(sofia_profile_t *profile, const char *file, const char *func, int line)
2733 {
2734 switch_cache_db_handle_t *dbh = NULL;
2735 char *dsn;
2736
2737 if (!zstr(profile->odbc_dsn)) {
2738 dsn = profile->odbc_dsn;
2739 } else {
2740 dsn = profile->dbname;
2741 }
2742
2743 if (_switch_cache_db_get_db_handle_dsn(&dbh, dsn, file, func, line) != SWITCH_STATUS_SUCCESS) {
2744 dbh = NULL;
2745 }
2746
2747 return dbh;
2748 }
2749
sofia_glue_actually_execute_sql_trans(sofia_profile_t * profile,char * sql,switch_mutex_t * mutex)2750 void sofia_glue_actually_execute_sql_trans(sofia_profile_t *profile, char *sql, switch_mutex_t *mutex)
2751 {
2752 switch_cache_db_handle_t *dbh = NULL;
2753
2754 if (mutex) {
2755 switch_mutex_lock(mutex);
2756 }
2757
2758
2759 if (!(dbh = sofia_glue_get_db_handle(profile))) {
2760 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n");
2761
2762 goto end;
2763 }
2764
2765 switch_cache_db_persistant_execute_trans_full(dbh, sql, 1,
2766 profile->pre_trans_execute,
2767 profile->post_trans_execute,
2768 profile->inner_pre_trans_execute,
2769 profile->inner_post_trans_execute
2770 );
2771
2772 switch_cache_db_release_db_handle(&dbh);
2773
2774 end:
2775
2776 if (mutex) {
2777 switch_mutex_unlock(mutex);
2778 }
2779 }
2780
sofia_glue_actually_execute_sql(sofia_profile_t * profile,char * sql,switch_mutex_t * mutex)2781 void sofia_glue_actually_execute_sql(sofia_profile_t *profile, char *sql, switch_mutex_t *mutex)
2782 {
2783 switch_cache_db_handle_t *dbh = NULL;
2784 char *err = NULL;
2785
2786 if (mutex) {
2787 switch_mutex_lock(mutex);
2788 }
2789
2790 if (!(dbh = sofia_glue_get_db_handle(profile))) {
2791 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n");
2792
2793 if (mutex) {
2794 switch_mutex_unlock(mutex);
2795 }
2796
2797 return;
2798 }
2799
2800 switch_cache_db_execute_sql(dbh, sql, &err);
2801
2802 if (mutex) {
2803 switch_mutex_unlock(mutex);
2804 }
2805
2806 if (err) {
2807 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: [%s]\n%s\n", err, sql);
2808 free(err);
2809 }
2810
2811 switch_cache_db_release_db_handle(&dbh);
2812 }
2813
sofia_glue_execute_sql_callback(sofia_profile_t * profile,switch_mutex_t * mutex,char * sql,switch_core_db_callback_func_t callback,void * pdata)2814 switch_bool_t sofia_glue_execute_sql_callback(sofia_profile_t *profile,
2815 switch_mutex_t *mutex, char *sql, switch_core_db_callback_func_t callback, void *pdata)
2816 {
2817 switch_bool_t ret = SWITCH_FALSE;
2818 char *errmsg = NULL;
2819 switch_cache_db_handle_t *dbh = NULL;
2820
2821 if (mutex) {
2822 switch_mutex_lock(mutex);
2823 }
2824
2825 if (!(dbh = sofia_glue_get_db_handle(profile))) {
2826 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n");
2827
2828 if (mutex) {
2829 switch_mutex_unlock(mutex);
2830 }
2831
2832 return ret;
2833 }
2834
2835 switch_cache_db_execute_sql_callback(dbh, sql, callback, pdata, &errmsg);
2836
2837 if (mutex) {
2838 switch_mutex_unlock(mutex);
2839 }
2840
2841 if (errmsg) {
2842 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: [%s] %s\n", sql, errmsg);
2843 free(errmsg);
2844 }
2845
2846 switch_cache_db_release_db_handle(&dbh);
2847
2848 return ret;
2849 }
2850
sofia_glue_execute_sql2str(sofia_profile_t * profile,switch_mutex_t * mutex,char * sql,char * resbuf,size_t len)2851 char *sofia_glue_execute_sql2str(sofia_profile_t *profile, switch_mutex_t *mutex, char *sql, char *resbuf, size_t len)
2852 {
2853 char *ret = NULL;
2854 char *err = NULL;
2855 switch_cache_db_handle_t *dbh = NULL;
2856
2857 if (mutex) {
2858 switch_mutex_lock(mutex);
2859 }
2860
2861 if (!(dbh = sofia_glue_get_db_handle(profile))) {
2862 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB\n");
2863
2864 if (mutex) {
2865 switch_mutex_unlock(mutex);
2866 }
2867
2868 return NULL;
2869 }
2870
2871 ret = switch_cache_db_execute_sql2str(dbh, sql, resbuf, len, &err);
2872
2873 if (mutex) {
2874 switch_mutex_unlock(mutex);
2875 }
2876
2877 if (err) {
2878 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: [%s]\n%s\n", err, sql);
2879 free(err);
2880 }
2881
2882 switch_cache_db_release_db_handle(&dbh);
2883
2884 return ret;
2885 }
2886
sofia_glue_get_register_host(const char * uri)2887 char *sofia_glue_get_register_host(const char *uri)
2888 {
2889 char *register_host = NULL;
2890 const char *s;
2891 char *p = NULL;
2892
2893 if (zstr(uri)) {
2894 return NULL;
2895 }
2896
2897 if ((s = switch_stristr("sip:", uri))) {
2898 s += 4;
2899 } else if ((s = switch_stristr("sips:", uri))) {
2900 s += 5;
2901 }
2902
2903 if (!s) {
2904 return NULL;
2905 }
2906
2907 register_host = strdup(s);
2908
2909 switch_assert(register_host);
2910
2911 /* remove port for register_host for testing nat acl take into account
2912 ipv6 addresses which are required to have brackets around the addr
2913 */
2914
2915 if ((p = strchr(register_host, ']'))) {
2916 if (*(p + 1) == ':') {
2917 *(p + 1) = '\0';
2918 }
2919 } else {
2920 if ((p = strrchr(register_host, ':'))) {
2921 *p = '\0';
2922 }
2923 }
2924
2925 /* register_proxy should always start with "sip:" or "sips:" */
2926 assert(register_host);
2927
2928 return register_host;
2929 }
2930
sofia_glue_strip_proto(const char * uri)2931 const char *sofia_glue_strip_proto(const char *uri)
2932 {
2933 char *p;
2934
2935 if ((p = strchr(uri, ':'))) {
2936 return p + 1;
2937 }
2938
2939 return uri;
2940 }
2941
sofia_cid_name2type(const char * name)2942 sofia_cid_type_t sofia_cid_name2type(const char *name)
2943 {
2944 if (!strcasecmp(name, "rpid")) {
2945 return CID_TYPE_RPID;
2946 }
2947
2948 if (!strcasecmp(name, "pid")) {
2949 return CID_TYPE_PID;
2950 }
2951
2952 return CID_TYPE_NONE;
2953
2954 }
2955
2956 /* all the values of the structure are initialized to NULL */
2957 /* in case of failure the function returns NULL */
2958 /* sofia_destination->route can be NULL */
sofia_glue_get_destination(char * data)2959 sofia_destination_t *sofia_glue_get_destination(char *data)
2960 {
2961 sofia_destination_t *dst = NULL;
2962 char *to = NULL;
2963 char *contact = NULL;
2964 char *route = NULL;
2965 char *route_uri = NULL;
2966 char *eoc = NULL;
2967 char *p = NULL;
2968
2969 if (zstr(data)) {
2970 return NULL;
2971 }
2972
2973 if (!(dst = (sofia_destination_t *) malloc(sizeof(sofia_destination_t)))) {
2974 return NULL;
2975 }
2976
2977 /* return a copy of what is in the buffer between the first < and > */
2978 if (!(contact = sofia_glue_get_url_from_contact(data, 1))) {
2979 goto mem_fail;
2980 }
2981
2982 if ((eoc = strstr(contact, ";fs_path="))) {
2983 *eoc = '\0';
2984
2985 if (!(route = strdup(eoc + 9))) {
2986 goto mem_fail;
2987 }
2988
2989 for (p = route; p && *p; p++) {
2990 if (*p == '>' || *p == ';') {
2991 *p = '\0';
2992 break;
2993 }
2994 }
2995
2996 switch_url_decode(route);
2997
2998 if (!(route_uri = strdup(route))) {
2999 goto mem_fail;
3000 }
3001 if ((p = strchr(route_uri, ','))) {
3002 do {
3003 *p = '\0';
3004 } while ((--p > route_uri) && *p == ' ');
3005 }
3006 }
3007
3008 if (!(to = strdup(data))) {
3009 goto mem_fail;
3010 }
3011
3012 if ((eoc = strstr(to, ";fs_path="))) {
3013 *eoc++ = '>';
3014 *eoc = '\0';
3015 }
3016
3017 if ((p = strstr(contact, ";fs_"))) {
3018 *p = '\0';
3019 }
3020
3021 dst->contact = contact;
3022 dst->to = to;
3023 dst->route = route;
3024 dst->route_uri = route_uri;
3025 return dst;
3026
3027 mem_fail:
3028 switch_safe_free(contact);
3029 switch_safe_free(to);
3030 switch_safe_free(route);
3031 switch_safe_free(route_uri);
3032 switch_safe_free(dst);
3033 return NULL;
3034 }
3035
sofia_glue_free_destination(sofia_destination_t * dst)3036 void sofia_glue_free_destination(sofia_destination_t *dst)
3037 {
3038 if (dst) {
3039 switch_safe_free(dst->contact);
3040 switch_safe_free(dst->route);
3041 switch_safe_free(dst->route_uri);
3042 switch_safe_free(dst->to);
3043 switch_safe_free(dst);
3044 }
3045 }
3046
sofia_glue_send_notify(sofia_profile_t * profile,const char * user,const char * host,const char * event,const char * contenttype,const char * body,const char * o_contact,const char * network_ip,const char * call_id)3047 switch_status_t sofia_glue_send_notify(sofia_profile_t *profile, const char *user, const char *host, const char *event, const char *contenttype,
3048 const char *body, const char *o_contact, const char *network_ip, const char *call_id)
3049 {
3050 char *id = NULL;
3051 nua_handle_t *nh;
3052 sofia_destination_t *dst = NULL;
3053 char *contact_str, *contact, *user_via = NULL;
3054 char *route_uri = NULL, *p;
3055 char *ptr;
3056
3057 contact = sofia_glue_get_url_from_contact((char *) o_contact, 1);
3058
3059 if ((p = strstr(contact, ";fs_"))) {
3060 *p = '\0';
3061 }
3062
3063 if (!zstr(network_ip) && sofia_glue_check_nat(profile, network_ip)) {
3064 id = switch_mprintf("sip:%s@%s", user, profile->extsipip);
3065 switch_assert(id);
3066
3067 if ((ptr = sofia_glue_find_parameter(o_contact, "transport="))) {
3068 sofia_transport_t transport = sofia_glue_str2transport( ptr + 10 );
3069
3070 switch (transport) {
3071 case SOFIA_TRANSPORT_TCP:
3072 contact_str = profile->tcp_public_contact;
3073 break;
3074 case SOFIA_TRANSPORT_TCP_TLS:
3075 contact_str = sofia_test_pflag(profile, PFLAG_TLS) ?
3076 profile->tls_public_contact : profile->tcp_public_contact;
3077 break;
3078 default:
3079 contact_str = profile->public_url;
3080 break;
3081 }
3082 user_via = sofia_glue_create_external_via(NULL, profile, transport);
3083 } else {
3084 user_via = sofia_glue_create_external_via(NULL, profile, SOFIA_TRANSPORT_UDP);
3085 contact_str = profile->public_url;
3086 }
3087 } else {
3088 id = switch_mprintf("sip:%s@%s", user, host);
3089 switch_assert(id);
3090
3091 if ((ptr = sofia_glue_find_parameter(o_contact, "transport="))) {
3092 sofia_transport_t transport = sofia_glue_str2transport( ptr + 10 );
3093
3094 switch (transport) {
3095 case SOFIA_TRANSPORT_TCP:
3096 contact_str = profile->tcp_contact;
3097 break;
3098 case SOFIA_TRANSPORT_TCP_TLS:
3099 contact_str = sofia_test_pflag(profile, PFLAG_TLS) ?
3100 profile->tls_contact : profile->tcp_contact;
3101 break;
3102 default:
3103 contact_str = profile->url;
3104 break;
3105 }
3106 } else {
3107 contact_str = profile->url;
3108 }
3109 }
3110
3111 dst = sofia_glue_get_destination((char *) o_contact);
3112 switch_assert(dst);
3113
3114 if (dst->route_uri) {
3115 route_uri = sofia_glue_strip_uri(dst->route_uri);
3116 }
3117
3118 nh = nua_handle(profile->nua, NULL, NUTAG_URL(contact), SIPTAG_FROM_STR(id), SIPTAG_TO_STR(id), SIPTAG_CONTACT_STR(contact_str), TAG_END());
3119 nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
3120
3121 nua_notify(nh,
3122 NUTAG_NEWSUB(1),
3123 TAG_IF(dst->route_uri, NUTAG_PROXY(route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)),
3124 TAG_IF(user_via, SIPTAG_VIA_STR(user_via)),
3125 SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource"),
3126 TAG_IF(event, SIPTAG_EVENT_STR(event)),
3127 TAG_IF(call_id, SIPTAG_CALL_ID_STR(call_id)),
3128 TAG_IF(contenttype, SIPTAG_CONTENT_TYPE_STR(contenttype)), TAG_IF(body, SIPTAG_PAYLOAD_STR(body)), TAG_END());
3129
3130 switch_safe_free(contact);
3131 switch_safe_free(route_uri);
3132 switch_safe_free(id);
3133 sofia_glue_free_destination(dst);
3134 switch_safe_free(user_via);
3135
3136 return SWITCH_STATUS_SUCCESS;
3137 }
3138
3139
sofia_glue_tech_simplify(private_object_t * tech_pvt)3140 int sofia_glue_tech_simplify(private_object_t *tech_pvt)
3141 {
3142 const char *uuid, *network_addr_a = NULL, *network_addr_b = NULL, *simplify, *simplify_other_channel;
3143 switch_channel_t *other_channel = NULL, *inbound_channel = NULL;
3144 switch_core_session_t *other_session = NULL, *inbound_session = NULL;
3145 uint8_t did_simplify = 0;
3146 int r = 0;
3147
3148 if (!switch_channel_test_flag(tech_pvt->channel, CF_ANSWERED) || switch_channel_test_flag(tech_pvt->channel, CF_SIMPLIFY)) {
3149 goto end;
3150 }
3151
3152 if (switch_channel_test_flag(tech_pvt->channel, CF_BRIDGED) &&
3153 (uuid = switch_channel_get_partner_uuid(tech_pvt->channel)) && (other_session = switch_core_session_locate(uuid))) {
3154
3155 other_channel = switch_core_session_get_channel(other_session);
3156
3157 if (switch_channel_test_flag(other_channel, CF_ANSWERED)) { /* Check if the other channel is answered */
3158 simplify = switch_channel_get_variable(tech_pvt->channel, "sip_auto_simplify");
3159 simplify_other_channel = switch_channel_get_variable(other_channel, "sip_auto_simplify");
3160
3161 r = 1;
3162
3163 if (switch_true(simplify) && !switch_channel_test_flag(tech_pvt->channel, CF_BRIDGE_ORIGINATOR)) {
3164 network_addr_a = switch_channel_get_variable(tech_pvt->channel, "network_addr");
3165 network_addr_b = switch_channel_get_variable(other_channel, "network_addr");
3166 inbound_session = other_session;
3167 inbound_channel = other_channel;
3168 } else if (switch_true(simplify_other_channel) && !switch_channel_test_flag(other_channel, CF_BRIDGE_ORIGINATOR)) {
3169 network_addr_a = switch_channel_get_variable(other_channel, "network_addr");
3170 network_addr_b = switch_channel_get_variable(tech_pvt->channel, "network_addr");
3171 inbound_session = tech_pvt->session;
3172 inbound_channel = tech_pvt->channel;
3173 }
3174
3175 if (inbound_channel && inbound_session && !zstr(network_addr_a) && !zstr(network_addr_b) && !strcmp(network_addr_a, network_addr_b)) {
3176 if (strcmp(network_addr_a, switch_str_nil(tech_pvt->profile->sipip))
3177 && strcmp(network_addr_a, switch_str_nil(tech_pvt->profile->extsipip))) {
3178
3179 switch_core_session_message_t *msg;
3180
3181 switch_log_printf(SWITCH_CHANNEL_ID_LOG, __FILE__, __SWITCH_FUNC__, __LINE__, switch_channel_get_uuid(inbound_channel),
3182 SWITCH_LOG_NOTICE, "Will simplify channel [%s]\n", switch_channel_get_name(inbound_channel));
3183
3184 msg = switch_core_session_alloc(inbound_session, sizeof(*msg));
3185 MESSAGE_STAMP_FFL(msg);
3186 msg->message_id = SWITCH_MESSAGE_INDICATE_SIMPLIFY;
3187 msg->from = __FILE__;
3188 switch_core_session_receive_message(inbound_session, msg);
3189
3190 did_simplify = 1;
3191
3192 switch_core_recovery_track(inbound_session);
3193
3194 switch_channel_set_flag(inbound_channel, CF_SIMPLIFY);
3195
3196 }
3197 }
3198
3199 if (!did_simplify && inbound_channel) {
3200 switch_log_printf(SWITCH_CHANNEL_ID_LOG, __FILE__, __SWITCH_FUNC__, __LINE__, switch_channel_get_uuid(inbound_channel), SWITCH_LOG_NOTICE,
3201 "Could not simplify channel [%s]\n", switch_channel_get_name(inbound_channel));
3202 }
3203 }
3204
3205 switch_core_session_rwunlock(other_session);
3206 }
3207
3208
3209 end:
3210
3211 return r;
3212 }
3213
sofia_glue_pause_jitterbuffer(switch_core_session_t * session,switch_bool_t on)3214 void sofia_glue_pause_jitterbuffer(switch_core_session_t *session, switch_bool_t on)
3215 {
3216 switch_core_session_message_t *msg;
3217 msg = switch_core_session_alloc(session, sizeof(*msg));
3218 MESSAGE_STAMP_FFL(msg);
3219 msg->message_id = SWITCH_MESSAGE_INDICATE_JITTER_BUFFER;
3220 msg->string_arg = switch_core_session_strdup(session, on ? "pause" : "resume");
3221 msg->from = __FILE__;
3222
3223 switch_core_session_queue_message(session, msg);
3224 }
3225
3226
sofia_glue_build_vid_refresh_message(switch_core_session_t * session,const char * pl)3227 void sofia_glue_build_vid_refresh_message(switch_core_session_t *session, const char *pl)
3228 {
3229 switch_core_session_message_t *msg;
3230 msg = switch_core_session_alloc(session, sizeof(*msg));
3231 MESSAGE_STAMP_FFL(msg);
3232 msg->message_id = SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ;
3233 if (pl) {
3234 msg->string_arg = switch_core_session_strdup(session, pl);
3235 }
3236 msg->from = __FILE__;
3237
3238 switch_core_session_queue_message(session, msg);
3239 }
3240
3241
sofia_glue_gen_contact_str(sofia_profile_t * profile,sip_t const * sip,nua_handle_t * nh,sofia_dispatch_event_t * de,sofia_nat_parse_t * np)3242 char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, nua_handle_t *nh, sofia_dispatch_event_t *de, sofia_nat_parse_t *np)
3243 {
3244 char *contact_str = NULL;
3245 const char *contact_host;//, *contact_user;
3246 sip_contact_t const *contact;
3247 char *port;
3248 const char *display = "\"user\"";
3249 char new_port[25] = "";
3250 sofia_nat_parse_t lnp = { { 0 } };
3251 const char *ipv6;
3252 sip_from_t const *from;
3253
3254 if (!sip || !sip->sip_contact) {
3255 return NULL;
3256 }
3257
3258 from = sip->sip_from;
3259 contact = sip->sip_contact;
3260
3261 if (!np) {
3262 np = &lnp;
3263 }
3264
3265 sofia_glue_get_addr(de->data->e_msg, np->network_ip, sizeof(np->network_ip), &np->network_port);
3266
3267 if (sofia_glue_check_nat(profile, np->network_ip)) {
3268 np->is_auto_nat = 1;
3269 }
3270
3271 port = (char *) contact->m_url->url_port;
3272 contact_host = sip->sip_contact->m_url->url_host;
3273 //contact_user = sip->sip_contact->m_url->url_user;
3274
3275 display = contact->m_display;
3276
3277
3278 if (zstr(display)) {
3279 if (from) {
3280 display = from->a_display;
3281 if (zstr(display)) {
3282 display = "\"user\"";
3283 }
3284 }
3285 } else {
3286 display = "\"user\"";
3287 }
3288
3289 if (sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION)) {
3290 if (sip->sip_via) {
3291 const char *v_port = sip->sip_via->v_port;
3292 const char *v_host = sip->sip_via->v_host;
3293
3294 if (v_host && sip->sip_via->v_received) {
3295 np->is_nat = "via received";
3296 } else if (v_host && strcmp(np->network_ip, v_host)) {
3297 np->is_nat = "via host";
3298 } else if (v_port && atoi(v_port) != np->network_port) {
3299 np->is_nat = "via port";
3300 }
3301 }
3302 }
3303
3304 if (!np->is_nat && sip->sip_via && sip->sip_via->v_port &&
3305 atoi(sip->sip_via->v_port) == 5060 && np->network_port != 5060 ) {
3306 np->is_nat = "via port";
3307 }
3308
3309 if (!np->is_nat && profile->nat_acl_count) {
3310 uint32_t x = 0;
3311 int ok = 1;
3312 char *last_acl = NULL;
3313
3314 if (!zstr(contact_host)) {
3315 for (x = 0; x < profile->nat_acl_count; x++) {
3316 last_acl = profile->nat_acl[x];
3317 if (!(ok = switch_check_network_list_ip(contact_host, last_acl))) {
3318 break;
3319 }
3320 }
3321
3322 if (ok) {
3323 np->is_nat = last_acl;
3324 }
3325 }
3326 }
3327
3328 if (np->is_nat && profile->local_network && switch_check_network_list_ip(np->network_ip, profile->local_network)) {
3329 if (profile->debug) {
3330 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IP %s is on local network, not seting NAT mode.\n", np->network_ip);
3331 }
3332 np->is_nat = NULL;
3333 }
3334
3335 if (sip->sip_record_route) {
3336 char *full_contact = sip_header_as_string(nh->nh_home, (void *) contact);
3337 char *route = sofia_glue_strip_uri(sip_header_as_string(nh->nh_home, (void *) sip->sip_record_route));
3338 char *full_contact_dup;
3339 char *route_encoded;
3340 int route_encoded_len;
3341 full_contact_dup = sofia_glue_get_url_from_contact(full_contact, 1);
3342 route_encoded_len = (int)(strlen(route) * 3) + 1;
3343 switch_zmalloc(route_encoded, route_encoded_len);
3344 switch_url_encode(route, route_encoded, route_encoded_len);
3345 contact_str = switch_mprintf("%s <%s;fs_path=%s>", display, full_contact_dup, route_encoded);
3346 free(route);
3347 free(full_contact_dup);
3348 free(route_encoded);
3349 }
3350 else if (np->is_nat && np->fs_path) {
3351 char *full_contact = sip_header_as_string(nh->nh_home, (void *) contact);
3352 char *full_contact_dup;
3353 char *path_encoded;
3354 int path_encoded_len;
3355 char *path_val;
3356 const char *tp;
3357
3358 full_contact_dup = sofia_glue_get_url_from_contact(full_contact, 1);
3359
3360 if ((tp = switch_stristr("transport=", full_contact_dup))) {
3361 tp += 10;
3362 }
3363
3364 if (zstr(tp)) {
3365 tp = "udp";
3366 }
3367
3368 path_val = switch_mprintf("sip:%s:%d;transport=%s", np->network_ip, np->network_port, tp);
3369 path_encoded_len = (int)(strlen(path_val) * 3) + 1;
3370
3371 switch_zmalloc(path_encoded, path_encoded_len);
3372 switch_copy_string(path_encoded, ";fs_path=", 10);
3373 switch_url_encode(path_val, path_encoded + 9, path_encoded_len - 9);
3374
3375 contact_str = switch_mprintf("%s <%s;fs_nat=yes%s>", display, full_contact_dup, path_encoded);
3376
3377 free(full_contact_dup);
3378 free(path_encoded);
3379 free(path_val);
3380
3381 } else {
3382
3383 if (zstr(contact_host)) {
3384 np->is_nat = "No contact host";
3385 }
3386
3387 if (np->is_nat) {
3388 contact_host = np->network_ip;
3389 switch_snprintf(new_port, sizeof(new_port), ":%d", np->network_port);
3390 port = NULL;
3391 }
3392
3393
3394 if (port) {
3395 switch_snprintf(new_port, sizeof(new_port), ":%s", port);
3396 }
3397
3398 ipv6 = strchr(contact_host, ':');
3399
3400
3401 if (contact->m_url->url_params) {
3402 contact_str = switch_mprintf("%s <sip:%s%s%s%s%s%s;%s>%s",
3403 display, contact->m_url->url_user,
3404 contact->m_url->url_user ? "@" : "",
3405 ipv6 ? "[" : "",
3406 contact_host, ipv6 ? "]" : "", new_port, contact->m_url->url_params, np->is_nat ? ";fs_nat=yes" : "");
3407 } else {
3408 contact_str = switch_mprintf("%s <sip:%s%s%s%s%s%s>%s",
3409 display,
3410 contact->m_url->url_user,
3411 contact->m_url->url_user ? "@" : "",
3412 ipv6 ? "[" : "", contact_host, ipv6 ? "]" : "", new_port, np->is_nat ? ";fs_nat=yes" : "");
3413 }
3414 }
3415
3416 return contact_str;
3417 }
3418
sofia_glue_get_host(const char * str,switch_memory_pool_t * pool)3419 char *sofia_glue_get_host(const char *str, switch_memory_pool_t *pool)
3420 {
3421 char *s, *p;
3422
3423 if ((p = strchr(str, '@'))) {
3424 p++;
3425 } else {
3426 return NULL;
3427 }
3428
3429 if (pool) {
3430 s = switch_core_strdup(pool, p);
3431 } else {
3432 s = strdup(p);
3433 }
3434
3435 for (p = s; p && *p; p++) {
3436 if ((*p == ';') || (*p == '>')) {
3437 *p = '\0';
3438 break;
3439 }
3440 }
3441
3442 return s;
3443 }
3444
sofia_glue_fire_events(sofia_profile_t * profile)3445 void sofia_glue_fire_events(sofia_profile_t *profile)
3446 {
3447 void *pop = NULL;
3448
3449 while (profile->event_queue && switch_queue_trypop(profile->event_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
3450 switch_event_t *event = (switch_event_t *) pop;
3451 switch_event_fire(&event);
3452 }
3453
3454 }
3455
sofia_event_fire(sofia_profile_t * profile,switch_event_t ** event)3456 void sofia_event_fire(sofia_profile_t *profile, switch_event_t **event)
3457 {
3458 switch_queue_push(profile->event_queue, *event);
3459 *event = NULL;
3460 }
3461
sofia_glue_clear_soa(switch_core_session_t * session,switch_bool_t partner)3462 void sofia_glue_clear_soa(switch_core_session_t *session, switch_bool_t partner)
3463 {
3464 switch_core_session_t *other_session;
3465 struct private_object *tech_pvt = switch_core_session_get_private(session);
3466
3467 sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA);
3468
3469 if (partner && switch_core_session_get_partner(session, &other_session) == SWITCH_STATUS_SUCCESS) {
3470 if (switch_core_session_compare(session, other_session)) {
3471 struct private_object *other_tech_pvt = switch_core_session_get_private(other_session);
3472
3473 sofia_clear_flag(other_tech_pvt, TFLAG_ENABLE_SOA);
3474 }
3475 switch_core_session_rwunlock(other_session);
3476 }
3477
3478 }
3479
sofia_glue_get_profile_url(sofia_profile_t * profile,char * remote_ip,const sofia_transport_t transport)3480 char *sofia_glue_get_profile_url(sofia_profile_t *profile, char *remote_ip, const sofia_transport_t transport)
3481 {
3482 char *url = NULL;
3483 int check_nat = 0;
3484
3485 if (!zstr(remote_ip) && sofia_glue_check_nat(profile, remote_ip)) {
3486 check_nat = 1;
3487 }
3488
3489 if (sofia_glue_transport_has_tls(transport)) {
3490 if (check_nat && profile->tls_public_url) {
3491 url = profile->tls_public_url;
3492 } else {
3493 url = profile->tls_url;
3494 }
3495 } else {
3496 if (check_nat && profile->public_url) {
3497 url = profile->public_url;
3498 } else {
3499 url = profile->url;
3500 }
3501 }
3502
3503 if (!url) url = profile->url;
3504
3505 return url;
3506 }
3507
3508 /* For Emacs:
3509 * Local Variables:
3510 * mode:c
3511 * indent-tabs-mode:t
3512 * tab-width:4
3513 * c-basic-offset:4
3514 * End:
3515 * For VIM:
3516 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
3517 */
3518