Bug Summary

File:src/mod/endpoints/mod_sofia/mod_sofia.c
Warning:line 4992, column 79
Access to field 'extsipip' results in a dereference of a null pointer (loaded from variable 'profile')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name mod_sofia.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -menable-no-infs -menable-no-nans -menable-unsafe-fp-math -fno-signed-zeros -mreassociate -freciprocal-math -fno-trapping-math -ffp-contract=fast -ffast-math -ffinite-math-only -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -resource-dir /usr/lib/llvm-7/lib/clang/7.0.1 -D HAVE_CONFIG_H -I . -I ../../../../src/include -I ../../../../libs/esl/src/include -I ../../../../libs/xmlrpc-c -I /drone/src/src/include -I /drone/src/src/include -I /drone/src/libs/libteletone/src -D SWITCH_API_VISIBILITY=1 -D CJSON_API_VISIBILITY=1 -D HAVE_VISIBILITY=1 -I /usr/include/uuid -I /drone/src/src/include -I /drone/src/src/include -I /drone/src/libs/libteletone/src -D SWITCH_API_VISIBILITY=1 -D CJSON_API_VISIBILITY=1 -D HAVE_VISIBILITY=1 -D HAVE_OPENSSL -I . -I /usr/include/sofia-sip-1.13 -D HAVE_STIRSHAKEN -D PIC -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.1/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-result -Wno-misleading-indentation -std=c99 -fdebug-compilation-dir /drone/src/src/mod/endpoints/mod_sofia -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -o /drone/src/scan-build/2021-10-18-155719-401-1 -x c mod_sofia.c -faddrsig
1/*
2 * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3 * Copyright (C) 2005-2021, 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 at freeswitch.org>
28 * Paul D. Tinsley <pdt at jackhammer.org>
29 * Bret McDanel <trixter AT 0xdecafbad.com>
30 * Raymond Chandler <intralanman@freeswitch.org>
31 * Emmanuel Schmidbauer <eschmidbauer@gmail.com>
32 * Kathleen King <kathleen.king@quentustech.com>
33 *
34 *
35 * mod_sofia.c -- SOFIA SIP Endpoint
36 *
37 */
38
39/* Best viewed in a 160 x 60 VT100 Terminal or so the line below at least fits across your screen*/
40/*************************************************************************************************************************************************************/
41#include "mod_sofia.h"
42#include "sofia-sip/sip_extra.h"
43
44#if HAVE_STIRSHAKEN1
45#include <stir_shaken.h>
46#endif
47
48SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)switch_status_t mod_sofia_load (switch_loadable_module_interface_t
**module_interface, switch_memory_pool_t *pool)
;
49SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sofia_shutdown)switch_status_t mod_sofia_shutdown (void);
50SWITCH_MODULE_DEFINITION(mod_sofia, mod_sofia_load, mod_sofia_shutdown, NULL)static const char modname[] = "mod_sofia" ; __attribute__((visibility
("default"))) switch_loadable_module_function_table_t mod_sofia_module_interface
= { 5, mod_sofia_load, mod_sofia_shutdown, ((void*)0), SMODF_NONE
}
;
51
52struct mod_sofia_globals mod_sofia_globals;
53switch_endpoint_interface_t *sofia_endpoint_interface;
54
55#define STRLEN15 15
56
57void mod_sofia_shutdown_cleanup();
58static switch_status_t sofia_on_init(switch_core_session_t *session);
59
60static switch_status_t sofia_on_exchange_media(switch_core_session_t *session);
61static switch_status_t sofia_on_soft_execute(switch_core_session_t *session);
62static switch_status_t sofia_acknowledge_call(switch_core_session_t *session);
63static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
64 switch_caller_profile_t *outbound_profile, switch_core_session_t **new_session,
65 switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause);
66static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
67static switch_status_t sofia_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
68static switch_status_t sofia_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
69static switch_status_t sofia_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
70static switch_status_t sofia_read_text_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
71static switch_status_t sofia_write_text_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
72static switch_status_t sofia_kill_channel(switch_core_session_t *session, int sig);
73
74/* BODY OF THE MODULE */
75/*************************************************************************************************************************************************************/
76
77/*
78 State methods they get called when the state changes to the specific state
79 returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
80 so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
81*/
82static switch_status_t sofia_on_init(switch_core_session_t *session)
83{
84 const char *hval = NULL((void*)0);
85 switch_channel_t *channel = switch_core_session_get_channel(session);
86 private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
87 switch_status_t status = SWITCH_STATUS_SUCCESS;
88
89 switch_assert(tech_pvt != NULL)((tech_pvt != ((void*)0)) ? (void) (0) : __assert_fail ("tech_pvt != ((void*)0)"
, "mod_sofia.c", 89, __extension__ __PRETTY_FUNCTION__))
;
90
91
92 switch_mutex_lock(tech_pvt->sofia_mutex);
93
94
95 switch_core_media_check_dtmf_type(session);
96
97 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 97, (const char*)(session)
, SWITCH_LOG_DEBUG, "%s SOFIA INIT\n", switch_channel_get_name(channel));
98 if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
99 switch_core_media_absorb_sdp(session);
100 }
101
102 if ((hval = switch_channel_get_variable(channel, "sip_watch_headers")switch_channel_get_variable_dup(channel, "sip_watch_headers",
SWITCH_TRUE, -1)
)) {
103 char *dupvar = NULL((void*)0);
104 char *watch_headers[10];
105 unsigned int numhdrs = 0;
106 unsigned int i = 0;
107 dupvar = switch_core_session_strdup(session, hval)switch_core_perform_session_strdup(session, hval, "mod_sofia.c"
, (const char *)__func__, 107)
;
108 numhdrs = switch_separate_string(dupvar, ',', watch_headers, switch_arraylen(watch_headers)(sizeof(watch_headers) / sizeof(watch_headers[0])));
109 if (numhdrs) {
110 char **wheaders = switch_core_session_alloc(session, ((numhdrs+1) * sizeof(wheaders[0])))switch_core_perform_session_alloc(session, ((numhdrs+1) * sizeof
(wheaders[0])), "mod_sofia.c", (const char *)__func__, 110)
;
111 for (i = 0; i < numhdrs; i++) {
112 wheaders[i] = watch_headers[i];
113 }
114 wheaders[i] = NULL((void*)0);
115 tech_pvt->watch_headers = wheaders;
116 }
117 }
118
119 if (switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING) || switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING_BRIDGE)) {
120 sofia_set_flag(tech_pvt, TFLAG_RECOVERED)(tech_pvt)->flags[TFLAG_RECOVERED] = 1;
121 }
122
123 if (sofia_test_flag(tech_pvt, TFLAG_OUTBOUND)((tech_pvt)->flags[TFLAG_OUTBOUND] ? 1 : 0) || switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING)) {
124 if (sofia_glue_do_invite(session) != SWITCH_STATUS_SUCCESS) {
125 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(channel, "mod_sofia.c", (const char
*)__func__, 125, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)
;
126 assert(switch_channel_get_state(channel) != CS_INIT)((switch_channel_get_state(channel) != CS_INIT) ? (void) (0) :
__assert_fail ("switch_channel_get_state(channel) != CS_INIT"
, "mod_sofia.c", 126, __extension__ __PRETTY_FUNCTION__))
;
127 status = SWITCH_STATUS_FALSE;
128 goto end;
129 }
130 }
131
132 end:
133
134 switch_mutex_unlock(tech_pvt->sofia_mutex);
135
136 return status;
137}
138
139static switch_status_t sofia_on_routing(switch_core_session_t *session)
140{
141 private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
142 switch_channel_t *channel = switch_core_session_get_channel(session);
143 switch_assert(tech_pvt != NULL)((tech_pvt != ((void*)0)) ? (void) (0) : __assert_fail ("tech_pvt != ((void*)0)"
, "mod_sofia.c", 143, __extension__ __PRETTY_FUNCTION__))
;
144
145 if (sofia_test_pflag(tech_pvt->profile, PFLAG_AUTO_INVITE_100)((tech_pvt->profile)->pflags[PFLAG_AUTO_INVITE_100] ? 1
: 0)
&&
146 !switch_channel_test_flag(channel, CF_ANSWERED) &&
147 switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
148 if (sofia_acknowledge_call(session) != SWITCH_STATUS_SUCCESS) {
149 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 149, (const char*)(session)
, SWITCH_LOG_DEBUG, "Call appears to be already acknowledged\n");
150 }
151 }
152
153 if (!sofia_test_flag(tech_pvt, TFLAG_HOLD_LOCK)((tech_pvt)->flags[TFLAG_HOLD_LOCK] ? 1 : 0)) {
154 sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD)switch_mutex_lock(tech_pvt->flag_mutex); (tech_pvt)->flags
[TFLAG_SIP_HOLD] = 0; switch_mutex_unlock(tech_pvt->flag_mutex
);
;
155 switch_channel_clear_flag(channel, CF_LEG_HOLDING);
156 }
157
158 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 158, (const char*)(session)
, SWITCH_LOG_DEBUG, "%s SOFIA ROUTING\n",
159 switch_channel_get_name(switch_core_session_get_channel(session)));
160
161 return SWITCH_STATUS_SUCCESS;
162}
163
164
165static switch_status_t sofia_on_reset(switch_core_session_t *session)
166{
167 private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
168 switch_channel_t *channel = switch_core_session_get_channel(session);
169 switch_assert(tech_pvt != NULL)((tech_pvt != ((void*)0)) ? (void) (0) : __assert_fail ("tech_pvt != ((void*)0)"
, "mod_sofia.c", 169, __extension__ __PRETTY_FUNCTION__))
;
170
171 if (!sofia_test_flag(tech_pvt, TFLAG_HOLD_LOCK)((tech_pvt)->flags[TFLAG_HOLD_LOCK] ? 1 : 0)) {
172 sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD)switch_mutex_lock(tech_pvt->flag_mutex); (tech_pvt)->flags
[TFLAG_SIP_HOLD] = 0; switch_mutex_unlock(tech_pvt->flag_mutex
);
;
173 switch_channel_clear_flag(channel, CF_LEG_HOLDING);
174 }
175
176 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 176, (const char*)(session)
, SWITCH_LOG_DEBUG, "%s SOFIA RESET\n",
177 switch_channel_get_name(switch_core_session_get_channel(session)));
178
179
180 return SWITCH_STATUS_SUCCESS;
181}
182
183
184static switch_status_t sofia_on_hibernate(switch_core_session_t *session)
185{
186 private_object_t *tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
187 switch_channel_t *channel = switch_core_session_get_channel(session);
188 switch_assert(tech_pvt != NULL)((tech_pvt != ((void*)0)) ? (void) (0) : __assert_fail ("tech_pvt != ((void*)0)"
, "mod_sofia.c", 188, __extension__ __PRETTY_FUNCTION__))
;
189
190 if (!sofia_test_flag(tech_pvt, TFLAG_HOLD_LOCK)((tech_pvt)->flags[TFLAG_HOLD_LOCK] ? 1 : 0)) {
191 sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD)switch_mutex_lock(tech_pvt->flag_mutex); (tech_pvt)->flags
[TFLAG_SIP_HOLD] = 0; switch_mutex_unlock(tech_pvt->flag_mutex
);
;
192 switch_channel_clear_flag(channel, CF_LEG_HOLDING);
193 }
194
195 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 195, (const char*)(session)
, SWITCH_LOG_DEBUG, "%s SOFIA HIBERNATE\n",
196 switch_channel_get_name(switch_core_session_get_channel(session)));
197
198
199 return SWITCH_STATUS_SUCCESS;
200}
201
202static switch_status_t sofia_on_execute(switch_core_session_t *session)
203{
204 private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
205 switch_channel_t *channel = switch_core_session_get_channel(session);
206 switch_assert(tech_pvt != NULL)((tech_pvt != ((void*)0)) ? (void) (0) : __assert_fail ("tech_pvt != ((void*)0)"
, "mod_sofia.c", 206, __extension__ __PRETTY_FUNCTION__))
;
207
208 if (!sofia_test_flag(tech_pvt, TFLAG_HOLD_LOCK)((tech_pvt)->flags[TFLAG_HOLD_LOCK] ? 1 : 0)) {
209 sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD)switch_mutex_lock(tech_pvt->flag_mutex); (tech_pvt)->flags
[TFLAG_SIP_HOLD] = 0; switch_mutex_unlock(tech_pvt->flag_mutex
);
;
210 switch_channel_clear_flag(channel, CF_LEG_HOLDING);
211 }
212
213 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 213, (const char*)(session)
, SWITCH_LOG_DEBUG, "%s SOFIA EXECUTE\n",
214 switch_channel_get_name(switch_core_session_get_channel(session)));
215
216 return SWITCH_STATUS_SUCCESS;
217}
218
219char *generate_pai_str(private_object_t *tech_pvt)
220{
221 switch_core_session_t *session = tech_pvt->session;
222 const char *callee_name = NULL((void*)0), *callee_number = NULL((void*)0);
223 const char *var, *header, *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent")switch_channel_get_variable_dup(tech_pvt->channel, "sip_user_agent"
, SWITCH_TRUE, -1)
;
224 char *pai = NULL((void*)0);
225 const char *host = switch_channel_get_variable(tech_pvt->channel, "sip_to_host")switch_channel_get_variable_dup(tech_pvt->channel, "sip_to_host"
, SWITCH_TRUE, -1)
;
226
227 if (zstr(host)_zstr(host)) {
228 host = tech_pvt->profile->sipip;
229 }
230
231 if (!sofia_test_pflag(tech_pvt->profile, PFLAG_PASS_CALLEE_ID)((tech_pvt->profile)->pflags[PFLAG_PASS_CALLEE_ID] ? 1 :
0)
|| !sofia_test_pflag(tech_pvt->profile, PFLAG_CID_IN_1XX)((tech_pvt->profile)->pflags[PFLAG_CID_IN_1XX] ? 1 : 0) ||
232 ((var = switch_channel_get_variable(tech_pvt->channel, "sip_cid_in_1xx")switch_channel_get_variable_dup(tech_pvt->channel, "sip_cid_in_1xx"
, SWITCH_TRUE, -1)
) && switch_false(var))) {
233 return NULL((void*)0);
234 }
235
236 if (zstr((callee_name = switch_channel_get_variable(tech_pvt->channel, "initial_callee_id_name")))_zstr((callee_name = switch_channel_get_variable_dup(tech_pvt
->channel, "initial_callee_id_name", SWITCH_TRUE, -1)))
&&
237 zstr((callee_name = switch_channel_get_variable(tech_pvt->channel, "effective_callee_id_name")))_zstr((callee_name = switch_channel_get_variable_dup(tech_pvt
->channel, "effective_callee_id_name", SWITCH_TRUE, -1)))
&&
238 zstr((callee_name = switch_channel_get_variable(tech_pvt->channel, "sip_callee_id_name")))_zstr((callee_name = switch_channel_get_variable_dup(tech_pvt
->channel, "sip_callee_id_name", SWITCH_TRUE, -1)))
) {
239 callee_name = switch_channel_get_variable(tech_pvt->channel, "callee_id_name")switch_channel_get_variable_dup(tech_pvt->channel, "callee_id_name"
, SWITCH_TRUE, -1)
;
240 }
241
242 if (zstr((callee_number = switch_channel_get_variable(tech_pvt->channel, "initial_callee_id_number")))_zstr((callee_number = switch_channel_get_variable_dup(tech_pvt
->channel, "initial_callee_id_number", SWITCH_TRUE, -1)))
&&
243 zstr((callee_number = switch_channel_get_variable(tech_pvt->channel, "effective_callee_id_number")))_zstr((callee_number = switch_channel_get_variable_dup(tech_pvt
->channel, "effective_callee_id_number", SWITCH_TRUE, -1))
)
&&
244 zstr((callee_number = switch_channel_get_variable(tech_pvt->channel, "sip_callee_id_number")))_zstr((callee_number = switch_channel_get_variable_dup(tech_pvt
->channel, "sip_callee_id_number", SWITCH_TRUE, -1)))
&&
245 zstr((callee_number = switch_channel_get_variable(tech_pvt->channel, "callee_id_number")))_zstr((callee_number = switch_channel_get_variable_dup(tech_pvt
->channel, "callee_id_number", SWITCH_TRUE, -1)))
) {
246
247 callee_number = tech_pvt->caller_profile->destination_number;
248 }
249
250 if (zstr(callee_name)_zstr(callee_name) && !zstr(callee_number)_zstr(callee_number)) {
251 callee_name = callee_number;
252 }
253
254 callee_number = switch_sanitize_number(switch_core_session_strdup(session, callee_number)switch_core_perform_session_strdup(session, callee_number, "mod_sofia.c"
, (const char *)__func__, 254)
);
255 callee_name = switch_sanitize_number(switch_core_session_strdup(session, callee_name)switch_core_perform_session_strdup(session, callee_name, "mod_sofia.c"
, (const char *)__func__, 255)
);
256
257 if (!zstr(callee_number)_zstr(callee_number) && (zstr(ua)_zstr(ua) || !switch_stristr("polycom", ua))) {
258 callee_number = switch_core_session_sprintf(session, "sip:%s@%s", callee_number, host);
259 }
260
261 header = (tech_pvt->cid_type == CID_TYPE_RPID && !switch_stristr("aastra", ua)) ? "Remote-Party-ID" : "P-Asserted-Identity";
262
263 if (!zstr(callee_name)_zstr(callee_name) && strcmp(callee_name, "_undef_") && !zstr(callee_number)_zstr(callee_number)) {
264 check_decode(callee_name, tech_pvt->session)do { ((tech_pvt->session) ? (void) (0) : __assert_fail ("tech_pvt->session"
, "mod_sofia.c", 264, __extension__ __PRETTY_FUNCTION__)); if
(!_zstr(callee_name)) { int d = 0; char *p; if (strchr(callee_name
, '%')) { char *tmp = switch_core_perform_session_strdup(tech_pvt
->session, callee_name, "mod_sofia.c", (const char *)__func__
, 264); switch_url_decode(tmp); callee_name = tmp; d++; } if (
(p = strchr(callee_name, '"'))) { if (!d) { char *tmp = switch_core_perform_session_strdup
(tech_pvt->session, callee_name, "mod_sofia.c", (const char
*)__func__, 264); callee_name = tmp; } if ((p = strchr(callee_name
, '"'))) { callee_name = p+1; } if ((p = strrchr(callee_name,
'"'))) { *p = '\0'; } } } break; } while (0)
;
265
266 if (switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote)) {
267 pai = switch_core_session_sprintf(tech_pvt->session, "%s: \"%s\" <%s>%s\n"
268 "X-FS-Display-Name: %s\nX-FS-Display-Number: %s\n",
269 header, callee_name, callee_number,
270 tech_pvt->cid_type == CID_TYPE_RPID && !switch_stristr("aastra", ua) ?
271 ";party=calling;privacy=off;screen=no" : "",
272 callee_name, callee_number);
273 } else {
274 pai = switch_core_session_sprintf(tech_pvt->session, "%s: \"%s\" <%s>%s\n", header, callee_name, callee_number,
275 tech_pvt->cid_type == CID_TYPE_RPID && !switch_stristr("aastra", ua) ?
276 ";party=calling;privacy=off;screen=no" : "");
277 }
278
279 }
280
281 return pai;
282}
283
284static switch_jb_t *sofia_get_jb(switch_core_session_t *session, switch_media_type_t type)
285{
286 private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
287
288 return switch_core_media_get_jb(tech_pvt->session, type);
289}
290
291/* map QSIG cause codes to SIP from RFC4497 section 8.4.1 */
292static int hangup_cause_to_sip(switch_call_cause_t cause)
293{
294 switch (cause) {
295 case SWITCH_CAUSE_UNALLOCATED_NUMBER:
296 case SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET:
297 case SWITCH_CAUSE_NO_ROUTE_DESTINATION:
298 return 404;
299 case SWITCH_CAUSE_USER_BUSY:
300 return 486;
301 case SWITCH_CAUSE_NO_USER_RESPONSE:
302 return 408;
303 case SWITCH_CAUSE_NO_ANSWER:
304 case SWITCH_CAUSE_SUBSCRIBER_ABSENT:
305 return 480;
306 case SWITCH_CAUSE_CALL_REJECTED:
307 return 603;
308 case SWITCH_CAUSE_NUMBER_CHANGED:
309 case SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION:
310 return 410;
311 case SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER:
312 case SWITCH_CAUSE_INVALID_PROFILE:
313 return 502;
314 case SWITCH_CAUSE_INVALID_NUMBER_FORMAT:
315 case SWITCH_CAUSE_INVALID_URL:
316 case SWITCH_CAUSE_INVALID_GATEWAY:
317 return 484;
318 case SWITCH_CAUSE_FACILITY_REJECTED:
319 return 501;
320 case SWITCH_CAUSE_NORMAL_UNSPECIFIED:
321 return 480;
322 case SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL:
323 case SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION:
324 case SWITCH_CAUSE_NETWORK_OUT_OF_ORDER:
325 case SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE:
326 case SWITCH_CAUSE_SWITCH_CONGESTION:
327 case SWITCH_CAUSE_GATEWAY_DOWN:
328 return 503;
329 case SWITCH_CAUSE_OUTGOING_CALL_BARRED:
330 case SWITCH_CAUSE_INCOMING_CALL_BARRED:
331 case SWITCH_CAUSE_BEARERCAPABILITY_NOTAUTH:
332 return 403;
333 case SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL:
334 return 503;
335 case SWITCH_CAUSE_BEARERCAPABILITY_NOTIMPL:
336 case SWITCH_CAUSE_INCOMPATIBLE_DESTINATION:
337 return 488;
338 case SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED:
339 case SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED:
340 return 501;
341 case SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE:
342 return 504;
343 case SWITCH_CAUSE_ORIGINATOR_CANCEL:
344 return 487;
345 case SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR:
346 return 483;
347 /* Custom mappings not part of RFC */
348 case SWITCH_CAUSE_BUSY_EVERYWHERE:
349 return 600;
350 case SWITCH_CAUSE_DECLINE:
351 return 603;
352 case SWITCH_CAUSE_DOES_NOT_EXIST_ANYWHERE:
353 return 604;
354 case SWITCH_CAUSE_NOT_ACCEPTABLE:
355 return 606;
356 case SWITCH_CAUSE_UNWANTED:
357 return 607;
358 /* STIR/SHAKEN */
359 case SWITCH_CAUSE_NO_IDENTITY:
360 return 428;
361 case SWITCH_CAUSE_BAD_IDENTITY_INFO:
362 return 429;
363 case SWITCH_CAUSE_UNSUPPORTED_CERTIFICATE:
364 return 437;
365 case SWITCH_CAUSE_INVALID_IDENTITY:
366 return 438;
367 case SWITCH_CAUSE_STALE_DATE:
368 return 403;
369 default:
370 return 480;
371 }
372}
373
374switch_status_t sofia_on_destroy(switch_core_session_t *session)
375{
376 private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
377 switch_channel_t *channel = switch_core_session_get_channel(session);
378
379 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 379, (const char*)(session)
, SWITCH_LOG_DEBUG, "%s SOFIA DESTROY\n", switch_channel_get_name(channel));
380
381 if (tech_pvt) {
382
383 if (tech_pvt->proxy_refer_msg) {
384 msg_ref_destroy(tech_pvt->proxy_refer_msg);
385 tech_pvt->proxy_refer_msg = NULL((void*)0);
386 }
387
388 if (tech_pvt->respond_phrase) {
389 switch_yield(100000)switch_sleep(100000);;
390 }
391
392 if (!zstr(tech_pvt->call_id)_zstr(tech_pvt->call_id)) {
393 switch_core_hash_delete_locked(tech_pvt->profile->chat_hash, tech_pvt->call_id, tech_pvt->profile->flag_mutex);
394 }
395
396
397 switch_mutex_lock(tech_pvt->profile->flag_mutex);
398 tech_pvt->profile->inuse--;
399 switch_mutex_unlock(tech_pvt->profile->flag_mutex);
400
401 switch_media_handle_destroy(session);
402
403
404 if (sofia_test_pflag(tech_pvt->profile, PFLAG_DESTROY)((tech_pvt->profile)->pflags[PFLAG_DESTROY] ? 1 : 0) && !tech_pvt->profile->inuse) {
405 sofia_profile_destroy(tech_pvt->profile);
406 }
407 }
408
409 return SWITCH_STATUS_SUCCESS;
410
411}
412
413switch_status_t sofia_on_hangup(switch_core_session_t *session)
414{
415 switch_core_session_t *a_session;
416 private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
417 switch_channel_t *channel = switch_core_session_get_channel(session);
418 switch_call_cause_t cause = switch_channel_get_cause(channel);
419 int sip_cause = hangup_cause_to_sip(cause);
420 const char *ps_cause = NULL((void*)0), *use_my_cause;
421 const char *gateway_name = NULL((void*)0);
422 sofia_gateway_t *gateway_ptr = NULL((void*)0);
423
424 if ((gateway_name = switch_channel_get_variable(channel, "sip_gateway_name")switch_channel_get_variable_dup(channel, "sip_gateway_name", SWITCH_TRUE
, -1)
)) {
425 gateway_ptr = sofia_reg_find_gateway(gateway_name)sofia_reg_find_gateway__("mod_sofia.c", (const char *)__func__
, 425, gateway_name)
;
426 }
427
428 if (!tech_pvt) {
429 return SWITCH_STATUS_SUCCESS;
430 }
431
432 switch_mutex_lock(tech_pvt->sofia_mutex);
433
434
435 if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
436 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
437 tech_pvt->profile->ob_failed_calls++;
438 } else {
439 tech_pvt->profile->ib_failed_calls++;
440 }
441
442 if (gateway_ptr) {
443 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
444 gateway_ptr->ob_failed_calls++;
445 } else {
446 gateway_ptr->ib_failed_calls++;
447 }
448 }
449 }
450
451 if (gateway_ptr) {
452 sofia_reg_release_gateway(gateway_ptr)sofia_reg_release_gateway__("mod_sofia.c", (const char *)__func__
, 452, gateway_ptr);
;
453 }
454
455 if (!((use_my_cause = switch_channel_get_variable(channel, "sip_ignore_remote_cause")switch_channel_get_variable_dup(channel, "sip_ignore_remote_cause"
, SWITCH_TRUE, -1)
) && switch_true(use_my_cause))) {
456 ps_cause = switch_channel_get_variable(channel, "last_bridge_" SWITCH_PROTO_SPECIFIC_HANGUP_CAUSE_VARIABLE)switch_channel_get_variable_dup(channel, "last_bridge_" "proto_specific_hangup_cause"
, SWITCH_TRUE, -1)
;
457 }
458
459 if (!zstr(ps_cause)_zstr(ps_cause) && (!strncasecmp(ps_cause, "sip:", 4) || !strncasecmp(ps_cause, "sips:", 5))) {
460 int new_cause = atoi(sofia_glue_strip_proto(ps_cause));
461 if (new_cause) {
462 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 462, (const char*)(session)
, SWITCH_LOG_DEBUG, "%s Overriding SIP cause %d with %d from the other leg\n",
463 switch_channel_get_name(channel), sip_cause, new_cause);
464 sip_cause = new_cause;
465 }
466 }
467
468 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 468, (const char*)(session)
, SWITCH_LOG_DEBUG, "Channel %s hanging up, cause: %s\n",
469 switch_channel_get_name(channel), switch_channel_cause2str(cause));
470
471 if (tech_pvt->hash_key && !sofia_test_pflag(tech_pvt->profile, PFLAG_DESTROY)((tech_pvt->profile)->pflags[PFLAG_DESTROY] ? 1 : 0)) {
472 switch_core_hash_delete_locked(tech_pvt->profile->chat_hash, tech_pvt->hash_key, tech_pvt->profile->flag_mutex);
473 }
474
475 if (session && tech_pvt->profile->pres_type) {
476 char *sql = switch_mprintf("delete from sip_dialogs where uuid='%q'", switch_core_session_get_uuid(session));
477 switch_assert(sql)((sql) ? (void) (0) : __assert_fail ("sql", "mod_sofia.c", 477
, __extension__ __PRETTY_FUNCTION__))
;
478 sofia_glue_execute_sql_now(tech_pvt->profile, &sql, SWITCH_TRUE);
479 }
480
481 if (tech_pvt->kick && (a_session = switch_core_session_locate(tech_pvt->kick)switch_core_session_perform_locate(tech_pvt->kick, "mod_sofia.c"
, (const char *)__func__, 481)
)) {
482 switch_channel_t *a_channel = switch_core_session_get_channel(a_session);
483 switch_channel_hangup(a_channel, switch_channel_get_cause(channel))switch_channel_perform_hangup(a_channel, "mod_sofia.c", (const
char *)__func__, 483, switch_channel_get_cause(channel))
;
484 switch_core_session_rwunlock(a_session);
485 }
486
487 if (sofia_test_pflag(tech_pvt->profile, PFLAG_DESTROY)((tech_pvt->profile)->pflags[PFLAG_DESTROY] ? 1 : 0)) {
488 sofia_set_flag(tech_pvt, TFLAG_BYE)(tech_pvt)->flags[TFLAG_BYE] = 1;
489 } else if (tech_pvt->nh && !sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0)) {
490 char reason[128] = "";
491 char *bye_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_BYE_HEADER_PREFIX"sip_bye_h_");
492 const char *val = NULL((void*)0);
493 const char *max_forwards = switch_channel_get_variable(channel, SWITCH_MAX_FORWARDS_VARIABLE)switch_channel_get_variable_dup(channel, "max_forwards", SWITCH_TRUE
, -1)
;
494 const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full")switch_channel_get_variable_dup(channel, "presence_call_info_full"
, SWITCH_TRUE, -1)
;
495 const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
496
497 val = switch_channel_get_variable(tech_pvt->channel, "disable_q850_reason")switch_channel_get_variable_dup(tech_pvt->channel, "disable_q850_reason"
, SWITCH_TRUE, -1)
;
498
499 if (!val || switch_false(val)) {
500 if ((val = switch_channel_get_variable(tech_pvt->channel, "sip_reason")switch_channel_get_variable_dup(tech_pvt->channel, "sip_reason"
, SWITCH_TRUE, -1)
)) {
501 switch_snprintf(reason, sizeof(reason), "%s", val);
502 } else {
503 if ((switch_channel_test_flag(channel, CF_INTERCEPT) || cause == SWITCH_CAUSE_PICKED_OFF || cause == SWITCH_CAUSE_LOSE_RACE)
504 && !switch_true(switch_channel_get_variable(channel, "ignore_completed_elsewhere")switch_channel_get_variable_dup(channel, "ignore_completed_elsewhere"
, SWITCH_TRUE, -1)
)) {
505 switch_snprintf(reason, sizeof(reason), "SIP;cause=200;text=\"Call completed elsewhere\"");
506 } else if (cause > 0 && cause < 128) {
507 switch_snprintf(reason, sizeof(reason), "Q.850;cause=%d;text=\"%s\"", cause, switch_channel_cause2str(cause));
508 } else {
509 switch_snprintf(reason, sizeof(reason), "SIP;cause=%d;text=\"%s\"", cause, switch_channel_cause2str(cause));
510 }
511 }
512 }
513
514 if (switch_channel_test_flag(channel, CF_INTERCEPT) || cause == SWITCH_CAUSE_PICKED_OFF || cause == SWITCH_CAUSE_LOSE_RACE) {
515 switch_channel_set_variable(channel, "call_completed_elsewhere", "true")switch_channel_set_variable_var_check(channel, "call_completed_elsewhere"
, "true", SWITCH_TRUE)
;
516 }
517
518 if (switch_channel_test_flag(channel, CF_ANSWERED) || sofia_test_flag(tech_pvt, TFLAG_ANS)((tech_pvt)->flags[TFLAG_ANS] ? 1 : 0)) {
519 if (!tech_pvt->got_bye) {
520 switch_channel_set_variable(channel, "sip_hangup_disposition", "send_bye")switch_channel_set_variable_var_check(channel, "sip_hangup_disposition"
, "send_bye", SWITCH_TRUE)
;
521 }
522 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 522, (const char*)(session)
, SWITCH_LOG_DEBUG, "Sending BYE to %s\n", switch_channel_get_name(channel));
523 if (!sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0)) {
524 nua_bye(tech_pvt->nh,
525 TAG_IF(!zstr(tech_pvt->route_uri), NUTAG_PROXY(tech_pvt->route_uri))!(!_zstr(tech_pvt->route_uri)) ? tag_skip : ntatag_default_proxy
, urltag_url_v((tech_pvt->route_uri))
,
526 SIPTAG_CONTACT(SIP_NONE)siptag_contact, siptag_contact_v(((void const *)-1L)),
527 TAG_IF(!zstr(reason), SIPTAG_REASON_STR(reason))!(!_zstr(reason)) ? tag_skip : siptag_reason_str, tag_str_v(reason
)
,
528 TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info))!(call_info) ? tag_skip : siptag_call_info_str, tag_str_v(call_info
)
,
529 TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via))!(!_zstr(tech_pvt->user_via)) ? tag_skip : siptag_via_str,
tag_str_v(tech_pvt->user_via)
,
530 TAG_IF(!zstr(bye_headers), SIPTAG_HEADER_STR(bye_headers))!(!_zstr(bye_headers)) ? tag_skip : siptag_header_str, tag_str_v
((bye_headers))
,
531 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
532 TAG_END()(tag_type_t)0, (tag_value_t)0);
533 }
534 } else {
535 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
536 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 536, (const char*)(session)
, SWITCH_LOG_DEBUG, "Sending CANCEL to %s\n", switch_channel_get_name(channel));
537 if (!tech_pvt->got_bye) {
538 switch_channel_set_variable(channel, "sip_hangup_disposition", "send_cancel")switch_channel_set_variable_var_check(channel, "sip_hangup_disposition"
, "send_cancel", SWITCH_TRUE)
;
539 switch_channel_set_variable(channel, "sip_invite_failure_status", "487")switch_channel_set_variable_var_check(channel, "sip_invite_failure_status"
, "487", SWITCH_TRUE)
;
540 switch_channel_set_variable(channel, "sip_invite_failure_phrase", "CANCEL")switch_channel_set_variable_var_check(channel, "sip_invite_failure_phrase"
, "CANCEL", SWITCH_TRUE)
;
541 }
542 if (!sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0)) {
543 nua_cancel(tech_pvt->nh,
544 SIPTAG_CONTACT(SIP_NONE)siptag_contact, siptag_contact_v(((void const *)-1L)),
545 TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info))!(call_info) ? tag_skip : siptag_call_info_str, tag_str_v(call_info
)
,
546 TAG_IF(!zstr(reason), SIPTAG_REASON_STR(reason))!(!_zstr(reason)) ? tag_skip : siptag_reason_str, tag_str_v(reason
)
, TAG_IF(!zstr(bye_headers), SIPTAG_HEADER_STR(bye_headers))!(!_zstr(bye_headers)) ? tag_skip : siptag_header_str, tag_str_v
((bye_headers))
,
547 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
548 TAG_END()(tag_type_t)0, (tag_value_t)0);
549 }
550 } else {
551 char *resp_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX"sip_rh_");
552 const char *phrase;
553 char *added_headers = NULL((void*)0);
554
555
556 if (tech_pvt->respond_phrase) {
557 //phrase = su_strdup(nua_handle_home(tech_pvt->nh), tech_pvt->respond_phrase);
558 phrase = tech_pvt->respond_phrase;
559 } else {
560 phrase = sip_status_phrase(sip_cause);
561 }
562
563 if (tech_pvt->respond_code) {
564 sip_cause = tech_pvt->respond_code;
565 switch (sip_cause) {
566 case 401:
567 case 407:
568 {
569 const char *to_host = switch_channel_get_variable(channel, "sip_challenge_realm")switch_channel_get_variable_dup(channel, "sip_challenge_realm"
, SWITCH_TRUE, -1)
;
570
571 if (zstr(to_host)_zstr(to_host)) {
572 to_host = switch_channel_get_variable(channel, "sip_to_host")switch_channel_get_variable_dup(channel, "sip_to_host", SWITCH_TRUE
, -1)
;
573 }
574
575 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 575, (const char*)(session)
, SWITCH_LOG_DEBUG, "Challenging call\n");
576 sofia_reg_auth_challenge(tech_pvt->profile, tech_pvt->nh, NULL((void*)0), REG_INVITE, to_host, 0, 0);
577 *reason = '\0';
578 }
579 break;
580
581 case 484:
582 {
583 const char *to = switch_channel_get_variable(channel, "sip_to_uri")switch_channel_get_variable_dup(channel, "sip_to_uri", SWITCH_TRUE
, -1)
;
584 char *to_uri = NULL((void*)0);
585
586 if (to) {
587 char *p;
588 to_uri = switch_core_session_sprintf(session, "sip:%s", to);
589 if ((p = strstr(to_uri, ":5060"))) {
590 *p = '\0';
591 }
592
593 tech_pvt->respond_dest = to_uri;
594
595 }
596
597 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 597, (const char*)(session)
, SWITCH_LOG_DEBUG, "Overlap Dial with %d %s\n", sip_cause, phrase);
598
599 }
600 break;
601
602 default:
603 break;
604
605 }
606 }
607
608 if (tech_pvt->respond_dest && !sofia_test_pflag(tech_pvt->profile, PFLAG_MANUAL_REDIRECT)((tech_pvt->profile)->pflags[PFLAG_MANUAL_REDIRECT] ? 1
: 0)
) {
609 added_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_HEADER_PREFIX"sip_h_");
610 }
611
612
613 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 613, (const char*)(session)
, SWITCH_LOG_DEBUG, "Responding to INVITE with: %d\n", sip_cause);
614 if (!tech_pvt->got_bye) {
615 switch_channel_set_variable(channel, "sip_hangup_disposition", "send_refuse")switch_channel_set_variable_var_check(channel, "sip_hangup_disposition"
, "send_refuse", SWITCH_TRUE)
;
616 }
617 if (!sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0)) {
618 char *cid = generate_pai_str(tech_pvt);
619
620 if (sip_cause > 299) {
621 switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38);
622 switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_REQ);
623 switch_channel_set_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_FAIL);
624 }
625
626 nua_respond(tech_pvt->nh, sip_cause, phrase,
627 TAG_IF(!zstr(reason), SIPTAG_REASON_STR(reason))!(!_zstr(reason)) ? tag_skip : siptag_reason_str, tag_str_v(reason
)
,
628 TAG_IF(cid, SIPTAG_HEADER_STR(cid))!(cid) ? tag_skip : siptag_header_str, tag_str_v((cid)),
629 TAG_IF(!zstr(bye_headers), SIPTAG_HEADER_STR(bye_headers))!(!_zstr(bye_headers)) ? tag_skip : siptag_header_str, tag_str_v
((bye_headers))
,
630 TAG_IF(!zstr(resp_headers), SIPTAG_HEADER_STR(resp_headers))!(!_zstr(resp_headers)) ? tag_skip : siptag_header_str, tag_str_v
((resp_headers))
,
631 TAG_IF(!zstr(added_headers), SIPTAG_HEADER_STR(added_headers))!(!_zstr(added_headers)) ? tag_skip : siptag_header_str, tag_str_v
((added_headers))
,
632 TAG_IF(tech_pvt->respond_dest, SIPTAG_CONTACT_STR(tech_pvt->respond_dest))!(tech_pvt->respond_dest) ? tag_skip : siptag_contact_str,
tag_str_v(tech_pvt->respond_dest)
,
633 TAG_IF(!zstr(max_forwards), SIPTAG_MAX_FORWARDS_STR(max_forwards))!(!_zstr(max_forwards)) ? tag_skip : siptag_max_forwards_str,
tag_str_v(max_forwards)
,
634 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
635 TAG_END()(tag_type_t)0, (tag_value_t)0);
636
637 switch_safe_free(resp_headers)if (resp_headers) {free(resp_headers);resp_headers=((void*)0)
;}
;
638 }
639 switch_safe_free(added_headers)if (added_headers) {free(added_headers);added_headers=((void*
)0);}
;
640 }
641 }
642 sofia_set_flag_locked(tech_pvt, TFLAG_BYE)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != NULL", "mod_sofia.c", 642, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags[TFLAG_BYE] = 1;switch_mutex_unlock(tech_pvt
->flag_mutex);
;
643 switch_safe_free(bye_headers)if (bye_headers) {free(bye_headers);bye_headers=((void*)0);};
644 }
645
646 if (cause == SWITCH_CAUSE_WRONG_CALL_STATE) {
647 switch_event_t *s_event;
648 if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_WRONG_CALL_STATE)switch_event_create_subclass_detailed("mod_sofia.c", (const char
* )(const char *)__func__, 648, &s_event, SWITCH_EVENT_CUSTOM
, "sofia::wrong_call_state")
== SWITCH_STATUS_SUCCESS) {
649 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from_user", tech_pvt->from_user);
650 switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "network_ip", tech_pvt->mparams.remote_ip);
651 switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "network_port", "%d", tech_pvt->mparams.remote_port);
652 switch_event_fire(&s_event)switch_event_fire_detailed("mod_sofia.c", (const char * )(const
char *)__func__, 652, &s_event, ((void*)0))
;
653 }
654 }
655
656 sofia_clear_flag(tech_pvt, TFLAG_IO)(tech_pvt)->flags[TFLAG_IO] = 0;
657
658 if (tech_pvt->sofia_private) {
659 /* set to NULL so that switch_core_session_locate no longer succeeds, but don't lose the UUID in uuid_str so we
660 * can fire events with session UUID */
661 tech_pvt->sofia_private->uuid = NULL((void*)0);
662 }
663
664 switch_mutex_unlock(tech_pvt->sofia_mutex);
665
666 return SWITCH_STATUS_SUCCESS;
667}
668
669static switch_status_t sofia_on_exchange_media(switch_core_session_t *session)
670{
671 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 671, (const char*)(session)
, SWITCH_LOG_DEBUG, "SOFIA EXCHANGE_MEDIA\n");
672 return SWITCH_STATUS_SUCCESS;
673}
674
675static switch_status_t sofia_on_soft_execute(switch_core_session_t *session)
676{
677 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 677, (const char*)(session)
, SWITCH_LOG_DEBUG, "SOFIA SOFT_EXECUTE\n");
678 return SWITCH_STATUS_SUCCESS;
679}
680
681static switch_status_t sofia_acknowledge_call(switch_core_session_t *session)
682{
683 struct private_object *tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
684 const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
685
686 if (!tech_pvt->sent_100) {
687 nua_respond(tech_pvt->nh, SIP_100_TRYING100, sip_100_Trying, TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
, TAG_END()(tag_type_t)0, (tag_value_t)0);
688 tech_pvt->sent_100 = 1;
689 return SWITCH_STATUS_SUCCESS;
690 }
691
692 return SWITCH_STATUS_FALSE;
693}
694
695static switch_status_t sofia_answer_channel(switch_core_session_t *session)
696{
697 private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
698 switch_channel_t *channel = switch_core_session_get_channel(session);
699 switch_status_t status;
700 uint32_t session_timeout = tech_pvt->profile->session_timeout;
701 const char *val;
702 const char *b_sdp = NULL((void*)0);
703 int is_proxy = 0;
704 int is_3pcc_proxy = 0;
705 int is_3pcc = 0;
706 char *sticky = NULL((void*)0);
707 const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full")switch_channel_get_variable_dup(channel, "presence_call_info_full"
, SWITCH_TRUE, -1)
;
708 const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
709
710 if(sofia_acknowledge_call(session) == SWITCH_STATUS_SUCCESS) {
711 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 711, (const char*)(session)
, SWITCH_LOG_WARNING, "Dialplan did not acknowledge_call; sent 100 Trying");
712 }
713
714 if (switch_channel_test_flag(channel, CF_CONFERENCE) && !zstr(tech_pvt->reply_contact)_zstr(tech_pvt->reply_contact) && !switch_stristr(";isfocus", tech_pvt->reply_contact)) {
715 tech_pvt->reply_contact = switch_core_session_sprintf(session, "%s;isfocus", tech_pvt->reply_contact);
716 }
717
718 //switch_core_media_set_local_sdp
719 if(sofia_test_flag(tech_pvt, TFLAG_3PCC_INVITE)((tech_pvt)->flags[TFLAG_3PCC_INVITE] ? 1 : 0)) {
720 // SNARK: complete hack to get final ack sent when a 3pcc invite has been passed from the other leg in bypass_media mode.
721 // This code handles the pass_indication sent after the 3pcc ack is received by the other leg in the is_3pcc && is_proxy case below.
722 // Is there a better place to hang this...?
723 b_sdp = switch_channel_get_variable(channel, SWITCH_B_SDP_VARIABLE)switch_channel_get_variable_dup(channel, "switch_m_sdp", SWITCH_TRUE
, -1)
;
724 switch_core_media_set_local_sdp(session, b_sdp, SWITCH_TRUE);
725
726 if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MEDIA)) {
727 sofia_media_activate_rtp(tech_pvt);
728 switch_core_media_patch_sdp(tech_pvt->session);
729 switch_core_media_proxy_remote_addr(tech_pvt->session, NULL((void*)0));
730 }
731
732 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 732, (const char*)(session)
, SWITCH_LOG_DEBUG,
733 "3PCC-PROXY nomedia - sending ack, SDP:\n%s\n", tech_pvt->mparams.local_sdp_str);
734
735
736 if (sofia_use_soa(tech_pvt)((tech_pvt)->flags[TFLAG_ENABLE_SOA] ? 1 : 0)) {
737 nua_ack(tech_pvt->nh,
738 TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via))!(!_zstr(tech_pvt->user_via)) ? tag_skip : siptag_via_str,
tag_str_v(tech_pvt->user_via)
,
739 SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
740 SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str)soatag_user_sdp_str, tag_str_v(tech_pvt->mparams.local_sdp_str
)
,
741 SOATAG_REUSE_REJECTED(1)soatag_reuse_rejected, tag_bool_v(1),
742 SOATAG_RTP_SELECT(1)soatag_rtp_select, tag_int_v(1),
743 SOATAG_AUDIO_AUX("cn telephone-event")soatag_audio_aux, tag_str_v("cn telephone-event"),
744 TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1))!(((tech_pvt->profile)->pflags[PFLAG_DISABLE_100REL] ? 1
: 0)) ? tag_skip : nutag_include_extra_sdp, tag_bool_v(1)
,
745 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
746 TAG_END()(tag_type_t)0, (tag_value_t)0);
747 } else {
748 nua_ack(tech_pvt->nh,
749 NUTAG_MEDIA_ENABLE(0)nutag_media_enable, tag_bool_v(0),
750 TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via))!(!_zstr(tech_pvt->user_via)) ? tag_skip : siptag_via_str,
tag_str_v(tech_pvt->user_via)
,
751 SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
752 TAG_IF(tech_pvt->mparams.local_sdp_str, SIPTAG_CONTENT_TYPE_STR("application/sdp"))!(tech_pvt->mparams.local_sdp_str) ? tag_skip : siptag_content_type_str
, tag_str_v("application/sdp")
,
753 TAG_IF(tech_pvt->mparams.local_sdp_str, SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str))!(tech_pvt->mparams.local_sdp_str) ? tag_skip : siptag_payload_str
, tag_str_v(tech_pvt->mparams.local_sdp_str)
,
754 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
755 SOATAG_AUDIO_AUX("cn telephone-event")soatag_audio_aux, tag_str_v("cn telephone-event"),
756 TAG_END()(tag_type_t)0, (tag_value_t)0);
757 }
758
759
760 sofia_clear_flag(tech_pvt, TFLAG_3PCC_INVITE)(tech_pvt)->flags[TFLAG_3PCC_INVITE] = 0; // all done
761 sofia_set_flag_locked(tech_pvt, TFLAG_ANS)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != NULL", "mod_sofia.c", 761, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags[TFLAG_ANS] = 1;switch_mutex_unlock(tech_pvt
->flag_mutex);
;
762 sofia_set_flag_locked(tech_pvt, TFLAG_SDP)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != NULL", "mod_sofia.c", 762, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags[TFLAG_SDP] = 1;switch_mutex_unlock(tech_pvt
->flag_mutex);
;
763 switch_channel_mark_answered(channel)switch_channel_perform_mark_answered(channel, "mod_sofia.c", (
const char *)__func__, 763)
; // ... and remember to actually answer the call!
764 return SWITCH_STATUS_SUCCESS;
765 }
766
767 if (sofia_test_flag(tech_pvt, TFLAG_ANS)((tech_pvt)->flags[TFLAG_ANS] ? 1 : 0) || switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
768 return SWITCH_STATUS_SUCCESS;
769 }
770
771 b_sdp = switch_channel_get_variable(channel, SWITCH_B_SDP_VARIABLE)switch_channel_get_variable_dup(channel, "switch_m_sdp", SWITCH_TRUE
, -1)
;
772 is_proxy = (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA));
773 is_3pcc_proxy = (sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY)((tech_pvt->profile)->pflags[PFLAG_3PCC_PROXY] ? 1 : 0) && sofia_test_flag(tech_pvt, TFLAG_3PCC)((tech_pvt)->flags[TFLAG_3PCC] ? 1 : 0));
774 is_3pcc = (!sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY)((tech_pvt->profile)->pflags[PFLAG_3PCC_PROXY] ? 1 : 0) && sofia_test_flag(tech_pvt, TFLAG_3PCC)((tech_pvt)->flags[TFLAG_3PCC] ? 1 : 0));
775
776 if (b_sdp && is_proxy && !is_3pcc_proxy) {
777 switch_core_media_set_local_sdp(session, b_sdp, SWITCH_TRUE);
778
779 if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
780 switch_core_media_patch_sdp(tech_pvt->session);
781 if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
782 return SWITCH_STATUS_FALSE;
783 }
784 }
785 } else {
786 /* This if statement check and handles the 3pcc proxy mode */
787
788 if (is_3pcc) {
789 switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
790 tech_pvt->mparams.local_sdp_str = NULL((void*)0);
791 switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
792 switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL((void*)0), 0, NULL((void*)0), 0);
793 } else if (is_3pcc_proxy) {
794
795 if (!(sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY)((tech_pvt->profile)->pflags[PFLAG_3PCC_PROXY] ? 1 : 0))) {
796 switch_channel_set_flag(channel, CF_3PCC)switch_channel_set_flag_value(channel, CF_3PCC, 1);
797 }
798
799 if (b_sdp && is_proxy && !switch_channel_var_true(channel, "3pcc_always_gen_sdp")) {
800 switch_core_media_set_local_sdp(session, b_sdp, SWITCH_TRUE);
801 } else {
802 switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0);
803 switch_core_media_prepare_codecs(session, 1);
804 switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL((void*)0), 0, NULL((void*)0), 1);
805 sofia_set_flag_locked(tech_pvt, TFLAG_3PCC)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != NULL", "mod_sofia.c", 805, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags[TFLAG_3PCC] = 1;switch_mutex_unlock(tech_pvt
->flag_mutex);
;
806 }
807
808 if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
809 switch_core_media_patch_sdp(tech_pvt->session);
810 if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
811 return SWITCH_STATUS_FALSE;
812 }
813 }
814 }
815
816 if (is_3pcc || is_3pcc_proxy) {
817 /* Send the 200 OK */
818 if (!sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0)) {
819 char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX"sip_rh_");
820
821 if (sofia_use_soa(tech_pvt)((tech_pvt)->flags[TFLAG_ENABLE_SOA] ? 1 : 0)) {
822
823 nua_respond(tech_pvt->nh, SIP_200_OK200, sip_200_OK,
824 TAG_IF(is_proxy, NUTAG_AUTOANSWER(0))!(is_proxy) ? tag_skip : nutag_autoanswer, tag_bool_v(0),
825 SIPTAG_CONTACT_STR(tech_pvt->profile->url)siptag_contact_str, tag_str_v(tech_pvt->profile->url),
826 SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str)soatag_user_sdp_str, tag_str_v(tech_pvt->mparams.local_sdp_str
)
,
827 TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info))!(call_info) ? tag_skip : siptag_call_info_str, tag_str_v(call_info
)
,
828 SOATAG_REUSE_REJECTED(1)soatag_reuse_rejected, tag_bool_v(1),
829 SOATAG_RTP_SELECT(1)soatag_rtp_select, tag_int_v(1),
830 SOATAG_AUDIO_AUX("cn telephone-event")soatag_audio_aux, tag_str_v("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1)nutag_include_extra_sdp, tag_bool_v(1),
831 TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers))!(!_zstr(extra_headers)) ? tag_skip : siptag_header_str, tag_str_v
((extra_headers))
,
832 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
833 TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
834 SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT))!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
, TAG_END()(tag_type_t)0, (tag_value_t)0);
835 } else {
836 nua_respond(tech_pvt->nh, SIP_200_OK200, sip_200_OK,
837 NUTAG_MEDIA_ENABLE(0)nutag_media_enable, tag_bool_v(0),
838 SIPTAG_CONTACT_STR(tech_pvt->profile->url)siptag_contact_str, tag_str_v(tech_pvt->profile->url),
839 TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers))!(!_zstr(extra_headers)) ? tag_skip : siptag_header_str, tag_str_v
((extra_headers))
,
840 TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info))!(call_info) ? tag_skip : siptag_call_info_str, tag_str_v(call_info
)
,
841 SIPTAG_CONTENT_TYPE_STR("application/sdp")siptag_content_type_str, tag_str_v("application/sdp"),
842 SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str)siptag_payload_str, tag_str_v(tech_pvt->mparams.local_sdp_str
)
,
843 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
844 TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
845 SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT))!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
, TAG_END()(tag_type_t)0, (tag_value_t)0);
846 }
847
848
849 switch_safe_free(extra_headers)if (extra_headers) {free(extra_headers);extra_headers=((void*
)0);}
;
850 }
851
852 if (is_3pcc_proxy) {
853 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 853, (const char*)(session)
, SWITCH_LOG_DEBUG, "3PCC-PROXY, Sent a 200 OK, waiting for ACK\n");
854 /* Unlock the session signal to allow the ack to make it in */
855 // Maybe we should timeout?
856 switch_mutex_unlock(tech_pvt->sofia_mutex);
857
858 while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE) && !sofia_test_flag(tech_pvt, TFLAG_3PCC_HAS_ACK)((tech_pvt)->flags[TFLAG_3PCC_HAS_ACK] ? 1 : 0)) {
859 switch_cond_next();
860 }
861
862 /* Regain lock on sofia */
863 switch_mutex_lock(tech_pvt->sofia_mutex);
864
865 if (is_proxy) {
866 sofia_clear_flag(tech_pvt, TFLAG_3PCC_HAS_ACK)(tech_pvt)->flags[TFLAG_3PCC_HAS_ACK] = 0;
867 sofia_clear_flag(tech_pvt, TFLAG_3PCC)(tech_pvt)->flags[TFLAG_3PCC] = 0;
868 switch_core_session_pass_indication(session, SWITCH_MESSAGE_INDICATE_ANSWER);
869 }
870
871 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 871, (const char*)(session)
, SWITCH_LOG_DEBUG, "3PCC-PROXY, Done waiting for ACK\n");
872 return SWITCH_STATUS_SUCCESS;
873 }
874 }
875
876 if ((is_proxy && !b_sdp) || sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION)((tech_pvt)->flags[TFLAG_LATE_NEGOTIATION] ? 1 : 0) ||
877 switch_core_media_codec_chosen(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO) != SWITCH_STATUS_SUCCESS) {
878 sofia_clear_flag_locked(tech_pvt, TFLAG_LATE_NEGOTIATION)switch_mutex_lock(tech_pvt->flag_mutex); (tech_pvt)->flags
[TFLAG_LATE_NEGOTIATION] = 0; switch_mutex_unlock(tech_pvt->
flag_mutex);
;
879
880 if (is_proxy) {
881 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 881, (const char*)(session)
, SWITCH_LOG_DEBUG, "Disabling proxy mode due to call answer with no bridge\n");
882 switch_channel_clear_flag(channel, CF_PROXY_MEDIA);
883 switch_channel_clear_flag(channel, CF_PROXY_MODE);
884 }
885
886 if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
887 const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE)switch_channel_get_variable_dup(channel, "switch_r_sdp", SWITCH_TRUE
, -1)
;
888
889 switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
890
891 if (zstr(r_sdp)_zstr(r_sdp) || sofia_media_tech_media(tech_pvt, r_sdp, SDP_TYPE_REQUEST) != SWITCH_STATUS_SUCCESS) {
892 switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR")switch_channel_set_variable_var_check(channel, "endpoint_disposition"
, "CODEC NEGOTIATION ERROR", SWITCH_TRUE)
;
893 //switch_mutex_lock(tech_pvt->sofia_mutex);
894 //nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
895 //switch_mutex_unlock(tech_pvt->sofia_mutex);
896 return SWITCH_STATUS_FALSE;
897 }
898 }
899 }
900
901 if ((status = switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0)) != SWITCH_STATUS_SUCCESS) {
902 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(channel, "mod_sofia.c", (const char
*)__func__, 902, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)
;
903 return status;
904 }
905
906 switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL((void*)0), 0, NULL((void*)0), 0);
907 if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
908 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(channel, "mod_sofia.c", (const char
*)__func__, 908, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)
;
909 }
910
911 if (tech_pvt->nh) {
912 if (tech_pvt->mparams.local_sdp_str) {
913 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 913, (const char*)(session)
, SWITCH_LOG_DEBUG, "Local SDP %s:\n%s\n", switch_channel_get_name(channel),
914 tech_pvt->mparams.local_sdp_str);
915 }
916 }
917
918 }
919
920 if (sofia_test_flag(tech_pvt, TFLAG_NAT)((tech_pvt)->flags[TFLAG_NAT] ? 1 : 0) ||
921 (val = switch_channel_get_variable(channel, "sip-force-contact")switch_channel_get_variable_dup(channel, "sip-force-contact",
SWITCH_TRUE, -1)
) ||
922 ((val = switch_channel_get_variable(channel, "sip_sticky_contact")switch_channel_get_variable_dup(channel, "sip_sticky_contact"
, SWITCH_TRUE, -1)
) && switch_true(val))) {
923 sticky = tech_pvt->record_route;
924 session_timeout = SOFIA_NAT_SESSION_TIMEOUT90;
925 switch_channel_set_variable(channel, "sip_nat_detected", "true")switch_channel_set_variable_var_check(channel, "sip_nat_detected"
, "true", SWITCH_TRUE)
;
926 }
927
928 if ((val = switch_channel_get_variable(channel, SOFIA_SESSION_TIMEOUT)switch_channel_get_variable_dup(channel, "sofia_session_timeout"
, SWITCH_TRUE, -1)
)) {
929 int v_session_timeout = atoi(val);
930 if (v_session_timeout >= 0) {
931 session_timeout = v_session_timeout;
932 }
933 }
934
935 if (!sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0)) {
936 char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX"sip_rh_");
937 char *cid = NULL((void*)0);
938
939
940 cid = generate_pai_str(tech_pvt);
941
942
943 if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) && tech_pvt->mparams.early_sdp && tech_pvt->mparams.local_sdp_str) {
944 char *a, *b;
945
946 /* start at the s= line to avoid some devices who update the o= between messages */
947 a = strstr(tech_pvt->mparams.early_sdp, "s=");
948 b = strstr(tech_pvt->mparams.local_sdp_str, "s=");
949
950 if (!a || !b || strcmp(a, b)) {
951
952 /* The SIP RFC for SOA forbids sending a 183 with one sdp then a 200 with another but it won't do us much good unless
953 we do so in this case we will abandon the SOA rules and go rogue.
954 */
955 sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA)(tech_pvt)->flags[TFLAG_ENABLE_SOA] = 0;
956 }
957 }
958
959 if ((tech_pvt->mparams.last_sdp_str && strstr(tech_pvt->mparams.last_sdp_str, "a=setup")) ||
960 (tech_pvt->mparams.local_sdp_str && strstr(tech_pvt->mparams.local_sdp_str, "a=setup"))) {
961 session_timeout = 0;
962 }
963
964 if ((tech_pvt->session_timeout = session_timeout)) {
965 tech_pvt->session_refresher = switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? nua_local_refresher : nua_remote_refresher;
966 if (sofia_test_pflag(tech_pvt->profile, PFLAG_UPDATE_REFRESHER)((tech_pvt->profile)->pflags[PFLAG_UPDATE_REFRESHER] ? 1
: 0)
|| switch_channel_var_true(tech_pvt->channel, "sip_update_refresher")) {
967 tech_pvt->update_refresher = 1;
968 }
969 } else {
970 tech_pvt->session_refresher = nua_no_refresher;
971 }
972
973 if (sofia_use_soa(tech_pvt)((tech_pvt)->flags[TFLAG_ENABLE_SOA] ? 1 : 0)) {
974 nua_respond(tech_pvt->nh, SIP_200_OK200, sip_200_OK,
975 NUTAG_AUTOANSWER(0)nutag_autoanswer, tag_bool_v(0),
976 TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info))!(call_info) ? tag_skip : siptag_call_info_str, tag_str_v(call_info
)
,
977 TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route))!(sticky) ? tag_skip : ntatag_default_proxy, urltag_url_v((tech_pvt
->record_route))
,
978 TAG_IF(cid, SIPTAG_HEADER_STR(cid))!(cid) ? tag_skip : siptag_header_str, tag_str_v((cid)),
979 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
980 NUTAG_SESSION_TIMER(tech_pvt->session_timeout)nutag_session_timer, tag_uint_v((tech_pvt->session_timeout
))
,
981 NUTAG_SESSION_REFRESHER(tech_pvt->session_refresher)nutag_session_refresher, tag_int_v((tech_pvt->session_refresher
))
,
982 NUTAG_UPDATE_REFRESH(tech_pvt->update_refresher)nutag_update_refresh, tag_bool_v((tech_pvt->update_refresher
))
,
983 SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
984 SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info"))siptag_call_info_str, tag_str_v(switch_channel_get_variable_dup
(tech_pvt->channel, "sip_h_" "call_info", SWITCH_TRUE, -1)
)
,
985 SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str)soatag_user_sdp_str, tag_str_v(tech_pvt->mparams.local_sdp_str
)
,
986 SOATAG_REUSE_REJECTED(1)soatag_reuse_rejected, tag_bool_v(1),
987 SOATAG_AUDIO_AUX("cn telephone-event")soatag_audio_aux, tag_str_v("cn telephone-event"),
988 TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1))!(((tech_pvt->profile)->pflags[PFLAG_DISABLE_100REL] ? 1
: 0)) ? tag_skip : nutag_include_extra_sdp, tag_bool_v(1)
,
989 SOATAG_RTP_SELECT(1)soatag_rtp_select, tag_int_v(1),
990 TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers))!(!_zstr(extra_headers)) ? tag_skip : siptag_header_str, tag_str_v
((extra_headers))
,
991 TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
992 SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT))!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
, TAG_END()(tag_type_t)0, (tag_value_t)0);
993 } else {
994 nua_respond(tech_pvt->nh, SIP_200_OK200, sip_200_OK,
995 NUTAG_AUTOANSWER(0)nutag_autoanswer, tag_bool_v(0),
996 NUTAG_MEDIA_ENABLE(0)nutag_media_enable, tag_bool_v(0),
997 TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info))!(call_info) ? tag_skip : siptag_call_info_str, tag_str_v(call_info
)
,
998 TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route))!(sticky) ? tag_skip : ntatag_default_proxy, urltag_url_v((tech_pvt
->record_route))
,
999 TAG_IF(cid, SIPTAG_HEADER_STR(cid))!(cid) ? tag_skip : siptag_header_str, tag_str_v((cid)),
1000 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
1001 NUTAG_SESSION_TIMER(tech_pvt->session_timeout)nutag_session_timer, tag_uint_v((tech_pvt->session_timeout
))
,
1002 NUTAG_SESSION_REFRESHER(tech_pvt->session_refresher)nutag_session_refresher, tag_int_v((tech_pvt->session_refresher
))
,
1003 NUTAG_UPDATE_REFRESH(tech_pvt->update_refresher)nutag_update_refresh, tag_bool_v((tech_pvt->update_refresher
))
,
1004 SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
1005 SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info"))siptag_call_info_str, tag_str_v(switch_channel_get_variable_dup
(tech_pvt->channel, "sip_h_" "call_info", SWITCH_TRUE, -1)
)
,
1006 SIPTAG_CONTENT_TYPE_STR("application/sdp")siptag_content_type_str, tag_str_v("application/sdp"),
1007 SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str)siptag_payload_str, tag_str_v(tech_pvt->mparams.local_sdp_str
)
,
1008 TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers))!(!_zstr(extra_headers)) ? tag_skip : siptag_header_str, tag_str_v
((extra_headers))
,
1009 TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
1010 SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT))!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
, TAG_END()(tag_type_t)0, (tag_value_t)0);
1011 }
1012 switch_safe_free(extra_headers)if (extra_headers) {free(extra_headers);extra_headers=((void*
)0);}
;
1013 sofia_set_flag_locked(tech_pvt, TFLAG_ANS)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != NULL", "mod_sofia.c", 1013, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags[TFLAG_ANS] = 1;switch_mutex_unlock(tech_pvt
->flag_mutex);
;
1014 }
1015
1016 return SWITCH_STATUS_SUCCESS;
1017}
1018
1019static switch_status_t sofia_read_text_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
1020{
1021 switch_status_t status;
1022
1023 if (switch_channel_test_flag(switch_core_session_get_channel(session), CF_MSRP)) {
1024 switch_msrp_session_t *msrp_session = switch_core_media_get_msrp_session(session);
1025 switch_frame_t *rframe = &msrp_session->frame;
1026 switch_msrp_msg_t *msrp_msg = switch_msrp_session_pop_msg(msrp_session);
1027 const char *msrp_h_content_type = NULL((void*)0);
1028
1029 if (msrp_msg) {
1030 msrp_h_content_type = switch_msrp_msg_get_header(msrp_msg, MSRP_H_CONTENT_TYPE);
1031 }
1032
1033 rframe->flags = 0;
1034 rframe->data = msrp_session->frame_data;
1035 rframe->buflen = sizeof(msrp_session->frame_data);
1036
1037 if (msrp_msg && msrp_msg->method == MSRP_METHOD_SEND &&
1038 msrp_msg->payload &&
1039 !switch_stristr("?OTRv3?", msrp_msg->payload) &&
1040 !switch_stristr("application/im-iscomposing", msrp_msg->payload) &&
1041 msrp_h_content_type &&
1042 (switch_stristr("text/plain", msrp_h_content_type) ||
1043 switch_stristr("text/html", msrp_h_content_type) ||
1044 switch_stristr("message/cpim", msrp_h_content_type))) {
1045
1046 rframe->datalen = msrp_msg->payload_bytes;
1047 rframe->packetlen = msrp_msg->payload_bytes + 12;
1048 memcpy(rframe->data, msrp_msg->payload, msrp_msg->payload_bytes + 1); /* include the last NULL byte */
1049
1050 rframe->m = 1;
1051 *frame = rframe;
1052
1053 if (!strcasecmp(msrp_h_content_type, "message/cpim")) {
1054 char *stripped_text = switch_html_strip((char *)rframe->data);
1055 memcpy(rframe->data, stripped_text, strlen(stripped_text)+1);
1056 rframe->datalen = strlen(stripped_text);
1057 free(stripped_text);
1058 }
1059
1060 switch_msrp_msg_destroy(&msrp_msg);
1061 status = SWITCH_STATUS_SUCCESS;
1062 } else {
1063 rframe->datalen = 2;
1064 rframe->flags = SFF_CNG;
1065 *frame = rframe;
1066 status = SWITCH_STATUS_SUCCESS;
1067 }
1068
1069 return status;
1070 }
1071
1072 return switch_core_media_read_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_TEXT);
1073}
1074
1075static switch_status_t sofia_write_text_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
1076{
1077 if (switch_channel_test_flag(switch_core_session_get_channel(session), CF_MSRP)) {
1078 switch_msrp_session_t *msrp_session = switch_core_media_get_msrp_session(session);
1079
1080 if (frame && msrp_session) {
1081 switch_msrp_msg_t *msrp_msg = switch_msrp_msg_create();
1082 switch_status_t status = SWITCH_STATUS_SUCCESS;
1083
1084 // switch_msrp_msg_add_header(&msrp_msg, MSRP_H_CONTENT_TYPE, "message/cpim");
1085 switch_msrp_msg_add_header(msrp_msg, MSRP_H_CONTENT_TYPE, "text/plain");
1086 switch_msrp_msg_set_payload(msrp_msg, frame->data, frame->datalen);
1087 status = switch_msrp_send(msrp_session, msrp_msg)switch_msrp_perform_send(msrp_session, msrp_msg, "mod_sofia.c"
, (const char *)__func__, 1087)
;
1088 switch_msrp_msg_destroy(&msrp_msg);
1089 return status;
1090 }
1091
1092 return SWITCH_STATUS_FALSE;
1093 }
1094
1095 return switch_core_media_write_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_TEXT);
1096}
1097
1098static switch_status_t sofia_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
1099{
1100 private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
1101
1102 switch_assert(tech_pvt != NULL)((tech_pvt != ((void*)0)) ? (void) (0) : __assert_fail ("tech_pvt != ((void*)0)"
, "mod_sofia.c", 1102, __extension__ __PRETTY_FUNCTION__))
;
1103
1104 if (sofia_test_flag(tech_pvt, TFLAG_HUP)((tech_pvt)->flags[TFLAG_HUP] ? 1 : 0)) {
1105 return SWITCH_STATUS_FALSE;
1106 }
1107#if 0
1108 while (!(tech_pvt->video_read_codec.implementation && switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO) && !switch_channel_test_flag(channel, CF_REQ_MEDIA))) {
1109 switch_ivr_parse_all_messages(tech_pvt->session);
1110
1111 if (--sanity && switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) {
1112 switch_yield(10000)switch_sleep(10000);;
1113 } else {
1114 switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE)switch_channel_perform_hangup(tech_pvt->channel, "mod_sofia.c"
, (const char *)__func__, 1114, SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE
)
;
1115 return SWITCH_STATUS_GENERR;
1116 }
1117 }
1118#endif
1119
1120
1121 return switch_core_media_read_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_VIDEO);
1122
1123}
1124
1125static switch_status_t sofia_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
1126{
1127 private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
1128 switch_assert(tech_pvt != NULL)((tech_pvt != ((void*)0)) ? (void) (0) : __assert_fail ("tech_pvt != ((void*)0)"
, "mod_sofia.c", 1128, __extension__ __PRETTY_FUNCTION__))
;
1129
1130#if 0
1131 while (!(tech_pvt->video_read_codec.implementation && switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO))) {
1132 if (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE)) {
1133 switch_yield(10000)switch_sleep(10000);;
1134 } else {
1135 return SWITCH_STATUS_GENERR;
1136 }
1137 }
1138#endif
1139
1140 if (sofia_test_flag(tech_pvt, TFLAG_HUP)((tech_pvt)->flags[TFLAG_HUP] ? 1 : 0)) {
1141 return SWITCH_STATUS_FALSE;
1142 }
1143
1144 if (!sofia_test_flag(tech_pvt, TFLAG_RTP)((tech_pvt)->flags[TFLAG_RTP] ? 1 : 0)) {
1145 return SWITCH_STATUS_GENERR;
1146 }
1147
1148 if (!sofia_test_flag(tech_pvt, TFLAG_IO)((tech_pvt)->flags[TFLAG_IO] ? 1 : 0)) {
1149 return SWITCH_STATUS_SUCCESS;
1150 }
1151
1152 if (SWITCH_STATUS_SUCCESS == switch_core_media_write_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_VIDEO)) {
1153 return SWITCH_STATUS_SUCCESS;
1154 }
1155
1156 return SWITCH_STATUS_FALSE;
1157}
1158
1159static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
1160{
1161 private_object_t *tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
1162 switch_status_t status = SWITCH_STATUS_FALSE;
1163
1164 switch_assert(tech_pvt != NULL)((tech_pvt != ((void*)0)) ? (void) (0) : __assert_fail ("tech_pvt != ((void*)0)"
, "mod_sofia.c", 1164, __extension__ __PRETTY_FUNCTION__))
;
1165
1166 if (!sofia_test_pflag(tech_pvt->profile, PFLAG_RUNNING)((tech_pvt->profile)->pflags[PFLAG_RUNNING] ? 1 : 0)) {
1167 switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_NORMAL_CLEARING)switch_channel_perform_hangup(tech_pvt->channel, "mod_sofia.c"
, (const char *)__func__, 1167, SWITCH_CAUSE_NORMAL_CLEARING)
;
1168 return SWITCH_STATUS_FALSE;
1169 }
1170
1171 if (sofia_test_flag(tech_pvt, TFLAG_HUP)((tech_pvt)->flags[TFLAG_HUP] ? 1 : 0)) {
1172 return SWITCH_STATUS_FALSE;
1173 }
1174
1175 if (!(switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO))){
1176 return SWITCH_STATUS_INUSE;
1177 }
1178
1179 sofia_set_flag_locked(tech_pvt, TFLAG_READING)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != NULL", "mod_sofia.c", 1179, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags[TFLAG_READING] = 1;switch_mutex_unlock
(tech_pvt->flag_mutex);
;
1180
1181 if (sofia_test_flag(tech_pvt, TFLAG_HUP)((tech_pvt)->flags[TFLAG_HUP] ? 1 : 0) || sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0)) {
1182 return SWITCH_STATUS_FALSE;
1183 }
1184
1185 status = switch_core_media_read_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_AUDIO);
1186
1187 sofia_clear_flag_locked(tech_pvt, TFLAG_READING)switch_mutex_lock(tech_pvt->flag_mutex); (tech_pvt)->flags
[TFLAG_READING] = 0; switch_mutex_unlock(tech_pvt->flag_mutex
);
;
1188
1189 return status;
1190}
1191
1192static switch_status_t sofia_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
1193{
1194 private_object_t *tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
1195 switch_channel_t *channel = switch_core_session_get_channel(session);
1196 switch_status_t status = SWITCH_STATUS_SUCCESS;
1197
1198 switch_assert(tech_pvt != NULL)((tech_pvt != ((void*)0)) ? (void) (0) : __assert_fail ("tech_pvt != ((void*)0)"
, "mod_sofia.c", 1198, __extension__ __PRETTY_FUNCTION__))
;
1199
1200
1201 if (!switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
1202 if (switch_channel_up_nosig(channel)(switch_channel_get_state(channel) < CS_HANGUP)) {
1203 return SWITCH_STATUS_SUCCESS;
1204 } else {
1205 return SWITCH_STATUS_GENERR;
1206 }
1207 }
1208
1209 if (switch_channel_test_flag(channel, CF_REQ_MEDIA)) {
1210 if (++tech_pvt->req_media_counter > 2000) {
1211 switch_channel_clear_flag(channel, CF_REQ_MEDIA);
1212 switch_channel_hangup(channel, SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE)switch_channel_perform_hangup(channel, "mod_sofia.c", (const char
*)__func__, 1212, SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE)
;
1213 return SWITCH_STATUS_FALSE;
1214 } else {
1215 return SWITCH_STATUS_SUCCESS;
1216 }
1217 } else {
1218 tech_pvt->req_media_counter = 0;
1219 }
1220
1221 if (sofia_test_flag(tech_pvt, TFLAG_HUP)((tech_pvt)->flags[TFLAG_HUP] ? 1 : 0)) {
1222 return SWITCH_STATUS_FALSE;
1223 }
1224
1225#if 0
1226 if (!sofia_test_flag(tech_pvt, TFLAG_RTP)((tech_pvt)->flags[TFLAG_RTP] ? 1 : 0)) {
1227 return SWITCH_STATUS_GENERR;
1228 }
1229
1230 if (!sofia_test_flag(tech_pvt, TFLAG_IO)((tech_pvt)->flags[TFLAG_IO] ? 1 : 0)) {
1231 return SWITCH_STATUS_SUCCESS;
1232 }
1233#endif
1234
1235 if (sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0)) {
1236 return SWITCH_STATUS_FALSE;
1237 }
1238
1239 sofia_set_flag_locked(tech_pvt, TFLAG_WRITING)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != NULL", "mod_sofia.c", 1239, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags[TFLAG_WRITING] = 1;switch_mutex_unlock
(tech_pvt->flag_mutex);
;
1240
1241 if (switch_core_media_write_frame(session, frame, flags, stream_id, SWITCH_MEDIA_TYPE_AUDIO)) {
1242 status = SWITCH_STATUS_SUCCESS;
1243 }
1244
1245 sofia_clear_flag_locked(tech_pvt, TFLAG_WRITING)switch_mutex_lock(tech_pvt->flag_mutex); (tech_pvt)->flags
[TFLAG_WRITING] = 0; switch_mutex_unlock(tech_pvt->flag_mutex
);
;
1246 return status;
1247}
1248
1249static switch_status_t sofia_kill_channel(switch_core_session_t *session, int sig)
1250{
1251 private_object_t *tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
1252
1253 if (!tech_pvt) {
1254 return SWITCH_STATUS_FALSE;
1255 }
1256
1257 switch (sig) {
1258 case SWITCH_SIG_BREAK:
1259 if (switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
1260 switch_core_media_break(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
1261 }
1262 if (switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO)) {
1263 switch_core_media_break(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO);
1264 }
1265 break;
1266 case SWITCH_SIG_KILL:
1267 default:
1268 sofia_clear_flag_locked(tech_pvt, TFLAG_IO)switch_mutex_lock(tech_pvt->flag_mutex); (tech_pvt)->flags
[TFLAG_IO] = 0; switch_mutex_unlock(tech_pvt->flag_mutex);
;
1269 sofia_set_flag_locked(tech_pvt, TFLAG_HUP)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != NULL", "mod_sofia.c", 1269, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags[TFLAG_HUP] = 1;switch_mutex_unlock(tech_pvt
->flag_mutex);
;
1270
1271 if (switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
1272 switch_core_media_kill_socket(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
1273 }
1274 if (switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO)) {
1275 switch_core_media_kill_socket(tech_pvt->session, SWITCH_MEDIA_TYPE_VIDEO);
1276 }
1277 break;
1278 }
1279 return SWITCH_STATUS_SUCCESS;
1280}
1281
1282
1283static switch_status_t sofia_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
1284{
1285 private_object_t *tech_pvt;
1286 char message[128] = "";
1287 switch_core_media_dtmf_t dtmf_type;
1288
1289 tech_pvt = (private_object_t *) switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
1290 switch_assert(tech_pvt != NULL)((tech_pvt != ((void*)0)) ? (void) (0) : __assert_fail ("tech_pvt != ((void*)0)"
, "mod_sofia.c", 1290, __extension__ __PRETTY_FUNCTION__))
;
1291
1292 switch_core_media_check_dtmf_type(session);
1293
1294 dtmf_type = tech_pvt->mparams.dtmf_type;
1295
1296 /* We only can send INFO when we have no media */
1297 if (!switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO) ||
1298 !switch_channel_media_ready(tech_pvt->channel)switch_channel_test_ready(tech_pvt->channel, SWITCH_TRUE, SWITCH_TRUE
)
|| switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE)) {
1299 dtmf_type = DTMF_INFO;
1300 }
1301
1302 switch (dtmf_type) {
1303 case DTMF_2833:
1304 {
1305 return switch_core_media_queue_rfc2833(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, dtmf);
1306 }
1307 case DTMF_INFO:
1308 {
1309 if (dtmf->digit == 'w') {
1310 switch_yield(500000)switch_sleep(500000);;
1311 } else if (dtmf->digit == 'W') {
1312 switch_yield(1000000)switch_sleep(1000000);;
1313 } else {
1314 snprintf(message, sizeof(message), "Signal=%c\r\nDuration=%d\r\n", dtmf->digit, dtmf->duration / 8);
1315 switch_mutex_lock(tech_pvt->sofia_mutex);
1316 nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("application/dtmf-relay")siptag_content_type_str, tag_str_v("application/dtmf-relay"), SIPTAG_PAYLOAD_STR(message)siptag_payload_str, tag_str_v(message), TAG_END()(tag_type_t)0, (tag_value_t)0);
1317 switch_mutex_unlock(tech_pvt->sofia_mutex);
1318 }
1319 }
1320 break;
1321 case DTMF_NONE:
1322 break;
1323 default:
1324 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 1324, (const char*)(session)
, SWITCH_LOG_WARNING, "Unhandled DTMF type!\n");
1325 break;
1326 }
1327
1328 return SWITCH_STATUS_SUCCESS;
1329}
1330
1331static switch_status_t sofia_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
1332{
1333 switch_channel_t *channel = switch_core_session_get_channel(session);
1334 private_object_t *tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
1335 switch_status_t status = SWITCH_STATUS_SUCCESS;
1336
1337 switch_assert(tech_pvt != NULL)((tech_pvt != ((void*)0)) ? (void) (0) : __assert_fail ("tech_pvt != ((void*)0)"
, "mod_sofia.c", 1337, __extension__ __PRETTY_FUNCTION__))
;
1338
1339 if (msg->message_id == SWITCH_MESSAGE_INDICATE_SIGNAL_DATA) {
1340 sofia_dispatch_event_t *de = (sofia_dispatch_event_t *) msg->pointer_arg;
1341 switch_mutex_lock(tech_pvt->sofia_mutex);
1342 if (switch_core_session_in_thread(session)) {
1343 de->session = session;
1344 }
1345
1346 sofia_process_dispatch_event(&de);
1347
1348
1349 switch_mutex_unlock(tech_pvt->sofia_mutex);
1350 goto end;
1351 }
1352
1353
1354 if (switch_channel_down(channel)(switch_channel_check_signal(channel, SWITCH_TRUE) || switch_channel_get_state
(channel) >= CS_HANGUP)
|| sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0)) {
1355 status = SWITCH_STATUS_FALSE;
1356 goto end;
1357 }
1358
1359 if (switch_channel_test_flag(channel, CF_CONFERENCE) && !zstr(tech_pvt->reply_contact)_zstr(tech_pvt->reply_contact) && !switch_stristr(";isfocus", tech_pvt->reply_contact)) {
1360 tech_pvt->reply_contact = switch_core_session_sprintf(session, "%s;isfocus", tech_pvt->reply_contact);
1361 }
1362
1363 /* ones that do not need to lock sofia mutex */
1364 switch (msg->message_id) {
1365 case SWITCH_MESSAGE_INDICATE_KEEPALIVE:
1366 {
1367 if (msg->numeric_arg) {
1368 sofia_set_flag_locked(tech_pvt, TFLAG_KEEPALIVE)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != NULL", "mod_sofia.c", 1368, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags[TFLAG_KEEPALIVE] = 1;switch_mutex_unlock
(tech_pvt->flag_mutex);
;
1369 } else {
1370 sofia_clear_flag_locked(tech_pvt, TFLAG_KEEPALIVE)switch_mutex_lock(tech_pvt->flag_mutex); (tech_pvt)->flags
[TFLAG_KEEPALIVE] = 0; switch_mutex_unlock(tech_pvt->flag_mutex
);
;
1371 }
1372 }
1373 break;
1374 case SWITCH_MESSAGE_HEARTBEAT_EVENT:
1375 {
1376 char pl[160] = "";
1377
1378 switch_snprintf(pl, sizeof(pl), "KEEP-ALIVE %d\n", ++tech_pvt->keepalive);
1379
1380 if (sofia_test_flag(tech_pvt, TFLAG_KEEPALIVE)((tech_pvt)->flags[TFLAG_KEEPALIVE] ? 1 : 0)) {
1381 if (tech_pvt->profile->keepalive == KA_MESSAGE) {
1382 nua_message(tech_pvt->nh,
1383 SIPTAG_CONTENT_TYPE_STR("text/plain")siptag_content_type_str, tag_str_v("text/plain"),
1384 TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via))!(!_zstr(tech_pvt->user_via)) ? tag_skip : siptag_via_str,
tag_str_v(tech_pvt->user_via)
,
1385 SIPTAG_PAYLOAD_STR(pl)siptag_payload_str, tag_str_v(pl),
1386 TAG_END()(tag_type_t)0, (tag_value_t)0);
1387 } else if (tech_pvt->profile->keepalive == KA_INFO) {
1388 nua_info(tech_pvt->nh,
1389 SIPTAG_CONTENT_TYPE_STR("text/plain")siptag_content_type_str, tag_str_v("text/plain"),
1390 TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via))!(!_zstr(tech_pvt->user_via)) ? tag_skip : siptag_via_str,
tag_str_v(tech_pvt->user_via)
,
1391 SIPTAG_PAYLOAD_STR(pl)siptag_payload_str, tag_str_v(pl),
1392 TAG_END()(tag_type_t)0, (tag_value_t)0);
1393 }
1394 }
1395 }
1396 break;
1397 case SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH:
1398 case SWITCH_MESSAGE_INDICATE_APPLICATION_EXEC:
1399 break;
1400 case SWITCH_MESSAGE_INDICATE_MEDIA_RENEG:
1401 {
1402 if (msg->string_arg) {
1403 sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA)(tech_pvt)->flags[TFLAG_ENABLE_SOA] = 0;
1404 }
1405
1406 sofia_glue_do_invite(session);
1407 }
1408 break;
1409 case SWITCH_MESSAGE_INDICATE_BRIDGE:
1410 switch_channel_set_variable(channel, SOFIA_REPLACES_HEADER, NULL)switch_channel_set_variable_var_check(channel, "_sofia_replaces_"
, ((void*)0), SWITCH_TRUE)
;
1411
1412 if (switch_true(switch_channel_get_variable(channel, "sip_auto_simplify")switch_channel_get_variable_dup(channel, "sip_auto_simplify",
SWITCH_TRUE, -1)
)) {
1413 sofia_set_flag(tech_pvt, TFLAG_SIMPLIFY)(tech_pvt)->flags[TFLAG_SIMPLIFY] = 1;
1414 }
1415
1416
1417 break;
1418 case SWITCH_MESSAGE_INDICATE_BLIND_TRANSFER_RESPONSE:
1419 {
1420 const char *event;
1421 const char *uuid;
1422 char *xdest;
1423
1424 if (msg->string_arg) {
1425 const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
1426 nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1)nutag_newsub, tag_bool_v(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0")siptag_content_type_str, tag_str_v("message/sipfrag;version=2.0"
)
,
1427 NUTAG_SUBSTATE(nua_substate_terminated)nutag_substate, tag_int_v(nua_substate_terminated),
1428 SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource")siptag_subscription_state_str, tag_str_v("terminated;reason=noresource"
)
,
1429 SIPTAG_PAYLOAD_STR(msg->string_arg)siptag_payload_str, tag_str_v(msg->string_arg),
1430 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
1431 SIPTAG_EVENT_STR("refer")siptag_event_str, tag_str_v("refer"), TAG_END()(tag_type_t)0, (tag_value_t)0);
1432 goto end;
1433 }
1434
1435 event = switch_channel_get_variable(channel, "sip_blind_transfer_event")switch_channel_get_variable_dup(channel, "sip_blind_transfer_event"
, SWITCH_TRUE, -1)
;
1436 uuid = switch_channel_get_variable(channel, "blind_transfer_uuid")switch_channel_get_variable_dup(channel, "blind_transfer_uuid"
, SWITCH_TRUE, -1)
;
1437
1438 if (event && uuid) {
1439 char payload_str[255] = "SIP/2.0 403 Forbidden\r\n";
1440 const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
1441 if (msg->numeric_arg) {
1442 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 1442, (const char*)(session)
, SWITCH_LOG_DEBUG,
1443 "%s Completing blind transfer with success\n", switch_channel_get_name(channel));
1444 switch_set_string(payload_str, "SIP/2.0 200 OK\r\n")switch_copy_string(payload_str, "SIP/2.0 200 OK\r\n", sizeof(
payload_str))
;
1445 } else if (uuid) {
1446 switch_core_session_t *other_session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "mod_sofia.c", (const
char *)__func__, 1446)
;
1447 if (other_session) {
1448 switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
1449 const char *invite_failure_status = switch_channel_get_variable(other_channel, "sip_invite_failure_status")switch_channel_get_variable_dup(other_channel, "sip_invite_failure_status"
, SWITCH_TRUE, -1)
;
1450 const char *invite_failure_str = switch_channel_get_variable(other_channel, "sip_invite_failure_status")switch_channel_get_variable_dup(other_channel, "sip_invite_failure_status"
, SWITCH_TRUE, -1)
;
1451 if (!zstr(invite_failure_status)_zstr(invite_failure_status) && !zstr(invite_failure_str)_zstr(invite_failure_str)) {
1452 snprintf(payload_str, sizeof(payload_str), "SIP/2.0 %s %s\r\n", invite_failure_status, invite_failure_str);
1453 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 1453, (const char*)(session)
, SWITCH_LOG_DEBUG,
1454 "%s Completing blind transfer with custom failure: %s %s\n",
1455 switch_channel_get_name(channel), invite_failure_status, invite_failure_str);
1456 }
1457 switch_core_session_rwunlock(other_session);
1458 }
1459 }
1460 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 1460, (const char*)(session)
, SWITCH_LOG_DEBUG,
1461 "%s Completing blind transfer with status: %s\n", switch_channel_get_name(channel), payload_str);
1462 nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1)nutag_newsub, tag_bool_v(1), SIPTAG_CONTENT_TYPE_STR("message/sipfrag;version=2.0")siptag_content_type_str, tag_str_v("message/sipfrag;version=2.0"
)
,
1463 NUTAG_SUBSTATE(nua_substate_terminated)nutag_substate, tag_int_v(nua_substate_terminated),
1464 SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource")siptag_subscription_state_str, tag_str_v("terminated;reason=noresource"
)
,
1465 SIPTAG_PAYLOAD_STR(payload_str)siptag_payload_str, tag_str_v(payload_str),
1466 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
1467 SIPTAG_EVENT_STR(event)siptag_event_str, tag_str_v(event), TAG_END()(tag_type_t)0, (tag_value_t)0);
1468
1469
1470 if (!msg->numeric_arg) {
1471 xdest = switch_core_session_sprintf(session, "intercept:%s", uuid);
1472 switch_ivr_session_transfer(session, xdest, "inline", NULL((void*)0));
1473 }
1474 }
1475
1476 }
1477 goto end;
1478 case SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS:
1479 if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
1480 sofia_clear_flag(tech_pvt, TFLAG_EARLY_MEDIA)(tech_pvt)->flags[TFLAG_EARLY_MEDIA] = 0;
1481 }
1482 goto end;
1483 case SWITCH_MESSAGE_INDICATE_ANSWER:
1484 case SWITCH_MESSAGE_INDICATE_PROGRESS:
1485 {
1486 const char *var;
1487 const char *presence_data = switch_channel_get_variable(channel, "presence_data")switch_channel_get_variable_dup(channel, "presence_data", SWITCH_TRUE
, -1)
;
1488 const char *presence_id = switch_channel_get_variable(channel, "presence_id")switch_channel_get_variable_dup(channel, "presence_id", SWITCH_TRUE
, -1)
;
1489
1490
1491 if ((var = switch_channel_get_variable(channel, "sip_force_nat_mode")switch_channel_get_variable_dup(channel, "sip_force_nat_mode"
, SWITCH_TRUE, -1)
) && switch_true(var)) {
1492 sofia_set_flag(tech_pvt, TFLAG_NAT)(tech_pvt)->flags[TFLAG_NAT] = 1;
1493 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 1493, (const char*)(session)
, SWITCH_LOG_DEBUG, "Setting NAT mode based on manual variable\n");
1494 switch_channel_set_variable(channel, "sip_nat_detected", "true")switch_channel_set_variable_var_check(channel, "sip_nat_detected"
, "true", SWITCH_TRUE)
;
1495 }
1496
1497 if ((var = switch_channel_get_variable(channel, "sip_enable_soa")switch_channel_get_variable_dup(channel, "sip_enable_soa", SWITCH_TRUE
, -1)
)) {
1498 if (switch_true(var)) {
1499 sofia_set_flag(tech_pvt, TFLAG_ENABLE_SOA)(tech_pvt)->flags[TFLAG_ENABLE_SOA] = 1;
1500 } else {
1501 sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA)(tech_pvt)->flags[TFLAG_ENABLE_SOA] = 0;
1502 }
1503 }
1504
1505
1506 if (presence_id || presence_data) {
1507 char *sql = switch_mprintf("update sip_dialogs set presence_id='%q',presence_data='%q' "
1508 "where uuid='%q';\n", switch_str_nil(presence_id)(presence_id ? presence_id : ""), switch_str_nil(presence_data)(presence_data ? presence_data : ""),
1509 switch_core_session_get_uuid(session));
1510 switch_assert(sql)((sql) ? (void) (0) : __assert_fail ("sql", "mod_sofia.c", 1510
, __extension__ __PRETTY_FUNCTION__))
;
1511 sofia_glue_execute_sql_now(tech_pvt->profile, &sql, SWITCH_TRUE);
1512 }
1513
1514 if (sofia_test_media_flag(tech_pvt->profile, SCMF_AUTOFIX_TIMING)((tech_pvt->profile)->media_flags[SCMF_AUTOFIX_TIMING] ?
1 : 0)
) {
1515 switch_core_media_reset_autofix(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
1516 }
1517 }
1518 break;
1519 default:
1520 break;
1521 }
1522
1523 /* ones that do need to lock sofia mutex */
1524 switch_mutex_lock(tech_pvt->sofia_mutex);
1525
1526 if (switch_channel_down(channel)(switch_channel_check_signal(channel, SWITCH_TRUE) || switch_channel_get_state
(channel) >= CS_HANGUP)
|| sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0)) {
1527 status = SWITCH_STATUS_FALSE;
1528 goto end_lock;
1529 }
1530
1531 switch (msg->message_id) {
1532
1533 case SWITCH_MESSAGE_INDICATE_DEFLECT: {
1534
1535 char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_HEADER_PREFIX"sip_h_");
1536 char ref_to[1024] = "";
1537 const char *var;
1538 const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
1539
1540 if (!strcasecmp(msg->string_arg, "sip:")) {
1541 const char *format = strchr(tech_pvt->profile->sipip, ':') ? "sip:%s@[%s]" : "sip:%s@%s";
1542
1543 switch_snprintf(ref_to, sizeof(ref_to), format, msg->string_arg, tech_pvt->profile->sipip);
1544 } else {
1545 switch_set_string(ref_to, msg->string_arg)switch_copy_string(ref_to, msg->string_arg, sizeof(ref_to)
)
;
1546 }
1547
1548 nua_refer(tech_pvt->nh, SIPTAG_REFER_TO_STR(ref_to)siptag_refer_to_str, tag_str_v(ref_to), SIPTAG_REFERRED_BY_STR(tech_pvt->contact_url)siptag_referred_by_str, tag_str_v(tech_pvt->contact_url),
1549 TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers))!(!_zstr(extra_headers)) ? tag_skip : siptag_header_str, tag_str_v
((extra_headers))
,
1550 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
1551 TAG_END()(tag_type_t)0, (tag_value_t)0);
1552
1553 if (msg->string_array_arg[0]) {
1554 tech_pvt->proxy_refer_uuid = (char *)msg->string_array_arg[0];
1555 } else {
1556 switch_mutex_unlock(tech_pvt->sofia_mutex);
1557 sofia_wait_for_reply(tech_pvt, 9999, 10);
1558 switch_mutex_lock(tech_pvt->sofia_mutex);
1559
1560 if ((var = switch_channel_get_variable(tech_pvt->channel, "sip_refer_reply")switch_channel_get_variable_dup(tech_pvt->channel, "sip_refer_reply"
, SWITCH_TRUE, -1)
)) {
1561 msg->string_reply = switch_core_session_strdup(session, var)switch_core_perform_session_strdup(session, var, "mod_sofia.c"
, (const char *)__func__, 1561)
;
1562 } else {
1563 msg->string_reply = "no reply";
1564 }
1565
1566 switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_BLIND_TRANSFER)switch_channel_perform_hangup(tech_pvt->channel, "mod_sofia.c"
, (const char *)__func__, 1566, SWITCH_CAUSE_BLIND_TRANSFER)
;
1567 }
1568
1569 switch_safe_free(extra_headers)if (extra_headers) {free(extra_headers);extra_headers=((void*
)0);}
;
1570 }
1571 break;
1572
1573 case SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ:
1574 if (switch_channel_media_up(channel)(switch_channel_test_flag(channel, CF_ANSWERED) || switch_channel_test_flag
(channel, CF_EARLY_MEDIA))
&& !switch_channel_test_flag(channel, CF_AVPF) && !switch_channel_test_flag(channel, CF_MANUAL_VID_REFRESH) &&
1575 switch_channel_var_true(channel, "sofia_send_info_vid_refresh")) {
1576 const char *pl = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<media_control><vc_primitive><to_encoder><picture_fast_update /></to_encoder></vc_primitive></media_control>\n";
1577 switch_time_t now = switch_micro_time_now();
1578
1579 if (!tech_pvt->last_vid_info || (now - tech_pvt->last_vid_info) > 500000) {
1580
1581 tech_pvt->last_vid_info = now;
1582
1583 if (!zstr(msg->string_arg)_zstr(msg->string_arg)) {
1584 pl = msg->string_arg;
1585 }
1586
1587 nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("application/media_control+xml")siptag_content_type_str, tag_str_v("application/media_control+xml"
)
, SIPTAG_PAYLOAD_STR(pl)siptag_payload_str, tag_str_v(pl), TAG_END()(tag_type_t)0, (tag_value_t)0);
1588 }
1589
1590 }
1591 break;
1592 case SWITCH_MESSAGE_INDICATE_BROADCAST:
1593 {
1594 const char *ip = NULL((void*)0), *port = NULL((void*)0);
1595 ip = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE)switch_channel_get_variable_dup(channel, "remote_media_ip", SWITCH_TRUE
, -1)
;
1596 port = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE)switch_channel_get_variable_dup(channel, "remote_media_port",
SWITCH_TRUE, -1)
;
1597 if (ip && port) {
1598 switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, ip, (switch_port_t)atoi(port), msg->string_arg, 1);
1599 }
1600
1601 if (!sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0)) {
1602 const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
1603
1604 if (sofia_use_soa(tech_pvt)((tech_pvt)->flags[TFLAG_ENABLE_SOA] ? 1 : 0)) {
1605 nua_respond(tech_pvt->nh, SIP_200_OK200, sip_200_OK,
1606 SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
1607 SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str)soatag_user_sdp_str, tag_str_v(tech_pvt->mparams.local_sdp_str
)
,
1608 SOATAG_REUSE_REJECTED(1)soatag_reuse_rejected, tag_bool_v(1),
1609 SOATAG_AUDIO_AUX("cn telephone-event")soatag_audio_aux, tag_str_v("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1)nutag_include_extra_sdp, tag_bool_v(1),
1610 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
1611 TAG_END()(tag_type_t)0, (tag_value_t)0);
1612 } else {
1613 nua_respond(tech_pvt->nh, SIP_200_OK200, sip_200_OK,
1614 NUTAG_MEDIA_ENABLE(0)nutag_media_enable, tag_bool_v(0),
1615 SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
1616 SIPTAG_CONTENT_TYPE_STR("application/sdp")siptag_content_type_str, tag_str_v("application/sdp"), SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str)siptag_payload_str, tag_str_v(tech_pvt->mparams.local_sdp_str
)
,
1617 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
1618 TAG_END()(tag_type_t)0, (tag_value_t)0);
1619 }
1620 switch_channel_mark_answered(channel)switch_channel_perform_mark_answered(channel, "mod_sofia.c", (
const char *)__func__, 1620)
;
1621 }
1622 }
1623 break;
1624 case SWITCH_MESSAGE_INDICATE_NOMEDIA:
1625 {
1626 sofia_glue_do_invite(session);
1627 }
1628 break;
1629
1630 case SWITCH_MESSAGE_INDICATE_MEDIA_REDIRECT:
1631 {
1632
1633 if (zstr(msg->string_arg)_zstr(msg->string_arg)) { /* no sdp requires proxy of ack */
1634 switch_core_session_t *other_session;
1635
1636 if (switch_core_session_get_partner(session, &other_session)switch_core_session_perform_get_partner(session, &other_session
, "mod_sofia.c", (const char *)__func__, 1636)
== SWITCH_STATUS_SUCCESS) {
1637 if (switch_core_session_compare(session, other_session)) {
1638 private_object_t *other_tech_pvt = switch_core_session_get_private(other_session)switch_core_session_get_private_class(other_session, SWITCH_PVT_PRIMARY
)
;
1639 sofia_set_flag(other_tech_pvt, TFLAG_PASS_ACK)(other_tech_pvt)->flags[TFLAG_PASS_ACK] = 1;
1640 }
1641 switch_core_session_rwunlock(other_session);
1642 }
1643 }
1644
1645 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 1645, (const char*)(session)
, SWITCH_LOG_DEBUG, "%s Sending media re-direct:\n%s\n",
1646 switch_channel_get_name(channel), switch_str_nil(msg->string_arg)(msg->string_arg ? msg->string_arg : ""));
1647 switch_core_media_set_local_sdp(session, msg->string_arg, SWITCH_TRUE);
1648
1649 if (zstr(tech_pvt->mparams.local_sdp_str)_zstr(tech_pvt->mparams.local_sdp_str)) {
1650 sofia_set_flag(tech_pvt, TFLAG_3PCC_INVITE)(tech_pvt)->flags[TFLAG_3PCC_INVITE] = 1;
1651 }
1652
1653 sofia_set_flag_locked(tech_pvt, TFLAG_SENT_UPDATE)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != NULL", "mod_sofia.c", 1653, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags[TFLAG_SENT_UPDATE] = 1;switch_mutex_unlock
(tech_pvt->flag_mutex);
;
1654
1655 if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
1656 switch_channel_set_flag(channel, CF_REQ_MEDIA)switch_channel_set_flag_value(channel, CF_REQ_MEDIA, 1);
1657 }
1658 sofia_glue_do_invite(session);
1659
1660 }
1661 break;
1662
1663 case SWITCH_MESSAGE_INDICATE_T38_DESCRIPTION:
1664 {
1665 switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options");
1666 const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
1667
1668 if (!t38_options) {
1669 nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE488, sip_488_Not_acceptable, TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
, TAG_END()(tag_type_t)0, (tag_value_t)0);
1670 goto end_lock;
1671 }
1672
1673 switch_core_media_start_udptl(tech_pvt->session, t38_options);
1674
1675 switch_core_media_set_udptl_image_sdp(tech_pvt->session, t38_options, msg->numeric_arg);
1676
1677 if (!sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0)) {
1678 char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_RESPONSE_HEADER_PREFIX"sip_rh_");
1679 if (sofia_use_soa(tech_pvt)((tech_pvt)->flags[TFLAG_ENABLE_SOA] ? 1 : 0)) {
1680 nua_respond(tech_pvt->nh, SIP_200_OK200, sip_200_OK,
1681 NUTAG_AUTOANSWER(0)nutag_autoanswer, tag_bool_v(0),
1682 SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
1683 SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info"))siptag_call_info_str, tag_str_v(switch_channel_get_variable_dup
(tech_pvt->channel, "sip_h_" "call_info", SWITCH_TRUE, -1)
)
,
1684 SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str)soatag_user_sdp_str, tag_str_v(tech_pvt->mparams.local_sdp_str
)
,
1685 SOATAG_REUSE_REJECTED(1)soatag_reuse_rejected, tag_bool_v(1),
1686 SOATAG_ORDERED_USER(1)soatag_ordered_user, tag_bool_v(1),
1687 SOATAG_AUDIO_AUX("cn telephone-event")soatag_audio_aux, tag_str_v("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1)nutag_include_extra_sdp, tag_bool_v(1),
1688 TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers))!(!_zstr(extra_headers)) ? tag_skip : siptag_header_str, tag_str_v
((extra_headers))
,
1689 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
1690 TAG_END()(tag_type_t)0, (tag_value_t)0);
1691 } else {
1692 nua_respond(tech_pvt->nh, SIP_200_OK200, sip_200_OK,
1693 NUTAG_AUTOANSWER(0)nutag_autoanswer, tag_bool_v(0),
1694 NUTAG_MEDIA_ENABLE(0)nutag_media_enable, tag_bool_v(0),
1695 SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
1696 SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info"))siptag_call_info_str, tag_str_v(switch_channel_get_variable_dup
(tech_pvt->channel, "sip_h_" "call_info", SWITCH_TRUE, -1)
)
,
1697 SIPTAG_CONTENT_TYPE_STR("application/sdp")siptag_content_type_str, tag_str_v("application/sdp"),
1698 SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str)siptag_payload_str, tag_str_v(tech_pvt->mparams.local_sdp_str
)
,
1699 TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers))!(!_zstr(extra_headers)) ? tag_skip : siptag_header_str, tag_str_v
((extra_headers))
,
1700 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
1701 TAG_END()(tag_type_t)0, (tag_value_t)0);
1702 }
1703 switch_safe_free(extra_headers)if (extra_headers) {free(extra_headers);extra_headers=((void*
)0);}
;
1704 sofia_set_flag_locked(tech_pvt, TFLAG_ANS)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != NULL", "mod_sofia.c", 1704, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags[TFLAG_ANS] = 1;switch_mutex_unlock(tech_pvt
->flag_mutex);
;
1705 }
1706 }
1707 break;
1708
1709 case SWITCH_MESSAGE_INDICATE_REQUEST_IMAGE_MEDIA:
1710 {
1711 switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options");
1712
1713 if (t38_options) {
1714 switch_core_media_set_udptl_image_sdp(tech_pvt->session, t38_options, msg->numeric_arg);
1715
1716 if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
1717 switch_channel_set_flag(channel, CF_REQ_MEDIA)switch_channel_set_flag_value(channel, CF_REQ_MEDIA, 1);
1718 }
1719 sofia_set_flag_locked(tech_pvt, TFLAG_SENT_UPDATE)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != NULL", "mod_sofia.c", 1719, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags[TFLAG_SENT_UPDATE] = 1;switch_mutex_unlock
(tech_pvt->flag_mutex);
;
1720 sofia_glue_do_invite(session);
1721 } else {
1722 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 1722, (const char*)(session)
, SWITCH_LOG_WARNING, "%s Request to send IMAGE on channel with not t38 options.\n",
1723 switch_channel_get_name(channel));
1724 }
1725 }
1726 break;
1727
1728 case SWITCH_MESSAGE_INDICATE_3P_NOMEDIA:
1729 {
1730 char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_HEADER_PREFIX"sip_h_");
1731 const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
1732
1733 switch_channel_clear_flag(tech_pvt->channel, CF_MEDIA_ACK);
1734 switch_channel_set_flag(tech_pvt->channel, CF_REQ_MEDIA)switch_channel_set_flag_value(tech_pvt->channel, CF_REQ_MEDIA
, 1)
;
1735
1736 sofia_glue_clear_soa(session, SWITCH_TRUE);
1737
1738 nua_invite(tech_pvt->nh,
1739 NUTAG_MEDIA_ENABLE(0)nutag_media_enable, tag_bool_v(0),
1740 TAG_IF(msg->string_arg, SIPTAG_CONTENT_TYPE_STR("application/sdp"))!(msg->string_arg) ? tag_skip : siptag_content_type_str, tag_str_v
("application/sdp")
,
1741 SIPTAG_PAYLOAD_STR(msg->string_arg)siptag_payload_str, tag_str_v(msg->string_arg),
1742 TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers))!(!_zstr(extra_headers)) ? tag_skip : siptag_header_str, tag_str_v
((extra_headers))
,
1743 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
1744 TAG_END()(tag_type_t)0, (tag_value_t)0);
1745
1746 switch_safe_free(extra_headers)if (extra_headers) {free(extra_headers);extra_headers=((void*
)0);}
;
1747 }
1748 break;
1749 case SWITCH_MESSAGE_INDICATE_3P_MEDIA:
1750 {
1751 char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_HEADER_PREFIX"sip_h_");
1752 const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
1753
1754 sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA)(tech_pvt)->flags[TFLAG_ENABLE_SOA] = 0;
1755
1756 switch_channel_clear_flag(tech_pvt->channel, CF_MEDIA_ACK);
1757 switch_channel_clear_flag(tech_pvt->channel, CF_MEDIA_SET);
1758 switch_channel_set_flag(tech_pvt->channel, CF_REQ_MEDIA)switch_channel_set_flag_value(tech_pvt->channel, CF_REQ_MEDIA
, 1)
;
1759
1760 sofia_glue_clear_soa(session, SWITCH_TRUE);
1761
1762 nua_invite(tech_pvt->nh, NUTAG_MEDIA_ENABLE(0)nutag_media_enable, tag_bool_v(0), SIPTAG_PAYLOAD_STR("")siptag_payload_str, tag_str_v(""),
1763 TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers))!(!_zstr(extra_headers)) ? tag_skip : siptag_header_str, tag_str_v
((extra_headers))
,
1764 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
1765 TAG_END()(tag_type_t)0, (tag_value_t)0);
1766
1767 switch_safe_free(extra_headers)if (extra_headers) {free(extra_headers);extra_headers=((void*
)0);}
;
1768 }
1769 break;
1770
1771 case SWITCH_MESSAGE_INDICATE_MEDIA:
1772 {
1773 uint32_t send_invite = 1;
1774 const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE)switch_channel_get_variable_dup(channel, "switch_r_sdp", SWITCH_TRUE
, -1)
;
1775
1776 switch_channel_clear_flag(channel, CF_PROXY_MODE);
1777 switch_core_media_set_local_sdp(session, NULL((void*)0), SWITCH_FALSE);
1778
1779 if (!(switch_channel_test_flag(channel, CF_ANSWERED) || switch_channel_test_flag(channel, CF_EARLY_MEDIA))) {
1780 if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
1781
1782 switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
1783 if (sofia_media_tech_media(tech_pvt, r_sdp, SDP_TYPE_REQUEST) != SWITCH_STATUS_SUCCESS) {
1784 switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR")switch_channel_set_variable_var_check(channel, "endpoint_disposition"
, "CODEC NEGOTIATION ERROR", SWITCH_TRUE)
;
1785 status = SWITCH_STATUS_FALSE;
1786 goto end_lock;
1787 }
1788 send_invite = 0;
1789 }
1790 }
1791
1792
1793 switch_core_media_set_sdp_codec_string(tech_pvt->session, r_sdp, SDP_TYPE_RESPONSE);
1794 switch_channel_set_variable(tech_pvt->channel, "absolute_codec_string", switch_channel_get_variable(tech_pvt->channel, "ep_codec_string"))switch_channel_set_variable_var_check(tech_pvt->channel, "absolute_codec_string"
, switch_channel_get_variable_dup(tech_pvt->channel, "ep_codec_string"
, SWITCH_TRUE, -1), SWITCH_TRUE)
;
1795 switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
1796
1797 if ((status = switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0)) != SWITCH_STATUS_SUCCESS) {
1798 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(channel, "mod_sofia.c", (const char
*)__func__, 1798, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)
;
1799 goto end_lock;
1800 }
1801
1802 switch_core_media_gen_local_sdp(session, SDP_TYPE_REQUEST, NULL((void*)0), 0, NULL((void*)0), 1);
1803
1804 if (!msg->numeric_arg) {
1805 if (send_invite) {
1806 if (!switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
1807 switch_channel_set_flag(channel, CF_REQ_MEDIA)switch_channel_set_flag_value(channel, CF_REQ_MEDIA, 1);
1808 }
1809 sofia_glue_do_invite(session);
1810 } else {
1811 status = SWITCH_STATUS_FALSE;
1812 }
1813 }
1814 }
1815 break;
1816
1817 case SWITCH_MESSAGE_INDICATE_PHONE_EVENT:
1818 {
1819 const char *event = "talk";
1820 const char *full_to = NULL((void*)0);
1821
1822 if (!zstr(msg->string_arg)_zstr(msg->string_arg) && strcasecmp(msg->string_arg, event)) {
1823 if (!strcasecmp(msg->string_arg, "hold")) {
1824 event = "hold";
1825 } else if (strncasecmp(msg->string_arg, "talk", 4)) {
1826 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 1826, (const char*)(session)
, SWITCH_LOG_WARNING, "Invalid event.\n");
1827 }
1828 }
1829
1830 if (!switch_channel_test_flag(channel, CF_ANSWERED) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
1831 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 1831, (const char*)(session)
, SWITCH_LOG_ERROR,
1832 "Operation not permitted on an inbound non-answered call leg!\n");
1833 } else {
1834 const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
1835 full_to = switch_str_nil(switch_channel_get_variable(channel, "sip_full_to"))(switch_channel_get_variable_dup(channel, "sip_full_to", SWITCH_TRUE
, -1) ? switch_channel_get_variable_dup(channel, "sip_full_to"
, SWITCH_TRUE, -1) : "")
;
1836 nua_notify(tech_pvt->nh, NUTAG_NEWSUB(1)nutag_newsub, tag_bool_v(1), NUTAG_SUBSTATE(nua_substate_active)nutag_substate, tag_int_v(nua_substate_active),
1837 TAG_IF((full_to), SIPTAG_TO_STR(full_to))!((full_to)) ? tag_skip : siptag_to_str, tag_str_v(full_to),SIPTAG_SUBSCRIPTION_STATE_STR("active")siptag_subscription_state_str, tag_str_v("active"),
1838 SIPTAG_EVENT_STR(event)siptag_event_str, tag_str_v(event),
1839 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
1840 TAG_END()(tag_type_t)0, (tag_value_t)0);
1841 }
1842
1843 }
1844 break;
1845 case SWITCH_MESSAGE_INDICATE_MESSAGE:
1846 {
1847 char ct[256] = "text/plain";
1848 int ok = 0;
1849 const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
1850
1851 if (!zstr(msg->string_array_arg[3])_zstr(msg->string_array_arg[3]) && !strcmp(msg->string_array_arg[3], tech_pvt->caller_profile->uuid)) {
1852 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
1852, ((void*)0)
, SWITCH_LOG_NOTICE, "Not sending message back to sender\n");
1853 break;
1854 }
1855
1856 if (switch_stristr("send_message", tech_pvt->x_freeswitch_support_remote)) {
1857 ok = 1;
1858 }
1859
1860 if (switch_true(switch_channel_get_variable(channel, "fs_send_unsupported_message")switch_channel_get_variable_dup(channel, "fs_send_unsupported_message"
, SWITCH_TRUE, -1)
)) {
1861 ok = 1;
1862 }
1863
1864 if (ok) {
1865 const char *pl = NULL((void*)0);
1866
1867 if (!zstr(msg->string_array_arg[0])_zstr(msg->string_array_arg[0]) && !zstr(msg->string_array_arg[1])_zstr(msg->string_array_arg[1])) {
1868 switch_snprintf(ct, sizeof(ct), "%s/%s", msg->string_array_arg[0], msg->string_array_arg[1]);
1869 }
1870
1871 if (!zstr(msg->string_array_arg[2])_zstr(msg->string_array_arg[2])) {
1872 pl = msg->string_array_arg[2];
1873 }
1874
1875 nua_message(tech_pvt->nh,
1876 SIPTAG_CONTENT_TYPE_STR(ct)siptag_content_type_str, tag_str_v(ct),
1877 TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via))!(!_zstr(tech_pvt->user_via)) ? tag_skip : siptag_via_str,
tag_str_v(tech_pvt->user_via)
,
1878 TAG_IF(pl, SIPTAG_PAYLOAD_STR(pl))!(pl) ? tag_skip : siptag_payload_str, tag_str_v(pl),
1879 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
1880 TAG_END()(tag_type_t)0, (tag_value_t)0);
1881 } else {
1882 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 1882, (const char*)(session)
, SWITCH_LOG_DEBUG,
1883 "%s send_message is not supported.\n", switch_channel_get_name(channel));
1884 }
1885 }
1886 break;
1887 case SWITCH_MESSAGE_INDICATE_INFO:
1888 {
1889 char ct[256] = "freeswitch/data";
1890 int ok = 0;
1891 const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
1892
1893 if (switch_stristr("send_info", tech_pvt->x_freeswitch_support_remote)) {
1894 ok = 1;
1895 }
1896
1897 if (switch_true(switch_channel_get_variable_dup(channel, "fs_send_unsupported_info", SWITCH_FALSE, -1))) {
1898 ok = 1;
1899 }
1900
1901 if (ok) {
1902 char *headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_INFO_HEADER_PREFIX"sip_info_h_");
1903 const char *pl = NULL((void*)0);
1904
1905 if (!zstr(msg->string_array_arg[0])_zstr(msg->string_array_arg[0]) && !zstr(msg->string_array_arg[1])_zstr(msg->string_array_arg[1])) {
1906 switch_snprintf(ct, sizeof(ct), "%s/%s", msg->string_array_arg[0], msg->string_array_arg[1]);
1907 }
1908
1909 if (!zstr(msg->string_array_arg[2])_zstr(msg->string_array_arg[2])) {
1910 pl = msg->string_array_arg[2];
1911 }
1912
1913 nua_info(tech_pvt->nh,
1914 SIPTAG_CONTENT_TYPE_STR(ct)siptag_content_type_str, tag_str_v(ct),
1915 TAG_IF(!zstr(headers), SIPTAG_HEADER_STR(headers))!(!_zstr(headers)) ? tag_skip : siptag_header_str, tag_str_v(
(headers))
,
1916 TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via))!(!_zstr(tech_pvt->user_via)) ? tag_skip : siptag_via_str,
tag_str_v(tech_pvt->user_via)
,
1917 TAG_IF(pl, SIPTAG_PAYLOAD_STR(pl))!(pl) ? tag_skip : siptag_payload_str, tag_str_v(pl),
1918 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
1919 TAG_END()(tag_type_t)0, (tag_value_t)0);
1920
1921 switch_safe_free(headers)if (headers) {free(headers);headers=((void*)0);};
1922 } else {
1923 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 1923, (const char*)(session)
, SWITCH_LOG_DEBUG, "%s send_info is not supported.\n", switch_channel_get_name(channel));
1924 }
1925 }
1926 break;
1927 case SWITCH_MESSAGE_INDICATE_SIMPLIFY:
1928 {
1929 char *ref_to, *ref_by;
1930 const char *uuid;
1931 const char *call_id = NULL((void*)0), *to_user = NULL((void*)0), *to_host = NULL((void*)0), *to_tag = NULL((void*)0), *from_tag = NULL((void*)0), *from_user = NULL((void*)0), *from_host = NULL((void*)0);
1932
1933 if ((uuid = switch_channel_get_partner_uuid(channel))) {
1934 switch_core_session_t *rsession;
1935 if ((rsession = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "mod_sofia.c", (const
char *)__func__, 1935)
)) {
1936 switch_channel_t *rchannel = switch_core_session_get_channel(rsession);
1937 call_id = switch_channel_get_variable(rchannel, "sip_call_id")switch_channel_get_variable_dup(rchannel, "sip_call_id", SWITCH_TRUE
, -1)
;
1938
1939 to_user = switch_channel_get_variable(rchannel, "sip_to_user")switch_channel_get_variable_dup(rchannel, "sip_to_user", SWITCH_TRUE
, -1)
;
1940
1941 if (switch_channel_direction(rchannel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
1942 to_host = switch_channel_get_variable(rchannel, "sip_to_host")switch_channel_get_variable_dup(rchannel, "sip_to_host", SWITCH_TRUE
, -1)
;
1943 from_user = switch_channel_get_variable(channel, "sip_from_user")switch_channel_get_variable_dup(channel, "sip_from_user", SWITCH_TRUE
, -1)
;
1944 from_host = switch_channel_get_variable(channel, "sip_from_host")switch_channel_get_variable_dup(channel, "sip_from_host", SWITCH_TRUE
, -1)
;
1945 to_tag = switch_channel_get_variable(rchannel, "sip_to_tag")switch_channel_get_variable_dup(rchannel, "sip_to_tag", SWITCH_TRUE
, -1)
;
1946 from_tag = switch_channel_get_variable(rchannel, "sip_from_tag")switch_channel_get_variable_dup(rchannel, "sip_from_tag", SWITCH_TRUE
, -1)
;
1947 } else {
1948 to_host = switch_channel_get_variable(channel, "sip_to_host")switch_channel_get_variable_dup(channel, "sip_to_host", SWITCH_TRUE
, -1)
;
1949 from_user = switch_channel_get_variable(rchannel, "sip_from_user")switch_channel_get_variable_dup(rchannel, "sip_from_user", SWITCH_TRUE
, -1)
;
1950 from_host = switch_channel_get_variable(rchannel, "sip_from_host")switch_channel_get_variable_dup(rchannel, "sip_from_host", SWITCH_TRUE
, -1)
;
1951 from_tag = switch_channel_get_variable(rchannel, "sip_to_tag")switch_channel_get_variable_dup(rchannel, "sip_to_tag", SWITCH_TRUE
, -1)
;
1952 to_tag = switch_channel_get_variable(rchannel, "sip_from_tag")switch_channel_get_variable_dup(rchannel, "sip_from_tag", SWITCH_TRUE
, -1)
;
1953 }
1954
1955 switch_core_session_rwunlock(rsession);
1956 }
1957 }
1958
1959 if (to_user && to_host && from_user && from_host && call_id && to_tag && from_tag) {
1960 char in[512] = "", out[1536] = "";
1961 const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
1962
1963 switch_snprintf(in, sizeof(in), "%s;to-tag=%s;from-tag=%s", call_id, to_tag, from_tag);
1964 switch_url_encode(in, out, sizeof(out));
1965
1966 ref_to = switch_mprintf("<sip:%s@%s?Replaces=%s>", to_user, to_host, out);
1967 ref_by = switch_mprintf("<sip:%s@%s>", from_user, from_host);
1968
1969 nua_refer(tech_pvt->nh, SIPTAG_REFER_TO_STR(ref_to)siptag_refer_to_str, tag_str_v(ref_to), SIPTAG_REFERRED_BY_STR(ref_by)siptag_referred_by_str, tag_str_v(ref_by),
1970 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
1971 TAG_END()(tag_type_t)0, (tag_value_t)0);
1972 switch_safe_free(ref_to)if (ref_to) {free(ref_to);ref_to=((void*)0);};
1973 switch_safe_free(ref_by)if (ref_by) {free(ref_by);ref_by=((void*)0);};
1974 }
1975 }
1976 break;
1977 case SWITCH_MESSAGE_INDICATE_DISPLAY:
1978 {
1979 const char *name = NULL((void*)0), *number = NULL((void*)0);
1980 const char *call_info = NULL((void*)0);
1981
1982 if (!sofia_test_pflag(tech_pvt->profile, PFLAG_SEND_DISPLAY_UPDATE)((tech_pvt->profile)->pflags[PFLAG_SEND_DISPLAY_UPDATE]
? 1 : 0)
) {
1983 goto end_lock;
1984 }
1985
1986 name = msg->string_array_arg[0];
1987 number = msg->string_array_arg[1];
1988 call_info = switch_channel_get_variable(channel, "presence_call_info_full")switch_channel_get_variable_dup(channel, "presence_call_info_full"
, SWITCH_TRUE, -1)
;
1989
1990 if (!zstr(name)_zstr(name) && strcmp(name, "_undef_")) {
1991 char message[256] = "";
1992 const char *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent")switch_channel_get_variable_dup(tech_pvt->channel, "sip_user_agent"
, SWITCH_TRUE, -1)
;
1993 const char *allow = switch_channel_get_variable(tech_pvt->channel, "sip_allow")switch_channel_get_variable_dup(tech_pvt->channel, "sip_allow"
, SWITCH_TRUE, -1)
;
1994 switch_event_t *event;
1995 int update_allowed = 0;
1996 const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
1997
1998 check_decode(name, tech_pvt->session)do { ((tech_pvt->session) ? (void) (0) : __assert_fail ("tech_pvt->session"
, "mod_sofia.c", 1998, __extension__ __PRETTY_FUNCTION__)); if
(!_zstr(name)) { int d = 0; char *p; if (strchr(name, '%')) {
char *tmp = switch_core_perform_session_strdup(tech_pvt->
session, name, "mod_sofia.c", (const char *)__func__, 1998); switch_url_decode
(tmp); name = tmp; d++; } if ((p = strchr(name, '"'))) { if (
!d) { char *tmp = switch_core_perform_session_strdup(tech_pvt
->session, name, "mod_sofia.c", (const char *)__func__, 1998
); name = tmp; } if ((p = strchr(name, '"'))) { name = p+1; }
if ((p = strrchr(name, '"'))) { *p = '\0'; } } } break; } while
(0)
;
1999
2000 if (allow) {
2001 update_allowed = !!switch_stristr("UPDATE", allow);
2002 }
2003
2004 if (zstr(number)_zstr(number)) {
2005 number = tech_pvt->caller_profile->destination_number;
2006 }
2007
2008 switch_ivr_eavesdrop_update_display(session, name, number);
2009
2010 if (!sofia_test_flag(tech_pvt, TFLAG_UPDATING_DISPLAY)((tech_pvt)->flags[TFLAG_UPDATING_DISPLAY] ? 1 : 0) && switch_channel_test_flag(channel, CF_ANSWERED)) {
2011 if (zstr(tech_pvt->last_sent_callee_id_name)_zstr(tech_pvt->last_sent_callee_id_name) || strcmp(tech_pvt->last_sent_callee_id_name, name) ||
2012 zstr(tech_pvt->last_sent_callee_id_number)_zstr(tech_pvt->last_sent_callee_id_number) || strcmp(tech_pvt->last_sent_callee_id_number, number)) {
2013
2014 if (switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote)) {
2015 snprintf(message, sizeof(message), "X-FS-Display-Name: %s\nX-FS-Display-Number: %s\n", name, number);
2016
2017 if (switch_channel_test_flag(tech_pvt->channel, CF_LAZY_ATTENDED_TRANSFER)) {
2018 snprintf(message + strlen(message), sizeof(message) - strlen(message), "X-FS-Lazy-Attended-Transfer: true\n");
2019 switch_channel_clear_flag(tech_pvt->channel, CF_LAZY_ATTENDED_TRANSFER);
2020 switch_channel_clear_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER);
2021 }
2022
2023 if (switch_channel_test_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER)) {
2024 snprintf(message + strlen(message), sizeof(message) - strlen(message), "X-FS-Attended-Transfer: true\n");
2025 switch_channel_clear_flag(tech_pvt->channel, CF_ATTENDED_TRANSFER);
2026 }
2027
2028 nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/update_display")siptag_content_type_str, tag_str_v("message/update_display"),
2029 TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message))!(!(*(message) == '\0')) ? tag_skip : siptag_header_str, tag_str_v
((message))
,
2030 TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via))!(!_zstr(tech_pvt->user_via)) ? tag_skip : siptag_via_str,
tag_str_v(tech_pvt->user_via)
,
2031 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
2032 TAG_END()(tag_type_t)0, (tag_value_t)0);
2033 } else if (ua && switch_stristr("snom", ua)) {
2034 const char *ver_str = NULL((void*)0);
2035 int version = 0;
2036
2037 ver_str = switch_stristr( "/", ua);
2038
2039 if ( ver_str ) {
2040 char *argv[4] = { 0 };
2041 char *dotted = strdup( ver_str + 1 );
2042 switch_assert(dotted)((dotted) ? (void) (0) : __assert_fail ("dotted", "mod_sofia.c"
, 2042, __extension__ __PRETTY_FUNCTION__))
;
2043 switch_separate_string(dotted, '.', argv, (sizeof(argv) / sizeof(argv[0])));
2044 if ( argv[0] && argv[1] && argv[2] ) {
2045 version = ( atoi(argv[0]) * 10000 ) + ( atoi(argv[1]) * 100 ) + atoi(argv[2]);
2046 }
2047 switch_safe_free( dotted )if (dotted) {free(dotted);dotted=((void*)0);};
2048 }
2049
2050 if ( version >= 80424 ) {
2051 if (zstr(name)_zstr(name)) {
2052 snprintf(message, sizeof(message), "From: %s\r\nTo:\r\n", number);
2053 } else {
2054 snprintf(message, sizeof(message), "From: \"%s\" %s\r\nTo:\r\n", name, number);
2055 }
2056 } else {
2057 if (zstr(name)_zstr(name)) {
2058 snprintf(message, sizeof(message), "From:\r\nTo: %s\r\n", number);
2059 } else {
2060 snprintf(message, sizeof(message), "From:\r\nTo: \"%s\" %s\r\n", name, number);
2061 }
2062 }
2063
2064 nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag")siptag_content_type_str, tag_str_v("message/sipfrag"),
2065 TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via))!(!_zstr(tech_pvt->user_via)) ? tag_skip : siptag_via_str,
tag_str_v(tech_pvt->user_via)
, SIPTAG_PAYLOAD_STR(message)siptag_payload_str, tag_str_v(message), TAG_END()(tag_type_t)0, (tag_value_t)0);
2066 } else if (update_allowed && ua && (switch_stristr("polycom", ua) ||
2067 (switch_stristr("aastra", ua) && !switch_stristr("Intelligate", ua)) ||
2068 (switch_stristr("cisco/spa50", ua) ||
2069 switch_stristr("cisco/spa525", ua)) ||
2070 switch_stristr("cisco/spa30", ua) ||
2071 switch_stristr("Grandstream", ua) ||
2072 switch_stristr("Yealink", ua) ||
2073 switch_stristr("Mitel", ua) ||
2074 switch_stristr("Panasonic", ua))) {
2075 snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <sip:%s@%s>", name, number, tech_pvt->profile->sipip);
2076
2077 sofia_set_flag_locked(tech_pvt, TFLAG_UPDATING_DISPLAY)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != NULL", "mod_sofia.c", 2077, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags[TFLAG_UPDATING_DISPLAY] = 1;switch_mutex_unlock
(tech_pvt->flag_mutex);
;
2078 nua_update(tech_pvt->nh,
2079 NUTAG_SESSION_TIMER(tech_pvt->session_timeout)nutag_session_timer, tag_uint_v((tech_pvt->session_timeout
))
,
2080 NUTAG_SESSION_REFRESHER(tech_pvt->session_refresher)nutag_session_refresher, tag_int_v((tech_pvt->session_refresher
))
,
2081 NUTAG_UPDATE_REFRESH(tech_pvt->update_refresher)nutag_update_refresh, tag_bool_v((tech_pvt->update_refresher
))
,
2082 TAG_IF(!zstr(tech_pvt->privacy), SIPTAG_PRIVACY_STR(tech_pvt->privacy))!(!_zstr(tech_pvt->privacy)) ? tag_skip : siptag_privacy_str
, tag_str_v(tech_pvt->privacy)
,
2083 TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info))!(call_info) ? tag_skip : siptag_call_info_str, tag_str_v(call_info
)
,
2084 TAG_IF(!zstr(tech_pvt->route_uri), NUTAG_PROXY(tech_pvt->route_uri))!(!_zstr(tech_pvt->route_uri)) ? tag_skip : ntatag_default_proxy
, urltag_url_v((tech_pvt->route_uri))
,
2085 TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message))!(!(*(message) == '\0')) ? tag_skip : siptag_header_str, tag_str_v
((message))
,
2086 TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via))!(!_zstr(tech_pvt->user_via)) ? tag_skip : siptag_via_str,
tag_str_v(tech_pvt->user_via)
,
2087 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
2088 TAG_END()(tag_type_t)0, (tag_value_t)0);
2089 }
2090
2091 tech_pvt->last_sent_callee_id_name = switch_core_session_strdup(tech_pvt->session, name)switch_core_perform_session_strdup(tech_pvt->session, name
, "mod_sofia.c", (const char *)__func__, 2091)
;
2092 tech_pvt->last_sent_callee_id_number = switch_core_session_strdup(tech_pvt->session, number)switch_core_perform_session_strdup(tech_pvt->session, number
, "mod_sofia.c", (const char *)__func__, 2092)
;
2093
2094
2095 if (switch_event_create(&event, SWITCH_EVENT_CALL_UPDATE)switch_event_create_subclass_detailed("mod_sofia.c", (const char
* )(const char *)__func__, 2095, &event, SWITCH_EVENT_CALL_UPDATE
, ((void*)0))
== SWITCH_STATUS_SUCCESS) {
2096 const char *uuid = switch_channel_get_partner_uuid(channel);
2097 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Direction", "SEND");
2098
2099
2100 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sent-Callee-ID-Name", name);
2101 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Sent-Callee-ID-Number", number);
2102
2103 //switch_channel_set_profile_var(channel, "callee_id_name", name);
2104 //switch_channel_set_profile_var(channel, "callee_id_number", number);
2105
2106 if (uuid) {
2107 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridged-To", uuid);
2108 }
2109 switch_channel_event_set_data(channel, event);
2110 switch_event_fire(&event)switch_event_fire_detailed("mod_sofia.c", (const char * )(const
char *)__func__, 2110, &event, ((void*)0))
;
2111 }
2112 } else {
2113 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 2113, (const char*)(session)
, SWITCH_LOG_DEBUG, "Not sending same id again \"%s\" <%s>\n", name, number);
2114 }
2115 }
2116 }
2117 }
2118 break;
2119
2120 case SWITCH_MESSAGE_INDICATE_HOLD:
2121 {
2122
2123 if (msg->numeric_arg) {
2124 switch_core_media_toggle_hold(session, 1);
2125 } else {
2126
2127 sofia_set_flag_locked(tech_pvt, TFLAG_SIP_HOLD)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != NULL", "mod_sofia.c", 2127, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags[TFLAG_SIP_HOLD] = 1;switch_mutex_unlock
(tech_pvt->flag_mutex);
;
2128 switch_channel_set_flag(channel, CF_LEG_HOLDING)switch_channel_set_flag_value(channel, CF_LEG_HOLDING, 1);
2129 sofia_glue_do_invite(session);
2130 if (!zstr(msg->string_arg)_zstr(msg->string_arg)) {
2131 char message[256] = "";
2132 const char *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent")switch_channel_get_variable_dup(tech_pvt->channel, "sip_user_agent"
, SWITCH_TRUE, -1)
;
2133 const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
2134
2135 if (ua && switch_stristr("snom", ua)) {
2136 snprintf(message, sizeof(message), "From:\r\nTo: \"%s\" %s\r\n", msg->string_arg, tech_pvt->caller_profile->destination_number);
2137 nua_info(tech_pvt->nh, SIPTAG_CONTENT_TYPE_STR("message/sipfrag")siptag_content_type_str, tag_str_v("message/sipfrag"),
2138 TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via))!(!_zstr(tech_pvt->user_via)) ? tag_skip : siptag_via_str,
tag_str_v(tech_pvt->user_via)
,
2139 SIPTAG_PAYLOAD_STR(message)siptag_payload_str, tag_str_v(message),
2140 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
2141 TAG_END()(tag_type_t)0, (tag_value_t)0);
2142 } else if (ua && switch_stristr("polycom", ua)) {
2143 snprintf(message, sizeof(message), "P-Asserted-Identity: \"%s\" <%s>", msg->string_arg, tech_pvt->caller_profile->destination_number);
2144 nua_update(tech_pvt->nh,
2145 NUTAG_SESSION_TIMER(tech_pvt->session_timeout)nutag_session_timer, tag_uint_v((tech_pvt->session_timeout
))
,
2146 NUTAG_SESSION_REFRESHER(tech_pvt->session_refresher)nutag_session_refresher, tag_int_v((tech_pvt->session_refresher
))
,
2147 NUTAG_UPDATE_REFRESH(tech_pvt->update_refresher)nutag_update_refresh, tag_bool_v((tech_pvt->update_refresher
))
,
2148 TAG_IF(!zstr(tech_pvt->route_uri), NUTAG_PROXY(tech_pvt->route_uri))!(!_zstr(tech_pvt->route_uri)) ? tag_skip : ntatag_default_proxy
, urltag_url_v((tech_pvt->route_uri))
,
2149 TAG_IF(!zstr_buf(message), SIPTAG_HEADER_STR(message))!(!(*(message) == '\0')) ? tag_skip : siptag_header_str, tag_str_v
((message))
,
2150 TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via))!(!_zstr(tech_pvt->user_via)) ? tag_skip : siptag_via_str,
tag_str_v(tech_pvt->user_via)
,
2151 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
2152 TAG_END()(tag_type_t)0, (tag_value_t)0);
2153 }
2154 }
2155 }
2156 }
2157 break;
2158
2159 case SWITCH_MESSAGE_INDICATE_UNHOLD:
2160 {
2161 sofia_clear_flag_locked(tech_pvt, TFLAG_SIP_HOLD)switch_mutex_lock(tech_pvt->flag_mutex); (tech_pvt)->flags
[TFLAG_SIP_HOLD] = 0; switch_mutex_unlock(tech_pvt->flag_mutex
);
;
2162 switch_channel_clear_flag(channel, CF_LEG_HOLDING);
2163 sofia_glue_do_invite(session);
2164 }
2165 break;
2166 case SWITCH_MESSAGE_INDICATE_REDIRECT:
2167
2168#define MAX_REDIR128 128
2169
2170 if (!zstr(msg->string_arg)_zstr(msg->string_arg)) {
2171
2172 if (!switch_channel_test_flag(channel, CF_ANSWERED) && !sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0)) {
2173 char *mydest = (char *) msg->string_arg;
2174 char *argv[MAX_REDIR128] = { 0 };
2175 char *mydata = NULL((void*)0), *newdest = NULL((void*)0);
2176 int argc = 0, i;
2177 switch_size_t len = 0;
2178 switch_call_cause_t sip_redirect_cause = SWITCH_CAUSE_NORMAL_UNSPECIFIED;
2179 char *dest = switch_core_session_strdup(session, mydest)switch_core_perform_session_strdup(session, mydest, "mod_sofia.c"
, (const char *)__func__, 2179)
;
2180
2181 if ((argc = switch_separate_string(dest, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 2) {
2182 const char *redirect_cause = argv[1];
2183 sip_redirect_cause = switch_channel_str2cause(redirect_cause);
2184 }
2185
2186 if (strchr(dest, ',')) {
2187 mydata = dest;
2188 len = strlen(mydata) * 2;
2189 newdest = switch_core_session_alloc(session, len)switch_core_perform_session_alloc(session, len, "mod_sofia.c"
, (const char *)__func__, 2189)
;
2190
2191 argc = switch_split(mydata, ',', argv)switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof
(argv[0])))
;
2192
2193 for (i = 0; i < argc; i++) {
2194 if (!strchr(argv[i], '<') && !strchr(argv[i], '>')) {
2195 if (argc > 1) {
2196 if (i == argc - 1) {
2197 switch_snprintf(newdest + strlen(newdest), len - strlen(newdest), "\"unknown\" <%s>;q=%1.3f",
2198 argv[i], (double)((double)(MAX_REDIR128 + 1 - i))/1000);
2199 } else {
2200 switch_snprintf(newdest + strlen(newdest), len - strlen(newdest), "\"unknown\" <%s>;q=%1.3f,",
2201 argv[i], (double)((double)(MAX_REDIR128 + 1 - i))/1000);
2202 }
2203 } else {
2204 if (i == argc - 1) {
2205 switch_snprintf(newdest + strlen(newdest), len - strlen(newdest), "\"unknown\" <%s>", argv[i]);
2206 } else {
2207 switch_snprintf(newdest + strlen(newdest), len - strlen(newdest), "\"unknown\" <%s>,", argv[i]);
2208 }
2209 }
2210 } else {
2211 if (i == argc - 1) {
2212 switch_snprintf(newdest + strlen(newdest), len - strlen(newdest), "%s", argv[i]);
2213 } else {
2214 switch_snprintf(newdest + strlen(newdest), len - strlen(newdest), "%s,", argv[i]);
2215 }
2216 }
2217 }
2218
2219 dest = newdest;
2220 } else {
2221
2222 if (!strchr(dest, '<') && !strchr(dest, '>')) {
2223 dest = switch_core_session_sprintf(session, "\"unknown\" <%s>", dest);
2224 }
2225 }
2226
2227 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 2227, (const char*)(session)
, SWITCH_LOG_DEBUG, "Redirecting to %s\n", dest);
2228
2229 tech_pvt->respond_dest = dest;
2230
2231 if (argc > 1) {
2232 tech_pvt->respond_code = 300;
2233 tech_pvt->respond_phrase = "Multiple Choices";
2234 } else {
2235 tech_pvt->respond_code = 302;
2236 tech_pvt->respond_phrase = "Moved Temporarily";
2237 }
2238
2239 if (sip_redirect_cause == SWITCH_CAUSE_NONE) {
2240 sip_redirect_cause = SWITCH_CAUSE_NORMAL_UNSPECIFIED;
2241 }
2242 switch_channel_hangup(tech_pvt->channel, sip_redirect_cause)switch_channel_perform_hangup(tech_pvt->channel, "mod_sofia.c"
, (const char *)__func__, 2242, sip_redirect_cause)
;
2243
2244 } else {
2245 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 2245, (const char*)(session)
, SWITCH_LOG_WARNING, "Too late for redirecting, already answered\n");
2246
2247 }
2248 }
2249 break;
2250 case SWITCH_MESSAGE_INDICATE_RESPOND:
2251 {
2252 const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
2253
2254 if (switch_channel_test_flag(tech_pvt->channel, CF_AWAITING_STREAM_CHANGE)) {
2255 switch_channel_clear_flag(tech_pvt->channel, CF_AWAITING_STREAM_CHANGE);
2256
2257 switch_core_session_local_crypto_key(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
2258 switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL((void*)0), 0, NULL((void*)0), 0);
2259
2260 if (sofia_use_soa(tech_pvt)((tech_pvt)->flags[TFLAG_ENABLE_SOA] ? 1 : 0)) {
2261 nua_respond(tech_pvt->nh, SIP_200_OK200, sip_200_OK,
2262 SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
2263 SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str)soatag_user_sdp_str, tag_str_v(tech_pvt->mparams.local_sdp_str
)
,
2264 SOATAG_REUSE_REJECTED(1)soatag_reuse_rejected, tag_bool_v(1),
2265 SOATAG_AUDIO_AUX("cn telephone-event")soatag_audio_aux, tag_str_v("cn telephone-event"),
2266 TAG_IF(sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_100REL), NUTAG_INCLUDE_EXTRA_SDP(1))!(((tech_pvt->profile)->pflags[PFLAG_DISABLE_100REL] ? 1
: 0)) ? tag_skip : nutag_include_extra_sdp, tag_bool_v(1)
,
2267 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
2268 TAG_END()(tag_type_t)0, (tag_value_t)0);
2269 } else {
2270 nua_respond(tech_pvt->nh, SIP_200_OK200, sip_200_OK,
2271 NUTAG_MEDIA_ENABLE(0)nutag_media_enable, tag_bool_v(0),
2272 SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
2273 SIPTAG_CONTENT_TYPE_STR("application/sdp")siptag_content_type_str, tag_str_v("application/sdp"),
2274 SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str)siptag_payload_str, tag_str_v(tech_pvt->mparams.local_sdp_str
)
,
2275 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
2276 TAG_END()(tag_type_t)0, (tag_value_t)0);
2277 }
2278 }
2279
2280 if (msg->numeric_arg || msg->string_arg) {
2281 int code = msg->numeric_arg;
2282 const char *reason = NULL((void*)0);
2283
2284 if (code > 0) {
2285 reason = msg->string_arg;
2286 } else {
2287 if (!zstr(msg->string_arg)_zstr(msg->string_arg)) {
2288 if ((code = atoi(msg->string_arg))) {
2289 if ((reason = strchr(msg->string_arg, ' '))) {
2290 reason++;
2291 }
2292 }
2293 }
2294 }
2295
2296 if (!code) {
2297 code = 488;
2298 }
2299
2300 if (!switch_channel_test_flag(channel, CF_ANSWERED) && code >= 300) {
2301 if (sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0)) {
2302 goto end_lock;
2303 }
2304 }
2305
2306 if (zstr(reason)_zstr(reason) && code != 407 && code != 302) {
2307 reason = sip_status_phrase(code);
2308 if (zstr(reason)_zstr(reason)) {
2309 reason = "Because";
2310 }
2311 }
2312
2313 /* Dialplan should really use acknowledge_call application instead of respond application to send 100 */
2314 if (code == 100) {
2315 status = sofia_acknowledge_call(session);
2316 goto end_lock;
2317 }
2318
2319 if (tech_pvt->proxy_refer_uuid) {
2320 if (tech_pvt->proxy_refer_msg) {
2321 nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh)((su_home_t *)(tech_pvt->nh)), reason),
2322 SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
2323 SIPTAG_EXPIRES_STR("60")siptag_expires_str, tag_str_v("60"),
2324 NUTAG_WITH_THIS_MSG(tech_pvt->proxy_refer_msg)nutag_with, tag_ptr_v(tech_pvt->proxy_refer_msg),
2325 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
2326 TAG_END()(tag_type_t)0, (tag_value_t)0);
2327 msg_ref_destroy(tech_pvt->proxy_refer_msg);
2328 tech_pvt->proxy_refer_msg = NULL((void*)0);
2329 }
2330 goto end_lock;
2331 }
2332
2333 if (code == 302 && !zstr(msg->string_arg)_zstr(msg->string_arg)) {
2334 char *p;
2335
2336 if ((p = strchr(msg->string_arg, ' '))) {
2337 *p = '\0';
2338 msg->string_arg = p;
2339 }
2340
2341 msg->message_id = SWITCH_MESSAGE_INDICATE_REDIRECT;
2342 switch_core_session_receive_message(session, msg)switch_core_session_perform_receive_message(session, msg, "mod_sofia.c"
, (const char *)__func__, 2342)
;
2343 goto end_lock;
2344 } else {
2345 if (!sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0)) {
2346 char *extra_headers = sofia_glue_get_extra_headers(channel, SOFIA_SIP_PROGRESS_HEADER_PREFIX"sip_ph_");
2347 char *sdp = (char *) msg->pointer_arg;
2348
2349 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 2349, (const char*)(session)
, SWITCH_LOG_DEBUG, "Responding with %d [%s]\n", code, reason);
2350 sofia_clear_flag(tech_pvt, TFLAG_REINVITED)(tech_pvt)->flags[TFLAG_REINVITED] = 0;
2351
2352 if (!zstr((sdp))_zstr((sdp))) {
2353 if (!strcasecmp(sdp, "t38")) {
2354 switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options");
2355 if (t38_options) {
2356 switch_core_media_set_udptl_image_sdp(tech_pvt->session, t38_options, 0);
2357 if (switch_core_media_ready(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO)) {
2358 switch_channel_clear_flag(tech_pvt->channel, CF_NOTIMER_DURING_BRIDGE);
2359 switch_core_media_udptl_mode(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO);
2360 }
2361 }
2362 } else {
2363 switch_core_media_set_local_sdp(session, sdp, SWITCH_TRUE);
2364 }
2365
2366 if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
2367 switch_core_media_patch_sdp(tech_pvt->session);
2368 switch_core_media_proxy_remote_addr(session, NULL((void*)0));
2369 }
2370
2371 if (sofia_use_soa(tech_pvt)((tech_pvt)->flags[TFLAG_ENABLE_SOA] ? 1 : 0)) {
2372 nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh)((su_home_t *)(tech_pvt->nh)), reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
2373 SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str)soatag_user_sdp_str, tag_str_v(tech_pvt->mparams.local_sdp_str
)
,
2374 SOATAG_REUSE_REJECTED(1)soatag_reuse_rejected, tag_bool_v(1),
2375 SOATAG_AUDIO_AUX("cn telephone-event")soatag_audio_aux, tag_str_v("cn telephone-event"), NUTAG_INCLUDE_EXTRA_SDP(1)nutag_include_extra_sdp, tag_bool_v(1),
2376 TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers))!(!_zstr(extra_headers)) ? tag_skip : siptag_header_str, tag_str_v
((extra_headers))
,
2377 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
2378 TAG_END()(tag_type_t)0, (tag_value_t)0);
2379 } else {
2380 nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh)((su_home_t *)(tech_pvt->nh)), reason), SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
2381 NUTAG_MEDIA_ENABLE(0)nutag_media_enable, tag_bool_v(0),
2382 SIPTAG_CONTENT_TYPE_STR("application/sdp")siptag_content_type_str, tag_str_v("application/sdp"),
2383 SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str)siptag_payload_str, tag_str_v(tech_pvt->mparams.local_sdp_str
)
,
2384 TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers))!(!_zstr(extra_headers)) ? tag_skip : siptag_header_str, tag_str_v
((extra_headers))
,
2385 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
2386 TAG_END()(tag_type_t)0, (tag_value_t)0);
2387 }
2388
2389 if (sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY)((tech_pvt->profile)->pflags[PFLAG_3PCC_PROXY] ? 1 : 0) && sofia_test_flag(tech_pvt, TFLAG_3PCC)((tech_pvt)->flags[TFLAG_3PCC] ? 1 : 0)) {
2390 /* Unlock the session signal to allow the ack to make it in */
2391 // Maybe we should timeout?
2392 switch_mutex_unlock(tech_pvt->sofia_mutex);
2393
2394 while (switch_channel_ready(channel)switch_channel_test_ready(channel, SWITCH_TRUE, SWITCH_FALSE) && !sofia_test_flag(tech_pvt, TFLAG_3PCC_HAS_ACK)((tech_pvt)->flags[TFLAG_3PCC_HAS_ACK] ? 1 : 0)) {
2395 switch_ivr_parse_all_events(session);
2396 switch_yield(10000)switch_sleep(10000);;
2397 }
2398
2399 /* Regain lock on sofia */
2400 switch_mutex_lock(tech_pvt->sofia_mutex);
2401
2402 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 2402, (const char*)(session)
, SWITCH_LOG_DEBUG, "3PCC-PROXY, Done waiting for ACK\n");
2403 sofia_clear_flag(tech_pvt, TFLAG_3PCC)(tech_pvt)->flags[TFLAG_3PCC] = 0;
2404 sofia_clear_flag(tech_pvt, TFLAG_3PCC_HAS_ACK)(tech_pvt)->flags[TFLAG_3PCC_HAS_ACK] = 0;
2405 switch_core_session_pass_indication(session, SWITCH_MESSAGE_INDICATE_ANSWER);
2406 }
2407 } else {
2408 if (msg->numeric_arg && !(switch_channel_test_flag(channel, CF_ANSWERED) && code == 488)) {
2409 if (code > 399) {
2410 switch_call_cause_t cause = sofia_glue_sip_cause_to_freeswitch(code);
2411 if (code == 401 || cause == 407) cause = SWITCH_CAUSE_USER_CHALLENGE;
2412
2413 tech_pvt->respond_code = code;
2414 tech_pvt->respond_phrase = switch_core_session_strdup(tech_pvt->session, reason)switch_core_perform_session_strdup(tech_pvt->session, reason
, "mod_sofia.c", (const char *)__func__, 2414)
;
2415 switch_channel_hangup(tech_pvt->channel, cause)switch_channel_perform_hangup(tech_pvt->channel, "mod_sofia.c"
, (const char *)__func__, 2415, cause)
;
2416 } else {
2417 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 2417, (const char*)(session)
, SWITCH_LOG_WARNING, "Cannot respond.\n");
2418 }
2419 } else {
2420 nua_respond(tech_pvt->nh, code, su_strdup(nua_handle_home(tech_pvt->nh)((su_home_t *)(tech_pvt->nh)), reason),
2421 SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
2422 TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers))!(!_zstr(extra_headers)) ? tag_skip : siptag_header_str, tag_str_v
((extra_headers))
,
2423 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
2424 TAG_END()(tag_type_t)0, (tag_value_t)0);
2425 }
2426
2427 }
2428 switch_safe_free(extra_headers)if (extra_headers) {free(extra_headers);extra_headers=((void*
)0);}
;
2429 }
2430 }
2431
2432 }
2433 }
2434 break;
2435 case SWITCH_MESSAGE_INDICATE_ALERTING:
2436 {
2437 char *extra_header = sofia_glue_get_extra_headers(channel, SOFIA_SIP_PROGRESS_HEADER_PREFIX"sip_ph_");
2438 const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full")switch_channel_get_variable_dup(channel, "presence_call_info_full"
, SWITCH_TRUE, -1)
;
2439 char *cid = generate_pai_str(tech_pvt);
2440 const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
2441
2442 nua_respond(tech_pvt->nh, SIP_180_RINGING180, sip_180_Ringing,
2443 SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
2444 TAG_IF(cid, SIPTAG_HEADER_STR(cid))!(cid) ? tag_skip : siptag_header_str, tag_str_v((cid)),
2445 TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info))!(call_info) ? tag_skip : siptag_call_info_str, tag_str_v(call_info
)
,
2446 TAG_IF(!zstr(extra_header), SIPTAG_HEADER_STR(extra_header))!(!_zstr(extra_header)) ? tag_skip : siptag_header_str, tag_str_v
((extra_header))
,
2447 TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
2448 SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT))!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
,
2449 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
2450 TAG_END()(tag_type_t)0, (tag_value_t)0);
2451 }
2452 break;
2453 case SWITCH_MESSAGE_INDICATE_ACKNOWLEDGE_CALL:
2454 status = sofia_acknowledge_call(session);
2455 break;
2456 case SWITCH_MESSAGE_INDICATE_RINGING:
2457 {
2458 switch_ring_ready_t ring_ready_val = msg->numeric_arg;
2459
2460 if(sofia_acknowledge_call(session) == SWITCH_STATUS_SUCCESS) {
2461 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 2461, (const char*)(session)
, SWITCH_LOG_WARNING, "Dialplan did not acknowledge_call; sent 100 Trying");
2462 }
2463
2464 if (!switch_channel_test_flag(channel, CF_RING_READY) && !sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0) &&
2465 !switch_channel_test_flag(channel, CF_EARLY_MEDIA) && !switch_channel_test_flag(channel, CF_ANSWERED)) {
2466 char *extra_header = sofia_glue_get_extra_headers(channel, SOFIA_SIP_PROGRESS_HEADER_PREFIX"sip_ph_");
2467 const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full")switch_channel_get_variable_dup(channel, "presence_call_info_full"
, SWITCH_TRUE, -1)
;
2468 char *cid = generate_pai_str(tech_pvt);
2469 const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
2470
2471 /* Set sip_to_tag to local tag for inbound channels. */
2472 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
2473 const char* to_tag = "";
2474 to_tag = switch_str_nil(nta_leg_get_tag(nua_get_dialog_state_leg(tech_pvt->nh)))(nta_leg_get_tag(nua_get_dialog_state_leg(tech_pvt->nh)) ?
nta_leg_get_tag(nua_get_dialog_state_leg(tech_pvt->nh)) :
"")
;
2475 if(to_tag) {
2476 switch_channel_set_variable(channel, "sip_to_tag", to_tag)switch_channel_set_variable_var_check(channel, "sip_to_tag", to_tag
, SWITCH_TRUE)
;
2477 }
2478 }
2479
2480 switch (ring_ready_val) {
2481
2482 case SWITCH_RING_READY_QUEUED:
2483
2484 nua_respond(tech_pvt->nh, SIP_182_QUEUED182, sip_182_Queued,
2485 SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
2486 TAG_IF(cid, SIPTAG_HEADER_STR(cid))!(cid) ? tag_skip : siptag_header_str, tag_str_v((cid)),
2487 TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info))!(call_info) ? tag_skip : siptag_call_info_str, tag_str_v(call_info
)
,
2488 TAG_IF(!zstr(extra_header), SIPTAG_HEADER_STR(extra_header))!(!_zstr(extra_header)) ? tag_skip : siptag_header_str, tag_str_v
((extra_header))
,
2489 TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
2490 SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT))!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
,
2491 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
2492 TAG_END()(tag_type_t)0, (tag_value_t)0);
2493 break;
2494
2495 case SWITCH_RING_READY_RINGING:
2496 default:
2497
2498 nua_respond(tech_pvt->nh, SIP_180_RINGING180, sip_180_Ringing,
2499 SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
2500 TAG_IF(cid, SIPTAG_HEADER_STR(cid))!(cid) ? tag_skip : siptag_header_str, tag_str_v((cid)),
2501 TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info))!(call_info) ? tag_skip : siptag_call_info_str, tag_str_v(call_info
)
,
2502 TAG_IF(!zstr(extra_header), SIPTAG_HEADER_STR(extra_header))!(!_zstr(extra_header)) ? tag_skip : siptag_header_str, tag_str_v
((extra_header))
,
2503 TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
2504 SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT))!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
,
2505 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
2506 TAG_END()(tag_type_t)0, (tag_value_t)0);
2507
2508 break;
2509 }
2510
2511
2512 switch_safe_free(extra_header)if (extra_header) {free(extra_header);extra_header=((void*)0)
;}
;
2513 switch_channel_mark_ring_ready(channel)switch_channel_perform_mark_ring_ready_value(channel, SWITCH_RING_READY_RINGING
, "mod_sofia.c", (const char *)__func__, 2513)
;
2514 }
2515 }
2516 break;
2517 case SWITCH_MESSAGE_INDICATE_ANSWER:
2518 status = sofia_answer_channel(session);
2519 break;
2520 case SWITCH_MESSAGE_INDICATE_PROGRESS:
2521 {
2522 char *sticky = NULL((void*)0);
2523 const char *val = NULL((void*)0);
2524 const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full")switch_channel_get_variable_dup(channel, "presence_call_info_full"
, SWITCH_TRUE, -1)
;
2525 const char *b_sdp = NULL((void*)0);
2526 int is_proxy = 0, is_3pcc_proxy = 0;
2527 int send_sip_code = 183;
2528 const char * p_send_sip_msg = sip_183_Session_progress;
2529
2530 if(sofia_acknowledge_call(session) == SWITCH_STATUS_SUCCESS) {
2531 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 2531, (const char*)(session)
, SWITCH_LOG_WARNING, "Dialplan did not acknowledge_call; sent 100 Trying");
2532 }
2533
2534 b_sdp = switch_channel_get_variable(channel, SWITCH_B_SDP_VARIABLE)switch_channel_get_variable_dup(channel, "switch_m_sdp", SWITCH_TRUE
, -1)
;
2535 is_proxy = (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA));
2536 is_3pcc_proxy = (sofia_test_pflag(tech_pvt->profile, PFLAG_3PCC_PROXY)((tech_pvt->profile)->pflags[PFLAG_3PCC_PROXY] ? 1 : 0) && sofia_test_flag(tech_pvt, TFLAG_3PCC)((tech_pvt)->flags[TFLAG_3PCC] ? 1 : 0));
2537
2538 // send 180 instead of 183 if variable "early_use_180" is "true"
2539 if (switch_true(switch_channel_get_variable(channel, "early_use_180")switch_channel_get_variable_dup(channel, "early_use_180", SWITCH_TRUE
, -1)
)) {
2540 send_sip_code = 180;
2541 p_send_sip_msg = sip_180_Ringing;
2542 }
2543
2544 if (b_sdp && is_proxy && !is_3pcc_proxy) {
2545 switch_core_media_set_local_sdp(session, b_sdp, SWITCH_TRUE);
2546
2547 if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
2548 switch_core_media_patch_sdp(tech_pvt->session);
2549 if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
2550 status = SWITCH_STATUS_FALSE;
2551 goto end_lock;
2552 }
2553 }
2554 }
2555
2556 if (!sofia_test_flag(tech_pvt, TFLAG_ANS)((tech_pvt)->flags[TFLAG_ANS] ? 1 : 0) && !sofia_test_flag(tech_pvt, TFLAG_EARLY_MEDIA)((tech_pvt)->flags[TFLAG_EARLY_MEDIA] ? 1 : 0)) {
2557
2558 sofia_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != NULL", "mod_sofia.c", 2558, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags[TFLAG_EARLY_MEDIA] = 1;switch_mutex_unlock
(tech_pvt->flag_mutex);
;
2559 switch_log_printf(SWITCH_CHANNEL_ID_SESSION, msg->_file, msg->_func, msg->_line,
2560 (const char*)session, SWITCH_LOG_INFO, "Sending early media\n");
2561
2562 /* Transmit 183 Progress with SDP */
2563 if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
2564 const char *sdp = NULL((void*)0);
2565 if ((sdp = switch_channel_get_variable(channel, SWITCH_B_SDP_VARIABLE)switch_channel_get_variable_dup(channel, "switch_m_sdp", SWITCH_TRUE
, -1)
)) {
2566 switch_core_media_set_local_sdp(session, sdp, SWITCH_TRUE);
2567 }
2568 if (switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
2569
2570 switch_core_media_patch_sdp(tech_pvt->session);
2571
2572 if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
2573 status = SWITCH_STATUS_FALSE;
2574 goto end_lock;
2575 }
2576 }
2577 } else {
2578 if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION)((tech_pvt)->flags[TFLAG_LATE_NEGOTIATION] ? 1 : 0) ||
2579 switch_core_media_codec_chosen(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO) != SWITCH_STATUS_SUCCESS) {
2580 sofia_clear_flag_locked(tech_pvt, TFLAG_LATE_NEGOTIATION)switch_mutex_lock(tech_pvt->flag_mutex); (tech_pvt)->flags
[TFLAG_LATE_NEGOTIATION] = 0; switch_mutex_unlock(tech_pvt->
flag_mutex);
;
2581 if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
2582 const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE)switch_channel_get_variable_dup(channel, "switch_r_sdp", SWITCH_TRUE
, -1)
;
2583
2584
2585 switch_core_media_prepare_codecs(tech_pvt->session, SWITCH_TRUE);
2586 if (zstr(r_sdp)_zstr(r_sdp) || sofia_media_tech_media(tech_pvt, r_sdp, SDP_TYPE_REQUEST) != SWITCH_STATUS_SUCCESS) {
2587 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 2587, (const char*)(session)
, SWITCH_LOG_WARNING,
2588 "CODEC NEGOTIATION ERROR. SDP:\n%s\n", r_sdp ? r_sdp : "NO SDP!");
2589 switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "CODEC NEGOTIATION ERROR")switch_channel_set_variable_var_check(channel, "endpoint_disposition"
, "CODEC NEGOTIATION ERROR", SWITCH_TRUE)
;
2590 //nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE, TAG_END());
2591 status = SWITCH_STATUS_FALSE;
2592 goto end_lock;
2593 }
2594 }
2595 }
2596
2597 switch_channel_check_zrtp(tech_pvt->channel);
2598
2599 if ((status = switch_core_media_choose_port(tech_pvt->session, SWITCH_MEDIA_TYPE_AUDIO, 0)) != SWITCH_STATUS_SUCCESS) {
2600 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(channel, "mod_sofia.c", (const char
*)__func__, 2600, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)
;
2601 goto end_lock;
2602 }
2603 switch_core_media_gen_local_sdp(session, SDP_TYPE_RESPONSE, NULL((void*)0), 0, NULL((void*)0), 0);
2604 if (sofia_media_activate_rtp(tech_pvt) != SWITCH_STATUS_SUCCESS) {
2605 switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)switch_channel_perform_hangup(channel, "mod_sofia.c", (const char
*)__func__, 2605, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER)
;
2606 }
2607 if (tech_pvt->mparams.local_sdp_str) {
2608 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 2608, (const char*)(session)
, SWITCH_LOG_DEBUG, "Ring SDP:\n%s\n", tech_pvt->mparams.local_sdp_str);
2609 }
2610 }
2611 switch_channel_mark_pre_answered(channel)switch_channel_perform_mark_pre_answered(channel, "mod_sofia.c"
, (const char *)__func__, 2611)
;
2612
2613
2614 if (sofia_test_flag(tech_pvt, TFLAG_NAT)((tech_pvt)->flags[TFLAG_NAT] ? 1 : 0) ||
2615 (val = switch_channel_get_variable(channel, "sip-force-contact")switch_channel_get_variable_dup(channel, "sip-force-contact",
SWITCH_TRUE, -1)
) ||
2616 ((val = switch_channel_get_variable(channel, "sip_sticky_contact")switch_channel_get_variable_dup(channel, "sip_sticky_contact"
, SWITCH_TRUE, -1)
) && switch_true(val))) {
2617 sticky = tech_pvt->record_route;
2618 switch_channel_set_variable(channel, "sip_nat_detected", "true")switch_channel_set_variable_var_check(channel, "sip_nat_detected"
, "true", SWITCH_TRUE)
;
2619 }
2620
2621 if (!sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0)) {
2622 char *extra_header = sofia_glue_get_extra_headers(channel, SOFIA_SIP_PROGRESS_HEADER_PREFIX"sip_ph_");
2623 char *cid = NULL((void*)0);
2624 const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
2625
2626 cid = generate_pai_str(tech_pvt);
2627
2628
2629 if (switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE) &&
2630 tech_pvt->mparams.early_sdp && strcmp(tech_pvt->mparams.early_sdp, tech_pvt->mparams.local_sdp_str)) {
2631 /* The SIP RFC for SOA forbids sending a 183 with one sdp then a 200 with another but it won't do us much good unless
2632 we do so in this case we will abandon the SOA rules and go rogue.
2633 */
2634 sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA)(tech_pvt)->flags[TFLAG_ENABLE_SOA] = 0;
2635 }
2636
2637 tech_pvt->mparams.early_sdp = switch_core_session_strdup(tech_pvt->session, tech_pvt->mparams.local_sdp_str)switch_core_perform_session_strdup(tech_pvt->session, tech_pvt
->mparams.local_sdp_str, "mod_sofia.c", (const char *)__func__
, 2637)
;
2638
2639 if (sofia_use_soa(tech_pvt)((tech_pvt)->flags[TFLAG_ENABLE_SOA] ? 1 : 0)) {
2640 nua_respond(tech_pvt->nh,
2641 send_sip_code, p_send_sip_msg,
2642 NUTAG_AUTOANSWER(0)nutag_autoanswer, tag_bool_v(0),
2643 TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route))!(sticky) ? tag_skip : ntatag_default_proxy, urltag_url_v((tech_pvt
->record_route))
,
2644 TAG_IF(cid, SIPTAG_HEADER_STR(cid))!(cid) ? tag_skip : siptag_header_str, tag_str_v((cid)),
2645 SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
2646 SOATAG_REUSE_REJECTED(1)soatag_reuse_rejected, tag_bool_v(1),
2647 SOATAG_RTP_SELECT(1)soatag_rtp_select, tag_int_v(1),
2648 SOATAG_ADDRESS(tech_pvt->mparams.adv_sdp_audio_ip)soatag_address, tag_str_v(tech_pvt->mparams.adv_sdp_audio_ip
)
,
2649 SOATAG_USER_SDP_STR(tech_pvt->mparams.local_sdp_str)soatag_user_sdp_str, tag_str_v(tech_pvt->mparams.local_sdp_str
)
, SOATAG_AUDIO_AUX("cn telephone-event")soatag_audio_aux, tag_str_v("cn telephone-event"),
2650 TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info))!(call_info) ? tag_skip : siptag_call_info_str, tag_str_v(call_info
)
,
2651 TAG_IF(!zstr(extra_header), SIPTAG_HEADER_STR(extra_header))!(!_zstr(extra_header)) ? tag_skip : siptag_header_str, tag_str_v
((extra_header))
,
2652 TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
2653 SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT))!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
,
2654 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
2655 TAG_END()(tag_type_t)0, (tag_value_t)0);
2656 } else {
2657 nua_respond(tech_pvt->nh,
2658 send_sip_code, p_send_sip_msg,
2659 NUTAG_AUTOANSWER(0)nutag_autoanswer, tag_bool_v(0),
2660 NUTAG_MEDIA_ENABLE(0)nutag_media_enable, tag_bool_v(0),
2661 TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route))!(sticky) ? tag_skip : ntatag_default_proxy, urltag_url_v((tech_pvt
->record_route))
,
2662 TAG_IF(cid, SIPTAG_HEADER_STR(cid))!(cid) ? tag_skip : siptag_header_str, tag_str_v((cid)),
2663 SIPTAG_CONTACT_STR(tech_pvt->reply_contact)siptag_contact_str, tag_str_v(tech_pvt->reply_contact),
2664 SIPTAG_CONTENT_TYPE_STR("application/sdp")siptag_content_type_str, tag_str_v("application/sdp"),
2665 SIPTAG_PAYLOAD_STR(tech_pvt->mparams.local_sdp_str)siptag_payload_str, tag_str_v(tech_pvt->mparams.local_sdp_str
)
,
2666 TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info))!(call_info) ? tag_skip : siptag_call_info_str, tag_str_v(call_info
)
,
2667 TAG_IF(!zstr(extra_header), SIPTAG_HEADER_STR(extra_header))!(!_zstr(extra_header)) ? tag_skip : siptag_header_str, tag_str_v
((extra_header))
,
2668 TAG_IF(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote),!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
2669 SIPTAG_HEADER_STR("X-FS-Support: " FREESWITCH_SUPPORT))!(switch_stristr("update_display", tech_pvt->x_freeswitch_support_remote
)) ? tag_skip : siptag_header_str, tag_str_v(("X-FS-Support: "
"update_display,send_info"))
,
2670 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
2671 TAG_END()(tag_type_t)0, (tag_value_t)0);
2672 }
2673 switch_safe_free(extra_header)if (extra_header) {free(extra_header);extra_header=((void*)0)
;}
;
2674 }
2675 }
2676 }
2677 break;
2678
2679 case SWITCH_MESSAGE_INDICATE_UDPTL_MODE:
2680 {
2681 switch_t38_options_t *t38_options = switch_channel_get_private(channel, "t38_options");
2682
2683 if (!t38_options) {
2684 const char *session_id_header = sofia_glue_session_id_header(tech_pvt->session, tech_pvt->profile);
2685
2686 nua_respond(tech_pvt->nh, SIP_488_NOT_ACCEPTABLE488, sip_488_Not_acceptable, TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
, TAG_END()(tag_type_t)0, (tag_value_t)0);
2687 }
2688 }
2689 break;
2690
2691 case SWITCH_MESSAGE_INDICATE_SESSION_ID:
2692 {
2693 if (sofia_test_pflag(tech_pvt->profile, PFLAG_RFC7989_SESSION_ID)((tech_pvt->profile)->pflags[PFLAG_RFC7989_SESSION_ID] ?
1 : 0)
&& switch_channel_test_flag(channel, CF_ANSWERED)) {
2694 sofia_glue_do_invite(session);
2695 }
2696 }
2697 break;
2698
2699 default:
2700 break;
2701 }
2702
2703 end_lock:
2704
2705 //if (msg->message_id == SWITCH_MESSAGE_INDICATE_ANSWER || msg->message_id == SWITCH_MESSAGE_INDICATE_PROGRESS) {
2706 //sofia_send_callee_id(session, NULL, NULL);
2707 //}
2708
2709 switch_mutex_unlock(tech_pvt->sofia_mutex);
2710
2711 end:
2712
2713 if (switch_channel_down(channel)(switch_channel_check_signal(channel, SWITCH_TRUE) || switch_channel_get_state
(channel) >= CS_HANGUP)
|| sofia_test_flag(tech_pvt, TFLAG_BYE)((tech_pvt)->flags[TFLAG_BYE] ? 1 : 0)) {
2714 status = SWITCH_STATUS_FALSE;
2715 }
2716
2717 return status;
2718
2719}
2720
2721static switch_status_t sofia_receive_event(switch_core_session_t *session, switch_event_t *event)
2722{
2723 struct private_object *tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
2724 char *body;
2725 nua_handle_t *msg_nh;
2726
2727 switch_assert(tech_pvt != NULL)((tech_pvt != ((void*)0)) ? (void) (0) : __assert_fail ("tech_pvt != ((void*)0)"
, "mod_sofia.c", 2727, __extension__ __PRETTY_FUNCTION__))
;
2728
2729 if (!(body = switch_event_get_body(event))) {
2730 body = "";
2731 }
2732
2733 if (tech_pvt->hash_key) {
2734 switch_mutex_lock(tech_pvt->sofia_mutex);
2735 msg_nh = nua_handle(tech_pvt->profile->nua, NULL((void*)0),
2736 SIPTAG_FROM_STR(tech_pvt->chat_from)siptag_from_str, tag_str_v(tech_pvt->chat_from),
2737 NUTAG_URL(tech_pvt->chat_to)nutag_url, urltag_url_v(tech_pvt->chat_to), SIPTAG_TO_STR(tech_pvt->chat_to)siptag_to_str, tag_str_v(tech_pvt->chat_to), TAG_END()(tag_type_t)0, (tag_value_t)0);
2738 nua_handle_bind(msg_nh, &mod_sofia_globals.destroy_private);
2739 nua_message(msg_nh, SIPTAG_CONTENT_TYPE_STR("text/html")siptag_content_type_str, tag_str_v("text/html"), SIPTAG_PAYLOAD_STR(body)siptag_payload_str, tag_str_v(body), TAG_END()(tag_type_t)0, (tag_value_t)0);
2740 switch_mutex_unlock(tech_pvt->sofia_mutex);
2741 }
2742
2743 return SWITCH_STATUS_SUCCESS;
2744}
2745
2746typedef switch_status_t (*sofia_command_t) (char **argv, int argc, switch_stream_handle_t *stream);
2747
2748const char *sofia_state_names[] = {
2749 "UNREGED",
2750 "TRYING",
2751 "REGISTER",
2752 "REGED",
2753 "UNREGISTER",
2754 "FAILED",
2755 "FAIL_WAIT",
2756 "EXPIRED",
2757 "NOREG",
2758 "DOWN",
2759 "TIMEOUT",
2760 NULL((void*)0)
2761};
2762
2763const char *sofia_state_string(int state)
2764{
2765 if (state >= REG_STATE_LAST) return "";
2766
2767 return sofia_state_names[state];
2768}
2769
2770struct cb_helper_sql2str {
2771 char *buf;
2772 size_t len;
2773 int matches;
2774};
2775
2776struct cb_helper {
2777 uint32_t row_process;
2778 sofia_profile_t *profile;
2779 switch_stream_handle_t *stream;
2780 switch_bool_t dedup;
2781};
2782
2783
2784
2785static int show_reg_callback(void *pArg, int argc, char **argv, char **columnNames)
2786{
2787 struct cb_helper *cb = (struct cb_helper *) pArg;
2788 char exp_buf[128] = "";
2789 int exp_secs = 0;
2790 switch_time_exp_t tm;
2791
2792 cb->row_process++;
2793
2794 if (argv[6]) {
2795 time_t now = switch_epoch_time_now(NULL((void*)0));
2796 switch_time_t etime = atoi(argv[6]);
2797 switch_size_t retsize;
2798
2799 exp_secs = (int)(etime - now);
2800 switch_time_exp_lt(&tm, switch_time_from_sec(etime)((switch_time_t)(etime) * 1000000));
2801 switch_strftime_nocheck(exp_buf, &retsize, sizeof(exp_buf), "%Y-%m-%d %T", &tm);
2802 }
2803
2804 cb->stream->write_function(cb->stream,
2805 "Call-ID: \t%s\n"
2806 "User: \t%s@%s\n"
2807 "Contact: \t%s\n"
2808 "Agent: \t%s\n"
2809 "Status: \t%s(%s) EXP(%s) EXPSECS(%d)\n"
2810 "Ping-Status:\t%s\n"
2811 "Ping-Time:\t%0.2f\n"
2812 "Host: \t%s\n"
2813 "IP: \t%s\n"
2814 "Port: \t%s\n"
2815 "Auth-User: \t%s\n"
2816 "Auth-Realm: \t%s\n"
2817 "MWI-Account:\t%s@%s\n\n",
2818 switch_str_nil(argv[0])(argv[0] ? argv[0] : ""), switch_str_nil(argv[1])(argv[1] ? argv[1] : ""), switch_str_nil(argv[2])(argv[2] ? argv[2] : ""), switch_str_nil(argv[3])(argv[3] ? argv[3] : ""),
2819 switch_str_nil(argv[7])(argv[7] ? argv[7] : ""), switch_str_nil(argv[4])(argv[4] ? argv[4] : ""), switch_str_nil(argv[5])(argv[5] ? argv[5] : ""), exp_buf, exp_secs, switch_str_nil(argv[18])(argv[18] ? argv[18] : ""),
2820 (float)atoll(switch_str_nil(argv[19])(argv[19] ? argv[19] : ""))/1000, switch_str_nil(argv[11])(argv[11] ? argv[11] : ""), switch_str_nil(argv[12])(argv[12] ? argv[12] : ""),
2821 switch_str_nil(argv[13])(argv[13] ? argv[13] : ""), switch_str_nil(argv[14])(argv[14] ? argv[14] : ""),
2822 switch_str_nil(argv[15])(argv[15] ? argv[15] : ""), switch_str_nil(argv[16])(argv[16] ? argv[16] : ""), switch_str_nil(argv[17])(argv[17] ? argv[17] : ""));
2823 return 0;
2824}
2825
2826static int show_reg_callback_xml(void *pArg, int argc, char **argv, char **columnNames)
2827{
2828 struct cb_helper *cb = (struct cb_helper *) pArg;
2829 char exp_buf[128] = "";
2830 switch_time_exp_t tm;
2831 const int buflen = 2048;
2832 char xmlbuf[2048];
2833 int exp_secs = 0;
2834
2835 cb->row_process++;
2836
2837 if (argv[6]) {
2838 time_t now = switch_epoch_time_now(NULL((void*)0));
2839 switch_time_t etime = atoi(argv[6]);
2840 switch_size_t retsize;
2841
2842 exp_secs = (int)(etime - now);
2843 switch_time_exp_lt(&tm, switch_time_from_sec(etime)((switch_time_t)(etime) * 1000000));
2844 switch_strftime_nocheck(exp_buf, &retsize, sizeof(exp_buf), "%Y-%m-%d %T", &tm);
2845 }
2846
2847 cb->stream->write_function(cb->stream, " <registration>\n");
2848 cb->stream->write_function(cb->stream, " <call-id>%s</call-id>\n", switch_str_nil(argv[0])(argv[0] ? argv[0] : ""));
2849 cb->stream->write_function(cb->stream, " <user>%s@%s</user>\n", switch_str_nil(argv[1])(argv[1] ? argv[1] : ""), switch_str_nil(argv[2])(argv[2] ? argv[2] : ""));
2850 cb->stream->write_function(cb->stream, " <contact>%s</contact>\n", switch_amp_encode(switch_str_nil(argv[3])(argv[3] ? argv[3] : ""), xmlbuf, buflen));
2851 cb->stream->write_function(cb->stream, " <agent>%s</agent>\n", switch_amp_encode(switch_str_nil(argv[7])(argv[7] ? argv[7] : ""), xmlbuf, buflen));
2852 cb->stream->write_function(cb->stream, " <status>%s(%s) exp(%s) expsecs(%d)</status>\n", switch_str_nil(argv[4])(argv[4] ? argv[4] : ""), switch_str_nil(argv[5])(argv[5] ? argv[5] : ""),
2853 exp_buf, exp_secs);
2854 cb->stream->write_function(cb->stream, " <ping-status>%s</ping-status>\n", switch_str_nil(argv[18])(argv[18] ? argv[18] : ""));
2855 cb->stream->write_function(cb->stream, " <ping-time>%0.2f</ping-time>\n", (float)atoll(switch_str_nil(argv[19])(argv[19] ? argv[19] : ""))/1000);
2856 cb->stream->write_function(cb->stream, " <host>%s</host>\n", switch_str_nil(argv[11])(argv[11] ? argv[11] : ""));
2857 cb->stream->write_function(cb->stream, " <network-ip>%s</network-ip>\n", switch_str_nil(argv[12])(argv[12] ? argv[12] : ""));
2858 cb->stream->write_function(cb->stream, " <network-port>%s</network-port>\n", switch_str_nil(argv[13])(argv[13] ? argv[13] : ""));
2859 cb->stream->write_function(cb->stream, " <sip-auth-user>%s</sip-auth-user>\n",
2860 switch_url_encode(switch_str_nil(argv[14])(argv[14] ? argv[14] : ""), xmlbuf, sizeof(xmlbuf)));
2861 cb->stream->write_function(cb->stream, " <sip-auth-realm>%s</sip-auth-realm>\n", switch_str_nil(argv[15])(argv[15] ? argv[15] : ""));
2862 cb->stream->write_function(cb->stream, " <mwi-account>%s@%s</mwi-account>\n", switch_str_nil(argv[16])(argv[16] ? argv[16] : ""), switch_str_nil(argv[17])(argv[17] ? argv[17] : ""));
2863 cb->stream->write_function(cb->stream, " </registration>\n");
2864
2865 return 0;
2866}
2867
2868static int sql2str_callback(void *pArg, int argc, char **argv, char **columnNames)
2869{
2870 struct cb_helper_sql2str *cbt = (struct cb_helper_sql2str *) pArg;
2871
2872 switch_copy_string(cbt->buf, argv[0], cbt->len);
2873 cbt->matches++;
2874 return 0;
2875}
2876
2877uint32_t sofia_profile_reg_count(sofia_profile_t *profile)
2878{
2879 struct cb_helper_sql2str cb;
2880 char reg_count[80] = "";
2881 char *sql;
2882 cb.buf = reg_count;
2883 cb.len = sizeof(reg_count);
2884 sql = switch_mprintf("select count(*) from sip_registrations where profile_name = '%q'", profile->name);
2885 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sql2str_callback, &cb);
2886 free(sql);
2887 return strtoul(reg_count, NULL((void*)0), 10);
2888}
2889
2890static const char *status_names[] = { "DOWN", "UP", NULL((void*)0) };
2891
2892static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t *stream)
2893{
2894 sofia_profile_t *profile = NULL((void*)0);
2895 sofia_gateway_t *gp;
2896 switch_hash_index_t *hi;
2897 void *val;
2898 const void *vvar;
2899 int c = 0;
2900 int ac = 0;
2901 const char *line = "=================================================================================================";
2902
2903 if (argc > 0) {
2904 if (argc == 1) {
2905 /* show summary of all gateways */
2906
2907 uint32_t ib_failed = 0;
2908 uint32_t ib = 0;
2909 uint32_t ob_failed = 0;
2910 uint32_t ob = 0;
2911
2912 stream->write_function(stream, "%25s\t%32s\t%s\t%9s\t%s\t%s\n", "Profile::Gateway-Name", " Data ", "State", "Ping Time", "IB Calls(F/T)", "OB Calls(F/T)");
2913 stream->write_function(stream, "%s\n", line);
2914 switch_mutex_lock(mod_sofia_globals.hash_mutex);
2915 for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash)switch_core_hash_first_iter(mod_sofia_globals.profile_hash, (
(void*)0))
; hi; hi = switch_core_hash_next(&hi)) {
2916 switch_core_hash_this(hi, &vvar, NULL((void*)0), &val);
2917 profile = (sofia_profile_t *) val;
2918 if (sofia_test_pflag(profile, PFLAG_RUNNING)((profile)->pflags[PFLAG_RUNNING] ? 1 : 0)) {
2919
2920 if (!strcmp(vvar, profile->name)) { /* not an alias */
2921 for (gp = profile->gateways; gp; gp = gp->next) {
2922 char *pkey = switch_mprintf("%s::%s", profile->name, gp->name);
2923
2924 switch_assert(gp->state < REG_STATE_LAST)((gp->state < REG_STATE_LAST) ? (void) (0) : __assert_fail
("gp->state < REG_STATE_LAST", "mod_sofia.c", 2924, __extension__
__PRETTY_FUNCTION__))
;
2925
2926 c++;
2927 ib_failed += gp->ib_failed_calls;
2928 ib += gp->ib_calls;
2929 ob_failed += gp->ob_failed_calls;
2930 ob += gp->ob_calls;
2931
2932 stream->write_function(stream, "%25s\t%32s\t%s\t%6.2f\t%u/%u\t%u/%u",
2933 pkey, gp->register_to, sofia_state_names[gp->state], gp->ping_time,
2934 gp->ib_failed_calls, gp->ib_calls, gp->ob_failed_calls, gp->ob_calls);
2935 free(pkey);
2936
2937 if (gp->state == REG_STATE_FAILED || gp->state == REG_STATE_TRYING) {
2938 time_t now = switch_epoch_time_now(NULL((void*)0));
2939 if (gp->reg_timeout > now) {
2940 stream->write_function(stream, " (retry: %ds)", gp->reg_timeout - now);
2941 } else {
2942 stream->write_function(stream, " (retry: NEVER)");
2943 }
2944 }
2945 stream->write_function(stream, "\n");
2946 }
2947 }
2948 }
2949 }
2950 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
2951 stream->write_function(stream, "%s\n", line);
2952 stream->write_function(stream, "%d gateway%s: Inbound(Failed/Total): %u/%u,"
2953 "Outbound(Failed/Total):%u/%u\n", c, c == 1 ? "" : "s", ib_failed, ib, ob_failed, ob);
2954
2955 return SWITCH_STATUS_SUCCESS;
2956 }
2957
2958 if (!strcasecmp(argv[0], "gateway")) {
2959 if ((gp = sofia_reg_find_gateway(argv[1])sofia_reg_find_gateway__("mod_sofia.c", (const char *)__func__
, 2959, argv[1])
)) {
2960 switch_assert(gp->state < REG_STATE_LAST)((gp->state < REG_STATE_LAST) ? (void) (0) : __assert_fail
("gp->state < REG_STATE_LAST", "mod_sofia.c", 2960, __extension__
__PRETTY_FUNCTION__))
;
2961
2962 stream->write_function(stream, "%s\n", line);
2963 stream->write_function(stream, "Name \t%s\n", switch_str_nil(gp->name)(gp->name ? gp->name : ""));
2964 stream->write_function(stream, "Profile \t%s\n", gp->profile->name);
2965 stream->write_function(stream, "Scheme \t%s\n", switch_str_nil(gp->register_scheme)(gp->register_scheme ? gp->register_scheme : ""));
2966 stream->write_function(stream, "Realm \t%s\n", switch_str_nil(gp->register_realm)(gp->register_realm ? gp->register_realm : ""));
2967 stream->write_function(stream, "Username\t%s\n", switch_str_nil(gp->register_username)(gp->register_username ? gp->register_username : ""));
2968 stream->write_function(stream, "Password\t%s\n", zstr(gp->register_password)_zstr(gp->register_password) ? "no" : "yes");
2969 stream->write_function(stream, "From \t%s\n", switch_str_nil(gp->register_from)(gp->register_from ? gp->register_from : ""));
2970 stream->write_function(stream, "Contact \t%s\n", switch_str_nil(gp->register_contact)(gp->register_contact ? gp->register_contact : ""));
2971 stream->write_function(stream, "Exten \t%s\n", switch_str_nil(gp->extension)(gp->extension ? gp->extension : ""));
2972 stream->write_function(stream, "To \t%s\n", switch_str_nil(gp->register_to)(gp->register_to ? gp->register_to : ""));
2973 stream->write_function(stream, "Proxy \t%s\n", switch_str_nil(gp->register_proxy)(gp->register_proxy ? gp->register_proxy : ""));
2974 stream->write_function(stream, "Context \t%s\n", switch_str_nil(gp->register_context)(gp->register_context ? gp->register_context : ""));
2975 stream->write_function(stream, "Expires \t%s\n", switch_str_nil(gp->expires_str)(gp->expires_str ? gp->expires_str : ""));
2976 stream->write_function(stream, "Freq \t%d\n", gp->freq);
2977 stream->write_function(stream, "Ping \t%d\n", gp->ping);
2978 stream->write_function(stream, "PingFreq\t%d\n", gp->ping_freq);
2979 stream->write_function(stream, "PingTime\t%0.2f\n", gp->ping_time);
2980 stream->write_function(stream, "PingState\t%d/%d/%d\n", gp->ping_min, gp->ping_count, gp->ping_max);
2981 stream->write_function(stream, "State \t%s\n", sofia_state_names[gp->state]);
2982 stream->write_function(stream, "Status \t%s%s\n", status_names[gp->status], gp->pinging ? " (ping)" : "");
2983 stream->write_function(stream, "Uptime \t%lds\n", gp->status == SOFIA_GATEWAY_UP ? (switch_time_now()-gp->uptime)/1000000 : 0);
2984 stream->write_function(stream, "CallsIN \t%u\n", gp->ib_calls);
2985 stream->write_function(stream, "CallsOUT\t%u\n", gp->ob_calls);
2986 stream->write_function(stream, "FailedCallsIN\t%u\n", gp->ib_failed_calls);
2987 stream->write_function(stream, "FailedCallsOUT\t%u\n", gp->ob_failed_calls);
2988 stream->write_function(stream, "%s\n", line);
2989 sofia_reg_release_gateway(gp)sofia_reg_release_gateway__("mod_sofia.c", (const char *)__func__
, 2989, gp);
;
2990 } else {
2991 stream->write_function(stream, "Invalid Gateway!\n");
2992 }
2993 } else if (!strcasecmp(argv[0], "profile")) {
2994 struct cb_helper cb;
2995 char *sql = NULL((void*)0);
2996 uint32_t x = 0;
2997
2998 cb.row_process = 0;
2999
3000
3001 if ((argv[1]) && (profile = sofia_glue_find_profile(argv[1])sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 3001, argv[1])
)) {
3002 if (!argv[2] || (strcasecmp(argv[2], "reg") && strcasecmp(argv[2], "user"))) {
3003 stream->write_function(stream, "%s\n", line);
3004 stream->write_function(stream, "Name \t%s\n", switch_str_nil(argv[1])(argv[1] ? argv[1] : ""));
3005 stream->write_function(stream, "Domain Name \t%s\n", profile->domain_name ? profile->domain_name : "N/A");
3006 if (strcasecmp(argv[1], profile->name)) {
3007 stream->write_function(stream, "Alias Of \t%s\n", switch_str_nil(profile->name)(profile->name ? profile->name : ""));
3008 }
3009 stream->write_function(stream, "Auto-NAT \t%s\n", sofia_test_pflag(profile, PFLAG_AUTO_NAT)((profile)->pflags[PFLAG_AUTO_NAT] ? 1 : 0) ? "true" : "false");
3010 stream->write_function(stream, "DBName \t%s\n", profile->dbname ? profile->dbname : switch_str_nil(profile->odbc_dsn)(profile->odbc_dsn ? profile->odbc_dsn : ""));
3011 stream->write_function(stream, "Pres Hosts \t%s\n", switch_str_nil(profile->presence_hosts)(profile->presence_hosts ? profile->presence_hosts : ""
)
);
3012 stream->write_function(stream, "Dialplan \t%s\n", switch_str_nil(profile->dialplan)(profile->dialplan ? profile->dialplan : ""));
3013 stream->write_function(stream, "Context \t%s\n", switch_str_nil(profile->context)(profile->context ? profile->context : ""));
3014 stream->write_function(stream, "Challenge Realm \t%s\n", zstr(profile->challenge_realm)_zstr(profile->challenge_realm) ? "auto_to" : profile->challenge_realm);
3015
3016 for (x = 0; x < profile->rtpip_index; x++) {
3017 stream->write_function(stream, "RTP-IP \t%s\n", switch_str_nil(profile->rtpip[x])(profile->rtpip[x] ? profile->rtpip[x] : ""));
3018 }
3019
3020 for (x = 0; x < profile->rtpip_index6; x++) {
3021 stream->write_function(stream, "RTP-IP \t%s\n", switch_str_nil(profile->rtpip6[x])(profile->rtpip6[x] ? profile->rtpip6[x] : ""));
3022 }
3023
3024 if (profile->extrtpip) {
3025 stream->write_function(stream, "Ext-RTP-IP \t%s\n", profile->extrtpip);
3026 }
3027
3028 stream->write_function(stream, "SIP-IP \t%s\n", switch_str_nil(profile->sipip)(profile->sipip ? profile->sipip : ""));
3029 if (profile->extsipip) {
3030 stream->write_function(stream, "Ext-SIP-IP \t%s\n", profile->extsipip);
3031 }
3032 if (! sofia_test_pflag(profile, PFLAG_TLS)((profile)->pflags[PFLAG_TLS] ? 1 : 0) || ! profile->tls_only) {
3033 stream->write_function(stream, "URL \t%s\n", switch_str_nil(profile->url)(profile->url ? profile->url : ""));
3034 stream->write_function(stream, "BIND-URL \t%s\n", switch_str_nil(profile->bindurl)(profile->bindurl ? profile->bindurl : ""));
3035 }
3036 if (sofia_test_pflag(profile, PFLAG_TLS)((profile)->pflags[PFLAG_TLS] ? 1 : 0)) {
3037 stream->write_function(stream, "TLS-URL \t%s\n", switch_str_nil(profile->tls_url)(profile->tls_url ? profile->tls_url : ""));
3038 stream->write_function(stream, "TLS-BIND-URL \t%s\n", switch_str_nil(profile->tls_bindurl)(profile->tls_bindurl ? profile->tls_bindurl : ""));
3039 }
3040 if (profile->ws_bindurl) {
3041 stream->write_function(stream, "WS-BIND-URL \t%s\n", switch_str_nil(profile->ws_bindurl)(profile->ws_bindurl ? profile->ws_bindurl : ""));
3042 }
3043 if (profile->wss_bindurl) {
3044 stream->write_function(stream, "WSS-BIND-URL \t%s\n", switch_str_nil(profile->wss_bindurl)(profile->wss_bindurl ? profile->wss_bindurl : ""));
3045 }
3046 stream->write_function(stream, "HOLD-MUSIC \t%s\n", zstr(profile->hold_music)_zstr(profile->hold_music) ? "N/A" : profile->hold_music);
3047 stream->write_function(stream, "OUTBOUND-PROXY \t%s\n", zstr(profile->outbound_proxy)_zstr(profile->outbound_proxy) ? "N/A" : profile->outbound_proxy);
3048 stream->write_function(stream, "CODECS IN \t%s\n", switch_str_nil(profile->inbound_codec_string)(profile->inbound_codec_string ? profile->inbound_codec_string
: "")
);
3049 stream->write_function(stream, "CODECS OUT \t%s\n", switch_str_nil(profile->outbound_codec_string)(profile->outbound_codec_string ? profile->outbound_codec_string
: "")
);
3050
3051 stream->write_function(stream, "TEL-EVENT \t%d\n", profile->te);
3052 if (profile->dtmf_type == DTMF_2833) {
3053 stream->write_function(stream, "DTMF-MODE \trfc2833\n");
3054 } else if (profile->dtmf_type == DTMF_INFO) {
3055 stream->write_function(stream, "DTMF-MODE \tinfo\n");
3056 } else {
3057 stream->write_function(stream, "DTMF-MODE \tnone\n");
3058 }
3059 stream->write_function(stream, "CNG \t%d\n", profile->cng_pt);
3060 stream->write_function(stream, "SESSION-TO \t%d\n", profile->session_timeout);
3061 stream->write_function(stream, "MAX-DIALOG \t%d\n", profile->max_proceeding);
3062 stream->write_function(stream, "NOMEDIA \t%s\n", sofia_test_flag(profile, TFLAG_INB_NOMEDIA)((profile)->flags[TFLAG_INB_NOMEDIA] ? 1 : 0) ? "true" : "false");
3063 stream->write_function(stream, "LATE-NEG \t%s\n", sofia_test_flag(profile, TFLAG_LATE_NEGOTIATION)((profile)->flags[TFLAG_LATE_NEGOTIATION] ? 1 : 0) ? "true" : "false");
3064 stream->write_function(stream, "PROXY-MEDIA \t%s\n", sofia_test_flag(profile, TFLAG_PROXY_MEDIA)((profile)->flags[TFLAG_PROXY_MEDIA] ? 1 : 0) ? "true" : "false");
3065 stream->write_function(stream, "ZRTP-PASSTHRU \t%s\n", sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU)((profile)->flags[TFLAG_ZRTP_PASSTHRU] ? 1 : 0) ? "true" : "false");
3066 stream->write_function(stream, "AGGRESSIVENAT \t%s\n",
3067 sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION)((profile)->pflags[PFLAG_AGGRESSIVE_NAT_DETECTION] ? 1 : 0
)
? "true" : "false");
3068 if (profile->user_agent_filter) {
3069 stream->write_function(stream, "USER-AGENT-FILTER\t%s\n", switch_str_nil(profile->user_agent_filter)(profile->user_agent_filter ? profile->user_agent_filter
: "")
);
3070 }
3071 if (profile->max_registrations_perext > 0) {
3072 stream->write_function(stream, "MAX-REG-PEREXT \t%d\n", profile->max_registrations_perext);
3073 }
3074 stream->write_function(stream, "CALLS-IN \t%u\n", profile->ib_calls);
3075 stream->write_function(stream, "FAILED-CALLS-IN \t%u\n", profile->ib_failed_calls);
3076 stream->write_function(stream, "CALLS-OUT \t%u\n", profile->ob_calls);
3077 stream->write_function(stream, "FAILED-CALLS-OUT \t%u\n", profile->ob_failed_calls);
3078 stream->write_function(stream, "REGISTRATIONS \t%lu\n", sofia_profile_reg_count(profile));
3079 }
3080
3081 cb.profile = profile;
3082 cb.stream = stream;
3083
3084 if (argv[2] && !strcasecmp(argv[2], "pres") && argv[3]) {
3085 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
3086 "rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
3087 "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
3088 " from sip_registrations where profile_name='%q' and presence_hosts like '%%%q%%'", profile->name, argv[3]);
3089 }
3090 if (!sql && argv[2] && !strcasecmp(argv[2], "reg") && argv[3]) {
3091 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
3092 "rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
3093 "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host, ping_status,ping_time"
3094 " from sip_registrations where profile_name='%q' and contact like '%%%q%%'", profile->name, argv[3]);
3095 }
3096 if (!sql && argv[2] && !strcasecmp(argv[2], "reg")) {
3097 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
3098 "rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
3099 "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
3100 " from sip_registrations where profile_name='%q'", profile->name);
3101 }
3102 if (!sql && argv[2] && !strcasecmp(argv[2], "user") && argv[3]) {
3103 char *dup = strdup(argv[3]);
3104 char *host = NULL((void*)0), *user = NULL((void*)0);
3105 char *sqlextra = NULL((void*)0);
3106
3107 switch_assert(dup)((dup) ? (void) (0) : __assert_fail ("dup", "mod_sofia.c", 3107
, __extension__ __PRETTY_FUNCTION__))
;
3108
3109 if ((host = strchr(dup, '@'))) {
3110 *host++ = '\0';
3111 user = dup;
3112 } else {
3113 host = dup;
3114 }
3115
3116 if (zstr(user)_zstr(user)) {
3117 sqlextra = switch_mprintf("(sip_host='%q')", host);
3118 } else if (zstr(host)_zstr(host)) {
3119 sqlextra = switch_mprintf("(sip_user='%q')", user);
3120 } else {
3121 sqlextra = switch_mprintf("(sip_user='%q' and sip_host='%q')", user, host);
3122 }
3123
3124 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
3125 "rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
3126 "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
3127 " from sip_registrations where profile_name='%q' and %s", profile->name, sqlextra);
3128 switch_safe_free(dup)if (dup) {free(dup);dup=((void*)0);};
3129 switch_safe_free(sqlextra)if (sqlextra) {free(sqlextra);sqlextra=((void*)0);};
3130 }
3131
3132 if (sql) {
3133 stream->write_function(stream, "\nRegistrations:\n%s\n", line);
3134
3135 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, show_reg_callback, &cb);
3136 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
3137
3138 stream->write_function(stream, "Total items returned: %d\n", cb.row_process);
3139 stream->write_function(stream, "%s\n", line);
3140 }
3141
3142 sofia_glue_release_profile(profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 3142, profile)
;
3143
3144 } else {
3145 stream->write_function(stream, "Invalid Profile!\n");
3146 }
3147 } else {
3148 stream->write_function(stream, "Invalid Syntax!\n");
3149 }
3150
3151 return SWITCH_STATUS_SUCCESS;
3152 }
3153
3154 stream->write_function(stream, "%25s\t%s\t %40s\t%s\n", "Name", " Type", "Data", "State");
3155 stream->write_function(stream, "%s\n", line);
3156 switch_mutex_lock(mod_sofia_globals.hash_mutex);
3157 for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash)switch_core_hash_first_iter(mod_sofia_globals.profile_hash, (
(void*)0))
; hi; hi = switch_core_hash_next(&hi)) {
3158 switch_core_hash_this(hi, &vvar, NULL((void*)0), &val);
3159 profile = (sofia_profile_t *) val;
3160 if (sofia_test_pflag(profile, PFLAG_RUNNING)((profile)->pflags[PFLAG_RUNNING] ? 1 : 0)) {
3161
3162 if (strcmp(vvar, profile->name)) {
3163 ac++;
3164 stream->write_function(stream, "%25s\t%s\t %40s\t%s\n", vvar, " alias", profile->name, "ALIASED");
3165 } else {
3166 if (! sofia_test_pflag(profile, PFLAG_TLS)((profile)->pflags[PFLAG_TLS] ? 1 : 0) || ! profile->tls_only) {
3167 stream->write_function(stream, "%25s\t%s\t %40s\t%s (%u)\n", profile->name, "profile", profile->url,
3168 sofia_test_pflag(profile, PFLAG_RUNNING)((profile)->pflags[PFLAG_RUNNING] ? 1 : 0) ? "RUNNING" : "DOWN", profile->inuse);
3169 }
3170
3171 if (sofia_test_pflag(profile, PFLAG_TLS)((profile)->pflags[PFLAG_TLS] ? 1 : 0)) {
3172 stream->write_function(stream, "%25s\t%s\t %40s\t%s (%u) (TLS)\n", profile->name, "profile", profile->tls_url,
3173 sofia_test_pflag(profile, PFLAG_RUNNING)((profile)->pflags[PFLAG_RUNNING] ? 1 : 0) ? "RUNNING" : "DOWN", profile->inuse);
3174 }
3175
3176 c++;
3177
3178 for (gp = profile->gateways; gp; gp = gp->next) {
3179 char *pkey = switch_mprintf("%s::%s", profile->name, gp->name);
3180
3181 switch_assert(gp->state < REG_STATE_LAST)((gp->state < REG_STATE_LAST) ? (void) (0) : __assert_fail
("gp->state < REG_STATE_LAST", "mod_sofia.c", 3181, __extension__
__PRETTY_FUNCTION__))
;
3182
3183 stream->write_function(stream, "%25s\t%s\t %40s\t%s", pkey, "gateway", gp->register_to, sofia_state_names[gp->state]);
3184 free(pkey);
3185
3186 if (gp->state == REG_STATE_FAILED || gp->state == REG_STATE_TRYING) {
3187 time_t now = switch_epoch_time_now(NULL((void*)0));
3188 if (gp->retry > now) {
3189 stream->write_function(stream, " (retry: %ds)", gp->retry - now);
3190 } else {
3191 stream->write_function(stream, " (retry: NEVER)");
3192 }
3193 }
3194 stream->write_function(stream, "\n");
3195 }
3196 }
3197 }
3198 }
3199 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
3200 stream->write_function(stream, "%s\n", line);
3201 stream->write_function(stream, "%d profile%s %d alias%s\n", c, c == 1 ? "" : "s", ac, ac == 1 ? "" : "es");
3202 return SWITCH_STATUS_SUCCESS;
3203}
3204
3205static void xml_gateway_status(sofia_gateway_t *gp, switch_stream_handle_t *stream)
3206{
3207 char xmlbuf[2096];
3208 const int buflen = 2096;
3209
3210 stream->write_function(stream, " <gateway>\n");
3211 stream->write_function(stream, " <name>%s</name>\n", switch_str_nil(gp->name)(gp->name ? gp->name : ""));
3212 stream->write_function(stream, " <profile>%s</profile>\n", gp->profile->name);
3213 stream->write_function(stream, " <scheme>%s</scheme>\n", switch_str_nil(gp->register_scheme)(gp->register_scheme ? gp->register_scheme : ""));
3214 stream->write_function(stream, " <realm>%s</realm>\n", switch_str_nil(gp->register_realm)(gp->register_realm ? gp->register_realm : ""));
3215 stream->write_function(stream, " <username>%s</username>\n", switch_str_nil(gp->register_username)(gp->register_username ? gp->register_username : ""));
3216 stream->write_function(stream, " <password>%s</password>\n", zstr(gp->register_password)_zstr(gp->register_password) ? "no" : "yes");
3217 stream->write_function(stream, " <from>%s</from>\n", switch_amp_encode(switch_str_nil(gp->register_from)(gp->register_from ? gp->register_from : ""), xmlbuf, buflen));
3218 stream->write_function(stream, " <contact>%s</contact>\n", switch_amp_encode(switch_str_nil(gp->register_contact)(gp->register_contact ? gp->register_contact : ""), xmlbuf, buflen));
3219 stream->write_function(stream, " <exten>%s</exten>\n", switch_amp_encode(switch_str_nil(gp->extension)(gp->extension ? gp->extension : ""), xmlbuf, buflen));
3220 stream->write_function(stream, " <to>%s</to>\n", switch_str_nil(gp->register_to)(gp->register_to ? gp->register_to : ""));
3221 stream->write_function(stream, " <proxy>%s</proxy>\n", switch_str_nil(gp->register_proxy)(gp->register_proxy ? gp->register_proxy : ""));
3222 stream->write_function(stream, " <context>%s</context>\n", switch_str_nil(gp->register_context)(gp->register_context ? gp->register_context : ""));
3223 stream->write_function(stream, " <expires>%s</expires>\n", switch_str_nil(gp->expires_str)(gp->expires_str ? gp->expires_str : ""));
3224 stream->write_function(stream, " <freq>%d</freq>\n", gp->freq);
3225 stream->write_function(stream, " <ping>%d</ping>\n", gp->ping);
3226 stream->write_function(stream, " <pingfreq>%d</pingfreq>\n", gp->ping_freq);
3227 stream->write_function(stream, " <pingmin>%d</pingmin>\n", gp->ping_min);
3228 stream->write_function(stream, " <pingcount>%d</pingcount>\n", gp->ping_count);
3229 stream->write_function(stream, " <pingmax>%d</pingmax>\n", gp->ping_max);
3230 stream->write_function(stream, " <pingtime>%0.2f</pingtime>\n", gp->ping_time);
3231 stream->write_function(stream, " <pinging>%d</pinging>\n", gp->pinging);
3232 stream->write_function(stream, " <state>%s</state>\n", sofia_state_names[gp->state]);
3233 stream->write_function(stream, " <status>%s</status>\n", status_names[gp->status]);
3234 stream->write_function(stream, " <uptime-usec>%ld</uptime-usec>\n", gp->status == SOFIA_GATEWAY_UP ? switch_time_now()-gp->uptime : 0);
3235 stream->write_function(stream, " <calls-in>%u</calls-in>\n", gp->ib_calls);
3236 stream->write_function(stream, " <calls-out>%u</calls-out>\n", gp->ob_calls);
3237 stream->write_function(stream, " <failed-calls-in>%u</failed-calls-in>\n", gp->ib_failed_calls);
3238 stream->write_function(stream, " <failed-calls-out>%u</failed-calls-out>\n", gp->ob_failed_calls);
3239
3240 if (gp->state == REG_STATE_FAILED || gp->state == REG_STATE_TRYING) {
3241 time_t now = switch_epoch_time_now(NULL((void*)0));
3242 if (gp->retry > now) {
3243 stream->write_function(stream, " <retry>%ds</retry>\n", gp->retry - now);
3244 } else {
3245 stream->write_function(stream, " <retry>NEVER</retry>\n");
3246 }
3247 }
3248
3249 stream->write_function(stream, " </gateway>\n");
3250}
3251
3252static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handle_t *stream)
3253{
3254 sofia_profile_t *profile = NULL((void*)0);
3255 sofia_gateway_t *gp;
3256 switch_hash_index_t *hi;
3257 void *val;
3258 const void *vvar;
3259 int c = 0;
3260 int ac = 0;
3261 const char *header = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>";
3262
3263 if (argc > 0) {
3264 if (argc == 1) {
3265 /* show summary of all gateways */
3266
3267 stream->write_function(stream, "%s\n", header);
3268 stream->write_function(stream, "<gateways>\n", header);
3269
3270 switch_mutex_lock(mod_sofia_globals.hash_mutex);
3271 for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash)switch_core_hash_first_iter(mod_sofia_globals.profile_hash, (
(void*)0))
; hi; hi = switch_core_hash_next(&hi)) {
3272 switch_core_hash_this(hi, &vvar, NULL((void*)0), &val);
3273 profile = (sofia_profile_t *) val;
3274 if (sofia_test_pflag(profile, PFLAG_RUNNING)((profile)->pflags[PFLAG_RUNNING] ? 1 : 0)) {
3275
3276 if (!strcmp(vvar, profile->name)) { /* not an alias */
3277 for (gp = profile->gateways; gp; gp = gp->next) {
3278 switch_assert(gp->state < REG_STATE_LAST)((gp->state < REG_STATE_LAST) ? (void) (0) : __assert_fail
("gp->state < REG_STATE_LAST", "mod_sofia.c", 3278, __extension__
__PRETTY_FUNCTION__))
;
3279
3280 xml_gateway_status(gp, stream);
3281 }
3282 }
3283 }
3284 }
3285 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
3286 stream->write_function(stream, "</gateways>\n");
3287 } else if (!strcasecmp(argv[0], "gateway")) {
3288 if ((gp = sofia_reg_find_gateway(argv[1])sofia_reg_find_gateway__("mod_sofia.c", (const char *)__func__
, 3288, argv[1])
)) {
3289 switch_assert(gp->state < REG_STATE_LAST)((gp->state < REG_STATE_LAST) ? (void) (0) : __assert_fail
("gp->state < REG_STATE_LAST", "mod_sofia.c", 3289, __extension__
__PRETTY_FUNCTION__))
;
3290 stream->write_function(stream, "%s\n", header);
3291 xml_gateway_status(gp, stream);
3292 sofia_reg_release_gateway(gp)sofia_reg_release_gateway__("mod_sofia.c", (const char *)__func__
, 3292, gp);
;
3293 } else {
3294 stream->write_function(stream, "Invalid Gateway!\n");
3295 }
3296 } else if (!strcasecmp(argv[0], "profile")) {
3297 struct cb_helper cb;
3298 char *sql = NULL((void*)0);
3299 uint32_t x = 0;
3300
3301 cb.row_process = 0;
3302
3303 if ((argv[1]) && (profile = sofia_glue_find_profile(argv[1])sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 3303, argv[1])
)) {
3304 stream->write_function(stream, "%s\n", header);
3305 stream->write_function(stream, "<profile>\n");
3306 if (!argv[2] || (strcasecmp(argv[2], "reg") && strcasecmp(argv[2], "user"))) {
3307 stream->write_function(stream, " <profile-info>\n");
3308 stream->write_function(stream, " <name>%s</name>\n", switch_str_nil(argv[1])(argv[1] ? argv[1] : ""));
3309 stream->write_function(stream, " <domain-name>%s</domain-name>\n", profile->domain_name ? profile->domain_name : "N/A");
3310 if (strcasecmp(argv[1], profile->name)) {
3311 stream->write_function(stream, " <alias-of>%s</alias-of>\n", switch_str_nil(profile->name)(profile->name ? profile->name : ""));
3312 }
3313 stream->write_function(stream, " <auto-nat>%s</auto-nat>\n", sofia_test_pflag(profile, PFLAG_AUTO_NAT)((profile)->pflags[PFLAG_AUTO_NAT] ? 1 : 0) ? "true" : "false");
3314 stream->write_function(stream, " <db-name>%s</db-name>\n", profile->dbname ? profile->dbname : switch_str_nil(profile->odbc_dsn)(profile->odbc_dsn ? profile->odbc_dsn : ""));
3315 stream->write_function(stream, " <pres-hosts>%s</pres-hosts>\n", switch_str_nil(profile->presence_hosts)(profile->presence_hosts ? profile->presence_hosts : ""
)
);
3316 stream->write_function(stream, " <dialplan>%s</dialplan>\n", switch_str_nil(profile->dialplan)(profile->dialplan ? profile->dialplan : ""));
3317 stream->write_function(stream, " <context>%s</context>\n", switch_str_nil(profile->context)(profile->context ? profile->context : ""));
3318 stream->write_function(stream, " <challenge-realm>%s</challenge-realm>\n",
3319 zstr(profile->challenge_realm)_zstr(profile->challenge_realm) ? "auto_to" : profile->challenge_realm);
3320 for (x = 0; x < profile->rtpip_index; x++) {
3321 stream->write_function(stream, " <rtp-ip>%s</rtp-ip>\n", switch_str_nil(profile->rtpip[x])(profile->rtpip[x] ? profile->rtpip[x] : ""));
3322 }
3323 for (x = 0; x < profile->rtpip_index6; x++) {
3324 stream->write_function(stream, " <rtp-ip>%s</rtp-ip>\n", switch_str_nil(profile->rtpip6[x])(profile->rtpip6[x] ? profile->rtpip6[x] : ""));
3325 }
3326 if (profile->extrtpip) {
3327 stream->write_function(stream, " <ext-rtp-ip>%s</ext-rtp-ip>\n", profile->extrtpip);
3328 }
3329 stream->write_function(stream, " <sip-ip>%s</sip-ip>\n", switch_str_nil(profile->sipip)(profile->sipip ? profile->sipip : ""));
3330 if (profile->extsipip) {
3331 stream->write_function(stream, " <ext-sip-ip>%s</ext-sip-ip>\n", profile->extsipip);
3332 }
3333 if (! sofia_test_pflag(profile, PFLAG_TLS)((profile)->pflags[PFLAG_TLS] ? 1 : 0) || ! profile->tls_only) {
3334 stream->write_function(stream, " <url>%s</url>\n", switch_str_nil(profile->url)(profile->url ? profile->url : ""));
3335 stream->write_function(stream, " <bind-url>%s</bind-url>\n", switch_str_nil(profile->bindurl)(profile->bindurl ? profile->bindurl : ""));
3336 }
3337 if (sofia_test_pflag(profile, PFLAG_TLS)((profile)->pflags[PFLAG_TLS] ? 1 : 0)) {
3338 stream->write_function(stream, " <tls-url>%s</tls-url>\n", switch_str_nil(profile->tls_url)(profile->tls_url ? profile->tls_url : ""));
3339 stream->write_function(stream, " <tls-bind-url>%s</tls-bind-url>\n", switch_str_nil(profile->tls_bindurl)(profile->tls_bindurl ? profile->tls_bindurl : ""));
3340 }
3341 if (profile->ws_bindurl) {
3342 stream->write_function(stream, " <ws-bind-url>%s</ws-bind-url>\n", switch_str_nil(profile->ws_bindurl)(profile->ws_bindurl ? profile->ws_bindurl : ""));
3343 }
3344 if (profile->wss_bindurl) {
3345 stream->write_function(stream, " <wss-bind-url>%s</wss-bind-url>\n", switch_str_nil(profile->wss_bindurl)(profile->wss_bindurl ? profile->wss_bindurl : ""));
3346 }
3347 stream->write_function(stream, " <hold-music>%s</hold-music>\n", zstr(profile->hold_music)_zstr(profile->hold_music) ? "N/A" : profile->hold_music);
3348 stream->write_function(stream, " <outbound-proxy>%s</outbound-proxy>\n",
3349 zstr(profile->outbound_proxy)_zstr(profile->outbound_proxy) ? "N/A" : profile->outbound_proxy);
3350 stream->write_function(stream, " <inbound-codecs>%s</inbound-codecs>\n", switch_str_nil(profile->inbound_codec_string)(profile->inbound_codec_string ? profile->inbound_codec_string
: "")
);
3351 stream->write_function(stream, " <outbound-codecs>%s</outbound-codecs>\n", switch_str_nil(profile->outbound_codec_string)(profile->outbound_codec_string ? profile->outbound_codec_string
: "")
);
3352
3353 stream->write_function(stream, " <tel-event>%d</tel-event>\n", profile->te);
3354 if (profile->dtmf_type == DTMF_2833) {
3355 stream->write_function(stream, " <dtmf-mode>rfc2833</dtmf-mode>\n");
3356 } else if (profile->dtmf_type == DTMF_INFO) {
3357 stream->write_function(stream, " <dtmf-mode>info</dtmf-mode>\n");
3358 } else {
3359 stream->write_function(stream, " <dtmf-mode>none</dtmf-mode>\n");
3360 }
3361 stream->write_function(stream, " <cng>%d</cng>\n", profile->cng_pt);
3362 stream->write_function(stream, " <session-to>%d</session-to>\n", profile->session_timeout);
3363 stream->write_function(stream, " <max-dialog>%d</max-dialog>\n", profile->max_proceeding);
3364 stream->write_function(stream, " <nomedia>%s</nomedia>\n", sofia_test_flag(profile, TFLAG_INB_NOMEDIA)((profile)->flags[TFLAG_INB_NOMEDIA] ? 1 : 0) ? "true" : "false");
3365 stream->write_function(stream, " <late-neg>%s</late-neg>\n", sofia_test_flag(profile, TFLAG_LATE_NEGOTIATION)((profile)->flags[TFLAG_LATE_NEGOTIATION] ? 1 : 0) ? "true" : "false");
3366 stream->write_function(stream, " <proxy-media>%s</proxy-media>\n", sofia_test_flag(profile, TFLAG_PROXY_MEDIA)((profile)->flags[TFLAG_PROXY_MEDIA] ? 1 : 0) ? "true" : "false");
3367 stream->write_function(stream, " <zrtp-passthru>%s</zrtp-passthru>\n", sofia_test_flag(profile, TFLAG_ZRTP_PASSTHRU)((profile)->flags[TFLAG_ZRTP_PASSTHRU] ? 1 : 0) ? "true" : "false");
3368 stream->write_function(stream, " <aggressive-nat>%s</aggressive-nat>\n",
3369 sofia_test_pflag(profile, PFLAG_AGGRESSIVE_NAT_DETECTION)((profile)->pflags[PFLAG_AGGRESSIVE_NAT_DETECTION] ? 1 : 0
)
? "true" : "false");
3370 if (profile->user_agent_filter) {
3371 stream->write_function(stream, " <user-agent-filter>%s</user-agent-filter>\n", switch_str_nil(profile->user_agent_filter)(profile->user_agent_filter ? profile->user_agent_filter
: "")
);
3372 }
3373 if (profile->max_registrations_perext > 0) {
3374 stream->write_function(stream, " <max-registrations-per-extension>%d</max-registrations-per-extension>\n",
3375 profile->max_registrations_perext);
3376 }
3377 stream->write_function(stream, " <calls-in>%u</calls-in>\n", profile->ib_calls);
3378 stream->write_function(stream, " <calls-out>%u</calls-out>\n", profile->ob_calls);
3379 stream->write_function(stream, " <failed-calls-in>%u</failed-calls-in>\n", profile->ib_failed_calls);
3380 stream->write_function(stream, " <failed-calls-out>%u</failed-calls-out>\n", profile->ob_failed_calls);
3381 stream->write_function(stream, " <registrations>%lu</registrations>\n", sofia_profile_reg_count(profile));
3382 stream->write_function(stream, " </profile-info>\n");
3383 }
3384
3385 cb.profile = profile;
3386 cb.stream = stream;
3387
3388 if (argv[2] && !strcasecmp(argv[2], "pres") && argv[3]) {
3389
3390 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
3391 "rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
3392 "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
3393 " from sip_registrations where profile_name='%q' and presence_hosts like '%%%q%%'", profile->name, argv[3]);
3394 }
3395 if (!sql && argv[2] && !strcasecmp(argv[2], "reg") && argv[3]) {
3396
3397 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
3398 "rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
3399 "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
3400 " from sip_registrations where profile_name='%q' and contact like '%%%q%%'", profile->name, argv[3]);
3401 }
3402 if (!sql && argv[2] && !strcasecmp(argv[2], "reg")) {
3403
3404 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
3405 "rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
3406 "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
3407 " from sip_registrations where profile_name='%q'", profile->name);
3408 }
3409 if (!sql && argv[2] && !strcasecmp(argv[2], "user") && argv[3]) {
3410 char *dup = strdup(argv[3]);
3411 char *host = NULL((void*)0), *user = NULL((void*)0);
3412 char *sqlextra = NULL((void*)0);
3413
3414 switch_assert(dup)((dup) ? (void) (0) : __assert_fail ("dup", "mod_sofia.c", 3414
, __extension__ __PRETTY_FUNCTION__))
;
3415
3416 if ((host = strchr(dup, '@'))) {
3417 *host++ = '\0';
3418 user = dup;
3419 } else {
3420 host = dup;
3421 }
3422
3423 if (zstr(user)_zstr(user)) {
3424 sqlextra = switch_mprintf("(sip_host='%q')", host);
3425 } else if (zstr(host)_zstr(host)) {
3426 sqlextra = switch_mprintf("(sip_user='%q')", user);
3427 } else {
3428 sqlextra = switch_mprintf("(sip_user='%q' and sip_host='%q')", user, host);
3429 }
3430
3431 sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,"
3432 "rpid,expires,user_agent,server_user,server_host,profile_name,hostname,"
3433 "network_ip,network_port,sip_username,sip_realm,mwi_user,mwi_host,ping_status,ping_time"
3434 " from sip_registrations where profile_name='%q' and %s", profile->name, sqlextra);
3435 switch_safe_free(dup)if (dup) {free(dup);dup=((void*)0);};
3436 switch_safe_free(sqlextra)if (sqlextra) {free(sqlextra);sqlextra=((void*)0);};
3437 }
3438
3439 if (sql) {
3440 stream->write_function(stream, " <registrations>\n");
3441
3442 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, show_reg_callback_xml, &cb);
3443 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
3444
3445 stream->write_function(stream, " </registrations>\n");
3446 }
3447
3448 stream->write_function(stream, "</profile>\n");
3449
3450 sofia_glue_release_profile(profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 3450, profile)
;
3451 } else {
3452 stream->write_function(stream, "Invalid Profile!\n");
3453 }
3454 } else {
3455 stream->write_function(stream, "Invalid Syntax!\n");
3456 }
3457
3458 return SWITCH_STATUS_SUCCESS;
3459 }
3460
3461 stream->write_function(stream, "%s\n", header);
3462 stream->write_function(stream, "<profiles>\n");
3463 switch_mutex_lock(mod_sofia_globals.hash_mutex);
3464 for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash)switch_core_hash_first_iter(mod_sofia_globals.profile_hash, (
(void*)0))
; hi; hi = switch_core_hash_next(&hi)) {
3465 switch_core_hash_this(hi, &vvar, NULL((void*)0), &val);
3466 profile = (sofia_profile_t *) val;
3467 if (sofia_test_pflag(profile, PFLAG_RUNNING)((profile)->pflags[PFLAG_RUNNING] ? 1 : 0)) {
3468
3469 if (strcmp(vvar, profile->name)) {
3470 ac++;
3471 stream->write_function(stream, "<alias>\n<name>%s</name>\n<type>%s</type>\n<data>%s</data>\n<state>%s</state>\n</alias>\n", vvar, "alias",
3472 profile->name, "ALIASED");
3473 } else {
3474 if (! sofia_test_pflag(profile, PFLAG_TLS)((profile)->pflags[PFLAG_TLS] ? 1 : 0) || ! profile->tls_only){
3475 stream->write_function(stream, "<profile>\n<name>%s</name>\n<type>%s</type>\n<data>%s</data>\n<state>%s (%u)</state>\n</profile>\n",
3476 profile->name, "profile", profile->url, sofia_test_pflag(profile, PFLAG_RUNNING)((profile)->pflags[PFLAG_RUNNING] ? 1 : 0) ? "RUNNING" : "DOWN",
3477 profile->inuse);
3478 }
3479
3480 if (sofia_test_pflag(profile, PFLAG_TLS)((profile)->pflags[PFLAG_TLS] ? 1 : 0)) {
3481 stream->write_function(stream, "<profile>\n<name>%s</name>\n<type>%s</type>\n<data>%s</data>\n<state>%s (%u) (TLS)</state>\n</profile>\n",
3482 profile->name, "profile", profile->tls_url, sofia_test_pflag(profile, PFLAG_RUNNING)((profile)->pflags[PFLAG_RUNNING] ? 1 : 0) ? "RUNNING" : "DOWN",
3483 profile->inuse);
3484 }
3485 if (profile->ws_bindurl){
3486 stream->write_function(stream, "<profile>\n<name>%s</name>\n<type>%s</type>\n<data>%s</data>\n<state>%s (%u) (WS)</state>\n</profile>\n",
3487 profile->name, "profile", profile->ws_bindurl, sofia_test_pflag(profile, PFLAG_RUNNING)((profile)->pflags[PFLAG_RUNNING] ? 1 : 0) ? "RUNNING" : "DOWN",
3488 profile->inuse);
3489 }
3490 if (profile->wss_bindurl){
3491 stream->write_function(stream, "<profile>\n<name>%s</name>\n<type>%s</type>\n<data>%s</data>\n<state>%s (%u) (WSS)</state>\n</profile>\n",
3492 profile->name, "profile", profile->wss_bindurl, sofia_test_pflag(profile, PFLAG_RUNNING)((profile)->pflags[PFLAG_RUNNING] ? 1 : 0) ? "RUNNING" : "DOWN",
3493 profile->inuse);
3494 }
3495
3496 c++;
3497
3498 for (gp = profile->gateways; gp; gp = gp->next) {
3499 switch_assert(gp->state < REG_STATE_LAST)((gp->state < REG_STATE_LAST) ? (void) (0) : __assert_fail
("gp->state < REG_STATE_LAST", "mod_sofia.c", 3499, __extension__
__PRETTY_FUNCTION__))
;
3500 stream->write_function(stream, "<gateway>\n<name>%s</name>\n<type>%s</type>\n<data>%s</data>\n<state>%s</state>\n</gateway>\n",
3501 gp->name, "gateway", gp->register_to, sofia_state_names[gp->state]);
3502 if (gp->state == REG_STATE_FAILED || gp->state == REG_STATE_TRYING) {
3503 time_t now = switch_epoch_time_now(NULL((void*)0));
3504 if (gp->retry > now) {
3505 stream->write_function(stream, " (retry: %ds)", gp->retry - now);
3506 } else {
3507 stream->write_function(stream, " (retry: NEVER)");
3508 }
3509 }
3510 stream->write_function(stream, "\n");
3511 }
3512 }
3513 }
3514 }
3515 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
3516 stream->write_function(stream, "</profiles>\n");
3517 return SWITCH_STATUS_SUCCESS;
3518}
3519
3520static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t *stream)
3521{
3522 sofia_profile_t *profile = NULL((void*)0);
3523 char *profile_name = argv[0];
3524 const char *err;
3525
3526 if (argc < 2) {
3527 stream->write_function(stream, "Invalid Args!\n");
3528 return SWITCH_STATUS_SUCCESS;
3529 }
3530
3531 if (!strcasecmp(argv[1], "start")) {
3532
3533 switch_xml_reload(&err);
3534 stream->write_function(stream, "Reload XML [%s]\n", err);
3535
3536 if (config_sofia(SOFIA_CONFIG_RESCAN, argv[0]) == SWITCH_STATUS_SUCCESS) {
3537 stream->write_function(stream, "%s started successfully\n", argv[0]);
3538 } else {
3539 stream->write_function(stream, "Failure starting %s\n", argv[0]);
3540 }
3541 return SWITCH_STATUS_SUCCESS;
3542 }
3543
3544 if (argv[1] && !strcasecmp(argv[0], "restart") && !strcasecmp(argv[1], "all")) {
3545 sofia_glue_restart_all_profiles();
3546 return SWITCH_STATUS_SUCCESS;
3547 }
3548
3549 if (zstr(profile_name)_zstr(profile_name) || !(profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 3549, profile_name)
)) {
3550 stream->write_function(stream, "Invalid Profile [%s]", switch_str_nil(profile_name)(profile_name ? profile_name : ""));
3551 return SWITCH_STATUS_SUCCESS;
3552 }
3553
3554 if (!strcasecmp(argv[1], "killgw")) {
3555 sofia_gateway_t *gateway_ptr;
3556 if (argc < 3) {
3557 stream->write_function(stream, "-ERR missing gw name\n");
3558 goto done;
3559 }
3560
3561 if (!strcasecmp(argv[2], "_all_")) {
3562 sofia_glue_del_every_gateway(profile);
3563 stream->write_function(stream, "+OK every gateway marked for deletion.\n");
3564 } else {
3565 if ((gateway_ptr = sofia_reg_find_gateway(argv[2])sofia_reg_find_gateway__("mod_sofia.c", (const char *)__func__
, 3565, argv[2])
)) {
3566 sofia_glue_del_gateway(gateway_ptr);
3567 sofia_reg_release_gateway(gateway_ptr)sofia_reg_release_gateway__("mod_sofia.c", (const char *)__func__
, 3567, gateway_ptr);
;
3568 stream->write_function(stream, "+OK gateway marked for deletion.\n");
3569 } else {
3570 stream->write_function(stream, "-ERR no such gateway.\n");
3571 }
3572 }
3573
3574 goto done;
3575 } else if (!strcasecmp(argv[1], "startgw")) {
3576 if (argc < 3) {
3577 stream->write_function(stream, "-ERR missing gw name\n");
3578 goto done;
3579 }
3580
3581 switch_xml_reload(&err);
3582 stream->write_function(stream, "Reload XML [%s]\n", err);
3583
3584 if (config_gateway(profile->name, argv[2]) == SWITCH_STATUS_SUCCESS) {
3585 stream->write_function(stream, "+OK start gateway %s complete\n", argv[2]);
3586 } else {
3587 stream->write_function(stream, "-ERR cannot add gateway %s for profile %s\n", argv[2], profile->name);
3588 }
3589
3590 goto done;
3591 }
3592
3593 if (!strcasecmp(argv[1], "rescan")) {
3594
3595 switch_xml_reload(&err);
3596 stream->write_function(stream, "Reload XML [%s]\n", err);
3597
3598 if (config_sofia(SOFIA_CONFIG_RESCAN, profile->name) == SWITCH_STATUS_SUCCESS) {
3599 stream->write_function(stream, "+OK scan complete\n");
3600 } else {
3601 stream->write_function(stream, "-ERR cannot find config for profile %s\n", profile->name);
3602 }
3603 goto done;
3604 }
3605
3606 if (!strcasecmp(argv[1], "check_sync")) {
3607 if (argc > 2) {
3608 sofia_reg_check_call_id(profile, argv[2]);
3609 stream->write_function(stream, "+OK syncing all registrations matching specified call_id\n");
3610 } else {
3611 sofia_reg_check_sync(profile);
3612 stream->write_function(stream, "+OK syncing all registrations\n");
3613 }
3614
3615 goto done;
3616 }
3617
3618
3619 if (!strcasecmp(argv[1], "flush_inbound_reg")) {
3620 int reboot = 0;
3621
3622 if (argc > 2) {
3623 if (!strcasecmp(argv[2], "reboot")) {
3624 reboot = 1;
3625 argc = 2;
3626 }
3627 }
3628
3629 if (argc > 2) {
3630 if (argc > 3 && !strcasecmp(argv[3], "reboot")) {
3631 reboot = 1;
3632 }
3633
3634 sofia_reg_expire_call_id(profile, argv[2], reboot);
3635 stream->write_function(stream, "+OK %s all registrations matching specified call_id\n", reboot ? "rebooting" : "flushing");
3636 } else {
3637 sofia_reg_check_expire(profile, 0, reboot);
3638 stream->write_function(stream, "+OK %s all registrations\n", reboot ? "rebooting" : "flushing");
3639 }
3640
3641 goto done;
3642 }
3643
3644 if (!strcasecmp(argv[1], "recover")) {
3645 if (argv[2] && !strcasecmp(argv[2], "flush")) {
3646 sofia_glue_profile_recover(profile, SWITCH_TRUE);
3647
3648 stream->write_function(stream, "Flushing recovery database.\n");
3649 } else {
3650 int x = sofia_glue_profile_recover(profile, SWITCH_FALSE);
3651 if (x) {
3652 stream->write_function(stream, "Recovered %d session(s)\n", x);
3653 } else {
3654 stream->write_function(stream, "No sessions to recover.\n");
3655 }
3656 }
3657
3658 goto done;
3659 }
3660
3661 if (!strcasecmp(argv[1], "register")) {
3662 char *gname = argv[2];
3663 sofia_gateway_t *gateway_ptr;
3664
3665 if (zstr(gname)_zstr(gname)) {
3666 stream->write_function(stream, "No gateway name provided!\n");
3667 goto done;
3668 }
3669
3670 if (!strcasecmp(gname, "all")) {
3671 for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
3672 if (gateway_ptr->state != REG_STATE_NOREG) {
3673 gateway_ptr->retry = 0;
3674 gateway_ptr->state = REG_STATE_UNREGED;
3675 }
3676 }
3677 stream->write_function(stream, "+OK\n");
3678 } else if ((gateway_ptr = sofia_reg_find_gateway(gname)sofia_reg_find_gateway__("mod_sofia.c", (const char *)__func__
, 3678, gname)
)) {
3679 if (gateway_ptr->state != REG_STATE_NOREG) {
3680 gateway_ptr->retry = 0;
3681 gateway_ptr->state = REG_STATE_UNREGED;
3682 stream->write_function(stream, "+OK\n");
3683 sofia_reg_release_gateway(gateway_ptr)sofia_reg_release_gateway__("mod_sofia.c", (const char *)__func__
, 3683, gateway_ptr);
;
3684 } else {
3685 stream->write_function(stream, "-ERR NOREG gateway [%s] can't be registered!\n", gname);
3686 }
3687 } else {
3688 stream->write_function(stream, "Invalid gateway!\n");
3689 }
3690
3691 goto done;
3692 }
3693
3694 if (!strcasecmp(argv[1], "unregister")) {
3695 char *gname = argv[2];
3696 sofia_gateway_t *gateway_ptr;
3697
3698 if (zstr(gname)_zstr(gname)) {
3699 stream->write_function(stream, "No gateway name provided!\n");
3700 goto done;
3701 }
3702
3703 if (!strcasecmp(gname, "all")) {
3704 for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
3705 if (gateway_ptr->state != REG_STATE_NOREG) {
3706 gateway_ptr->retry = 0;
3707 gateway_ptr->state = REG_STATE_UNREGISTER;
3708 }
3709 }
3710 stream->write_function(stream, "+OK\n");
3711 } else if ((gateway_ptr = sofia_reg_find_gateway(gname)sofia_reg_find_gateway__("mod_sofia.c", (const char *)__func__
, 3711, gname)
)) {
3712 if (gateway_ptr->state != REG_STATE_NOREG) {
3713 gateway_ptr->retry = 0;
3714 gateway_ptr->state = REG_STATE_UNREGISTER;
3715 stream->write_function(stream, "+OK\n");
3716 sofia_reg_release_gateway(gateway_ptr)sofia_reg_release_gateway__("mod_sofia.c", (const char *)__func__
, 3716, gateway_ptr);
;
3717 } else {
3718 stream->write_function(stream, "-ERR NOREG gateway [%s] can't be unregistered!\n", gname);
3719 }
3720 } else {
3721 stream->write_function(stream, "Invalid gateway!\n");
3722 }
3723 goto done;
3724 }
3725
3726 if (!strcasecmp(argv[1], "stop") || !strcasecmp(argv[1], "restart")) {
3727 int rsec = 10;
3728 int diff = (int) (switch_epoch_time_now(NULL((void*)0)) - profile->started);
3729 int remain = rsec - diff;
3730 if (diff < rsec) {
3731 stream->write_function(stream, "Profile %s must be up for at least %d seconds to stop/restart.\nPlease wait %d second%s\n",
3732 profile->name, rsec, remain, remain == 1 ? "" : "s");
3733 } else {
3734
3735 switch_xml_reload(&err);
3736 stream->write_function(stream, "Reload XML [%s]\n", err);
3737
3738 if (!strcasecmp(argv[1], "stop")) {
3739 sofia_clear_pflag_locked(profile, PFLAG_RUNNING)switch_mutex_lock(profile->flag_mutex); (profile)->pflags
[PFLAG_RUNNING] = 0; switch_mutex_unlock(profile->flag_mutex
);
;
3740 if (argv[2] && !strcasecmp(argv[2], "wait")) {
3741 int loops = 20 * 2;
3742 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
3742, ((void*)0)
, SWITCH_LOG_NOTICE, "Waiting for %s to finish SIP transactions.\n", profile->name);
3743 while (!sofia_test_pflag(profile, PFLAG_SHUTDOWN)((profile)->pflags[PFLAG_SHUTDOWN] ? 1 : 0)) {
3744 switch_yield(500000)switch_sleep(500000);;
3745 if (!--loops) {
3746 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
3746, ((void*)0)
, SWITCH_LOG_WARNING, "Timeout Waiting for %s to finish SIP transactions.\n", profile->name);
3747 break;
3748 }
3749 }
3750 }
3751 stream->write_function(stream, "stopping: %s", profile->name);
3752 } else {
3753 sofia_set_pflag_locked(profile, PFLAG_RESPAWN)((profile->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("profile->flag_mutex != NULL", "mod_sofia.c", 3753, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(profile->flag_mutex
);(profile)->pflags[PFLAG_RESPAWN] = 1;switch_mutex_unlock
(profile->flag_mutex);
;
3754 sofia_clear_pflag_locked(profile, PFLAG_RUNNING)switch_mutex_lock(profile->flag_mutex); (profile)->pflags
[PFLAG_RUNNING] = 0; switch_mutex_unlock(profile->flag_mutex
);
;
3755 stream->write_function(stream, "restarting: %s", profile->name);
3756 }
3757 }
3758 goto done;
3759 }
3760
3761 if (!strcasecmp(argv[1], "siptrace")) {
3762 if (argc > 2) {
3763 int value = switch_true(argv[2]);
3764 nua_set_params(profile->nua, TPTAG_LOG(value)tptag_log, tag_bool_v((value)), TAG_END()(tag_type_t)0, (tag_value_t)0);
3765 stream->write_function(stream, "%s sip debugging on %s", value ? "Enabled" : "Disabled", profile->name);
3766 } else {
3767 stream->write_function(stream, "Usage: sofia profile <name> siptrace <on/off>\n");
3768 }
3769 goto done;
3770 }
3771
3772 if (!strcasecmp(argv[1], "capture")) {
3773 if (argc > 2) {
3774 int value = switch_true(argv[2]);
3775 nua_set_params(profile->nua, TPTAG_CAPT(value ? mod_sofia_globals.capture_server : NULL)tptag_capt, tag_str_v((value ? mod_sofia_globals.capture_server
: ((void*)0)))
, TAG_END()(tag_type_t)0, (tag_value_t)0);
3776 stream->write_function(stream, "%s sip capturing on %s", value ? "Enabled" : "Disabled", profile->name);
3777 } else {
3778 stream->write_function(stream, "Usage: sofia profile <name> capture <on/off>\n");
3779 }
3780 goto done;
3781 }
3782
3783 if (!strcasecmp(argv[1], "watchdog")) {
3784 if (argc > 2) {
3785 int value = switch_true(argv[2]);
3786 profile->watchdog_enabled = value;
3787 stream->write_function(stream, "%s sip debugging on %s", value ? "Enabled" : "Disabled", profile->name);
3788 } else {
3789 stream->write_function(stream, "Usage: sofia profile <name> watchdog <on/off>\n");
3790 }
3791 goto done;
3792 }
3793
3794
3795 if (!strcasecmp(argv[1], "gwlist")) {
3796 int up = 1;
3797
3798 if (argc > 2) {
3799 if (!strcasecmp(argv[2], "down")) {
3800 up = 0;
3801 }
3802 }
3803
3804 sofia_glue_gateway_list(profile, stream, up);
3805 goto done;
3806 }
3807
3808
3809 stream->write_function(stream, "-ERR Unknown command!\n");
3810
3811 done:
3812 sofia_glue_release_profile(profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 3812, profile)
;
3813
3814 return SWITCH_STATUS_SUCCESS;
3815}
3816
3817static int contact_callback(void *pArg, int argc, char **argv, char **columnNames)
3818{
3819 struct cb_helper *cb = (struct cb_helper *) pArg;
3820 char *contact;
3821
3822 cb->row_process++;
3823
3824 if (!zstr(argv[0])_zstr(argv[0]) && (contact = sofia_glue_get_url_from_contact(argv[0], 1))) {
3825 if (cb->dedup) {
3826 char *tmp = switch_mprintf("%ssofia/%s/sip:%s", argv[2], argv[1], sofia_glue_strip_proto(contact));
3827
3828 if (!strstr((char *)cb->stream->data, tmp)) {
3829 cb->stream->write_function(cb->stream, "%s,", tmp);
3830 }
3831
3832 free(tmp);
3833
3834 } else {
3835 cb->stream->write_function(cb->stream, "%ssofia/%s/sip:%s,", argv[2], argv[1], sofia_glue_strip_proto(contact));
3836 }
3837 free(contact);
3838 }
3839
3840 return 0;
3841}
3842
3843SWITCH_STANDARD_API(sofia_count_reg_function)static switch_status_t sofia_count_reg_function ( const char *
cmd, switch_core_session_t *session, switch_stream_handle_t *
stream)
3844{
3845 char *data;
3846 char *user = NULL((void*)0);
3847 char *domain = NULL((void*)0);
3848 char *concat = NULL((void*)0);
3849 char *profile_name = NULL((void*)0);
3850 char *p;
3851 char *reply = "-1";
3852 sofia_profile_t *profile = NULL((void*)0);
3853
3854 if (!cmd) {
3855 stream->write_function(stream, "%s", "");
3856 return SWITCH_STATUS_SUCCESS;
3857 }
3858
3859 data = strdup(cmd);
3860 switch_assert(data)((data) ? (void) (0) : __assert_fail ("data", "mod_sofia.c", 3860
, __extension__ __PRETTY_FUNCTION__))
;
3861
3862 if ((p = strchr(data, '/'))) {
3863 profile_name = data;
3864 *p++ = '\0';
3865 user = p;
3866 } else {
3867 user = data;
3868 }
3869
3870 if ((domain = strchr(user, '@'))) {
3871 *domain++ = '\0';
3872 if ((concat = strchr(domain, '/'))) {
3873 *concat++ = '\0';
3874 }
3875 } else {
3876 if ((concat = strchr(user, '/'))) {
3877 *concat++ = '\0';
3878 }
3879 }
3880
3881 if (!profile_name && domain) {
3882 profile_name = domain;
3883 }
3884
3885 if (profile_name) {
3886 char *sql;
3887
3888 if (!(profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 3888, profile_name)
)) {
3889 profile_name = domain;
3890 domain = NULL((void*)0);
3891 }
3892
3893 if (!profile && profile_name) {
3894 profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 3894, profile_name)
;
3895 }
3896
3897 if (profile) {
3898 struct cb_helper_sql2str cb;
3899 char reg_count[80] = "";
3900
3901 cb.buf = reg_count;
3902 cb.len = sizeof(reg_count);
3903
3904 if (!domain || !strchr(domain, '.')) {
3905 domain = profile->name;
3906 }
3907
3908 if (zstr(user)_zstr(user)) {
3909 sql = switch_mprintf("select count(*) "
3910 "from sip_registrations where (sip_host='%q' or presence_hosts like '%%%q%%')",
3911 domain, domain);
3912
3913 } else {
3914 sql = switch_mprintf("select count(*) "
3915 "from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
3916 user, domain, domain);
3917 }
3918 switch_assert(sql)((sql) ? (void) (0) : __assert_fail ("sql", "mod_sofia.c", 3918
, __extension__ __PRETTY_FUNCTION__))
;
3919 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sql2str_callback, &cb);
3920 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
3921 if (!zstr(reg_count)_zstr(reg_count)) {
3922 stream->write_function(stream, "%s", reg_count);
3923 } else {
3924 stream->write_function(stream, "0");
3925 }
3926 reply = NULL((void*)0);
3927
3928 }
3929 }
3930
3931 if (reply) {
3932 stream->write_function(stream, "%s", reply);
3933 }
3934
3935 switch_safe_free(data)if (data) {free(data);data=((void*)0);};
3936
3937 if (profile) {
3938 sofia_glue_release_profile(profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 3938, profile)
;
3939 }
3940
3941 return SWITCH_STATUS_SUCCESS;
3942}
3943
3944SWITCH_STANDARD_API(sofia_username_of_function)static switch_status_t sofia_username_of_function ( const char
*cmd, switch_core_session_t *session, switch_stream_handle_t
*stream)
3945{
3946 char *data;
3947 char *user = NULL((void*)0);
3948 char *domain = NULL((void*)0);
3949 char *profile_name = NULL((void*)0);
3950 char *p;
3951 char *reply = "";
3952 sofia_profile_t *profile = NULL((void*)0);
3953
3954 if (!cmd) {
3955 stream->write_function(stream, "%s", "");
3956 return SWITCH_STATUS_SUCCESS;
3957 }
3958
3959 data = strdup(cmd);
3960 switch_assert(data)((data) ? (void) (0) : __assert_fail ("data", "mod_sofia.c", 3960
, __extension__ __PRETTY_FUNCTION__))
;
3961
3962 if ((p = strchr(data, '/'))) {
3963 profile_name = data;
3964 *p++ = '\0';
3965 user = p;
3966 } else {
3967 user = data;
3968 }
3969
3970 if ((domain = strchr(user, '@'))) {
3971 *domain++ = '\0';
3972 }
3973
3974 if (!profile_name && domain) {
3975 profile_name = domain;
3976 }
3977
3978 if (profile_name) {
3979 char *sql;
3980
3981 if (!(profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 3981, profile_name)
)) {
3982 profile_name = domain;
3983 domain = NULL((void*)0);
3984 }
3985
3986 if (!profile && profile_name) {
3987 profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 3987, profile_name)
;
3988 }
3989
3990 if (profile) {
3991 struct cb_helper_sql2str cb;
3992 char username[256] = "";
3993
3994 cb.buf = username;
3995 cb.len = sizeof(username);
3996
3997 if (!domain || !strchr(domain, '.')) {
3998 domain = profile->name;
3999 }
4000
4001 switch_assert(!zstr(user))((!_zstr(user)) ? (void) (0) : __assert_fail ("!_zstr(user)",
"mod_sofia.c", 4001, __extension__ __PRETTY_FUNCTION__))
;
4002
4003 sql = switch_mprintf("select sip_username "
4004 "from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')",
4005 user, domain, domain);
4006
4007 switch_assert(sql)((sql) ? (void) (0) : __assert_fail ("sql", "mod_sofia.c", 4007
, __extension__ __PRETTY_FUNCTION__))
;
4008
4009 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, sql2str_callback, &cb);
4010 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
4011 if (!zstr(username)_zstr(username)) {
4012 stream->write_function(stream, "%s", username);
4013 } else {
4014 stream->write_function(stream, "");
4015 }
4016 reply = NULL((void*)0);
4017
4018 }
4019 }
4020
4021 if (reply) {
4022 stream->write_function(stream, "%s", reply);
4023 }
4024
4025 switch_safe_free(data)if (data) {free(data);data=((void*)0);};
4026
4027 if (profile) {
4028 sofia_glue_release_profile(profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 4028, profile)
;
4029 }
4030
4031 return SWITCH_STATUS_SUCCESS;
4032}
4033
4034static void select_from_profile(sofia_profile_t *profile,
4035 const char *user,
4036 const char *domain,
4037 const char *concat,
4038 const char *exclude_contact,
4039 const char *match_user_agent,
4040 switch_stream_handle_t *stream,
4041 switch_bool_t dedup)
4042{
4043 struct cb_helper cb;
4044 char *sql;
4045 char *sql_match_user_agent = NULL((void*)0);
4046 char *sql_exclude_contact = NULL((void*)0);
4047
4048 cb.row_process = 0;
4049
4050 cb.profile = profile;
4051 cb.stream = stream;
4052 cb.dedup = dedup;
4053
4054 if (match_user_agent) {
4055 sql_match_user_agent = switch_mprintf(" and user_agent like '%%%q%%'", match_user_agent);
4056 }
4057
4058 if (exclude_contact) {
4059 sql_exclude_contact = switch_mprintf(" and contact not like '%%%q%%'", exclude_contact);
4060 }
4061
4062 sql = switch_mprintf("select contact, profile_name, '%q' "
4063 "from sip_registrations where profile_name='%q' "
4064 "and upper(sip_user)=upper('%q') "
4065 "and (sip_host='%q' or presence_hosts like '%%%q%%')%s%s",
4066 (concat != NULL((void*)0)) ? concat : "", profile->name, user, domain, domain, (sql_match_user_agent!=NULL((void*)0)) ? sql_match_user_agent : "", (sql_exclude_contact!=NULL((void*)0)) ? sql_exclude_contact : "");
4067 switch_assert(sql)((sql) ? (void) (0) : __assert_fail ("sql", "mod_sofia.c", 4067
, __extension__ __PRETTY_FUNCTION__))
;
4068 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, contact_callback, &cb);
4069 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
4070 switch_safe_free(sql_exclude_contact)if (sql_exclude_contact) {free(sql_exclude_contact);sql_exclude_contact
=((void*)0);}
;
4071 switch_safe_free(sql_match_user_agent)if (sql_match_user_agent) {free(sql_match_user_agent);sql_match_user_agent
=((void*)0);}
;
4072
4073}
4074
4075SWITCH_STANDARD_API(sofia_contact_function)static switch_status_t sofia_contact_function ( const char *cmd
, switch_core_session_t *session, switch_stream_handle_t *stream
)
4076{
4077 char *data;
4078 char *user = NULL((void*)0);
4079 char *domain = NULL((void*)0), *dup_domain = NULL((void*)0);
4080 char *concat = NULL((void*)0);
4081 char *profile_name = NULL((void*)0);
4082 char *p;
4083
4084 sofia_profile_t *profile = NULL((void*)0);
4085 const char *exclude_contact = NULL((void*)0);
4086 const char *match_user_agent = NULL((void*)0);
4087 char *reply = "error/facility_not_subscribed";
4088 switch_stream_handle_t mystream = { 0 };
4089
4090 if (!cmd) {
4091 stream->write_function(stream, "%s", "");
4092 return SWITCH_STATUS_SUCCESS;
4093 }
4094
4095 if (session) {
4096 switch_channel_t *channel = switch_core_session_get_channel(session);
4097 exclude_contact = switch_channel_get_variable(channel, "sip_exclude_contact")switch_channel_get_variable_dup(channel, "sip_exclude_contact"
, SWITCH_TRUE, -1)
;
4098 match_user_agent = switch_channel_get_variable(channel, "sip_match_user_agent")switch_channel_get_variable_dup(channel, "sip_match_user_agent"
, SWITCH_TRUE, -1)
;
4099 }
4100
4101
4102 data = strdup(cmd);
4103 switch_assert(data)((data) ? (void) (0) : __assert_fail ("data", "mod_sofia.c", 4103
, __extension__ __PRETTY_FUNCTION__))
;
4104
4105 if ((p = strchr(data, '~'))) {
4106 profile_name = data;
4107 *p++ = '\0';
4108 match_user_agent = p;
4109 }
4110
4111 if ((p = strchr(data, '/'))) {
4112 profile_name = data;
4113 *p++ = '\0';
4114 user = p;
4115 } else {
4116 user = data;
4117 }
4118
4119 if ((domain = strchr(user, '@'))) {
4120 *domain++ = '\0';
4121 if ((concat = strchr(domain, '/'))) {
4122 *concat++ = '\0';
4123 }
4124 } else {
4125 if ((concat = strchr(user, '/'))) {
4126 *concat++ = '\0';
4127 }
4128 }
4129
4130 if (zstr(domain)_zstr(domain)) {
4131 dup_domain = switch_core_get_domain(SWITCH_TRUE);
4132 domain = dup_domain;
4133 }
4134
4135 if (zstr(profile_name)_zstr(profile_name) || strcmp(profile_name, "*") || zstr(domain)_zstr(domain)) {
4136 if (!zstr(profile_name)_zstr(profile_name)) {
4137 profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 4137, profile_name)
;
4138 }
4139
4140 if (!profile && !zstr(domain)_zstr(domain)) {
4141 profile = sofia_glue_find_profile(domain)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 4141, domain)
;
4142 }
4143 }
4144
4145 if (profile || !zstr(domain)_zstr(domain)) {
4146 SWITCH_STANDARD_STREAM(mystream)memset(&mystream, 0, sizeof(mystream)); mystream.data = malloc
(1024); ((mystream.data) ? (void) (0) : __assert_fail ("mystream.data"
, "mod_sofia.c", 4146, __extension__ __PRETTY_FUNCTION__)); memset
(mystream.data, 0, 1024); mystream.end = mystream.data; mystream
.data_size = 1024; mystream.write_function = switch_console_stream_write
; mystream.raw_write_function = switch_console_stream_raw_write
; mystream.alloc_len = 1024; mystream.alloc_chunk = 1024
;
4147 switch_assert(mystream.data)((mystream.data) ? (void) (0) : __assert_fail ("mystream.data"
, "mod_sofia.c", 4147, __extension__ __PRETTY_FUNCTION__))
;
4148 }
4149
4150 if (profile) {
4151 if (zstr(domain)_zstr(domain)) {
4152 domain = profile->name;
4153 }
4154
4155 if (!zstr(profile->domain_name)_zstr(profile->domain_name) && !zstr(profile_name)_zstr(profile_name) && !strcmp(profile_name, profile->name)) {
4156 domain = profile->domain_name;
4157 }
4158
4159 select_from_profile(profile, user, domain, concat, exclude_contact, match_user_agent, &mystream, SWITCH_FALSE);
4160 sofia_glue_release_profile(profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 4160, profile)
;
4161
4162 } else if (!zstr(domain)_zstr(domain)) {
4163 sofia_profile_t *profiles[1024] = {0};
4164 uint8_t i = 0, j;
4165 switch_mutex_lock(mod_sofia_globals.hash_mutex);
4166 if (mod_sofia_globals.profile_hash) {
4167 switch_hash_index_t *hi;
4168 const void *var;
4169 void *val;
4170
4171 for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash)switch_core_hash_first_iter(mod_sofia_globals.profile_hash, (
(void*)0))
; hi; hi = switch_core_hash_next(&hi)) {
4172 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
4173 if ((profile = (sofia_profile_t *) val) && !strcmp((char *)var, profile->name)) {
4174 sofia_glue_profile_rdlock(profile)sofia_glue_profile_rdlock__("mod_sofia.c", (const char *)__func__
, 4174, profile)
;
4175 profiles[i++] = profile;
4176 profile = NULL((void*)0);
4177 }
4178 }
4179 }
4180 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
4181 if (i) {
4182 for (j = 0; j < i; j++) {
4183 select_from_profile(profiles[j], user, domain, concat, exclude_contact, match_user_agent, &mystream, SWITCH_TRUE);
4184 sofia_glue_release_profile(profiles[j])sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 4184, profiles[j])
;
4185 }
4186 }
4187 }
4188
4189 reply = (char *) mystream.data;
4190
4191 if (zstr(reply)_zstr(reply)) {
4192 reply = "error/user_not_registered";
4193 } else if (end_of(reply)*(*reply == '\0' ? reply : reply + strlen(reply) - 1) == ',') {
4194 end_of(reply)*(*reply == '\0' ? reply : reply + strlen(reply) - 1) = '\0';
4195 }
4196
4197 stream->write_function(stream, "%s", reply);
4198 reply = NULL((void*)0);
4199
4200 switch_safe_free(mystream.data)if (mystream.data) {free(mystream.data);mystream.data=((void*
)0);}
;
4201
4202 switch_safe_free(data)if (data) {free(data);data=((void*)0);};
4203 switch_safe_free(dup_domain)if (dup_domain) {free(dup_domain);dup_domain=((void*)0);};
4204
4205 return SWITCH_STATUS_SUCCESS;
4206}
4207
4208struct list_result {
4209 int row_process;
4210 int single_col;
4211 switch_stream_handle_t *stream;
4212
4213};
4214static int list_result_callback(void *pArg, int argc, char **argv, char **columnNames)
4215{
4216 struct list_result *cbt = (struct list_result *) pArg;
4217 int i = 0;
4218
4219 cbt->row_process++;
4220
4221 if (cbt->row_process == 1) {
4222 for ( i = 0; i < argc; i++) {
4223 cbt->stream->write_function(cbt->stream,"%s", columnNames[i]);
4224 if (i < argc - 1) {
4225 cbt->stream->write_function(cbt->stream,"|");
4226 }
4227 }
4228 cbt->stream->write_function(cbt->stream,"\n");
4229
4230 }
4231 for ( i = 0; i < argc; i++) {
4232 cbt->stream->write_function(cbt->stream,"%s", zstr(argv[i])_zstr(argv[i]) ? "unknown" : argv[i]);
4233 if (i < argc - 1) {
4234 cbt->stream->write_function(cbt->stream,"|");
4235 }
4236 }
4237 if (!cbt->single_col)
4238 cbt->stream->write_function(cbt->stream,"\n");
4239 return 0;
4240}
4241
4242
4243static void get_presence_data(sofia_profile_t *profile, const char *user, const char *domain, const char *search, switch_stream_handle_t *stream)
4244{
4245 struct list_result cb;
4246 char *sql;
4247 char *select;
4248
4249 cb.row_process = 1;
4250 cb.single_col = 1;
4251 cb.stream = stream;
4252
4253 if (!strcasecmp(search, "status")) {
4254 select = switch_mprintf(" p.status ");
4255 } else if (!strcasecmp(search, "rpid")) {
4256 select = switch_mprintf(" p.rpid ");
4257 } else if (!strcasecmp(search, "user_agent")) {
4258 select = switch_mprintf(" r.user_agent ");
4259 } else {
4260 cb.row_process = 0;
4261 cb.single_col = 0;
4262 select = switch_mprintf(" p.status, p.rpid, r.user_agent, r.network_ip, r.network_port ");
4263 }
4264
4265 sql = switch_mprintf(" select %q from sip_registrations as r left join sip_presence as p "
4266 " on p.sip_host = r.sip_host and p.profile_name = r.profile_name and p.hostname = r.orig_hostname "
4267 " and p.sip_user = r.sip_user "
4268 " where r.sip_realm = '%q' and r.sip_user = '%q' and r.profile_name = '%q' ", select, domain, user, profile->name);
4269
4270 switch_assert(sql)((sql) ? (void) (0) : __assert_fail ("sql", "mod_sofia.c", 4270
, __extension__ __PRETTY_FUNCTION__))
;
4271 sofia_glue_execute_sql_callback(profile, profile->dbh_mutex, sql, list_result_callback, &cb);
4272 switch_safe_free(sql)if (sql) {free(sql);sql=((void*)0);};
4273 switch_safe_free(select)if (select) {free(select);select=((void*)0);};
4274}
4275
4276/* [list|status|rpid|user_agent] [profile/]<user>@domain */
4277SWITCH_STANDARD_API(sofia_presence_data_function)static switch_status_t sofia_presence_data_function ( const char
*cmd, switch_core_session_t *session, switch_stream_handle_t
*stream)
4278{
4279 char *argv[6] = { 0 };
4280 int argc;
4281 char *data;
4282 char *user = NULL((void*)0);
4283 char *domain = NULL((void*)0), *dup_domain = NULL((void*)0);
4284 char *concat = NULL((void*)0);
4285 char *search = NULL((void*)0);
4286 char *profile_name = NULL((void*)0);
4287 char *p;
4288 sofia_profile_t *profile = NULL((void*)0);
4289
4290 if (!cmd) {
4291 stream->write_function(stream, "%s", "");
4292 return SWITCH_STATUS_SUCCESS;
4293 }
4294
4295 data = strdup(cmd);
4296 switch_assert(data)((data) ? (void) (0) : __assert_fail ("data", "mod_sofia.c", 4296
, __extension__ __PRETTY_FUNCTION__))
;
4297
4298
4299 argc = switch_separate_string(data, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
4300 if (argc < 2) {
4301 stream->write_function(stream, "%s", "");
4302 return SWITCH_STATUS_SUCCESS;
4303 }
4304 search = argv[0];
4305
4306 if ((p = strchr(argv[1], '/'))) {
4307 profile_name = argv[1];
4308 *p++ = '\0';
4309 user = p;
4310 } else {
4311 user = argv[1];
4312 }
4313
4314 if ((domain = strchr(user, '@'))) {
4315 *domain++ = '\0';
4316 if ((concat = strchr(domain, '/'))) {
4317 *concat++ = '\0';
4318 }
4319 } else {
4320 if (user && (concat = strchr(user, '/'))) {
4321 *concat++ = '\0';
4322 }
4323 }
4324
4325 if (zstr(domain)_zstr(domain)) {
4326 dup_domain = switch_core_get_domain(SWITCH_TRUE);
4327 domain = dup_domain;
4328 }
4329
4330 if (!user) goto end;
4331
4332 if (zstr(profile_name)_zstr(profile_name) || strcmp(profile_name, "*") || zstr(domain)_zstr(domain)) {
4333 if (!zstr(profile_name)_zstr(profile_name)) {
4334 profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 4334, profile_name)
;
4335 }
4336
4337 if (!profile && !zstr(domain)_zstr(domain)) {
4338 profile = sofia_glue_find_profile(domain)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 4338, domain)
;
4339 }
4340 }
4341
4342 if (profile) {
4343 if (zstr(domain)_zstr(domain)) {
4344 domain = profile->name;
4345 }
4346
4347 if (!zstr(profile->domain_name)_zstr(profile->domain_name) && !zstr(profile_name)_zstr(profile_name) && !strcmp(profile_name, profile->name)) {
4348 domain = profile->domain_name;
4349 }
4350
4351 get_presence_data(profile, user, domain, search, stream);
4352 sofia_glue_release_profile(profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 4352, profile)
;
4353
4354 } else if (!zstr(domain)_zstr(domain)) {
4355 switch_mutex_lock(mod_sofia_globals.hash_mutex);
4356 if (mod_sofia_globals.profile_hash) {
4357 switch_hash_index_t *hi;
4358 const void *var;
4359 void *val;
4360
4361 for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash)switch_core_hash_first_iter(mod_sofia_globals.profile_hash, (
(void*)0))
; hi; hi = switch_core_hash_next(&hi)) {
4362 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
4363 if ((profile = (sofia_profile_t *) val) && !strcmp((char *)var, profile->name)) {
4364 get_presence_data(profile, user, domain, search, stream);
4365 profile = NULL((void*)0);
4366 }
4367 }
4368 }
4369 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
4370 }
4371
4372 if (!strcasecmp(search, "list"))
4373 stream->write_function(stream, "+OK\n");
4374
4375 end:
4376 switch_safe_free(data)if (data) {free(data);data=((void*)0);};
4377 switch_safe_free(dup_domain)if (dup_domain) {free(dup_domain);dup_domain=((void*)0);};
4378
4379 return SWITCH_STATUS_SUCCESS;
4380}
4381
4382/* <gateway_name> [ivar|ovar|var] <name> */
4383SWITCH_STANDARD_API(sofia_gateway_data_function)static switch_status_t sofia_gateway_data_function ( const char
*cmd, switch_core_session_t *session, switch_stream_handle_t
*stream)
4384{
4385 char *argv[4];
4386 char *mydata;
4387 int argc;
4388 sofia_gateway_t *gateway;
4389 char *gwname, *param, *varname;
4390 const char *val = NULL((void*)0);
4391
4392 if (zstr(cmd)_zstr(cmd)) {
4393 stream->write_function(stream, "-ERR Parameter missing\n");
4394 return SWITCH_STATUS_SUCCESS;
4395 }
4396 if (!(mydata = strdup(cmd))) {
4397 return SWITCH_STATUS_FALSE;
4398 }
4399
4400 if (!(argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) || !argv[0]) {
4401 goto end;
4402 }
4403
4404 gwname = argv[0];
4405 param = argv[1];
4406 varname = argv[2];
4407
4408 if (zstr(gwname)_zstr(gwname) || zstr(param)_zstr(param) || zstr(varname)_zstr(varname)) {
4409 goto end;
4410 }
4411
4412 if (!(gateway = sofia_reg_find_gateway(gwname)sofia_reg_find_gateway__("mod_sofia.c", (const char *)__func__
, 4412, gwname)
)) {
4413 goto end;
4414 }
4415
4416 if (!strcasecmp(param, "ivar") && gateway->ib_vars && (val = switch_event_get_header(gateway->ib_vars, varname)switch_event_get_header_idx(gateway->ib_vars, varname, -1))) {
4417 stream->write_function(stream, "%s", val);
4418 } else if (!strcasecmp(param, "ovar") && gateway->ob_vars && (val = switch_event_get_header(gateway->ob_vars, varname)switch_event_get_header_idx(gateway->ob_vars, varname, -1))) {
4419 stream->write_function(stream, "%s", val);
4420 } else if (!strcasecmp(param, "var")) {
4421 if (gateway->ib_vars && (val = switch_event_get_header(gateway->ib_vars, varname)switch_event_get_header_idx(gateway->ib_vars, varname, -1))) {
4422 stream->write_function(stream, "%s", val);
4423 } else if (gateway->ob_vars && (val = switch_event_get_header(gateway->ob_vars, varname)switch_event_get_header_idx(gateway->ob_vars, varname, -1))) {
4424 stream->write_function(stream, "%s", val);
4425 }
4426 }
4427
4428 sofia_reg_release_gateway(gateway)sofia_reg_release_gateway__("mod_sofia.c", (const char *)__func__
, 4428, gateway);
;
4429
4430 end:
4431 switch_safe_free(mydata)if (mydata) {free(mydata);mydata=((void*)0);};
4432 return SWITCH_STATUS_SUCCESS;
4433}
4434
4435SWITCH_STANDARD_API(sofia_function)static switch_status_t sofia_function ( const char *cmd, switch_core_session_t
*session, switch_stream_handle_t *stream)
4436{
4437 char *argv[1024] = { 0 };
4438 int argc = 0;
4439 char *mycmd = NULL((void*)0);
4440 switch_status_t status = SWITCH_STATUS_SUCCESS;
4441 sofia_command_t func = NULL((void*)0);
4442 int lead = 1;
4443 static const char usage_string[] = "USAGE:\n"
4444 "--------------------------------------------------------------------------------\n"
4445 "sofia global siptrace <on|off>\n"
4446 "sofia capture <on|off>\n"
4447 " watchdog <on|off>\n\n"
4448 "sofia profile <name> [start | stop | restart | rescan] [wait]\n"
4449 " flush_inbound_reg [<call_id> | <[user]@domain>] [reboot]\n"
4450 " check_sync [<call_id> | <[user]@domain>]\n"
4451 " [register | unregister] [<gateway name> | all]\n"
4452 " killgw <gateway name>\n"
4453 " [stun-auto-disable | stun-enabled] [true | false]]\n"
4454 " siptrace <on|off>\n"
4455 " capture <on|off>\n"
4456 " watchdog <on|off>\n\n"
4457 "sofia <status|xmlstatus> profile <name> [reg [<contact str>]] | [pres <pres str>] | [user <user@domain>]\n"
4458 "sofia <status|xmlstatus> gateway <name>\n\n"
4459 "sofia loglevel <all|default|tport|iptsec|nea|nta|nth_client|nth_server|nua|soa|sresolv|stun> [0-9]\n"
4460 "sofia tracelevel <console|alert|crit|err|warning|notice|info|debug>\n\n"
4461 "sofia help\n"
4462 "--------------------------------------------------------------------------------\n";
4463
4464 if (zstr(cmd)_zstr(cmd)) {
4465 stream->write_function(stream, "%s", usage_string);
4466 goto done;
4467 }
4468
4469 if (!(mycmd = strdup(cmd))) {
4470 status = SWITCH_STATUS_MEMERR;
4471 goto done;
4472 }
4473
4474 if (!(argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) || !argv[0]) {
4475 stream->write_function(stream, "%s", usage_string);
4476 goto done;
4477 }
4478
4479 if (!strcasecmp(argv[0], "profile")) {
4480 func = cmd_profile;
4481 } else if (!strcasecmp(argv[0], "status")) {
4482 func = cmd_status;
4483 } else if (!strcasecmp(argv[0], "xmlstatus")) {
4484 func = cmd_xml_status;
4485 } else if (!strcasecmp(argv[0], "jsonstatus")) {
4486 func = cmd_json_status;
4487 } else if (!strcasecmp(argv[0], "tracelevel")) {
4488 if (argv[1]) {
4489 mod_sofia_globals.tracelevel = switch_log_str2level(argv[1]);
4490 }
4491 stream->write_function(stream, "+OK tracelevel is %s", switch_log_level2str(mod_sofia_globals.tracelevel));
4492 goto done;
4493 } else if (!strcasecmp(argv[0], "loglevel")) {
4494 if (argc > 2 && argv[2] && switch_is_number(argv[2])) {
4495 int level = atoi(argv[2]);
4496 if (sofia_set_loglevel(argv[1], level) == SWITCH_STATUS_SUCCESS) {
4497 stream->write_function(stream, "Sofia log level for component [%s] has been set to [%d]", argv[1], level);
4498 } else {
4499 stream->write_function(stream, "%s", usage_string);
4500 }
4501 } else if (argc > 1 && argv[1]) {
4502 int level = sofia_get_loglevel(argv[1]);
4503 if (level >= 0) {
4504 stream->write_function(stream, "Sofia-sip loglevel for [%s] is [%d]", argv[1], level);
4505 } else {
4506 stream->write_function(stream, "%s", usage_string);
4507 }
4508 } else {
4509 stream->write_function(stream, "%s", usage_string);
4510 }
4511 goto done;
4512 } else if (!strcasecmp(argv[0], "help")) {
4513 stream->write_function(stream, "%s", usage_string);
4514 goto done;
4515 } else if (!strcasecmp(argv[0], "global")) {
4516 int ston = -1;
4517 int cton = -1;
4518 int wdon = -1;
4519 int stbyon = -1;
4520
4521 if (argc > 1) {
4522 if (!strcasecmp(argv[1], "debug")) {
4523
4524 if (argc > 2) {
4525 if (strstr(argv[2], "presence")) {
4526 mod_sofia_globals.debug_presence = 10;
4527 stream->write_function(stream, "+OK Debugging presence\n");
4528 }
4529
4530 if (strstr(argv[2], "sla")) {
4531 mod_sofia_globals.debug_sla = 10;
4532 stream->write_function(stream, "+OK Debugging sla\n");
4533 }
4534
4535 if (strstr(argv[2], "none")) {
4536 stream->write_function(stream, "+OK Debugging nothing\n");
4537 mod_sofia_globals.debug_presence = 0;
4538 mod_sofia_globals.debug_sla = 0;
4539 }
4540 }
4541
4542 stream->write_function(stream, "+OK Debugging summary: presence: %s sla: %s\n",
4543 mod_sofia_globals.debug_presence ? "on" : "off",
4544 mod_sofia_globals.debug_sla ? "on" : "off");
4545
4546 goto done;
4547 }
4548
4549 if (!strcasecmp(argv[1], "siptrace")) {
4550 if (argc > 2) {
4551 ston = switch_true(argv[2]);
4552 }
4553 }
4554
4555 if (!strcasecmp(argv[1], "standby")) {
4556 if (argc > 2) {
4557 stbyon = switch_true(argv[2]);
4558 }
4559 }
4560
4561 if (!strcasecmp(argv[1], "capture")) {
4562 if (argc > 2) {
4563 cton = switch_true(argv[2]);
4564 }
4565 }
4566
4567 if (!strcasecmp(argv[1], "watchdog")) {
4568 if (argc > 2) {
4569 wdon = switch_true(argv[2]);
4570 }
4571 }
4572 }
4573
4574 if (ston != -1) {
4575 sofia_glue_global_siptrace(ston);
4576 stream->write_function(stream, "+OK Global siptrace %s", ston ? "on" : "off");
4577 } else if (cton != -1) {
4578 sofia_glue_global_capture(cton);
4579 stream->write_function(stream, "+OK Global capture %s", cton ? "on" : "off");
4580 } else if (wdon != -1) {
4581 sofia_glue_global_watchdog(wdon);
4582 stream->write_function(stream, "+OK Global watchdog %s", wdon ? "on" : "off");
4583 } else if (stbyon != -1) {
4584 sofia_glue_global_standby(stbyon);
4585 stream->write_function(stream, "+OK Global standby %s", stbyon ? "on" : "off");
4586 } else {
4587 stream->write_function(stream, "-ERR Usage: siptrace <on|off>|capture <on|off>|watchdog <on|off>|debug <sla|presence|none");
4588 }
4589
4590 goto done;
4591
4592 } else if (!strcasecmp(argv[0], "recover")) {
4593 if (argv[1] && !strcasecmp(argv[1], "flush")) {
4594 sofia_glue_recover(SWITCH_TRUE);
4595 stream->write_function(stream, "Flushing recovery database.\n");
4596 } else {
4597 int x = sofia_glue_recover(SWITCH_FALSE);
4598 switch_event_t *event = NULL((void*)0);
4599
4600 if (x) {
4601 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM,switch_event_create_subclass_detailed("mod_sofia.c", (const char
* )(const char *)__func__, 4602, &event, SWITCH_EVENT_CUSTOM
, "sofia::recovery_recovered")
4602 MY_EVENT_RECOVERY_RECOVERED)switch_event_create_subclass_detailed("mod_sofia.c", (const char
* )(const char *)__func__, 4602, &event, SWITCH_EVENT_CUSTOM
, "sofia::recovery_recovered")
== SWITCH_STATUS_SUCCESS) {
4603 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "recovered_calls", "%d", x);
4604 switch_event_fire(&event)switch_event_fire_detailed("mod_sofia.c", (const char * )(const
char *)__func__, 4604, &event, ((void*)0))
;
4605 }
4606
4607 stream->write_function(stream, "Recovered %d call(s)\n", x);
4608 } else {
4609 if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM,switch_event_create_subclass_detailed("mod_sofia.c", (const char
* )(const char *)__func__, 4610, &event, SWITCH_EVENT_CUSTOM
, "sofia::recovery_recovered")
4610 MY_EVENT_RECOVERY_RECOVERED)switch_event_create_subclass_detailed("mod_sofia.c", (const char
* )(const char *)__func__, 4610, &event, SWITCH_EVENT_CUSTOM
, "sofia::recovery_recovered")
== SWITCH_STATUS_SUCCESS) {
4611 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "recovered_calls", "0");
4612 switch_event_fire(&event)switch_event_fire_detailed("mod_sofia.c", (const char * )(const
char *)__func__, 4612, &event, ((void*)0))
;
4613 }
4614
4615 stream->write_function(stream, "No calls to recover.\n");
4616 }
4617 }
4618
4619 goto done;
4620 }
4621
4622 if (func) {
4623 status = func(&argv[lead], argc - lead, stream);
4624 } else {
4625 stream->write_function(stream, "Unknown Command [%s]\n", argv[0]);
4626 }
4627
4628 done:
4629 switch_safe_free(mycmd)if (mycmd) {free(mycmd);mycmd=((void*)0);};
4630 return status;
4631}
4632
4633switch_io_routines_t sofia_io_routines = {
4634 /*.outgoing_channel */ sofia_outgoing_channel,
4635 /*.read_frame */ sofia_read_frame,
4636 /*.write_frame */ sofia_write_frame,
4637 /*.kill_channel */ sofia_kill_channel,
4638 /*.send_dtmf */ sofia_send_dtmf,
4639 /*.receive_message */ sofia_receive_message,
4640 /*.receive_event */ sofia_receive_event,
4641 /*.state_change */ NULL((void*)0),
4642 /*.read_video_frame */ sofia_read_video_frame,
4643 /*.write_video_frame */ sofia_write_video_frame,
4644 /*.read_text_frame */ sofia_read_text_frame,
4645 /*.write_text_frame */ sofia_write_text_frame,
4646 /*.state_run*/ NULL((void*)0),
4647 /*.get_jb*/ sofia_get_jb
4648};
4649
4650switch_state_handler_table_t sofia_event_handlers = {
4651 /*.on_init */ sofia_on_init,
4652 /*.on_routing */ sofia_on_routing,
4653 /*.on_execute */ sofia_on_execute,
4654 /*.on_hangup */ sofia_on_hangup,
4655 /*.on_exchange_media */ sofia_on_exchange_media,
4656 /*.on_soft_execute */ sofia_on_soft_execute,
4657 /*.on_consume_media */ NULL((void*)0),
4658 /*.on_hibernate */ sofia_on_hibernate,
4659 /*.on_reset */ sofia_on_reset,
4660 /*.on_park */ NULL((void*)0),
4661 /*.on_reporting */ NULL((void*)0),
4662 /*.on_destroy */ sofia_on_destroy
4663};
4664
4665static switch_status_t sofia_manage(char *relative_oid, switch_management_action_t action, char *data, switch_size_t datalen)
4666{
4667 return SWITCH_STATUS_SUCCESS;
4668}
4669
4670static int protect_dest_uri(switch_caller_profile_t *cp)
4671{
4672 char *p = cp->destination_number, *o = p;
4673 char *q = NULL((void*)0), *e = NULL((void*)0), *qenc = NULL((void*)0);
4674 switch_size_t enclen = 0;
4675 int mod = 0;
4676
4677 if (!(e = strchr(p, '@'))) {
4678 return 0;
4679 }
4680
4681 while((p = strchr(p, '/'))) {
4682 q = p++;
4683 }
4684
4685 if (q) {
4686 const char *i;
4687 int go = 0;
4688
4689 for (i = q+1; i && *i && *i != '@'; i++) {
4690 if (strchr(SWITCH_URL_UNSAFE"\r\n #%&+:;<=>?@[\\]^`{|}\"", *i)) {
4691 go = 1;
4692 }
4693 }
4694
4695 if (!go) return 0;
4696
4697 *q++ = '\0';
4698 } else {
4699 return 0;
4700 }
4701
4702 if (!strncasecmp(q, "sips:", 5)) {
4703 q += 5;
4704 } else if (!strncasecmp(q, "sip:", 4)) {
4705 q += 4;
4706 }
4707
4708 if (!(e = strchr(q, '@'))) {
4709 return 0;
4710 }
4711
4712 *e++ = '\0';
4713
4714 if (switch_needs_url_encode(q)) {
4715 enclen = (strlen(q) * 3) + 2;
4716 qenc = switch_core_alloc(cp->pool, enclen)switch_core_perform_alloc(cp->pool, enclen, "mod_sofia.c",
(const char *)__func__, 4716)
;
4717 switch_url_encode(q, qenc, enclen);
4718 mod = 1;
4719 }
4720
4721 cp->destination_number = switch_core_sprintf(cp->pool, "%s/%s@%s", o, qenc ? qenc : q, e);
4722
4723 return mod;
4724}
4725
4726static switch_call_cause_t sofia_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
4727 switch_caller_profile_t *outbound_profile, switch_core_session_t **new_session,
4728 switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
4729{
4730 switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
4731 switch_core_session_t *nsession = NULL((void*)0);
4732 char *data, *profile_name, *dest; //, *dest_num = NULL;
4733 sofia_profile_t *profile = NULL((void*)0);
4734 switch_caller_profile_t *caller_profile = NULL((void*)0);
4735 private_object_t *tech_pvt = NULL((void*)0);
4736 switch_channel_t *nchannel;
4737 char *host = NULL((void*)0), *dest_to = NULL((void*)0);
4738 const char *hval = NULL((void*)0);
4739 char *not_const = NULL((void*)0);
4740 int cid_locked = 0;
4741 switch_channel_t *o_channel = NULL((void*)0);
4742 sofia_gateway_t *gateway_ptr = NULL((void*)0);
4743 int mod = 0;
4744
4745 *new_session = NULL((void*)0);
4746
4747 if (!outbound_profile || zstr(outbound_profile->destination_number)_zstr(outbound_profile->destination_number)) {
1
Assuming 'outbound_profile' is non-null
2
Taking false branch
4748 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
4748, ((void*)0)
, SWITCH_LOG_CRIT, "Invalid Empty Destination\n");
4749 goto error;
4750 }
4751
4752 if (!switch_true(switch_event_get_header(var_event, "sofia_suppress_url_encoding")switch_event_get_header_idx(var_event, "sofia_suppress_url_encoding"
, -1)
)) {
3
Taking false branch
4753 mod = protect_dest_uri(outbound_profile);
4754 }
4755
4756 if (!(nsession = switch_core_session_request_uuid(sofia_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND,
4
Assuming 'nsession' is not null
5
Taking false branch
4757 flags, pool, switch_event_get_header(var_event, "origination_uuid")switch_event_get_header_idx(var_event, "origination_uuid", -1
)
))) {
4758 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
4758, ((void*)0)
, SWITCH_LOG_CRIT, "Error Creating Session\n");
4759 goto error;
4760 }
4761
4762 tech_pvt = sofia_glue_new_pvt(nsession);
4763
4764 data = switch_core_session_strdup(nsession, outbound_profile->destination_number)switch_core_perform_session_strdup(nsession, outbound_profile
->destination_number, "mod_sofia.c", (const char *)__func__
, 4764)
;
4765 if ((dest_to = strchr(data, '^'))) {
6
Assuming 'dest_to' is null
7
Taking false branch
4766 *dest_to++ = '\0';
4767 }
4768 profile_name = data;
4769
4770 nchannel = switch_core_session_get_channel(nsession);
4771
4772 if (session) {
8
Assuming 'session' is null
9
Taking false branch
4773 o_channel = switch_core_session_get_channel(session);
4774 }
4775
4776
4777 if ((hval = switch_event_get_header(var_event, "sip_invite_to_uri")switch_event_get_header_idx(var_event, "sip_invite_to_uri", -
1)
)) {
10
Assuming 'hval' is null
11
Taking false branch
4778 dest_to = switch_core_session_strdup(nsession, hval)switch_core_perform_session_strdup(nsession, hval, "mod_sofia.c"
, (const char *)__func__, 4778)
;
4779 }
4780
4781 if (!strncasecmp(profile_name, "gateway/", 8)) {
12
Taking true branch
4782 char *gw, *params;
4783
4784 if (!(gw = strchr(profile_name, '/'))) {
13
Assuming 'gw' is not null
14
Taking false branch
4785 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 4785, (const char*)(session)
, SWITCH_LOG_ERROR, "Invalid URL \'%s\'\n", profile_name);
4786 cause = SWITCH_CAUSE_INVALID_URL;
4787 goto error;
4788 }
4789
4790 *gw++ = '\0';
4791
4792 if (!(dest = strchr(gw, '/'))) {
15
Assuming 'dest' is not null
16
Taking false branch
4793 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 4793, (const char*)(session)
, SWITCH_LOG_ERROR, "Invalid URL \'%s\'\n", gw);
4794 cause = SWITCH_CAUSE_INVALID_URL;
4795 goto error;
4796 }
4797
4798 *dest++ = '\0';
4799
4800 if (!(gateway_ptr = sofia_reg_find_gateway(gw)sofia_reg_find_gateway__("mod_sofia.c", (const char *)__func__
, 4800, gw)
)) {
17
Assuming 'gateway_ptr' is not null
18
Taking false branch
4801 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 4801, (const char*)(session)
, SWITCH_LOG_ERROR, "Invalid Gateway \'%s\'\n", gw);
4802 cause = SWITCH_CAUSE_INVALID_GATEWAY;
4803 goto error;
4804 }
4805
4806 profile = gateway_ptr->profile;
19
Value assigned to 'profile'
4807
4808 if (gateway_ptr->status != SOFIA_GATEWAY_UP) {
20
Assuming the condition is false
21
Taking false branch
4809 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 4809, (const char*)(session)
, SWITCH_LOG_ERROR, "Gateway \'%s\' is down!\n", gw);
4810 cause = SWITCH_CAUSE_GATEWAY_DOWN;
4811 gateway_ptr->ob_failed_calls++;
4812 goto error;
4813 }
4814
4815 tech_pvt->transport = gateway_ptr->register_transport;
4816 tech_pvt->cid_type = gateway_ptr->cid_type;
4817 cid_locked = 1;
4818
4819 /*
4820 * Handle params, strip them off the destination and add them to the
4821 * invite contact.
4822 *
4823 */
4824
4825 if ((params = strchr(dest, ';'))) {
22
Assuming 'params' is null
23
Taking false branch
4826 char *tp_param;
4827
4828 *params++ = '\0';
4829
4830 if ((tp_param = (char *) switch_stristr("port=", params))) {
4831 tp_param += 5;
4832 tech_pvt->transport = sofia_glue_str2transport(tp_param);
4833 if (tech_pvt->transport == SOFIA_TRANSPORT_UNKNOWN) {
4834 cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
4835 gateway_ptr->ob_failed_calls++;
4836 goto error;
4837 }
4838 }
4839 }
4840
4841 if (tech_pvt->transport != gateway_ptr->register_transport) {
24
Taking false branch
4842 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 4842, (const char*)(session)
, SWITCH_LOG_ERROR,
4843 "You are trying to use a different transport type for this gateway (overriding the register-transport), this is unsupported!\n");
4844 cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
4845 goto error;
4846 }
4847
4848 if (profile && sofia_test_pflag(profile, PFLAG_STANDBY)((profile)->pflags[PFLAG_STANDBY] ? 1 : 0)) {
25
Assuming 'profile' is null
4849 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
4849, ((void*)0)
, SWITCH_LOG_CRIT, "System Paused\n");
4850 cause = SWITCH_CAUSE_SYSTEM_SHUTDOWN;
4851 goto error;
4852 }
4853
4854 tech_pvt->gateway_name = switch_core_session_strdup(nsession, gateway_ptr->name)switch_core_perform_session_strdup(nsession, gateway_ptr->
name, "mod_sofia.c", (const char *)__func__, 4854)
;
4855 switch_channel_set_variable(nchannel, "sip_gateway_name", gateway_ptr->name)switch_channel_set_variable_var_check(nchannel, "sip_gateway_name"
, gateway_ptr->name, SWITCH_TRUE)
;
4856
4857 if (!sofia_test_flag(gateway_ptr, REG_FLAG_CALLERID)((gateway_ptr)->flags[REG_FLAG_CALLERID] ? 1 : 0)) {
26
Taking true branch
4858 tech_pvt->gateway_from_str = switch_core_session_strdup(nsession, gateway_ptr->register_from)switch_core_perform_session_strdup(nsession, gateway_ptr->
register_from, "mod_sofia.c", (const char *)__func__, 4858)
;
4859 }
4860
4861 if (!strchr(dest, '@')) {
27
Assuming the condition is false
28
Taking false branch
4862 tech_pvt->dest = switch_core_session_sprintf(nsession, "sip:%s%s@%s", gateway_ptr->destination_prefix, dest, sofia_glue_strip_proto(gateway_ptr->register_proxy));
4863 } else {
4864 tech_pvt->dest = switch_core_session_sprintf(nsession, "sip:%s%s", gateway_ptr->destination_prefix, dest);
4865 }
4866
4867 if ((host = switch_core_session_strdup(nsession, tech_pvt->dest)switch_core_perform_session_strdup(nsession, tech_pvt->dest
, "mod_sofia.c", (const char *)__func__, 4867)
)) {
29
Assuming 'host' is null
30
Taking false branch
4868 char *pp = strchr(host, '@');
4869 if (pp) {
4870 host = pp + 1;
4871 } else {
4872 host = NULL((void*)0);
4873 dest_to = NULL((void*)0);
4874 }
4875 }
4876
4877 if (params) {
31
Taking false branch
4878 tech_pvt->invite_contact = switch_core_session_sprintf(nsession, "%s;%s", gateway_ptr->register_contact, params);
4879 tech_pvt->dest = switch_core_session_sprintf(nsession, "%s;%s", tech_pvt->dest, params);
4880 } else {
4881 tech_pvt->invite_contact = switch_core_session_strdup(nsession, gateway_ptr->register_contact)switch_core_perform_session_strdup(nsession, gateway_ptr->
register_contact, "mod_sofia.c", (const char *)__func__, 4881
)
;
4882 }
4883
4884 gateway_ptr->ob_calls++;
4885
4886 if (!zstr(gateway_ptr->from_domain)_zstr(gateway_ptr->from_domain) && !switch_channel_get_variable(nchannel, "sip_invite_domain")switch_channel_get_variable_dup(nchannel, "sip_invite_domain"
, SWITCH_TRUE, -1)
) {
4887
4888 if (!strcasecmp(gateway_ptr->from_domain, "auto-aleg-full")) {
4889 const char *sip_full_from = switch_channel_get_variable(o_channel, "sip_full_from")switch_channel_get_variable_dup(o_channel, "sip_full_from", SWITCH_TRUE
, -1)
;
4890
4891 if (!zstr(sip_full_from)_zstr(sip_full_from)) {
4892 switch_channel_set_variable(nchannel, "sip_force_full_from", sip_full_from)switch_channel_set_variable_var_check(nchannel, "sip_force_full_from"
, sip_full_from, SWITCH_TRUE)
;
4893 }
4894
4895 } else if (!strcasecmp(gateway_ptr->from_domain, "auto-aleg-domain")) {
4896 const char *sip_from_host = switch_channel_get_variable(o_channel, "sip_from_host")switch_channel_get_variable_dup(o_channel, "sip_from_host", SWITCH_TRUE
, -1)
;
4897
4898 if (!zstr(sip_from_host)_zstr(sip_from_host)) {
4899 switch_channel_set_variable(nchannel, "sip_invite_domain", sip_from_host)switch_channel_set_variable_var_check(nchannel, "sip_invite_domain"
, sip_from_host, SWITCH_TRUE)
;
4900 }
4901 } else {
4902 switch_channel_set_variable(nchannel, "sip_invite_domain", gateway_ptr->from_domain)switch_channel_set_variable_var_check(nchannel, "sip_invite_domain"
, gateway_ptr->from_domain, SWITCH_TRUE)
;
4903 }
4904 }
4905
4906 if (!zstr(gateway_ptr->outbound_sticky_proxy)_zstr(gateway_ptr->outbound_sticky_proxy) && !switch_channel_get_variable(nchannel, "sip_route_uri")switch_channel_get_variable_dup(nchannel, "sip_route_uri", SWITCH_TRUE
, -1)
) {
4907 switch_channel_set_variable(nchannel, "sip_route_uri", gateway_ptr->outbound_sticky_proxy)switch_channel_set_variable_var_check(nchannel, "sip_route_uri"
, gateway_ptr->outbound_sticky_proxy, SWITCH_TRUE)
;
4908 }
4909
4910 } else {
4911 if (!(dest = strchr(profile_name, '/'))) {
4912 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 4912, (const char*)(session)
, SWITCH_LOG_ERROR, "Invalid URL\n");
4913 cause = SWITCH_CAUSE_INVALID_URL;
4914 goto error;
4915 }
4916 *dest++ = '\0';
4917
4918 if (!(profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 4918, profile_name)
)) {
4919 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 4919, (const char*)(session)
, SWITCH_LOG_ERROR, "Invalid Profile\n");
4920 cause = SWITCH_CAUSE_INVALID_PROFILE;
4921 goto error;
4922 }
4923
4924 if (sofia_test_pflag(profile, PFLAG_STANDBY)((profile)->pflags[PFLAG_STANDBY] ? 1 : 0)) {
4925 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
4925, ((void*)0)
, SWITCH_LOG_CRIT, "System Paused\n");
4926 cause = SWITCH_CAUSE_SYSTEM_SHUTDOWN;
4927 goto error;
4928 }
4929
4930 if (profile->domain_name && strcmp(profile->domain_name, profile->name)) {
4931 profile_name = profile->domain_name;
4932 }
4933
4934 if (!strncasecmp(dest, "sip:", 4) || !strncasecmp(dest, "sips:", 5)) {
4935 char *c;
4936 tech_pvt->dest = switch_core_session_strdup(nsession, dest)switch_core_perform_session_strdup(nsession, dest, "mod_sofia.c"
, (const char *)__func__, 4936)
;
4937 if ((c = strchr(tech_pvt->dest, ':'))) {
4938 c++;
4939 tech_pvt->e_dest = switch_core_session_strdup(nsession, c)switch_core_perform_session_strdup(nsession, c, "mod_sofia.c"
, (const char *)__func__, 4939)
;
4940 }
4941 } else if (!mod && !strchr(dest, '@') && (host = strchr(dest, '%'))) {
4942 char buf[1024];
4943 *host = '@';
4944 tech_pvt->e_dest = switch_core_session_strdup(nsession, dest)switch_core_perform_session_strdup(nsession, dest, "mod_sofia.c"
, (const char *)__func__, 4944)
;
4945 *host++ = '\0';
4946 if (sofia_reg_find_reg_url(profile, dest, host, buf, sizeof(buf))) {
4947 tech_pvt->dest = switch_core_session_strdup(nsession, buf)switch_core_perform_session_strdup(nsession, buf, "mod_sofia.c"
, (const char *)__func__, 4947)
;
4948 tech_pvt->local_url = switch_core_session_sprintf(nsession, "%s@%s", dest, host);
4949 } else {
4950 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 4950, (const char*)(session)
, SWITCH_LOG_WARNING, "Cannot locate registered user %s@%s\n", dest, host);
4951 cause = SWITCH_CAUSE_USER_NOT_REGISTERED;
4952 goto error;
4953 }
4954 } else if (!(host = strchr(dest, '@'))) {
4955 char buf[1024];
4956 tech_pvt->e_dest = switch_core_session_strdup(nsession, dest)switch_core_perform_session_strdup(nsession, dest, "mod_sofia.c"
, (const char *)__func__, 4956)
;
4957 if (sofia_reg_find_reg_url(profile, dest, profile_name, buf, sizeof(buf))) {
4958 tech_pvt->dest = switch_core_session_strdup(nsession, buf)switch_core_perform_session_strdup(nsession, buf, "mod_sofia.c"
, (const char *)__func__, 4958)
;
4959 tech_pvt->local_url = switch_core_session_sprintf(nsession, "%s@%s", dest, profile_name);
4960 host = profile_name;
4961 } else {
4962 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 4962, (const char*)(session)
, SWITCH_LOG_WARNING, "Cannot locate registered user %s@%s\n", dest, profile_name);
4963 cause = SWITCH_CAUSE_USER_NOT_REGISTERED;
4964 goto error;
4965 }
4966 } else {
4967 host++;
4968
4969 if (!strchr(host, '.') || switch_true(switch_event_get_header(var_event, "sip_gethostbyname")switch_event_get_header_idx(var_event, "sip_gethostbyname", -
1)
)) {
4970 struct sockaddr_in sa;
4971 struct hostent *he = gethostbyname(host);
4972 char buf[50] = "", *tmp;
4973 const char *ip;
4974
4975 if (he) {
4976 memcpy(&sa.sin_addr, he->h_addrh_addr_list[0], sizeof(struct in_addr));
4977 ip = switch_inet_ntopinet_ntop(AF_INET2, &sa.sin_addr, buf, sizeof(buf));
4978 tmp = switch_string_replace(dest, host, ip);
4979 //host = switch_core_session_strdup(nsession, ip);
4980 //dest = switch_core_session_strdup(nsession, tmp);
4981 switch_channel_set_variable_printf(nchannel, "sip_route_uri", "sip:%s", tmp);
4982 free(tmp);
4983 }
4984 }
4985
4986 tech_pvt->dest = switch_core_session_alloc(nsession, strlen(dest) + 5)switch_core_perform_session_alloc(nsession, strlen(dest) + 5,
"mod_sofia.c", (const char *)__func__, 4986)
;
4987 tech_pvt->e_dest = switch_core_session_strdup(nsession, dest)switch_core_perform_session_strdup(nsession, dest, "mod_sofia.c"
, (const char *)__func__, 4987)
;
4988 switch_snprintf(tech_pvt->dest, strlen(dest) + 5, "sip:%s", dest);
4989 }
4990 }
4991
4992 switch_channel_set_variable_printf(nchannel, "sip_local_network_addr", "%s", profile->extsipip ? profile->extsipip : profile->sipip);
32
Access to field 'extsipip' results in a dereference of a null pointer (loaded from variable 'profile')
4993 switch_channel_set_variable(nchannel, "sip_profile_name", profile_name)switch_channel_set_variable_var_check(nchannel, "sip_profile_name"
, profile_name, SWITCH_TRUE)
;
4994
4995 if (switch_stristr("fs_path", tech_pvt->dest)) {
4996 char *remote_host = NULL((void*)0);
4997 const char *s;
4998
4999 if ((s = switch_stristr("fs_path=", tech_pvt->dest))) {
5000 s += 8;
5001 }
5002
5003 if (s) {
5004 remote_host = switch_core_session_strdup(nsession, s)switch_core_perform_session_strdup(nsession, s, "mod_sofia.c"
, (const char *)__func__, 5004)
;
5005 switch_url_decode(remote_host);
5006 }
5007 if (!zstr(remote_host)_zstr(remote_host)) {
5008 switch_split_user_domain(remote_host, NULL((void*)0), &tech_pvt->mparams.remote_ip);
5009 }
5010 }
5011
5012 if (zstr(tech_pvt->mparams.remote_ip)_zstr(tech_pvt->mparams.remote_ip)) {
5013 switch_split_user_domain(switch_core_session_strdup(nsession, tech_pvt->dest)switch_core_perform_session_strdup(nsession, tech_pvt->dest
, "mod_sofia.c", (const char *)__func__, 5013)
, NULL((void*)0), &tech_pvt->mparams.remote_ip);
5014 }
5015
5016 if (dest_to) {
5017 if (strchr(dest_to, '@')) {
5018 tech_pvt->dest_to = switch_core_session_sprintf(nsession, "sip:%s", dest_to);
5019 } else {
5020 tech_pvt->dest_to = switch_core_session_sprintf(nsession, "sip:%s@%s", dest_to, host ? host : profile->sipip);
5021 }
5022 }
5023
5024 if (!tech_pvt->dest_to) {
5025 tech_pvt->dest_to = tech_pvt->dest;
5026 }
5027
5028 if (!zstr(tech_pvt->dest)_zstr(tech_pvt->dest) && switch_stristr("transport=ws", tech_pvt->dest)) {
5029 switch_channel_set_variable(nchannel, "media_webrtc", "true")switch_channel_set_variable_var_check(nchannel, "media_webrtc"
, "true", SWITCH_TRUE)
;
5030 switch_core_session_set_ice(nsession);
5031 }
5032
5033
5034 sofia_glue_attach_private(nsession, profile, tech_pvt, dest);
5035
5036 if (tech_pvt->local_url) {
5037 switch_channel_set_variable(nchannel, "sip_local_url", tech_pvt->local_url)switch_channel_set_variable_var_check(nchannel, "sip_local_url"
, tech_pvt->local_url, SWITCH_TRUE)
;
5038 if (profile->pres_type) {
5039 const char *presence_id = switch_channel_get_variable(nchannel, "presence_id")switch_channel_get_variable_dup(nchannel, "presence_id", SWITCH_TRUE
, -1)
;
5040 if (zstr(presence_id)_zstr(presence_id)) {
5041 switch_channel_set_variable(nchannel, "presence_id", tech_pvt->local_url)switch_channel_set_variable_var_check(nchannel, "presence_id"
, tech_pvt->local_url, SWITCH_TRUE)
;
5042 }
5043 }
5044 }
5045 switch_channel_set_variable(nchannel, "sip_destination_url", tech_pvt->dest)switch_channel_set_variable_var_check(nchannel, "sip_destination_url"
, tech_pvt->dest, SWITCH_TRUE)
;
5046#if 0
5047 dest_num = switch_core_session_strdup(nsession, dest)switch_core_perform_session_strdup(nsession, dest, "mod_sofia.c"
, (const char *)__func__, 5047)
;
5048 if ((p = strchr(dest_num, '@'))) {
5049 *p = '\0';
5050
5051 if ((p = strrchr(dest_num, '/'))) {
5052 dest_num = p + 1;
5053 } else if ((p = (char *) switch_stristr("sip:", dest_num))) {
5054 dest_num = p + 4;
5055 } else if ((p = (char *) switch_stristr("sips:", dest_num))) {
5056 dest_num = p + 5;
5057 }
5058 }
5059
5060
5061 if (profile->pres_type) {
5062 char *sql;
5063 time_t now;
5064
5065 const char *presence_id = switch_channel_get_variable(nchannel, "presence_id")switch_channel_get_variable_dup(nchannel, "presence_id", SWITCH_TRUE
, -1)
;
5066 const char *presence_data = switch_channel_get_variable(nchannel, "presence_data")switch_channel_get_variable_dup(nchannel, "presence_data", SWITCH_TRUE
, -1)
;
5067
5068 if (zstr(presence_id)_zstr(presence_id)) {
5069 presence_id = switch_event_get_header(var_event, "presence_id")switch_event_get_header_idx(var_event, "presence_id", -1);
5070 }
5071
5072 if (zstr(presence_data)_zstr(presence_data)) {
5073 presence_data = switch_event_get_header(var_event, "presence_data")switch_event_get_header_idx(var_event, "presence_data", -1);
5074 }
5075
5076 now = switch_epoch_time_now(NULL((void*)0));
5077 sql = switch_mprintf("insert into sip_dialogs (uuid,presence_id,presence_data,profile_name,hostname,rcd,call_info_state) "
5078 "values ('%q', '%q', '%q', '%q', '%q', %ld, '')", switch_core_session_get_uuid(nsession),
5079 switch_str_nil(presence_id)(presence_id ? presence_id : ""), switch_str_nil(presence_data)(presence_data ? presence_data : ""), profile->name, mod_sofia_globals.hostname, (long) now);
5080 sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
5081 }
5082#endif
5083
5084 caller_profile = switch_caller_profile_clone(nsession, outbound_profile);
5085
5086
5087 caller_profile->destination_number = switch_sanitize_number(caller_profile->destination_number);
5088 not_const = (char *) caller_profile->caller_id_name;
5089 caller_profile->caller_id_name = switch_sanitize_number(not_const);
5090 not_const = (char *) caller_profile->caller_id_number;
5091 caller_profile->caller_id_number = switch_sanitize_number(not_const);
5092
5093
5094 //caller_profile->destination_number = switch_core_strdup(caller_profile->pool, dest_num);
5095 switch_channel_set_caller_profile(nchannel, caller_profile);
5096
5097
5098 if (gateway_ptr && gateway_ptr->ob_vars) {
5099 switch_event_header_t *hp;
5100 for (hp = gateway_ptr->ob_vars->headers; hp; hp = hp->next) {
5101 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(nsession)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 5101, (const char*)(nsession)
, SWITCH_LOG_DEBUG, "%s setting variable [%s]=[%s]\n",
5102 switch_channel_get_name(nchannel), hp->name, hp->value);
5103 if (!strncmp(hp->name, "p:", 2)) {
5104 switch_channel_set_profile_var(nchannel, hp->name + 2, hp->value);
5105 } else {
5106 switch_channel_set_variable(nchannel, hp->name, hp->value)switch_channel_set_variable_var_check(nchannel, hp->name, hp
->value, SWITCH_TRUE)
;
5107 }
5108 }
5109 }
5110
5111
5112
5113
5114 sofia_set_flag_locked(tech_pvt, TFLAG_OUTBOUND)((tech_pvt->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("tech_pvt->flag_mutex != NULL", "mod_sofia.c", 5114, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(tech_pvt->flag_mutex
);(tech_pvt)->flags[TFLAG_OUTBOUND] = 1;switch_mutex_unlock
(tech_pvt->flag_mutex);
;
5115 sofia_clear_flag_locked(tech_pvt, TFLAG_LATE_NEGOTIATION)switch_mutex_lock(tech_pvt->flag_mutex); (tech_pvt)->flags
[TFLAG_LATE_NEGOTIATION] = 0; switch_mutex_unlock(tech_pvt->
flag_mutex);
;
5116 if (switch_channel_get_state(nchannel) == CS_NEW) {
5117 switch_channel_set_state(nchannel, CS_INIT)switch_channel_perform_set_state(nchannel, "mod_sofia.c", (const
char *)__func__, 5117, CS_INIT)
;
5118 }
5119 tech_pvt->caller_profile = caller_profile;
5120 *new_session = nsession;
5121 cause = SWITCH_CAUSE_SUCCESS;
5122
5123 if ((hval = switch_event_get_header(var_event, "sip_enable_soa")switch_event_get_header_idx(var_event, "sip_enable_soa", -1))) {
5124 if (switch_true(hval)) {
5125 sofia_set_flag(tech_pvt, TFLAG_ENABLE_SOA)(tech_pvt)->flags[TFLAG_ENABLE_SOA] = 1;
5126 } else {
5127 sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA)(tech_pvt)->flags[TFLAG_ENABLE_SOA] = 0;
5128 }
5129 }
5130
5131 if ((hval = switch_event_get_header(var_event, "sip_auto_answer")switch_event_get_header_idx(var_event, "sip_auto_answer", -1)) && switch_true(hval)) {
5132 switch_channel_set_variable_printf(nchannel, "sip_h_Call-Info", "<sip:%s>;answer-after=0", profile->sipip);
5133 switch_channel_set_variable(nchannel, "sip_invite_params", "intercom=true")switch_channel_set_variable_var_check(nchannel, "sip_invite_params"
, "intercom=true", SWITCH_TRUE)
;
5134 }
5135
5136 if (((hval = switch_event_get_header(var_event, "effective_callee_id_name")switch_event_get_header_idx(var_event, "effective_callee_id_name"
, -1)
) ||
5137 (hval = switch_event_get_header(var_event, "sip_callee_id_name")switch_event_get_header_idx(var_event, "sip_callee_id_name", -
1)
)) && !zstr(hval)_zstr(hval)) {
5138 caller_profile->callee_id_name = switch_core_strdup(caller_profile->pool, hval)switch_core_perform_strdup(caller_profile->pool, hval, "mod_sofia.c"
, (const char *)__func__, 5138)
;
5139 }
5140
5141 if (((hval = switch_event_get_header(var_event, "effective_callee_id_number")switch_event_get_header_idx(var_event, "effective_callee_id_number"
, -1)
) ||
5142 (hval = switch_event_get_header(var_event, "sip_callee_id_number")switch_event_get_header_idx(var_event, "sip_callee_id_number"
, -1)
)) && !zstr(hval)_zstr(hval)) {
5143 caller_profile->callee_id_number = switch_core_strdup(caller_profile->pool, hval)switch_core_perform_strdup(caller_profile->pool, hval, "mod_sofia.c"
, (const char *)__func__, 5143)
;
5144 }
5145
5146 if (session) {
5147 const char *vval = NULL((void*)0);
5148
5149 switch_ivr_transfer_variable(session, nsession, SOFIA_REPLACES_HEADER"_sofia_replaces_");
5150
5151 if (!(vval = switch_channel_get_variable(o_channel, "sip_copy_custom_headers")switch_channel_get_variable_dup(o_channel, "sip_copy_custom_headers"
, SWITCH_TRUE, -1)
) || switch_true(vval)) {
5152 switch_ivr_transfer_variable(session, nsession, SOFIA_SIP_HEADER_PREFIX_T"~sip_h_");
5153 }
5154
5155 if (!(vval = switch_channel_get_variable(o_channel, "sip_copy_multipart")switch_channel_get_variable_dup(o_channel, "sip_copy_multipart"
, SWITCH_TRUE, -1)
) || switch_true(vval)) {
5156 switch_ivr_transfer_variable(session, nsession, "sip_multipart");
5157 }
5158 switch_ivr_transfer_variable(session, nsession, "rtp_video_fmtp");
5159 switch_ivr_transfer_variable(session, nsession, "sip-force-contact");
5160 switch_ivr_transfer_variable(session, nsession, "sip_sticky_contact");
5161 if (!cid_locked) {
5162 switch_ivr_transfer_variable(session, nsession, "sip_cid_type");
5163 }
5164
5165 if (switch_core_session_compare(session, nsession)) {
5166 /* It's another sofia channel! so lets cache what they use as a pt for telephone event so
5167 we can keep it the same
5168 */
5169 private_object_t *ctech_pvt;
5170 ctech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
5171 switch_assert(ctech_pvt != NULL)((ctech_pvt != ((void*)0)) ? (void) (0) : __assert_fail ("ctech_pvt != ((void*)0)"
, "mod_sofia.c", 5171, __extension__ __PRETTY_FUNCTION__))
;
5172 tech_pvt->bte = ctech_pvt->te;
5173 tech_pvt->bcng_pt = ctech_pvt->cng_pt;
5174 if (!cid_locked) {
5175 tech_pvt->cid_type = ctech_pvt->cid_type;
5176 }
5177
5178 if (sofia_test_flag(tech_pvt, TFLAG_ENABLE_SOA)((tech_pvt)->flags[TFLAG_ENABLE_SOA] ? 1 : 0)) {
5179 sofia_set_flag(ctech_pvt, TFLAG_ENABLE_SOA)(ctech_pvt)->flags[TFLAG_ENABLE_SOA] = 1;
5180 } else {
5181 sofia_clear_flag(ctech_pvt, TFLAG_ENABLE_SOA)(ctech_pvt)->flags[TFLAG_ENABLE_SOA] = 0;
5182 }
5183
5184 if (switch_channel_test_flag(o_channel, CF_ZRTP_PASSTHRU_REQ) && switch_channel_test_flag(o_channel, CF_ZRTP_HASH)) {
5185 const char *x = NULL((void*)0);
5186 switch_core_media_pass_zrtp_hash2(session, nsession);
5187 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 5187, (const char*)(session)
, SWITCH_LOG_DEBUG, "[zrtp_passthru] Setting a-leg inherit_codec=true\n");
5188 switch_channel_set_variable(o_channel, "inherit_codec", "true")switch_channel_set_variable_var_check(o_channel, "inherit_codec"
, "true", SWITCH_TRUE)
;
5189 if ((x = switch_channel_get_variable(o_channel, "ep_codec_string")switch_channel_get_variable_dup(o_channel, "ep_codec_string",
SWITCH_TRUE, -1)
)) {
5190 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 5190, (const char*)(session)
, SWITCH_LOG_DEBUG, "[zrtp_passthru] Setting b-leg absolute_codec_string='%s'\n", x);
5191 switch_channel_set_variable(nchannel, "absolute_codec_string", x)switch_channel_set_variable_var_check(nchannel, "absolute_codec_string"
, x, SWITCH_TRUE)
;
5192 }
5193 }
5194
5195 /* SNARK: lets copy this across so we can see if we're the other leg of 3PCC + bypass_media... */
5196 if (sofia_test_flag(ctech_pvt, TFLAG_3PCC)((ctech_pvt)->flags[TFLAG_3PCC] ? 1 : 0) && (switch_channel_test_flag(o_channel, CF_PROXY_MODE) || switch_channel_test_flag(o_channel, CF_PROXY_MEDIA))) {
5197 sofia_set_flag(tech_pvt, TFLAG_3PCC_INVITE)(tech_pvt)->flags[TFLAG_3PCC_INVITE] = 1;
5198 sofia_set_flag(tech_pvt, TFLAG_LATE_NEGOTIATION)(tech_pvt)->flags[TFLAG_LATE_NEGOTIATION] = 1;
5199 } else {
5200 sofia_clear_flag(tech_pvt, TFLAG_3PCC_INVITE)(tech_pvt)->flags[TFLAG_3PCC_INVITE] = 0;
5201 }
5202 }
5203
5204 switch_core_media_check_outgoing_proxy(nsession, session);
5205
5206 }
5207
5208 goto done;
5209
5210 error:
5211 /* gateway pointer lock is really a readlock of the profile so we let the profile release below free that lock if we have a profile */
5212 if (gateway_ptr && !profile) {
5213 sofia_reg_release_gateway(gateway_ptr)sofia_reg_release_gateway__("mod_sofia.c", (const char *)__func__
, 5213, gateway_ptr);
;
5214 }
5215
5216 if (nsession) {
5217 switch_core_session_destroy(&nsession)switch_core_session_perform_destroy(&nsession, "mod_sofia.c"
, (const char *)__func__, 5217)
;
5218 }
5219 if (pool) {
5220 *pool = NULL((void*)0);
5221 }
5222 done:
5223
5224 if (profile) {
5225 if (cause == SWITCH_CAUSE_SUCCESS) {
5226 profile->ob_calls++;
5227 } else {
5228 profile->ob_failed_calls++;
5229 }
5230 sofia_glue_release_profile(profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 5230, profile)
;
5231 }
5232 return cause;
5233}
5234
5235static int notify_csta_callback(void *pArg, int argc, char **argv, char **columnNames)
5236{
5237 nua_handle_t *nh;
5238 sofia_profile_t *ext_profile = NULL((void*)0), *profile = (sofia_profile_t *) pArg;
5239 int i = 0;
5240 char *user = argv[i++];
5241 char *host = argv[i++];
5242 char *contact_in = argv[i++];
5243 char *profile_name = argv[i++];
5244 char *call_id = argv[i++];
5245 char *full_from = argv[i++];
5246 char *full_to = argv[i++];
5247 int expires = atoi(argv[i++]);
5248 char *body = argv[i++];
5249 char *ct = argv[i++];
5250 char *id = NULL((void*)0);
5251 char *contact;
5252 sip_cseq_t *cseq = NULL((void*)0);
5253 uint32_t callsequence;
5254 sofia_destination_t *dst = NULL((void*)0);
5255 char *route_uri = NULL((void*)0);
5256
5257 time_t epoch_now = switch_epoch_time_now(NULL((void*)0));
5258 time_t expires_in = (expires - epoch_now);
5259 char *extra_headers = switch_mprintf("Subscription-State: active, %d\r\n", expires_in);
5260
5261 if (profile_name && strcasecmp(profile_name, profile->name)) {
5262 if ((ext_profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 5262, profile_name)
)) {
5263 profile = ext_profile;
5264 }
5265 }
5266
5267 id = switch_mprintf("sip:%s@%s", user, host);
5268 switch_assert(id)((id) ? (void) (0) : __assert_fail ("id", "mod_sofia.c", 5268
, __extension__ __PRETTY_FUNCTION__))
;
5269 contact = sofia_glue_get_url_from_contact(contact_in, 1);
5270
5271
5272 dst = sofia_glue_get_destination((char *) contact);
5273
5274 if (dst->route_uri) {
5275 route_uri = sofia_glue_strip_uri(dst->route_uri);
5276 }
5277
5278 callsequence = sofia_presence_get_cseq(profile);
5279
5280 //nh = nua_handle(profile->nua, NULL, NUTAG_URL(dst->contact), SIPTAG_FROM_STR(id), SIPTAG_TO_STR(id), SIPTAG_CONTACT_STR(profile->url), TAG_END());
5281 nh = nua_handle(profile->nua, NULL((void*)0), NUTAG_URL(dst->contact)nutag_url, urltag_url_v(dst->contact), SIPTAG_FROM_STR(full_to)siptag_from_str, tag_str_v(full_to), SIPTAG_TO_STR(full_from)siptag_to_str, tag_str_v(full_from), SIPTAG_CONTACT_STR(profile->url)siptag_contact_str, tag_str_v(profile->url), TAG_END()(tag_type_t)0, (tag_value_t)0);
5282 cseq = sip_cseq_create(nua_handle_get_home(nh), callsequence, SIP_METHOD_NOTIFYsip_method_notify, "NOTIFY");
5283
5284 nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
5285
5286 nua_notify(nh, NUTAG_NEWSUB(1)nutag_newsub, tag_bool_v(1),
5287 TAG_IF(dst->route_uri, NUTAG_PROXY(route_uri))!(dst->route_uri) ? tag_skip : ntatag_default_proxy, urltag_url_v
((route_uri))
, TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route))!(dst->route) ? tag_skip : siptag_route_str, tag_str_v(dst
->route)
, TAG_IF(call_id, SIPTAG_CALL_ID_STR(call_id))!(call_id) ? tag_skip : siptag_call_id_str, tag_str_v(call_id
)
,
5288 SIPTAG_EVENT_STR("as-feature-event")siptag_event_str, tag_str_v("as-feature-event"), SIPTAG_CONTENT_TYPE_STR(ct)siptag_content_type_str, tag_str_v(ct), TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers))!(!_zstr(extra_headers)) ? tag_skip : siptag_header_str, tag_str_v
((extra_headers))
, TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body))!(!_zstr(body)) ? tag_skip : siptag_payload_str, tag_str_v(body
)
, SIPTAG_CSEQ(cseq)siptag_cseq, siptag_cseq_v(cseq),
5289 TAG_END()(tag_type_t)0, (tag_value_t)0);
5290
5291
5292
5293 switch_safe_free(route_uri)if (route_uri) {free(route_uri);route_uri=((void*)0);};
5294 sofia_glue_free_destination(dst);
5295
5296 free(extra_headers);
5297 free(id);
5298 free(contact);
5299
5300 if (ext_profile) {
5301 sofia_glue_release_profile(ext_profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 5301, ext_profile)
;
5302 }
5303
5304 return 0;
5305}
5306
5307static int notify_callback(void *pArg, int argc, char **argv, char **columnNames)
5308{
5309
5310 nua_handle_t *nh;
5311 sofia_profile_t *ext_profile = NULL((void*)0), *profile = (sofia_profile_t *) pArg;
5312 char *user = argv[0];
5313 char *host = argv[1];
5314 char *contact_in = argv[2];
5315 char *profile_name = argv[3];
5316 char *ct = argv[4];
5317 char *es = argv[5];
5318 char *body = argv[6];
5319 char *id = NULL((void*)0);
5320 char *contact;
5321 sofia_destination_t *dst = NULL((void*)0);
5322 char *route_uri = NULL((void*)0);
5323
5324 if (profile_name && strcasecmp(profile_name, profile->name)) {
5325 if ((ext_profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 5325, profile_name)
)) {
5326 profile = ext_profile;
5327 }
5328 }
5329
5330 id = switch_mprintf("sip:%s@%s", user, host);
5331 switch_assert(id)((id) ? (void) (0) : __assert_fail ("id", "mod_sofia.c", 5331
, __extension__ __PRETTY_FUNCTION__))
;
5332 contact = sofia_glue_get_url_from_contact(contact_in, 1);
5333
5334
5335 dst = sofia_glue_get_destination((char *) contact);
5336
5337 if (dst->route_uri) {
5338 route_uri = sofia_glue_strip_uri(dst->route_uri);
5339 }
5340
5341 nh = nua_handle(profile->nua, NULL((void*)0), NUTAG_URL(dst->contact)nutag_url, urltag_url_v(dst->contact), SIPTAG_FROM_STR(id)siptag_from_str, tag_str_v(id), SIPTAG_TO_STR(id)siptag_to_str, tag_str_v(id), SIPTAG_CONTACT_STR(profile->url)siptag_contact_str, tag_str_v(profile->url), TAG_END()(tag_type_t)0, (tag_value_t)0);
5342
5343 nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
5344
5345 nua_notify(nh, NUTAG_NEWSUB(1)nutag_newsub, tag_bool_v(1), SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource")siptag_subscription_state_str, tag_str_v("terminated;reason=noresource"
)
,
5346 TAG_IF(dst->route_uri, NUTAG_PROXY(route_uri))!(dst->route_uri) ? tag_skip : ntatag_default_proxy, urltag_url_v
((route_uri))
, TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route))!(dst->route) ? tag_skip : siptag_route_str, tag_str_v(dst
->route)
,
5347 SIPTAG_EVENT_STR(es)siptag_event_str, tag_str_v(es), SIPTAG_CONTENT_TYPE_STR(ct)siptag_content_type_str, tag_str_v(ct), TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body))!(!_zstr(body)) ? tag_skip : siptag_payload_str, tag_str_v(body
)
, TAG_END()(tag_type_t)0, (tag_value_t)0);
5348
5349
5350 switch_safe_free(route_uri)if (route_uri) {free(route_uri);route_uri=((void*)0);};
5351 sofia_glue_free_destination(dst);
5352
5353 free(id);
5354 free(contact);
5355
5356 if (ext_profile) {
5357 sofia_glue_release_profile(ext_profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 5357, ext_profile)
;
5358 }
5359
5360 return 0;
5361}
5362
5363void general_event_handler(switch_event_t *event)
5364{
5365 switch (event->event_id) {
5366 case SWITCH_EVENT_NOTIFY:
5367 {
5368 const char *profile_name = switch_event_get_header(event, "profile")switch_event_get_header_idx(event, "profile", -1);
5369 const char *ct = switch_event_get_header(event, "content-type")switch_event_get_header_idx(event, "content-type", -1);
5370 const char *es = switch_event_get_header(event, "event-string")switch_event_get_header_idx(event, "event-string", -1);
5371 const char *user = switch_event_get_header(event, "user")switch_event_get_header_idx(event, "user", -1);
5372 const char *host = switch_event_get_header(event, "host")switch_event_get_header_idx(event, "host", -1);
5373 const char *call_id = switch_event_get_header(event, "call-id")switch_event_get_header_idx(event, "call-id", -1);
5374 const char *uuid = switch_event_get_header(event, "uuid")switch_event_get_header_idx(event, "uuid", -1);
5375 const char *body = switch_event_get_body(event);
5376 const char *to_uri = switch_event_get_header(event, "to-uri")switch_event_get_header_idx(event, "to-uri", -1);
5377 const char *from_uri = switch_event_get_header(event, "from-uri")switch_event_get_header_idx(event, "from-uri", -1);
5378 const char *extra_headers = switch_event_get_header(event, "extra-headers")switch_event_get_header_idx(event, "extra-headers", -1);
5379 const char *contact_uri = switch_event_get_header(event, "contact-uri")switch_event_get_header_idx(event, "contact-uri", -1);
5380 const char *no_sub_state = switch_event_get_header(event, "no-sub-state")switch_event_get_header_idx(event, "no-sub-state", -1);
5381
5382 sofia_profile_t *profile;
5383
5384 if (contact_uri) {
5385 if (!es) {
5386 es = "message-summary";
5387 }
5388
5389 if (!ct) {
5390 ct = "application/simple-message-summary";
5391 }
5392
5393 if (!profile_name) {
5394 profile_name = "default";
5395 }
5396
5397 if (!(profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 5397, profile_name)
)) {
5398 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5398, ((void*)0)
, SWITCH_LOG_ERROR, "Can't find profile %s\n", profile_name);
5399 return;
5400 }
5401
5402 if (to_uri && from_uri) {
5403 sofia_destination_t *dst = NULL((void*)0);
5404 nua_handle_t *nh;
5405 char *route_uri = NULL((void*)0);
5406 char *sip_sub_st = NULL((void*)0);
5407
5408 dst = sofia_glue_get_destination((char *) contact_uri);
5409
5410 if (dst->route_uri) {
5411 route_uri = sofia_glue_strip_uri(dst->route_uri);
5412 }
5413
5414 if (zstr(dst->contact)_zstr(dst->contact)) {
5415 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5415, ((void*)0)
, SWITCH_LOG_ERROR, "Invalid contact uri [%s]\n", switch_str_nil(dst->contact)(dst->contact ? dst->contact : ""));
5416 sofia_glue_free_destination(dst);
5417 switch_safe_free(route_uri)if (route_uri) {free(route_uri);route_uri=((void*)0);};
5418 sofia_glue_release_profile(profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 5418, profile)
;
5419 return;
5420 }
5421
5422 nh = nua_handle(profile->nua,
5423 NULL((void*)0),
5424 NUTAG_URL(dst->contact)nutag_url, urltag_url_v(dst->contact),
5425 SIPTAG_FROM_STR(from_uri)siptag_from_str, tag_str_v(from_uri),
5426 SIPTAG_TO_STR(to_uri)siptag_to_str, tag_str_v(to_uri),
5427 SIPTAG_CONTACT_STR(profile->url)siptag_contact_str, tag_str_v(profile->url),
5428 TAG_END()(tag_type_t)0, (tag_value_t)0);
5429
5430 nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
5431
5432 if (!switch_true(no_sub_state)) {
5433 sip_sub_st = "terminated;reason=noresource";
5434 }
5435
5436 nua_notify(nh,
5437 NUTAG_NEWSUB(1)nutag_newsub, tag_bool_v(1), TAG_IF(sip_sub_st, SIPTAG_SUBSCRIPTION_STATE_STR(sip_sub_st))!(sip_sub_st) ? tag_skip : siptag_subscription_state_str, tag_str_v
(sip_sub_st)
,
5438 TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri))!(dst->route_uri) ? tag_skip : ntatag_default_proxy, urltag_url_v
((dst->route_uri))
, TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route))!(dst->route) ? tag_skip : siptag_route_str, tag_str_v(dst
->route)
, TAG_IF(call_id, SIPTAG_CALL_ID_STR(call_id))!(call_id) ? tag_skip : siptag_call_id_str, tag_str_v(call_id
)
,
5439 SIPTAG_EVENT_STR(es)siptag_event_str, tag_str_v(es), SIPTAG_CONTENT_TYPE_STR(ct)siptag_content_type_str, tag_str_v(ct), TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body))!(!_zstr(body)) ? tag_skip : siptag_payload_str, tag_str_v(body
)
,
5440 TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers))!(!_zstr(extra_headers)) ? tag_skip : siptag_header_str, tag_str_v
((extra_headers))
,
5441 TAG_END()(tag_type_t)0, (tag_value_t)0);
5442
5443 switch_safe_free(route_uri)if (route_uri) {free(route_uri);route_uri=((void*)0);};
5444 sofia_glue_free_destination(dst);
5445 }
5446
5447 sofia_glue_release_profile(profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 5447, profile)
;
5448
5449 return;
5450 } else if (to_uri || from_uri) {
5451 if (!es) {
5452 es = "message-summary";
5453 }
5454
5455 if (!ct) {
5456 ct = "application/simple-message-summary";
5457 }
5458
5459 if (!profile_name) {
5460 profile_name = "default";
5461 }
5462
5463 if (!(profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 5463, profile_name)
)) {
5464 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5464, ((void*)0)
, SWITCH_LOG_ERROR, "Can't find profile %s\n", profile_name);
5465 return;
5466 }
5467
5468 if (to_uri && from_uri) {
5469 sofia_destination_t *dst = NULL((void*)0);
5470 nua_handle_t *nh;
5471 char *route_uri = NULL((void*)0);
5472
5473 dst = sofia_glue_get_destination((char *) to_uri);
5474
5475 if (dst->route_uri) {
5476 route_uri = sofia_glue_strip_uri(dst->route_uri);
5477 }
5478
5479
5480 nh = nua_handle(profile->nua,
5481 NULL((void*)0),
5482 NUTAG_URL(to_uri)nutag_url, urltag_url_v(to_uri),
5483 SIPTAG_FROM_STR(from_uri)siptag_from_str, tag_str_v(from_uri),
5484 SIPTAG_TO_STR(to_uri)siptag_to_str, tag_str_v(to_uri),
5485 SIPTAG_CONTACT_STR(profile->url)siptag_contact_str, tag_str_v(profile->url),
5486 TAG_END()(tag_type_t)0, (tag_value_t)0);
5487
5488 nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
5489
5490 nua_notify(nh,
5491 NUTAG_NEWSUB(1)nutag_newsub, tag_bool_v(1), SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource")siptag_subscription_state_str, tag_str_v("terminated;reason=noresource"
)
,
5492 TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri))!(dst->route_uri) ? tag_skip : ntatag_default_proxy, urltag_url_v
((dst->route_uri))
, TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route))!(dst->route) ? tag_skip : siptag_route_str, tag_str_v(dst
->route)
,
5493 SIPTAG_EVENT_STR(es)siptag_event_str, tag_str_v(es), SIPTAG_CONTENT_TYPE_STR(ct)siptag_content_type_str, tag_str_v(ct), TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body))!(!_zstr(body)) ? tag_skip : siptag_payload_str, tag_str_v(body
)
,
5494 TAG_IF(!zstr(extra_headers), SIPTAG_HEADER_STR(extra_headers))!(!_zstr(extra_headers)) ? tag_skip : siptag_header_str, tag_str_v
((extra_headers))
,
5495 TAG_END()(tag_type_t)0, (tag_value_t)0);
5496
5497
5498 switch_safe_free(route_uri)if (route_uri) {free(route_uri);route_uri=((void*)0);};
5499 sofia_glue_free_destination(dst);
5500 }
5501
5502 sofia_glue_release_profile(profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 5502, profile)
;
5503
5504 return;
5505 }
5506
5507 if (uuid && ct && es) {
5508 switch_core_session_t *session;
5509 private_object_t *tech_pvt;
5510
5511 if ((session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "mod_sofia.c", (const
char *)__func__, 5511)
)) {
5512 if ((tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
)) {
5513 const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
5514 nua_notify(tech_pvt->nh,
5515 NUTAG_NEWSUB(1)nutag_newsub, tag_bool_v(1), SIPTAG_SUBSCRIPTION_STATE_STR("terminated;reason=noresource")siptag_subscription_state_str, tag_str_v("terminated;reason=noresource"
)
,
5516 SIPTAG_EVENT_STR(es)siptag_event_str, tag_str_v(es), SIPTAG_CONTENT_TYPE_STR(ct)siptag_content_type_str, tag_str_v(ct), TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body))!(!_zstr(body)) ? tag_skip : siptag_payload_str, tag_str_v(body
)
,
5517 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
5518 TAG_END()(tag_type_t)0, (tag_value_t)0);
5519 }
5520 switch_core_session_rwunlock(session);
5521 }
5522 } else if (profile_name && ct && es && user && host && (profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 5522, profile_name)
)) {
5523 char *sql;
5524
5525 if (call_id) {
5526 sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,'%q','%q','%q' "
5527 "from sip_registrations where call_id='%q'", ct, es, switch_str_nil(body)(body ? body : ""), call_id);
5528 } else {
5529 if (!strcasecmp(es, "message-summary")) {
5530 sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,'%q','%q','%q' "
5531 "from sip_registrations where mwi_user='%q' and mwi_host='%q'",
5532 ct, es, switch_str_nil(body)(body ? body : ""), switch_str_nil(user)(user ? user : ""), switch_str_nil(host)(host ? host : "")
5533 );
5534 } else {
5535 sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,'%q','%q','%q' "
5536 "from sip_registrations where sip_user='%q' and sip_host='%q'",
5537 ct, es, switch_str_nil(body)(body ? body : ""), switch_str_nil(user)(user ? user : ""), switch_str_nil(host)(host ? host : "")
5538 );
5539
5540 }
5541 }
5542
5543
5544 switch_mutex_lock(profile->dbh_mutex);
5545 sofia_glue_execute_sql_callback(profile, NULL((void*)0), sql, notify_callback, profile);
5546 switch_mutex_unlock(profile->dbh_mutex);
5547 sofia_glue_release_profile(profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 5547, profile)
;
5548
5549 free(sql);
5550 }
5551
5552 }
5553 break;
5554 case SWITCH_EVENT_PHONE_FEATURE:
5555 {
5556 const char *profile_name = switch_event_get_header(event, "profile")switch_event_get_header_idx(event, "profile", -1);
5557 const char *user = switch_event_get_header(event, "user")switch_event_get_header_idx(event, "user", -1);
5558 const char *host = switch_event_get_header(event, "host")switch_event_get_header_idx(event, "host", -1);
5559 const char *call_id = switch_event_get_header(event, "call-id")switch_event_get_header_idx(event, "call-id", -1);
5560 const char *csta_event = switch_event_get_header(event, "Feature-Event")switch_event_get_header_idx(event, "Feature-Event", -1);
5561
5562 char *ct = "application/x-as-feature-event+xml";
5563 char *ct_m = NULL((void*)0);
5564
5565 sofia_profile_t *profile;
5566
5567 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5567, ((void*)0)
, SWITCH_LOG_DEBUG, "Phone Feature NOTIFY\n");
5568 if (profile_name && user && host && (profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 5568, profile_name)
)) {
5569 char *sql;
5570 switch_stream_handle_t stream = { 0 };
5571 SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc(
1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data"
, "mod_sofia.c", 5571, __extension__ __PRETTY_FUNCTION__)); memset
(stream.data, 0, 1024); stream.end = stream.data; stream.data_size
= 1024; stream.write_function = switch_console_stream_write;
stream.raw_write_function = switch_console_stream_raw_write;
stream.alloc_len = 1024; stream.alloc_chunk = 1024
;
5572
5573 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5573, ((void*)0)
, SWITCH_LOG_DEBUG, "we have all required vars\n");
5574
5575 if (csta_event) {
5576 if (!strcmp(csta_event, "init")) {
5577 char *boundary_string = "UniqueFreeSWITCHBoundary";
5578 switch_stream_handle_t dnd_stream = { 0 };
5579
5580 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5580, ((void*)0)
, SWITCH_LOG_DEBUG, "Sending multipart with DND and CFWD\n");
5581
5582 if (switch_event_get_header(event, "forward_immediate")switch_event_get_header_idx(event, "forward_immediate", -1)) {
5583 switch_stream_handle_t fwdi_stream = { 0 };
5584 SWITCH_STANDARD_STREAM(fwdi_stream)memset(&fwdi_stream, 0, sizeof(fwdi_stream)); fwdi_stream
.data = malloc(1024); ((fwdi_stream.data) ? (void) (0) : __assert_fail
("fwdi_stream.data", "mod_sofia.c", 5584, __extension__ __PRETTY_FUNCTION__
)); memset(fwdi_stream.data, 0, 1024); fwdi_stream.end = fwdi_stream
.data; fwdi_stream.data_size = 1024; fwdi_stream.write_function
= switch_console_stream_write; fwdi_stream.raw_write_function
= switch_console_stream_raw_write; fwdi_stream.alloc_len = 1024
; fwdi_stream.alloc_chunk = 1024
;
5585 write_csta_xml_chunk(event, fwdi_stream, "ForwardingEvent", "forwardImmediate");
5586 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5586, ((void*)0)
, SWITCH_LOG_DEBUG, "[%s] is %d bytes long\n", (char *)fwdi_stream.data, (int)strlen(fwdi_stream.data));
5587 stream.write_function(&stream, "--%s\r\nContent-Type: application/x-as-feature-event+xml\r\nContent-Length: %d\r\nContent-ID: <%si@%s>\r\n\r\n%s", boundary_string, strlen(fwdi_stream.data), user, host, fwdi_stream.data);
5588 switch_safe_free(fwdi_stream.data)if (fwdi_stream.data) {free(fwdi_stream.data);fwdi_stream.data
=((void*)0);}
;
5589 }
5590 if (switch_event_get_header(event, "forward_busy")switch_event_get_header_idx(event, "forward_busy", -1)) {
5591 switch_stream_handle_t fwdb_stream = { 0 };
5592 SWITCH_STANDARD_STREAM(fwdb_stream)memset(&fwdb_stream, 0, sizeof(fwdb_stream)); fwdb_stream
.data = malloc(1024); ((fwdb_stream.data) ? (void) (0) : __assert_fail
("fwdb_stream.data", "mod_sofia.c", 5592, __extension__ __PRETTY_FUNCTION__
)); memset(fwdb_stream.data, 0, 1024); fwdb_stream.end = fwdb_stream
.data; fwdb_stream.data_size = 1024; fwdb_stream.write_function
= switch_console_stream_write; fwdb_stream.raw_write_function
= switch_console_stream_raw_write; fwdb_stream.alloc_len = 1024
; fwdb_stream.alloc_chunk = 1024
;
5593 write_csta_xml_chunk(event, fwdb_stream, "ForwardingEvent", "forwardBusy");
5594 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5594, ((void*)0)
, SWITCH_LOG_DEBUG, "[%s] is %d bytes long\n", (char *)fwdb_stream.data, (int)strlen(fwdb_stream.data));
5595 stream.write_function(&stream, "--%s\r\nContent-Type: application/x-as-feature-event+xml\r\nContent-Length: %d\r\nContent-ID: <%sb@%s>\r\n\r\n%s", boundary_string, strlen(fwdb_stream.data), user, host, fwdb_stream.data);
5596 switch_safe_free(fwdb_stream.data)if (fwdb_stream.data) {free(fwdb_stream.data);fwdb_stream.data
=((void*)0);}
;
5597 }
5598 if (switch_event_get_header(event, "forward_no_answer")switch_event_get_header_idx(event, "forward_no_answer", -1)) {
5599 switch_stream_handle_t fwdna_stream = { 0 };
5600 SWITCH_STANDARD_STREAM(fwdna_stream)memset(&fwdna_stream, 0, sizeof(fwdna_stream)); fwdna_stream
.data = malloc(1024); ((fwdna_stream.data) ? (void) (0) : __assert_fail
("fwdna_stream.data", "mod_sofia.c", 5600, __extension__ __PRETTY_FUNCTION__
)); memset(fwdna_stream.data, 0, 1024); fwdna_stream.end = fwdna_stream
.data; fwdna_stream.data_size = 1024; fwdna_stream.write_function
= switch_console_stream_write; fwdna_stream.raw_write_function
= switch_console_stream_raw_write; fwdna_stream.alloc_len = 1024
; fwdna_stream.alloc_chunk = 1024
;
5601 write_csta_xml_chunk(event, fwdna_stream, "ForwardingEvent", "forwardNoAns");
5602 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5602, ((void*)0)
, SWITCH_LOG_DEBUG, "[%s] is %d bytes long\n", (char *)fwdna_stream.data, (int)strlen(fwdna_stream.data));
5603 stream.write_function(&stream, "--%s\r\nContent-Type: application/x-as-feature-event+xml\r\nContent-Length: %d\r\nContent-ID: <%sn@%s>\r\n\r\n%s", boundary_string, strlen(fwdna_stream.data), user, host, fwdna_stream.data);
5604 switch_safe_free(fwdna_stream.data)if (fwdna_stream.data) {free(fwdna_stream.data);fwdna_stream.
data=((void*)0);}
;
5605 }
5606
5607 SWITCH_STANDARD_STREAM(dnd_stream)memset(&dnd_stream, 0, sizeof(dnd_stream)); dnd_stream.data
= malloc(1024); ((dnd_stream.data) ? (void) (0) : __assert_fail
("dnd_stream.data", "mod_sofia.c", 5607, __extension__ __PRETTY_FUNCTION__
)); memset(dnd_stream.data, 0, 1024); dnd_stream.end = dnd_stream
.data; dnd_stream.data_size = 1024; dnd_stream.write_function
= switch_console_stream_write; dnd_stream.raw_write_function
= switch_console_stream_raw_write; dnd_stream.alloc_len = 1024
; dnd_stream.alloc_chunk = 1024
;
5608 write_csta_xml_chunk(event, dnd_stream, "DoNotDisturbEvent", NULL((void*)0));
5609 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5609, ((void*)0)
, SWITCH_LOG_DEBUG, "[%s] is %d bytes long\n", (char *)dnd_stream.data, (int)strlen(dnd_stream.data));
5610 stream.write_function(&stream, "--%s\r\nContent-Type: application/x-as-feature-event+xml\r\nContent-Length: %d\r\nContent-ID: <%sd@%s>\r\n\r\n%s", boundary_string, strlen(dnd_stream.data), user, host, dnd_stream.data);
5611 switch_safe_free(dnd_stream.data)if (dnd_stream.data) {free(dnd_stream.data);dnd_stream.data=(
(void*)0);}
;
5612
5613 stream.write_function(&stream, "--%s--\r\n", boundary_string);
5614
5615 ct_m = switch_mprintf("multipart/mixed; boundary=\"%s\"", boundary_string);
5616 ct = ct_m;
5617 } else {
5618 char *fwd_type = NULL((void*)0);
5619
5620 if (switch_event_get_header(event, "forward_immediate")switch_event_get_header_idx(event, "forward_immediate", -1)) {
5621 fwd_type = "forwardImmediate";
5622 } else if (switch_event_get_header(event, "forward_busy")switch_event_get_header_idx(event, "forward_busy", -1)) {
5623 fwd_type = "forwardBusy";
5624 } else if (switch_event_get_header(event, "forward_no_answer")switch_event_get_header_idx(event, "forward_no_answer", -1)) {
5625 fwd_type = "forwardNoAns";
5626 }
5627
5628 // this will need some work to handle the different types of forwarding events
5629 write_csta_xml_chunk(event, stream, csta_event, fwd_type);
5630 }
5631 }
5632
5633 if (call_id) {
5634 sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,call_id,full_from,full_to,expires,'%q', '%q' "
5635 "from sip_subscriptions where event='as-feature-event' and call_id='%q'", stream.data, ct, call_id);
5636 } else {
5637 sql = switch_mprintf("select sip_user,sip_host,contact,profile_name,call_id,full_from,full_to,expires,'%q', '%q' "
5638 "from sip_subscriptions where event='as-feature-event' and sip_user='%q' and sip_host='%q'", stream.data, ct, switch_str_nil(user)(user ? user : ""), switch_str_nil(host)(host ? host : "")
5639 );
5640 }
5641
5642 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5642, ((void*)0)
, SWITCH_LOG_DEBUG, "Query: %s\n", sql);
5643 switch_safe_free(stream.data)if (stream.data) {free(stream.data);stream.data=((void*)0);};
5644 switch_mutex_lock(profile->ireg_mutex);
5645 sofia_glue_execute_sql_callback(profile, NULL((void*)0), sql, notify_csta_callback, profile);
5646 switch_mutex_unlock(profile->ireg_mutex);
5647 sofia_glue_release_profile(profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 5647, profile)
;
5648
5649 free(sql);
5650 } else {
5651 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5651, ((void*)0)
, SWITCH_LOG_NOTICE, "missing something\n");
5652 }
5653 switch_safe_free(ct_m)if (ct_m) {free(ct_m);ct_m=((void*)0);};
5654 }
5655 break;
5656 case SWITCH_EVENT_SEND_MESSAGE:
5657 {
5658 const char *profile_name = switch_event_get_header(event, "profile")switch_event_get_header_idx(event, "profile", -1);
5659 const char *ct = switch_event_get_header(event, "content-type")switch_event_get_header_idx(event, "content-type", -1);
5660 const char *user = switch_event_get_header(event, "user")switch_event_get_header_idx(event, "user", -1);
5661 const char *host = switch_event_get_header(event, "host")switch_event_get_header_idx(event, "host", -1);
5662 const char *subject = switch_event_get_header(event, "subject")switch_event_get_header_idx(event, "subject", -1);
5663 const char *uuid = switch_event_get_header(event, "uuid")switch_event_get_header_idx(event, "uuid", -1);
5664 const char *body = switch_event_get_body(event);
5665
5666 sofia_profile_t *profile;
5667 nua_handle_t *nh;
5668
5669 if (ct && user && host) {
5670 char *id = NULL((void*)0);
5671 char *contact, *p;
5672 switch_console_callback_match_t *list = NULL((void*)0);
5673 switch_console_callback_match_node_t *m;
5674
5675 if (!profile_name || !(profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 5675, profile_name)
)) {
5676 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5676, ((void*)0)
, SWITCH_LOG_ERROR, "Can't find profile %s\n", profile_name);
5677 return;
5678 }
5679
5680 if (!(list = sofia_reg_find_reg_url_multi(profile, user, host))) {
5681 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5681, ((void*)0)
, SWITCH_LOG_ERROR, "Can't find registered user %s@%s\n", user, host);
5682 sofia_glue_release_profile(profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 5682, profile)
;
5683 return;
5684 }
5685
5686 id = switch_mprintf("sip:%s@%s", user, host);
5687
5688 switch_assert(id)((id) ? (void) (0) : __assert_fail ("id", "mod_sofia.c", 5688
, __extension__ __PRETTY_FUNCTION__))
;
5689
5690 for (m = list->head; m; m = m->next) {
5691 contact = sofia_glue_get_url_from_contact(m->val, 0);
5692
5693 if ((p = strstr(contact, ";fs_"))) {
5694 *p = '\0';
5695 }
5696
5697 nh = nua_handle(profile->nua,
5698 NULL((void*)0), NUTAG_URL(contact)nutag_url, urltag_url_v(contact), SIPTAG_FROM_STR(id)siptag_from_str, tag_str_v(id), SIPTAG_TO_STR(id)siptag_to_str, tag_str_v(id), SIPTAG_CONTACT_STR(profile->url)siptag_contact_str, tag_str_v(profile->url), TAG_END()(tag_type_t)0, (tag_value_t)0);
5699
5700 nua_message(nh, NUTAG_NEWSUB(1)nutag_newsub, tag_bool_v(1), SIPTAG_CONTENT_TYPE_STR(ct)siptag_content_type_str, tag_str_v(ct),
5701 TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body))!(!_zstr(body)) ? tag_skip : siptag_payload_str, tag_str_v(body
)
, TAG_IF(!zstr(subject), SIPTAG_SUBJECT_STR(subject))!(!_zstr(subject)) ? tag_skip : siptag_subject_str, tag_str_v
(subject)
, TAG_END()(tag_type_t)0, (tag_value_t)0);
5702 }
5703
5704 free(id);
5705 switch_console_free_matches(&list);
5706
5707 sofia_glue_release_profile(profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 5707, profile)
;
5708 } else if (uuid && ct) {
5709 switch_core_session_t *session;
5710 private_object_t *tech_pvt;
5711
5712 if ((session = switch_core_session_locate(uuid)switch_core_session_perform_locate(uuid, "mod_sofia.c", (const
char *)__func__, 5712)
)) {
5713 if ((tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
)) {
5714 const char *session_id_header = sofia_glue_session_id_header(session, tech_pvt->profile);
5715
5716 nua_message(tech_pvt->nh,
5717 SIPTAG_CONTENT_TYPE_STR(ct)siptag_content_type_str, tag_str_v(ct), SIPTAG_PAYLOAD_STR(body)siptag_payload_str, tag_str_v(body),
5718 TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body))!(!_zstr(body)) ? tag_skip : siptag_payload_str, tag_str_v(body
)
, TAG_IF(!zstr(subject), SIPTAG_SUBJECT_STR(subject))!(!_zstr(subject)) ? tag_skip : siptag_subject_str, tag_str_v
(subject)
,
5719 TAG_IF(!zstr(session_id_header), SIPTAG_HEADER_STR(session_id_header))!(!_zstr(session_id_header)) ? tag_skip : siptag_header_str, tag_str_v
((session_id_header))
,
5720 TAG_END()(tag_type_t)0, (tag_value_t)0);
5721 }
5722 switch_core_session_rwunlock(session);
5723 }
5724 }
5725 }
5726 break;
5727 case SWITCH_EVENT_SEND_INFO:
5728 {
5729 const char *profile_name = switch_event_get_header(event, "profile")switch_event_get_header_idx(event, "profile", -1);
5730 const char *ct = switch_event_get_header(event, "content-type")switch_event_get_header_idx(event, "content-type", -1);
5731 const char *cd = switch_event_get_header(event, "content-disposition")switch_event_get_header_idx(event, "content-disposition", -1);
5732 const char *to_uri = switch_event_get_header(event, "to-uri")switch_event_get_header_idx(event, "to-uri", -1);
5733 const char *local_user_full = switch_event_get_header(event, "local-user")switch_event_get_header_idx(event, "local-user", -1);
5734 const char *from_uri = switch_event_get_header(event, "from-uri")switch_event_get_header_idx(event, "from-uri", -1);
5735 const char *call_info = switch_event_get_header(event, "call-info")switch_event_get_header_idx(event, "call-info", -1);
5736 const char *alert_info = switch_event_get_header(event, "alert-info")switch_event_get_header_idx(event, "alert-info", -1);
5737 const char *call_id = switch_event_get_header(event, "call-id")switch_event_get_header_idx(event, "call-id", -1);
5738 const char *body = switch_event_get_body(event);
5739 sofia_profile_t *profile = NULL((void*)0);
5740 nua_handle_t *nh;
5741 char *local_dup = NULL((void*)0);
5742 char *local_user, *local_host;
5743 char buf[1024] = "";
5744 char *p;
5745
5746 if (!profile_name) {
5747 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5747, ((void*)0)
, SWITCH_LOG_ERROR, "Missing Profile Name\n");
5748 goto done;
5749 }
5750
5751 if (!call_id && !to_uri && !local_user_full) {
5752 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5752, ((void*)0)
, SWITCH_LOG_ERROR, "Missing To-URI header\n");
5753 goto done;
5754 }
5755
5756 if (!call_id && !from_uri) {
5757 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5757, ((void*)0)
, SWITCH_LOG_ERROR, "Missing From-URI header\n");
5758 goto done;
5759 }
5760
5761
5762 if (!(profile = sofia_glue_find_profile(profile_name)sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 5762, profile_name)
)) {
5763 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5763, ((void*)0)
, SWITCH_LOG_ERROR, "Can't find profile %s\n", profile_name);
5764 goto done;
5765 }
5766
5767 if (call_id) {
5768 nh = nua_handle_by_call_id(profile->nua, call_id);
5769
5770 if (!nh) {
5771 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5771, ((void*)0)
, SWITCH_LOG_ERROR, "Invalid Call-ID %s\n", call_id);
5772 goto done;
5773 }
5774 } else {
5775 if (local_user_full) {
5776 local_dup = strdup(local_user_full);
5777 switch_assert(local_dup)((local_dup) ? (void) (0) : __assert_fail ("local_dup", "mod_sofia.c"
, 5777, __extension__ __PRETTY_FUNCTION__))
;
5778 local_user = local_dup;
5779 if ((local_host = strchr(local_user, '@'))) {
5780 *local_host++ = '\0';
5781 }
5782
5783 if (!local_host || !sofia_reg_find_reg_url(profile, local_user, local_host, buf, sizeof(buf))) {
5784 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5784, ((void*)0)
, SWITCH_LOG_ERROR, "Can't find local user\n");
5785 goto done;
5786 }
5787
5788 to_uri = sofia_glue_get_url_from_contact(buf, 0);
5789
5790 if ((p = strstr(to_uri, ";fs_"))) {
5791 *p = '\0';
5792 }
5793
5794 }
5795
5796 nh = nua_handle(profile->nua,
5797 NULL((void*)0), NUTAG_URL(to_uri)nutag_url, urltag_url_v(to_uri), SIPTAG_FROM_STR(from_uri)siptag_from_str, tag_str_v(from_uri), SIPTAG_TO_STR(to_uri)siptag_to_str, tag_str_v(to_uri), SIPTAG_CONTACT_STR(profile->url)siptag_contact_str, tag_str_v(profile->url), TAG_END()(tag_type_t)0, (tag_value_t)0);
5798
5799 nua_handle_bind(nh, &mod_sofia_globals.destroy_private);
5800 }
5801
5802 nua_info(nh,
5803 TAG_IF(ct, SIPTAG_CONTENT_TYPE_STR(ct))!(ct) ? tag_skip : siptag_content_type_str, tag_str_v(ct),
5804 TAG_IF(cd, SIPTAG_CONTENT_DISPOSITION_STR(cd))!(cd) ? tag_skip : siptag_content_disposition_str, tag_str_v(
cd)
,
5805 TAG_IF(alert_info, SIPTAG_ALERT_INFO_STR(alert_info))!(alert_info) ? tag_skip : siptag_alert_info_str, tag_str_v(alert_info
)
,
5806 TAG_IF(call_info, SIPTAG_CALL_INFO_STR(call_info))!(call_info) ? tag_skip : siptag_call_info_str, tag_str_v(call_info
)
, TAG_IF(!zstr(body), SIPTAG_PAYLOAD_STR(body))!(!_zstr(body)) ? tag_skip : siptag_payload_str, tag_str_v(body
)
, TAG_END()(tag_type_t)0, (tag_value_t)0);
5807
5808 if (call_id && nh) {
5809 nua_handle_unref_user(nh);
5810 }
5811
5812 done:
5813
5814 if (profile) {
5815 sofia_glue_release_profile(profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 5815, profile)
;
5816 }
5817
5818 switch_safe_free(local_dup)if (local_dup) {free(local_dup);local_dup=((void*)0);};
5819
5820 }
5821 break;
5822 case SWITCH_EVENT_TRAP:
5823 {
5824 const char *cond = switch_event_get_header(event, "condition")switch_event_get_header_idx(event, "condition", -1);
5825 switch_hash_index_t *hi;
5826 const void *var;
5827 void *val;
5828 sofia_profile_t *profile;
5829
5830 if (zstr(cond)_zstr(cond)) {
5831 cond = "";
5832 }
5833
5834 if (!strcmp(cond, "network-external-address-change") && mod_sofia_globals.auto_restart) {
5835 const char *old_ip4 = switch_event_get_header_nil(event, "network-external-address-previous-v4")(switch_event_get_header_idx(event, "network-external-address-previous-v4"
, -1) ? switch_event_get_header_idx(event, "network-external-address-previous-v4"
, -1) : "")
;
5836 const char *new_ip4 = switch_event_get_header_nil(event, "network-external-address-change-v4")(switch_event_get_header_idx(event, "network-external-address-change-v4"
, -1) ? switch_event_get_header_idx(event, "network-external-address-change-v4"
, -1) : "")
;
5837
5838 switch_mutex_lock(mod_sofia_globals.hash_mutex);
5839 if (mod_sofia_globals.profile_hash && !zstr(old_ip4)_zstr(old_ip4) && !zstr(new_ip4)_zstr(new_ip4)) {
5840 for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash)switch_core_hash_first_iter(mod_sofia_globals.profile_hash, (
(void*)0))
; hi; hi = switch_core_hash_next(&hi)) {
5841 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
5842
5843 if ((profile = (sofia_profile_t *) val)) {
5844 if (!zstr(profile->extsipip)_zstr(profile->extsipip) && !strcmp(profile->extsipip, old_ip4)) {
5845 profile->extsipip = switch_core_strdup(profile->pool, new_ip4)switch_core_perform_strdup(profile->pool, new_ip4, "mod_sofia.c"
, (const char *)__func__, 5845)
;
5846 }
5847
5848 if (!zstr(profile->extrtpip)_zstr(profile->extrtpip) && !strcmp(profile->extrtpip, old_ip4)) {
5849 profile->extrtpip = switch_core_strdup(profile->pool, new_ip4)switch_core_perform_strdup(profile->pool, new_ip4, "mod_sofia.c"
, (const char *)__func__, 5849)
;
5850 }
5851 }
5852 }
5853 }
5854 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
5855 sofia_glue_restart_all_profiles();
5856 } else if (!strcmp(cond, "network-address-change") && mod_sofia_globals.auto_restart) {
5857 const char *old_ip4 = switch_event_get_header_nil(event, "network-address-previous-v4")(switch_event_get_header_idx(event, "network-address-previous-v4"
, -1) ? switch_event_get_header_idx(event, "network-address-previous-v4"
, -1) : "")
;
5858 const char *new_ip4 = switch_event_get_header_nil(event, "network-address-change-v4")(switch_event_get_header_idx(event, "network-address-change-v4"
, -1) ? switch_event_get_header_idx(event, "network-address-change-v4"
, -1) : "")
;
5859 const char *old_ip6 = switch_event_get_header_nil(event, "network-address-previous-v6")(switch_event_get_header_idx(event, "network-address-previous-v6"
, -1) ? switch_event_get_header_idx(event, "network-address-previous-v6"
, -1) : "")
;
5860 const char *new_ip6 = switch_event_get_header_nil(event, "network-address-change-v6")(switch_event_get_header_idx(event, "network-address-change-v6"
, -1) ? switch_event_get_header_idx(event, "network-address-change-v6"
, -1) : "")
;
5861
5862 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5862, ((void*)0)
, SWITCH_LOG_INFO, "EVENT_TRAP: IP change detected\n");
5863 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
5863, ((void*)0)
, SWITCH_LOG_INFO, "IP change detected [%s]->[%s] [%s]->[%s]\n", old_ip4, new_ip4, old_ip6, new_ip6);
5864
5865 snprintf(mod_sofia_globals.guess_ip, sizeof(mod_sofia_globals.guess_ip), "%s", new_ip4);
5866
5867 switch_mutex_lock(mod_sofia_globals.hash_mutex);
5868 if (mod_sofia_globals.profile_hash) {
5869 for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash)switch_core_hash_first_iter(mod_sofia_globals.profile_hash, (
(void*)0))
; hi; hi = switch_core_hash_next(&hi)) {
5870 int rb = 0;
5871 uint32_t x = 0;
5872 switch_core_hash_this(hi, &var, NULL((void*)0), &val);
5873 if ((profile = (sofia_profile_t *) val) && profile->auto_restart) {
5874 if (!strcmp(profile->sipip, old_ip4)) {
5875 profile->sipip = switch_core_strdup(profile->pool, new_ip4)switch_core_perform_strdup(profile->pool, new_ip4, "mod_sofia.c"
, (const char *)__func__, 5875)
;
5876 rb++;
5877 }
5878
5879 for (x = 0; x < profile->rtpip_index; x++) {
5880
5881 if (!strcmp(profile->rtpip[x], old_ip4)) {
5882 profile->rtpip[x] = switch_core_strdup(profile->pool, new_ip4)switch_core_perform_strdup(profile->pool, new_ip4, "mod_sofia.c"
, (const char *)__func__, 5882)
;
5883 rb++;
5884 }
5885
5886 if (!strcmp(profile->rtpip[x], old_ip6)) {
5887 profile->rtpip6[x] = switch_core_strdup(profile->pool, new_ip6)switch_core_perform_strdup(profile->pool, new_ip6, "mod_sofia.c"
, (const char *)__func__, 5887)
;
5888 rb++;
5889 }
5890 }
5891
5892
5893 if (!strcmp(profile->sipip, old_ip6)) {
5894 profile->sipip = switch_core_strdup(profile->pool, new_ip6)switch_core_perform_strdup(profile->pool, new_ip6, "mod_sofia.c"
, (const char *)__func__, 5894)
;
5895 rb++;
5896 }
5897
5898 if (rb) {
5899 sofia_set_pflag_locked(profile, PFLAG_RESPAWN)((profile->flag_mutex != ((void*)0)) ? (void) (0) : __assert_fail
("profile->flag_mutex != NULL", "mod_sofia.c", 5899, __extension__
__PRETTY_FUNCTION__));switch_mutex_lock(profile->flag_mutex
);(profile)->pflags[PFLAG_RESPAWN] = 1;switch_mutex_unlock
(profile->flag_mutex);
;
5900 sofia_clear_pflag_locked(profile, PFLAG_RUNNING)switch_mutex_lock(profile->flag_mutex); (profile)->pflags
[PFLAG_RUNNING] = 0; switch_mutex_unlock(profile->flag_mutex
);
;
5901 }
5902 }
5903 }
5904 }
5905 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
5906 }
5907
5908 }
5909 break;
5910 default:
5911 break;
5912 }
5913}
5914
5915static void general_queue_event_handler(switch_event_t *event)
5916{
5917 switch_event_t *dup;
5918 switch_event_dup(&dup, event);
5919 switch_queue_push(mod_sofia_globals.general_event_queue, dup);
5920}
5921
5922
5923void write_csta_xml_chunk(switch_event_t *event, switch_stream_handle_t stream, const char *csta_event, char *fwdtype)
5924{
5925 const char *device = switch_event_get_header(event, "device")switch_event_get_header_idx(event, "device", -1);
5926
5927 switch_assert(csta_event)((csta_event) ? (void) (0) : __assert_fail ("csta_event", "mod_sofia.c"
, 5927, __extension__ __PRETTY_FUNCTION__))
;
5928
5929 stream.write_function(&stream, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<%s xmlns=\"http://www.ecma-international.org/standards/ecma-323/csta/ed3\">\n", csta_event);
5930
5931 if (device) {
5932 stream.write_function(&stream, " <device>%s</device>\n", device);
5933 }
5934
5935 if (!strcmp(csta_event, "DoNotDisturbEvent")) {
5936 const char *dndstatus = switch_event_get_header(event, "doNotDisturbOn")switch_event_get_header_idx(event, "doNotDisturbOn", -1);
5937
5938 if (dndstatus) {
5939 stream.write_function(&stream, " <doNotDisturbOn>%s</doNotDisturbOn>\n", dndstatus);
5940 }
5941 } else if(!strcmp(csta_event, "ForwardingEvent")) {
5942 const char *fwdstatus = NULL((void*)0);
5943 const char *fwdto = NULL((void*)0);
5944 const char *ringcount = NULL((void*)0);
5945
5946 if (fwdtype && !zstr(fwdtype)_zstr(fwdtype)) {
5947 if (!strcmp("forwardImmediate", fwdtype)) {
5948 fwdto = switch_event_get_header(event, "forward_immediate")switch_event_get_header_idx(event, "forward_immediate", -1);
5949 fwdstatus = switch_event_get_header(event, "forward_immediate_enabled")switch_event_get_header_idx(event, "forward_immediate_enabled"
, -1)
;
5950 } else if (!strcmp("forwardBusy", fwdtype)) {
5951 fwdto = switch_event_get_header(event, "forward_busy")switch_event_get_header_idx(event, "forward_busy", -1);
5952 fwdstatus = switch_event_get_header(event, "forward_busy_enabled")switch_event_get_header_idx(event, "forward_busy_enabled", -1
)
;
5953 } else if (!strcmp("forwardNoAns", fwdtype)) {
5954 fwdto = switch_event_get_header(event, "forward_no_answer")switch_event_get_header_idx(event, "forward_no_answer", -1);
5955 fwdstatus = switch_event_get_header(event, "forward_no_answer_enabled")switch_event_get_header_idx(event, "forward_no_answer_enabled"
, -1)
;
5956 ringcount = switch_event_get_header(event, "ringCount")switch_event_get_header_idx(event, "ringCount", -1);
5957 }
5958
5959 stream.write_function(&stream, " <forwardingType>%s</forwardingType>\n", fwdtype);
5960 if (fwdstatus) {
5961 stream.write_function(&stream, " <forwardStatus>%s</forwardStatus>\n", fwdstatus);
5962 }
5963 if (fwdto) {
5964 stream.write_function(&stream, " <forwardTo>%s</forwardTo>\n", fwdto);
5965 }
5966 if (ringcount) {
5967 stream.write_function(&stream, " <ringCount>%s</ringCount>\n", ringcount);
5968 }
5969 }
5970 }
5971
5972 stream.write_function(&stream, "</%s>\n", csta_event);
5973}
5974
5975switch_status_t list_profiles_full(const char *line, const char *cursor, switch_console_callback_match_t **matches, switch_bool_t show_aliases)
5976{
5977 sofia_profile_t *profile = NULL((void*)0);
5978 switch_hash_index_t *hi;
5979 void *val;
5980 const void *vvar;
5981 switch_console_callback_match_t *my_matches = NULL((void*)0);
5982 switch_status_t status = SWITCH_STATUS_FALSE;
5983
5984 switch_mutex_lock(mod_sofia_globals.hash_mutex);
5985 for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash)switch_core_hash_first_iter(mod_sofia_globals.profile_hash, (
(void*)0))
; hi; hi = switch_core_hash_next(&hi)) {
5986 switch_core_hash_this(hi, &vvar, NULL((void*)0), &val);
5987
5988 profile = (sofia_profile_t *) val;
5989 if (!show_aliases && strcmp((char *)vvar, profile->name)) {
5990 continue;
5991 }
5992
5993 if (sofia_test_pflag(profile, PFLAG_RUNNING)((profile)->pflags[PFLAG_RUNNING] ? 1 : 0)) {
5994 switch_console_push_match(&my_matches, (const char *) vvar);
5995 }
5996 }
5997 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
5998
5999 if (my_matches) {
6000 *matches = my_matches;
6001 status = SWITCH_STATUS_SUCCESS;
6002 }
6003
6004
6005 return status;
6006}
6007
6008switch_status_t list_profiles(const char *line, const char *cursor, switch_console_callback_match_t **matches)
6009{
6010 return list_profiles_full(line, cursor, matches, SWITCH_TRUE);
6011}
6012
6013static switch_status_t list_gateways(const char *line, const char *cursor, switch_console_callback_match_t **matches)
6014{
6015 sofia_profile_t *profile = NULL((void*)0);
6016 switch_hash_index_t *hi;
6017 void *val;
6018 const void *vvar;
6019 switch_console_callback_match_t *my_matches = NULL((void*)0);
6020 switch_status_t status = SWITCH_STATUS_FALSE;
6021
6022 switch_mutex_lock(mod_sofia_globals.hash_mutex);
6023 for (hi = switch_core_hash_first(mod_sofia_globals.profile_hash)switch_core_hash_first_iter(mod_sofia_globals.profile_hash, (
(void*)0))
; hi; hi = switch_core_hash_next(&hi)) {
6024 switch_core_hash_this(hi, &vvar, NULL((void*)0), &val);
6025 profile = (sofia_profile_t *) val;
6026 if (sofia_test_pflag(profile, PFLAG_RUNNING)((profile)->pflags[PFLAG_RUNNING] ? 1 : 0)) {
6027 sofia_gateway_t *gp;
6028 switch_mutex_lock(profile->gw_mutex);
6029 for (gp = profile->gateways; gp; gp = gp->next) {
6030 switch_console_push_match(&my_matches, gp->name);
6031 }
6032 switch_mutex_unlock(profile->gw_mutex);
6033 }
6034 }
6035 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
6036
6037 if (my_matches) {
6038 *matches = my_matches;
6039 status = SWITCH_STATUS_SUCCESS;
6040 }
6041
6042 return status;
6043}
6044
6045
6046static switch_status_t list_profile_gateway(const char *line, const char *cursor, switch_console_callback_match_t **matches)
6047{
6048 sofia_profile_t *profile = NULL((void*)0);
6049 switch_console_callback_match_t *my_matches = NULL((void*)0);
6050 switch_status_t status = SWITCH_STATUS_FALSE;
6051 char *dup = NULL((void*)0);
6052 //int argc;
6053 char *argv[4] = { 0 };
6054
6055 if (zstr(line)_zstr(line)) {
6056 return SWITCH_STATUS_FALSE;
6057 }
6058
6059 dup = strdup(line);
6060 switch_split(dup, ' ', argv)switch_separate_string(dup, ' ', argv, (sizeof(argv) / sizeof
(argv[0])))
;
6061
6062 if (zstr(argv[2])_zstr(argv[2]) || !strcmp(argv[2], " ")) {
6063 goto end;
6064 }
6065
6066 if ((profile = sofia_glue_find_profile(argv[2])sofia_glue_find_profile__("mod_sofia.c", (const char *)__func__
, 6066, argv[2])
)) {
6067 sofia_gateway_t *gp;
6068 for (gp = profile->gateways; gp; gp = gp->next) {
6069 switch_console_push_match(&my_matches, gp->name);
6070 }
6071 sofia_glue_release_profile(profile)sofia_glue_release_profile__("mod_sofia.c", (const char *)__func__
, 6071, profile)
;
6072 }
6073
6074 if (my_matches) {
6075 *matches = my_matches;
6076 status = SWITCH_STATUS_SUCCESS;
6077 }
6078
6079 end:
6080
6081 switch_safe_free(dup)if (dup) {free(dup);dup=((void*)0);};
6082
6083 return status;
6084}
6085
6086SWITCH_STANDARD_APP(sofia_sla_function)static void sofia_sla_function (switch_core_session_t *session
, const char *data)
6087{
6088 private_object_t *tech_pvt;
6089 switch_core_session_t *bargee_session;
6090 switch_channel_t *channel = switch_core_session_get_channel(session);
6091
6092 if (zstr(data)_zstr(data)) {
6093 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6093, (const char*)(session)
, SWITCH_LOG_ERROR, "Usage: <uuid>\n");
6094 return;
6095 }
6096
6097 switch_channel_answer(channel)switch_channel_perform_answer(channel, "mod_sofia.c", (const char
*)__func__, 6097)
;
6098
6099 if ((bargee_session = switch_core_session_locate((char *)data)switch_core_session_perform_locate((char *)data, "mod_sofia.c"
, (const char *)__func__, 6099)
)) {
6100 if (bargee_session == session) {
6101 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6101, ((void*)0)
, SWITCH_LOG_WARNING, "BARGE: %s (cannot barge on myself)\n", (char *) data);
6102 } else {
6103
6104 if (switch_core_session_check_interface(bargee_session, sofia_endpoint_interface)) {
6105 tech_pvt = switch_core_session_get_private(bargee_session)switch_core_session_get_private_class(bargee_session, SWITCH_PVT_PRIMARY
)
;
6106 switch_channel_clear_flag(tech_pvt->channel, CF_SLA_BARGING);
6107 switch_channel_set_flag(tech_pvt->channel, CF_SLA_BARGE)switch_channel_set_flag_value(tech_pvt->channel, CF_SLA_BARGE
, 1)
;
6108 switch_ivr_transfer_variable(bargee_session, session, SWITCH_SIGNAL_BOND_VARIABLE"signal_bond");
6109 }
6110
6111 if (switch_core_session_check_interface(session, sofia_endpoint_interface)) {
6112 tech_pvt = switch_core_session_get_private(session)switch_core_session_get_private_class(session, SWITCH_PVT_PRIMARY
)
;
6113 switch_channel_set_flag(tech_pvt->channel, CF_SLA_BARGING)switch_channel_set_flag_value(tech_pvt->channel, CF_SLA_BARGING
, 1)
;
6114 }
6115
6116 switch_channel_set_variable(channel, "sip_barging_uuid", (char *)data)switch_channel_set_variable_var_check(channel, "sip_barging_uuid"
, (char *)data, SWITCH_TRUE)
;
6117 }
6118
6119 switch_core_session_rwunlock(bargee_session);
6120 }
6121
6122 switch_channel_execute_on(channel, "execute_on_sip_barge");
6123
6124 switch_ivr_eavesdrop_session(session, data, NULL((void*)0), ED_MUX_READ | ED_MUX_WRITE | ED_COPY_DISPLAY);
6125}
6126
6127#if HAVE_STIRSHAKEN1
6128static stir_shaken_as_t *sofia_stir_shaken_as = NULL((void*)0);
6129static stir_shaken_vs_t *sofia_stir_shaken_vs = NULL((void*)0);
6130
6131static switch_status_t sofia_stir_shaken_vs_create(stir_shaken_context_t *context)
6132{
6133 sofia_stir_shaken_vs = stir_shaken_vs_create(context);
6134 if (!sofia_stir_shaken_vs) {
6135 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6135, ((void*)0)
, SWITCH_LOG_ERROR, "Failed to create Identity verification service!\n");
6136 return SWITCH_STATUS_FALSE;
6137 }
6138 if (mod_sofia_globals.stir_shaken_vs_ca_dir) {
6139 stir_shaken_vs_load_ca_dir(context, sofia_stir_shaken_vs, mod_sofia_globals.stir_shaken_vs_ca_dir);
6140 }
6141 stir_shaken_vs_set_x509_cert_path_check(context, sofia_stir_shaken_vs, mod_sofia_globals.stir_shaken_vs_cert_path_check);
6142 stir_shaken_vs_set_connect_timeout(context, sofia_stir_shaken_vs, 3);
6143 //stir_shaken_vs_set_callback(context, sofia_stir_shaken_vs, shaken_callback);
6144 return SWITCH_STATUS_SUCCESS;
6145}
6146
6147static switch_status_t sofia_stir_shaken_as_create(stir_shaken_context_t *context)
6148{
6149 if (mod_sofia_globals.stir_shaken_as_key && mod_sofia_globals.stir_shaken_as_url) {
6150 sofia_stir_shaken_as = stir_shaken_as_create(context);
6151 if (!sofia_stir_shaken_as) {
6152 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6152, ((void*)0)
, SWITCH_LOG_ERROR, "Failed to create Identity authentication service!\n");
6153 return SWITCH_STATUS_FALSE;
6154 }
6155 if (stir_shaken_as_load_private_key(context, sofia_stir_shaken_as, mod_sofia_globals.stir_shaken_as_key) != STIR_SHAKEN_STATUS_OK) {
6156 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6156, ((void*)0)
, SWITCH_LOG_ERROR, "Failed to load key for Identity authentication service: %s", mod_sofia_globals.stir_shaken_as_key);
6157 stir_shaken_as_destroy(&sofia_stir_shaken_as);
6158 return SWITCH_STATUS_FALSE;
6159 }
6160 }
6161 return SWITCH_STATUS_SUCCESS;
6162}
6163#endif
6164
6165static void sofia_stir_shaken_create_services(void)
6166{
6167#if HAVE_STIRSHAKEN1
6168 stir_shaken_context_t context = { 0 };
6169 if (stir_shaken_init(&context, STIR_SHAKEN_LOGLEVEL_NOTHING0) != STIR_SHAKEN_STATUS_OK) {
6170 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6170, ((void*)0)
, SWITCH_LOG_CRIT, "Failed to initialize stirshaken library!\n");
6171 return;
6172 }
6173 sofia_stir_shaken_vs_create(&context);
6174 sofia_stir_shaken_as_create(&context);
6175#endif
6176}
6177
6178static void sofia_stir_shaken_destroy_services(void)
6179{
6180#if HAVE_STIRSHAKEN1
6181 stir_shaken_vs_destroy(&sofia_stir_shaken_vs);
6182 stir_shaken_as_destroy(&sofia_stir_shaken_as);
6183 stir_shaken_deinit();
6184#endif
6185}
6186
6187#if HAVE_STIRSHAKEN1
6188static char *canonicalize_phone_number(const char *number)
6189{
6190 // remove all characters except for digits, *, and # from the phone number
6191 // TODO determine if dial number and remove dial codes or add country code
6192 char *canonicalized_number = strdup(number ? number : "");
6193 size_t i = 0, j = 0;
6194 size_t number_len = strlen(canonicalized_number);
6195 for (i = 0; i < number_len; i++) {
6196 if (isdigit(canonicalized_number[i])((*__ctype_b_loc ())[(int) ((canonicalized_number[i]))] &
(unsigned short int) _ISdigit)
|| canonicalized_number[i] == '#' || canonicalized_number[i] == '*') {
6197 canonicalized_number[j] = canonicalized_number[i];
6198 j++;
6199 }
6200 }
6201 canonicalized_number[j] = '\0';
6202 return canonicalized_number;
6203}
6204
6205static switch_status_t sofia_stir_shaken_validate_passport_claims(switch_core_session_t *session, long iat, const char *orig, int orig_is_tn, const char *dest, int dest_is_tn)
6206{
6207 switch_channel_t *channel = switch_core_session_get_channel(session);
6208 const char *from = NULL((void*)0);
6209 const char *to = NULL((void*)0);
6210 char *canonicalized_from = NULL((void*)0);
6211 char *canonicalized_to = NULL((void*)0);
6212 switch_status_t status = SWITCH_STATUS_FALSE;
6213 switch_time_t now = switch_epoch_time_now(NULL((void*)0));
6214
6215 if (iat > now) {
6216 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6216, (const char*)(session)
, SWITCH_LOG_WARNING, "PASSporT iat is in the future\n");
6217 return SWITCH_STATUS_FALSE;
6218 } else if (now - iat > 60) {
6219 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6219, (const char*)(session)
, SWITCH_LOG_WARNING, "PASSporT iat is too old\n");
6220 return SWITCH_STATUS_FALSE;
6221 }
6222
6223 if (mod_sofia_globals.stir_shaken_vs_require_date || switch_true(switch_channel_get_variable(channel, "sip_stir_shaken_vs_require_date")switch_channel_get_variable_dup(channel, "sip_stir_shaken_vs_require_date"
, SWITCH_TRUE, -1)
)) {
6224 const char *sip_epoch_time_var = switch_channel_get_variable(channel, "sip_date_epoch_time")switch_channel_get_variable_dup(channel, "sip_date_epoch_time"
, SWITCH_TRUE, -1)
;
6225 switch_time_t sip_epoch_time;
6226
6227 if (zstr(sip_epoch_time_var)_zstr(sip_epoch_time_var)) {
6228 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6228, (const char*)(session)
, SWITCH_LOG_WARNING, "Missing required SIP Date\n");
6229 return SWITCH_STATUS_FALSE;
6230 }
6231 sip_epoch_time = strtol(sip_epoch_time_var, NULL((void*)0), 10);
6232 if (sip_epoch_time > now) {
6233 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6233, (const char*)(session)
, SWITCH_LOG_WARNING, "SIP Date %s is in the future\n", sip_epoch_time_var);
6234 return SWITCH_STATUS_FALSE;
6235 }
6236 if (now - sip_epoch_time > 60) {
6237 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6237, (const char*)(session)
, SWITCH_LOG_WARNING, "SIP Date %s is too old\n", sip_epoch_time_var);
6238 return SWITCH_STATUS_FALSE;
6239 }
6240 if ((iat > sip_epoch_time && iat - sip_epoch_time > 60) || (iat < sip_epoch_time && sip_epoch_time - iat > 60)) {
6241 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6241, (const char*)(session)
, SWITCH_LOG_WARNING, "SIP Date %s is too far from PASSporT iat %ld\n", sip_epoch_time_var, iat);
6242 return SWITCH_STATUS_FALSE;
6243 }
6244 // Date is within 60 seconds of now and within 60 seconds of iat
6245 }
6246
6247 if (orig_is_tn) {
6248 from = switch_channel_get_variable(channel, "sip_from_user")switch_channel_get_variable_dup(channel, "sip_from_user", SWITCH_TRUE
, -1)
;
6249 from = canonicalized_from = canonicalize_phone_number(from);
6250 } else {
6251 from = switch_channel_get_variable(channel, "sip_from_uri")switch_channel_get_variable_dup(channel, "sip_from_uri", SWITCH_TRUE
, -1)
;
6252 }
6253 if (dest_is_tn) {
6254 to = switch_channel_get_variable(channel, "sip_to_user")switch_channel_get_variable_dup(channel, "sip_to_user", SWITCH_TRUE
, -1)
;
6255 to = canonicalized_to = canonicalize_phone_number(to);
6256 } else {
6257 to = switch_channel_get_variable(channel, "sip_to_uri")switch_channel_get_variable_dup(channel, "sip_to_uri", SWITCH_TRUE
, -1)
;
6258 }
6259
6260 if (zstr(from)_zstr(from) || zstr(to)_zstr(to) || zstr(orig)_zstr(orig) || zstr(dest)_zstr(dest)) {
6261 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6261, (const char*)(session)
, SWITCH_LOG_WARNING, "Missing data to verify SIP From/To matches PASSporT claims. From=%s, To=%s, orig=%s, dest=%s\n", from, to, orig, dest);
6262 status = SWITCH_STATUS_FALSE;
6263 } else if (strcmp(orig, from) || strcmp(dest, to)) {
6264 status = SWITCH_STATUS_FALSE;
6265 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6265, (const char*)(session)
, SWITCH_LOG_WARNING, "SIP From/To does not match PASSporT claims. From=%s, To=%s, orig=%s, dest=%s\n", from, to, orig, dest);
6266 } else {
6267 status = SWITCH_STATUS_SUCCESS;
6268 }
6269 switch_safe_free(canonicalized_from)if (canonicalized_from) {free(canonicalized_from);canonicalized_from
=((void*)0);}
;
6270 switch_safe_free(canonicalized_to)if (canonicalized_to) {free(canonicalized_to);canonicalized_to
=((void*)0);}
;
6271 return status;
6272}
6273
6274/**
6275 * Returns first dest if found. Must be freed by caller.
6276 */
6277static char* sofia_stir_shaken_passport_get_dest(stir_shaken_passport_t *passport, int *is_tn)
6278{
6279 char *id = NULL((void*)0);
6280 char *dest = NULL((void*)0);
6281 int tn_form = 0;
6282 int id_int = 0;
6283 cJSON *item = NULL((void*)0);
6284 cJSON *destjson = NULL((void*)0);
6285 stir_shaken_context_t ss = { 0 };
6286
6287 if (!passport) return NULL((void*)0);
6288
6289 dest = stir_shaken_passport_get_grants_json(&ss, passport, "dest");
6290 if (!dest) {
6291 return NULL((void*)0);
6292 }
6293
6294 destjson = cJSON_Parse(dest);
6295 if (!destjson) {
6296 free(dest);
6297 return NULL((void*)0);
6298 }
6299
6300 if ((item = cJSON_GetObjectItem(destjson, "tn"))) {
6301 tn_form = 1;
6302 } else if ((item = cJSON_GetObjectItem(destjson, "uri"))) {
6303 tn_form = 0;
6304 } else {
6305 cJSON_Delete(destjson);
6306 free(dest);
6307 return NULL((void*)0);
6308 }
6309
6310 if (cJSON_IsArray(item)) {
6311 item = cJSON_GetArrayItem(item, 0);
6312 if (!item) {
6313 cJSON_Delete(destjson);
6314 free(dest);
6315 return NULL((void*)0);
6316 }
6317 } else {
6318 item = destjson;
6319 }
6320
6321 if (cJSON_IsString(item)) {
6322 id = strdup(item->valuestring);
6323 } else if (cJSON_IsNumber(item)) {
6324 id_int = item->valueint;
6325 id = malloc(20);
6326 if (!id) {
6327 cJSON_Delete(destjson);
6328 free(dest);
6329 return NULL((void*)0);
6330 }
6331 snprintf(id, 20, "%d", id_int);
6332 } else {
6333 cJSON_Delete(destjson);
6334 free(dest);
6335 return NULL((void*)0);
6336 }
6337
6338 if (is_tn) *is_tn = tn_form;
6339 cJSON_Delete(destjson);
6340 free(dest);
6341 return id;
6342}
6343
6344
6345#endif
6346
6347// TODO Date header must be present
6348// Date header must be < (expiration policy) age
6349// Date header must be within 1 minute of iat
6350
6351
6352/* Check signature in Identity header and save result to sip_verstat */
6353SWITCH_STANDARD_APP(sofia_stir_shaken_vs_function)static void sofia_stir_shaken_vs_function (switch_core_session_t
*session, const char *data)
6354{
6355 switch_channel_t *channel = switch_core_session_get_channel(session);
6356#if HAVE_STIRSHAKEN1
6357 stir_shaken_status_t verify_signature_status = STIR_SHAKEN_STATUS_FALSE;
6358 stir_shaken_context_t verify_signature_context = { 0 };
6359 stir_shaken_status_t validate_passport_status = STIR_SHAKEN_STATUS_FALSE;
6360 stir_shaken_context_t validate_passport_context = { 0 };
6361 stir_shaken_context_t get_grant_context = { 0 };
6362 stir_shaken_passport_t *passport = NULL((void*)0);
6363 stir_shaken_cert_t *cert = NULL((void*)0);
6364 stir_shaken_error_t stir_error = { 0 };
6365 switch_status_t claim_status = SWITCH_STATUS_FALSE;
6366 const char *identity_header = switch_channel_get_variable(channel, "sip_h_identity")switch_channel_get_variable_dup(channel, "sip_h_identity", SWITCH_TRUE
, -1)
;
6367 const char *attestation = NULL((void*)0);
6368 int orig_is_tn = 0;
6369 switch_bool_t hangup_on_fail = switch_true(switch_channel_get_variable(channel, "sip_stir_shaken_vs_hangup_on_fail")switch_channel_get_variable_dup(channel, "sip_stir_shaken_vs_hangup_on_fail"
, SWITCH_TRUE, -1)
);
6370
6371 // TODO: compact Identity header is not supported - this will require construction of PASSporT from SIP headers in order to check signature
6372
6373 if (zstr(identity_header)_zstr(identity_header)) {
6374 // Nothing to do
6375 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6375, (const char*)(session)
, SWITCH_LOG_DEBUG, "No-TN-Validation: no SIP Identity\n");
6376 switch_channel_set_variable(channel, "sip_verstat_detailed", "No-TN-Validation")switch_channel_set_variable_var_check(channel, "sip_verstat_detailed"
, "No-TN-Validation", SWITCH_TRUE)
;
6377 switch_channel_set_variable(channel, "sip_verstat", "No-TN-Validation")switch_channel_set_variable_var_check(channel, "sip_verstat",
"No-TN-Validation", SWITCH_TRUE)
;
6378 if (hangup_on_fail) {
6379 switch_channel_hangup(channel, SWITCH_CAUSE_NO_IDENTITY)switch_channel_perform_hangup(channel, "mod_sofia.c", (const char
*)__func__, 6379, SWITCH_CAUSE_NO_IDENTITY)
;
6380 }
6381 goto done;
6382 }
6383
6384 // verify the JWT signature in the SIP Identity header
6385 verify_signature_status = stir_shaken_vs_sih_verify(&verify_signature_context, sofia_stir_shaken_vs, identity_header, &cert, &passport);
6386 if (verify_signature_status != STIR_SHAKEN_STATUS_OK) {
6387 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6387, (const char*)(session)
, SWITCH_LOG_DEBUG, "PASSporT failed signature verification: %s\n", stir_shaken_get_error(&verify_signature_context, &stir_error));
6388 if (hangup_on_fail) {
6389 switch_channel_hangup(channel, SWITCH_CAUSE_INVALID_IDENTITY)switch_channel_perform_hangup(channel, "mod_sofia.c", (const char
*)__func__, 6389, SWITCH_CAUSE_INVALID_IDENTITY)
;
6390 goto done;
6391 }
6392 } else {
6393 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6393, (const char*)(session)
, SWITCH_LOG_DEBUG, "PASSporT passed signature verification\n");
6394 }
6395
6396 if (passport) {
6397 // validate the PASSporT is not expired
6398 int timeout = 60;
6399 const char *timeout_str = switch_channel_get_variable(channel, "sip_stir_shaken_vs_max_age")switch_channel_get_variable_dup(channel, "sip_stir_shaken_vs_max_age"
, SWITCH_TRUE, -1)
;
6400 if (timeout_str && switch_is_number(timeout_str)) {
6401 int new_timeout = atoi(timeout_str);
6402 if (new_timeout > 0) {
6403 timeout = new_timeout;
6404 }
6405 }
6406 validate_passport_status = stir_shaken_passport_validate_iat_against_freshness(&validate_passport_context, passport, timeout);
6407 if (validate_passport_status != STIR_SHAKEN_STATUS_OK) {
6408 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6408, (const char*)(session)
, SWITCH_LOG_DEBUG, "PASSporT failed stale check: %s\n", stir_shaken_get_error(&validate_passport_context, &stir_error));
6409 if (hangup_on_fail) {
6410 switch_channel_hangup(channel, SWITCH_CAUSE_STALE_DATE)switch_channel_perform_hangup(channel, "mod_sofia.c", (const char
*)__func__, 6410, SWITCH_CAUSE_STALE_DATE)
;
6411 goto done;
6412 }
6413 } else {
6414 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6414, (const char*)(session)
, SWITCH_LOG_DEBUG, "PASSporT passed stale check\n");
6415 }
6416
6417 // validate the required PASSporT headers and grants are set
6418 validate_passport_status = stir_shaken_passport_validate_headers_and_grants(&validate_passport_context, passport);
6419 if (validate_passport_status != STIR_SHAKEN_STATUS_OK) {
6420 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6420, (const char*)(session)
, SWITCH_LOG_DEBUG, "PASSporT failed header and grant validation: %s\n", stir_shaken_get_error(&validate_passport_context, &stir_error));
6421 if (hangup_on_fail) {
6422 switch_channel_hangup(channel, SWITCH_CAUSE_INVALID_IDENTITY)switch_channel_perform_hangup(channel, "mod_sofia.c", (const char
*)__func__, 6422, SWITCH_CAUSE_INVALID_IDENTITY)
;
6423 if (validate_passport_status == STIR_SHAKEN_STATUS_OK && verify_signature_status == STIR_SHAKEN_STATUS_OK) {
6424 switch_channel_hangup(channel, SWITCH_CAUSE_INCOMING_CALL_BARRED)switch_channel_perform_hangup(channel, "mod_sofia.c", (const char
*)__func__, 6424, SWITCH_CAUSE_INCOMING_CALL_BARRED)
;
6425 } else {
6426 switch_channel_hangup(channel, SWITCH_CAUSE_INVALID_IDENTITY)switch_channel_perform_hangup(channel, "mod_sofia.c", (const char
*)__func__, 6426, SWITCH_CAUSE_INVALID_IDENTITY)
;
6427 }
6428 goto done;
6429 }
6430 } else {
6431 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6431, (const char*)(session)
, SWITCH_LOG_DEBUG, "PASSporT passed header and grant validation\n");
6432 }
6433 }
6434
6435 if (passport) {
6436 // validate the PASSporT claims match the SIP headers
6437 stir_shaken_context_t validate_claims_context = { 0 };
6438 int dest_is_tn = 0;
6439 char *orig = stir_shaken_passport_get_identity(&validate_claims_context, passport, &orig_is_tn);
6440 char *dest = sofia_stir_shaken_passport_get_dest(passport, &dest_is_tn); // TODO libstirshaken should provide helper for 'dest' values
6441 long iat = stir_shaken_passport_get_grant_int(&validate_claims_context, passport, "iat");
6442 claim_status = sofia_stir_shaken_validate_passport_claims(session, iat, orig, orig_is_tn, dest, dest_is_tn);
6443 if (claim_status != SWITCH_STATUS_SUCCESS) {
6444 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6444, (const char*)(session)
, SWITCH_LOG_DEBUG, "PASSporT claims do not match SIP request\n");
6445 if (hangup_on_fail) {
6446 switch_channel_hangup(channel, SWITCH_CAUSE_INVALID_IDENTITY)switch_channel_perform_hangup(channel, "mod_sofia.c", (const char
*)__func__, 6446, SWITCH_CAUSE_INVALID_IDENTITY)
;
6447 switch_safe_free(orig)if (orig) {free(orig);orig=((void*)0);};
6448 switch_safe_free(dest)if (dest) {free(dest);dest=((void*)0);};
6449 goto done;
6450 }
6451 } else {
6452 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6452, (const char*)(session)
, SWITCH_LOG_DEBUG, "PASSporT claims match SIP request\n");
6453 }
6454 switch_safe_free(orig)if (orig) {free(orig);orig=((void*)0);};
6455 switch_safe_free(dest)if (dest) {free(dest);dest=((void*)0);};
6456 }
6457
6458 attestation = stir_shaken_passport_get_grant(&get_grant_context, passport, "attest");
6459
6460 if (!zstr(attestation)_zstr(attestation) && verify_signature_status == STIR_SHAKEN_STATUS_OK && validate_passport_status == STIR_SHAKEN_STATUS_OK && claim_status == SWITCH_STATUS_SUCCESS) {
6461 if (orig_is_tn) {
6462 switch_channel_set_variable_printf(channel, "sip_verstat_detailed", "TN-Validation-Passed-%s", attestation);
6463 } else {
6464 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6464, (const char*)(session)
, SWITCH_LOG_DEBUG, "No-TN-Validation: PASSporT orig is not a telephone number\n");
6465 switch_channel_set_variable(channel, "sip_verstat", "No-TN-Validation")switch_channel_set_variable_var_check(channel, "sip_verstat",
"No-TN-Validation", SWITCH_TRUE)
;
6466 }
6467 if (orig_is_tn && !strcmp(attestation, "A")) {
6468 // Signature is valid and call has "A" attestation
6469 switch_channel_set_variable(channel, "sip_verstat", "TN-Validation-Passed")switch_channel_set_variable_var_check(channel, "sip_verstat",
"TN-Validation-Passed", SWITCH_TRUE)
;
6470 } else {
6471 // Signature is valid and call has "B" or "C" attestation or is not from a phone number
6472 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6472, (const char*)(session)
, SWITCH_LOG_DEBUG, "No-TN-Validation: PASSporT only has \"%s\" attestation\n", attestation);
6473 switch_channel_set_variable(channel, "sip_verstat", "No-TN-Validation")switch_channel_set_variable_var_check(channel, "sip_verstat",
"No-TN-Validation", SWITCH_TRUE)
;
6474 }
6475 } else if (!passport || !cert || zstr(attestation)_zstr(attestation) || verify_signature_status == STIR_SHAKEN_STATUS_OK) {
6476 // failed to get cert / bad passport / no attestation / claims don't match SIP
6477 switch_channel_set_variable(channel, "sip_verstat_detailed", "No-TN-Validation")switch_channel_set_variable_var_check(channel, "sip_verstat_detailed"
, "No-TN-Validation", SWITCH_TRUE)
;
6478 switch_channel_set_variable(channel, "sip_verstat", "No-TN-Validation")switch_channel_set_variable_var_check(channel, "sip_verstat",
"No-TN-Validation", SWITCH_TRUE)
;
6479 } else {
6480 // bad signature
6481 switch_channel_set_variable_printf(channel, "sip_verstat_detailed", "TN-Validation-Failed-%s", attestation);
6482 switch_channel_set_variable(channel, "sip_verstat", "TN-Validation-Failed")switch_channel_set_variable_var_check(channel, "sip_verstat",
"TN-Validation-Failed", SWITCH_TRUE)
;
6483 }
6484
6485
6486done:
6487 stir_shaken_passport_destroy(&passport);
6488 stir_shaken_cert_destroy(&cert);
6489
6490#else
6491 switch_channel_set_variable(channel, "sip_verstat_detailed", "No-TN-Validation")switch_channel_set_variable_var_check(channel, "sip_verstat_detailed"
, "No-TN-Validation", SWITCH_TRUE)
;
6492 switch_channel_set_variable(channel, "sip_verstat", "No-TN-Validation")switch_channel_set_variable_var_check(channel, "sip_verstat",
"No-TN-Validation", SWITCH_TRUE)
;
6493#endif
6494 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6494, (const char*)(session)
, SWITCH_LOG_INFO, "verstat=%s, verstat_detailed=%s\n", switch_channel_get_variable(channel, "sip_verstat")switch_channel_get_variable_dup(channel, "sip_verstat", SWITCH_TRUE
, -1)
, switch_channel_get_variable(channel, "sip_verstat_detailed")switch_channel_get_variable_dup(channel, "sip_verstat_detailed"
, SWITCH_TRUE, -1)
);
6495}
6496
6497/* This assumes TN attestation for orig and dest only */
6498char *sofia_stir_shaken_as_create_identity_header(switch_core_session_t *session, const char *attest, const char *orig, const char *dest)
6499{
6500#if HAVE_STIRSHAKEN1
6501 stir_shaken_context_t as_context = { 0 };
6502 stir_shaken_passport_params_t passport_params = { 0 };
6503 char *canonical_desttn = NULL((void*)0);
6504 char *canonical_origtn = NULL((void*)0);
6505 char *passport = NULL((void*)0);
6506
6507 if (zstr(attest)_zstr(attest) || zstr(orig)_zstr(orig) || zstr(dest)_zstr(dest) || !mod_sofia_globals.stir_shaken_as_url) {
6508 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session)SWITCH_CHANNEL_ID_SESSION, "mod_sofia.c", (const char *)__func__
, 6508, (const char*)(session)
, SWITCH_LOG_WARNING, "Missing required parameter to create PASSporT\n");
6509 return NULL((void*)0);
6510 }
6511
6512 passport_params.attest = attest;
6513 passport_params.x5u = mod_sofia_globals.stir_shaken_as_url;
6514 passport_params.desttn_key = "tn";
6515 passport_params.desttn_val = canonical_desttn = canonicalize_phone_number(dest);
6516 passport_params.iat = switch_epoch_time_now(NULL((void*)0));
6517 passport_params.origtn_key = "tn";
6518 passport_params.origtn_val = canonical_origtn = canonicalize_phone_number(orig);
6519 passport_params.origid = switch_core_session_get_uuid(session);
6520
6521 passport = stir_shaken_as_authenticate_to_sih(&as_context, sofia_stir_shaken_as, &passport_params, NULL((void*)0));
6522 switch_safe_free(canonical_desttn)if (canonical_desttn) {free(canonical_desttn);canonical_desttn
=((void*)0);}
;
6523 switch_safe_free(canonical_origtn)if (canonical_origtn) {free(canonical_origtn);canonical_origtn
=((void*)0);}
;
6524 return passport;
6525#else
6526 return NULL((void*)0);
6527#endif
6528}
6529
6530
6531SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)switch_status_t mod_sofia_load (switch_loadable_module_interface_t
**module_interface, switch_memory_pool_t *pool)
6532{
6533 switch_chat_interface_t *chat_interface;
6534 switch_api_interface_t *api_interface;
6535 switch_management_interface_t *management_interface;
6536 switch_application_interface_t *app_interface;
6537 struct in_addr in;
6538 switch_status_t status;
6539
6540 memset(&mod_sofia_globals, 0, sizeof(mod_sofia_globals));
6541 mod_sofia_globals.destroy_private.destroy_nh = 1;
6542 mod_sofia_globals.destroy_private.is_static = 1;
6543 mod_sofia_globals.keep_private.is_static = 1;
6544 mod_sofia_globals.pool = pool;
6545 switch_mutex_init(&mod_sofia_globals.mutex, SWITCH_MUTEX_NESTED0x1, mod_sofia_globals.pool);
6546 switch_core_hash_init(&mod_sofia_globals.profile_hash)switch_core_hash_init_case(&mod_sofia_globals.profile_hash
, SWITCH_TRUE)
;
6547 switch_core_hash_init(&mod_sofia_globals.gateway_hash)switch_core_hash_init_case(&mod_sofia_globals.gateway_hash
, SWITCH_TRUE)
;
6548 switch_mutex_init(&mod_sofia_globals.hash_mutex, SWITCH_MUTEX_NESTED0x1, mod_sofia_globals.pool);
6549
6550 if (switch_event_reserve_subclass(MY_EVENT_NOTIFY_REFER)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::notify_refer"
)
!= SWITCH_STATUS_SUCCESS) {
6551 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6551, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_NOTIFY_REFER"sofia::notify_refer");
6552 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6553 }
6554
6555 if (switch_event_reserve_subclass(MY_EVENT_NOTIFY_WATCHED_HEADER)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::notify_watched_header"
)
!= SWITCH_STATUS_SUCCESS) {
6556 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6556, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_NOTIFY_WATCHED_HEADER"sofia::notify_watched_header");
6557 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6558 }
6559
6560 if (switch_event_reserve_subclass(MY_EVENT_UNREGISTER)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::unregister"
)
!= SWITCH_STATUS_SUCCESS) {
6561 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6561, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_UNREGISTER"sofia::unregister");
6562 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6563 }
6564
6565 if (switch_event_reserve_subclass(MY_EVENT_PROFILE_START)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::profile_start"
)
!= SWITCH_STATUS_SUCCESS) {
6566 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6566, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_PROFILE_START"sofia::profile_start");
6567 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6568 }
6569
6570 if (switch_event_reserve_subclass(MY_EVENT_REINVITE)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::reinvite"
)
!= SWITCH_STATUS_SUCCESS) {
6571 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6571, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REINVITE"sofia::reinvite");
6572 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6573 }
6574
6575 if (switch_event_reserve_subclass(MY_EVENT_REPLACED)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::replaced"
)
!= SWITCH_STATUS_SUCCESS) {
6576 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6576, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REPLACED"sofia::replaced");
6577 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6578 }
6579
6580 if (switch_event_reserve_subclass(MY_EVENT_TRANSFEROR)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::transferor"
)
!= SWITCH_STATUS_SUCCESS) {
6581 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6581, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_TRANSFEROR"sofia::transferor");
6582 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6583 }
6584
6585 if (switch_event_reserve_subclass(MY_EVENT_TRANSFEREE)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::transferee"
)
!= SWITCH_STATUS_SUCCESS) {
6586 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6586, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_TRANSFEREE"sofia::transferee");
6587 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6588 }
6589
6590 if (switch_event_reserve_subclass(MY_EVENT_ERROR)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::error"
)
!= SWITCH_STATUS_SUCCESS) {
6591 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6591, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_ERROR"sofia::error");
6592 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6593 }
6594
6595 if (switch_event_reserve_subclass(MY_EVENT_INTERCEPTED)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::intercepted"
)
!= SWITCH_STATUS_SUCCESS) {
6596 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6596, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_INTERCEPTED"sofia::intercepted");
6597 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6598 }
6599
6600 if (switch_event_reserve_subclass(MY_EVENT_GATEWAY_STATE)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::gateway_state"
)
!= SWITCH_STATUS_SUCCESS) {
6601 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6601, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_GATEWAY_STATE"sofia::gateway_state");
6602 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6603 }
6604
6605 if (switch_event_reserve_subclass(MY_EVENT_SIP_USER_STATE)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::sip_user_state"
)
!= SWITCH_STATUS_SUCCESS) {
6606 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6606, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_SIP_USER_STATE"sofia::sip_user_state");
6607 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6608 }
6609
6610 if (switch_event_reserve_subclass(MY_EVENT_GATEWAY_DEL)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::gateway_delete"
)
!= SWITCH_STATUS_SUCCESS) {
6611 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6611, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_GATEWAY_DEL"sofia::gateway_delete");
6612 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6613 }
6614
6615 if (switch_event_reserve_subclass(MY_EVENT_EXPIRE)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::expire"
)
!= SWITCH_STATUS_SUCCESS) {
6616 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6616, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_EXPIRE"sofia::expire");
6617 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6618 }
6619
6620 if (switch_event_reserve_subclass(MY_EVENT_REGISTER_ATTEMPT)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::register_attempt"
)
!= SWITCH_STATUS_SUCCESS) {
6621 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6621, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REGISTER_ATTEMPT"sofia::register_attempt");
6622 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6623 }
6624
6625 if (switch_event_reserve_subclass(MY_EVENT_REGISTER_FAILURE)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::register_failure"
)
!= SWITCH_STATUS_SUCCESS) {
6626 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6626, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REGISTER_FAILURE"sofia::register_failure");
6627 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6628 }
6629
6630 if (switch_event_reserve_subclass(MY_EVENT_PRE_REGISTER)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::pre_register"
)
!= SWITCH_STATUS_SUCCESS) {
6631 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6631, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_PRE_REGISTER"sofia::pre_register");
6632 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6633 }
6634
6635 if (switch_event_reserve_subclass(MY_EVENT_REGISTER)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::register"
)
!= SWITCH_STATUS_SUCCESS) {
6636 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6636, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_REGISTER"sofia::register");
6637 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6638 }
6639
6640 if (switch_event_reserve_subclass(MY_EVENT_GATEWAY_ADD)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::gateway_add"
)
!= SWITCH_STATUS_SUCCESS) {
6641 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6641, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_GATEWAY_ADD"sofia::gateway_add");
6642 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6643 }
6644
6645 if (switch_event_reserve_subclass(MY_EVENT_BYE_RESPONSE)switch_event_reserve_subclass_detailed("mod_sofia.c", "sofia::bye_response"
)
!= SWITCH_STATUS_SUCCESS) {
6646 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6646, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_BYE_RESPONSE"sofia::bye_response");
6647 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6648 }
6649
6650 switch_find_local_ip(mod_sofia_globals.guess_ip, sizeof(mod_sofia_globals.guess_ip), &mod_sofia_globals.guess_mask, AF_INET2);
6651 in.s_addr = mod_sofia_globals.guess_mask;
6652 switch_set_string(mod_sofia_globals.guess_mask_str, inet_ntoa(in))switch_copy_string(mod_sofia_globals.guess_mask_str, inet_ntoa
(in), sizeof(mod_sofia_globals.guess_mask_str))
;
6653
6654 strcpy(mod_sofia_globals.hostname, switch_core_get_switchname());
6655
6656 switch_mutex_lock(mod_sofia_globals.mutex);
6657 mod_sofia_globals.running = 1;
6658 switch_mutex_unlock(mod_sofia_globals.mutex);
6659
6660 mod_sofia_globals.auto_nat = (switch_nat_get_type() ? 1 : 0);
6661
6662 switch_queue_create(&mod_sofia_globals.presence_queue, SOFIA_QUEUE_SIZE50000, mod_sofia_globals.pool);
6663 switch_queue_create(&mod_sofia_globals.general_event_queue, SOFIA_QUEUE_SIZE50000, mod_sofia_globals.pool);
6664
6665 mod_sofia_globals.cpu_count = switch_core_cpu_count();
6666 mod_sofia_globals.max_msg_queues = (mod_sofia_globals.cpu_count / 2) + 1;
6667 if (mod_sofia_globals.max_msg_queues < 2) {
6668 mod_sofia_globals.max_msg_queues = 2;
6669 }
6670
6671 if (mod_sofia_globals.max_msg_queues > SOFIA_MAX_MSG_QUEUE64) {
6672 mod_sofia_globals.max_msg_queues = SOFIA_MAX_MSG_QUEUE64;
6673 }
6674
6675 switch_queue_create(&mod_sofia_globals.msg_queue, SOFIA_MSG_QUEUE_SIZE1000 * mod_sofia_globals.max_msg_queues, mod_sofia_globals.pool);
6676
6677 /* start one message thread */
6678 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6678, ((void*)0)
, SWITCH_LOG_INFO, "Starting initial message thread.\n");
6679
6680
6681 if (sofia_init() != SWITCH_STATUS_SUCCESS) {
6682 switch_goto_status(SWITCH_STATUS_GENERR, err)status = SWITCH_STATUS_GENERR; goto err;
6683 return SWITCH_STATUS_GENERR;
6684 }
6685
6686 if (config_sofia(SOFIA_CONFIG_LOAD, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
6687 mod_sofia_globals.running = 0;
6688 switch_goto_status(SWITCH_STATUS_GENERR, err)status = SWITCH_STATUS_GENERR; goto err;
6689 return SWITCH_STATUS_GENERR;
6690 }
6691
6692 sofia_msg_thread_start(0);
6693
6694 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6694, ((void*)0)
, SWITCH_LOG_DEBUG, "Waiting for profiles to start\n");
6695 switch_yield(1500000)switch_sleep(1500000);;
6696
6697 if (switch_event_bind(modname, SWITCH_EVENT_CUSTOM, MULTICAST_EVENT"multicast::event", event_handler, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
6698 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6698, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't bind!\n");
6699 switch_goto_status(SWITCH_STATUS_TERM, err)status = SWITCH_STATUS_TERM; goto err;
6700 }
6701
6702 if (switch_event_bind(modname, SWITCH_EVENT_CONFERENCE_DATA, SWITCH_EVENT_SUBCLASS_ANY((void*)0), sofia_presence_event_handler, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
6703 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6703, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't bind!\n");
6704 switch_goto_status(SWITCH_STATUS_GENERR, err)status = SWITCH_STATUS_GENERR; goto err;
6705 return SWITCH_STATUS_GENERR;
6706 }
6707
6708 if (switch_event_bind(modname, SWITCH_EVENT_PRESENCE_IN, SWITCH_EVENT_SUBCLASS_ANY((void*)0), sofia_presence_event_handler, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
6709
6710 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6710, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't bind!\n");
6711 switch_goto_status(SWITCH_STATUS_GENERR, err)status = SWITCH_STATUS_GENERR; goto err;
6712 return SWITCH_STATUS_GENERR;
6713 }
6714
6715 if (switch_event_bind(modname, SWITCH_EVENT_PRESENCE_OUT, SWITCH_EVENT_SUBCLASS_ANY((void*)0), sofia_presence_event_handler, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
6716
6717 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6717, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't bind!\n");
6718 switch_goto_status(SWITCH_STATUS_GENERR, err)status = SWITCH_STATUS_GENERR; goto err;
6719 return SWITCH_STATUS_GENERR;
6720 }
6721
6722 if (switch_event_bind(modname, SWITCH_EVENT_PRESENCE_PROBE, SWITCH_EVENT_SUBCLASS_ANY((void*)0), sofia_presence_event_handler, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
6723
6724 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6724, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't bind!\n");
6725 switch_goto_status(SWITCH_STATUS_GENERR, err)status = SWITCH_STATUS_GENERR; goto err;
6726 return SWITCH_STATUS_GENERR;
6727 }
6728
6729 if (switch_event_bind(modname, SWITCH_EVENT_ROSTER, SWITCH_EVENT_SUBCLASS_ANY((void*)0), sofia_presence_event_handler, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
6730 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6730, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't bind!\n");
6731 switch_goto_status(SWITCH_STATUS_GENERR, err)status = SWITCH_STATUS_GENERR; goto err;
6732 return SWITCH_STATUS_GENERR;
6733 }
6734
6735 if (switch_event_bind(modname, SWITCH_EVENT_MESSAGE_WAITING, SWITCH_EVENT_SUBCLASS_ANY((void*)0), sofia_presence_event_handler, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
6736 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6736, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't bind!\n");
6737 switch_goto_status(SWITCH_STATUS_GENERR, err)status = SWITCH_STATUS_GENERR; goto err;
6738 return SWITCH_STATUS_GENERR;
6739 }
6740
6741 if (switch_event_bind(modname, SWITCH_EVENT_TRAP, SWITCH_EVENT_SUBCLASS_ANY((void*)0), general_queue_event_handler, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
6742 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6742, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't bind!\n");
6743 switch_goto_status(SWITCH_STATUS_GENERR, err)status = SWITCH_STATUS_GENERR; goto err;
6744 return SWITCH_STATUS_GENERR;
6745 }
6746
6747 if (switch_event_bind(modname, SWITCH_EVENT_NOTIFY, SWITCH_EVENT_SUBCLASS_ANY((void*)0), general_queue_event_handler, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
6748 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6748, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't bind!\n");
6749 switch_goto_status(SWITCH_STATUS_GENERR, err)status = SWITCH_STATUS_GENERR; goto err;
6750 return SWITCH_STATUS_GENERR;
6751 }
6752
6753 if (switch_event_bind(modname, SWITCH_EVENT_PHONE_FEATURE, SWITCH_EVENT_SUBCLASS_ANY((void*)0), general_queue_event_handler, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
6754 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6754, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't bind!\n");
6755 switch_goto_status(SWITCH_STATUS_GENERR, err)status = SWITCH_STATUS_GENERR; goto err;
6756 return SWITCH_STATUS_GENERR;
6757 }
6758
6759 if (switch_event_bind(modname, SWITCH_EVENT_SEND_MESSAGE, SWITCH_EVENT_SUBCLASS_ANY((void*)0), general_queue_event_handler, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
6760 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6760, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't bind!\n");
6761 switch_goto_status(SWITCH_STATUS_GENERR, err)status = SWITCH_STATUS_GENERR; goto err;
6762 return SWITCH_STATUS_GENERR;
6763 }
6764
6765 if (switch_event_bind(modname, SWITCH_EVENT_SEND_INFO, SWITCH_EVENT_SUBCLASS_ANY((void*)0), general_queue_event_handler, NULL((void*)0)) != SWITCH_STATUS_SUCCESS) {
6766 switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_sofia.c", (const char *)__func__,
6766, ((void*)0)
, SWITCH_LOG_ERROR, "Couldn't bind!\n");
6767 switch_goto_status(SWITCH_STATUS_GENERR, err)status = SWITCH_STATUS_GENERR; goto err;
6768 return SWITCH_STATUS_GENERR;
6769 }
6770
6771 /* connect my internal structure to the blank pointer passed to me */
6772 *module_interface = switch_loadable_module_create_module_interface(pool, modname);
6773 sofia_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
6774 sofia_endpoint_interface->interface_name = "sofia";
6775 sofia_endpoint_interface->io_routines = &sofia_io_routines;
6776 sofia_endpoint_interface->state_handler = &sofia_event_handlers;
6777 sofia_endpoint_interface->recover_callback = sofia_recover_callback;
6778
6779 management_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_MANAGEMENT_INTERFACE);
6780 management_interface->relative_oid = "1001";
6781 management_interface->management_function = sofia_manage;
6782
6783 add_sofia_json_apis(module_interface);
6784
6785 SWITCH_ADD_APP(app_interface, "sofia_sla", "private sofia sla function",for (;;) { app_interface = (switch_application_interface_t *)
switch_loadable_module_create_interface(*module_interface, SWITCH_APPLICATION_INTERFACE
); app_interface->interface_name = "sofia_sla"; app_interface
->application_function = sofia_sla_function; app_interface
->short_desc = "private sofia sla function"; app_interface
->long_desc = "private sofia sla function"; app_interface->
syntax = "<uuid>"; app_interface->flags = SAF_NONE; break
; }
6786 "private sofia sla function", sofia_sla_function, "<uuid>", SAF_NONE)for (;;) { app_interface = (switch_application_interface_t *)
switch_loadable_module_create_interface(*module_interface, SWITCH_APPLICATION_INTERFACE
); app_interface->interface_name = "sofia_sla"; app_interface
->application_function = sofia_sla_function; app_interface
->short_desc = "private sofia sla function"; app_interface
->long_desc = "private sofia sla function"; app_interface->
syntax = "<uuid>"; app_interface->flags = SAF_NONE; break
; }
;
6787
6788 SWITCH_ADD_APP(app_interface, "sofia_stir_shaken_vs", "Verify SIP Identity header and store result in sip_verstat channel variable",for (;;) { app_interface = (switch_application_interface_t *)
switch_loadable_module_create_interface(*module_interface, SWITCH_APPLICATION_INTERFACE
); app_interface->interface_name = "sofia_stir_shaken_vs";
app_interface->application_function = sofia_stir_shaken_vs_function
; app_interface->short_desc = "Verify SIP Identity header and store result in sip_verstat channel variable"
; app_interface->long_desc = "Verify SIP Identity header and store result in sip_verstat channel variable"
; app_interface->syntax = ""; app_interface->flags = SAF_SUPPORT_NOMEDIA
; break; }
6789 "Verify SIP Identity header and store result in sip_verstat channel variable", sofia_stir_shaken_vs_function, "", SAF_SUPPORT_NOMEDIA)for (;;) { app_interface = (switch_application_interface_t *)
switch_loadable_module_create_interface(*module_interface, SWITCH_APPLICATION_INTERFACE
); app_interface->interface_name = "sofia_stir_shaken_vs";
app_interface->application_function = sofia_stir_shaken_vs_function
; app_interface->short_desc = "Verify SIP Identity header and store result in sip_verstat channel variable"
; app_interface->long_desc = "Verify SIP Identity header and store result in sip_verstat channel variable"
; app_interface->syntax = ""; app_interface->flags = SAF_SUPPORT_NOMEDIA
; break; }
;
6790
6791 SWITCH_ADD_API(api_interface, "sofia", "Sofia Controls", sofia_function, "<cmd> <args>")for (;;) { api_interface = (switch_api_interface_t *)switch_loadable_module_create_interface
(*module_interface, SWITCH_API_INTERFACE); api_interface->
interface_name = "sofia"; api_interface->desc = "Sofia Controls"
; api_interface->function = sofia_function; api_interface->
syntax = "<cmd> <args>"; break; }
;
6792 SWITCH_ADD_API(api_interface, "sofia_gateway_data", "Get data from a sofia gateway", sofia_gateway_data_function, "<gateway_name> [ivar|ovar|var] <name>")for (;;) { api_interface = (switch_api_interface_t *)switch_loadable_module_create_interface
(*module_interface, SWITCH_API_INTERFACE); api_interface->
interface_name = "sofia_gateway_data"; api_interface->desc
= "Get data from a sofia gateway"; api_interface->function
= sofia_gateway_data_function; api_interface->syntax = "<gateway_name> [ivar|ovar|var] <name>"
; break; }
;
6793 switch_console_set_complete("add sofia ::[help:status");
6794 switch_console_set_complete("add sofia status profile ::sofia::list_profiles reg");
6795 switch_console_set_complete("add sofia status gateway ::sofia::list_gateways");
6796
6797 switch_console_set_complete("add sofia loglevel ::[all:default:tport:iptsec:nea:nta:nth_client:nth_server:nua:soa:sresolv:stun ::[0:1:2:3:4:5:6:7:8:9");
6798 switch_console_set_complete("add sofia tracelevel ::[console:alert:crit:err:warning:notice:info:debug");
6799
6800 switch_console_set_complete("add sofia global ::[siptrace::standby::capture::watchdog ::[on:off");
6801 switch_console_set_complete("add sofia global debug ::[presence:sla:none");
6802
6803 switch_console_set_complete("add sofia profile restart all");
6804 switch_console_set_complete("add sofia profile ::sofia::list_profiles ::[start:rescan:restart:check_sync");
6805 switch_console_set_complete("add sofia profile ::sofia::list_profiles stop wait");
6806 switch_console_set_complete("add sofia profile ::sofia::list_profiles flush_inbound_reg reboot");
6807 switch_console_set_complete("add sofia profile ::sofia::list_profiles ::[register:unregister all");
6808 switch_console_set_complete("add sofia profile ::sofia::list_profiles ::[register:unregister:killgw:startgw ::sofia::list_profile_gateway");
6809 switch_console_set_complete("add sofia profile ::sofia::list_profiles killgw _all_");
6810 switch_console_set_complete("add sofia profile ::sofia::list_profiles startgw _all_");
6811 switch_console_set_complete("add sofia profile ::sofia::list_profiles ::[siptrace:capture:watchdog ::[on:off");
6812 switch_console_set_complete("add sofia profile ::sofia::list_profiles gwlist ::[up:down");
6813
6814 switch_console_set_complete("add sofia recover flush");
6815
6816 switch_console_set_complete("add sofia xmlstatus profile ::sofia::list_profiles reg");
6817 switch_console_set_complete("add sofia xmlstatus gateway ::sofia::list_gateways");
6818
6819 switch_console_add_complete_func("::sofia::list_profiles", list_profiles);
6820 switch_console_add_complete_func("::sofia::list_gateways", list_gateways);
6821 switch_console_add_complete_func("::sofia::list_profile_gateway", list_profile_gateway);
6822
6823
6824 SWITCH_ADD_API(api_interface, "sofia_username_of", "Sofia Username Lookup", sofia_username_of_function, "[profile/]<user>@<domain>")for (;;) { api_interface = (switch_api_interface_t *)switch_loadable_module_create_interface
(*module_interface, SWITCH_API_INTERFACE); api_interface->
interface_name = "sofia_username_of"; api_interface->desc =
"Sofia Username Lookup"; api_interface->function = sofia_username_of_function
; api_interface->syntax = "[profile/]<user>@<domain>"
; break; }
;
6825 SWITCH_ADD_API(api_interface, "sofia_contact", "Sofia Contacts", sofia_contact_function, "[profile/]<user>@<domain>")for (;;) { api_interface = (switch_api_interface_t *)switch_loadable_module_create_interface
(*module_interface, SWITCH_API_INTERFACE); api_interface->
interface_name = "sofia_contact"; api_interface->desc = "Sofia Contacts"
; api_interface->function = sofia_contact_function; api_interface
->syntax = "[profile/]<user>@<domain>"; break;
}
;
6826 SWITCH_ADD_API(api_interface, "sofia_count_reg", "Count Sofia registration", sofia_count_reg_function, "[profile/]<user>@<domain>")for (;;) { api_interface = (switch_api_interface_t *)switch_loadable_module_create_interface
(*module_interface, SWITCH_API_INTERFACE); api_interface->
interface_name = "sofia_count_reg"; api_interface->desc = "Count Sofia registration"
; api_interface->function = sofia_count_reg_function; api_interface
->syntax = "[profile/]<user>@<domain>"; break;
}
;
6827 SWITCH_ADD_API(api_interface, "sofia_dig", "SIP DIG", sip_dig_function, "<url>")for (;;) { api_interface = (switch_api_interface_t *)switch_loadable_module_create_interface
(*module_interface, SWITCH_API_INTERFACE); api_interface->
interface_name = "sofia_dig"; api_interface->desc = "SIP DIG"
; api_interface->function = sip_dig_function; api_interface
->syntax = "<url>"; break; }
;
6828 SWITCH_ADD_API(api_interface, "sofia_presence_data", "Sofia Presence Data", sofia_presence_data_function, "[list|status|rpid|user_agent] [profile/]<user>@domain")for (;;) { api_interface = (switch_api_interface_t *)switch_loadable_module_create_interface
(*module_interface, SWITCH_API_INTERFACE); api_interface->
interface_name = "sofia_presence_data"; api_interface->desc
= "Sofia Presence Data"; api_interface->function = sofia_presence_data_function
; api_interface->syntax = "[list|status|rpid|user_agent] [profile/]<user>@domain"
; break; }
;
6829 SWITCH_ADD_CHAT(chat_interface, SOFIA_CHAT_PROTO, sofia_presence_chat_send)for (;;) { chat_interface = (switch_chat_interface_t *)switch_loadable_module_create_interface
(*module_interface, SWITCH_CHAT_INTERFACE); chat_interface->
chat_send = sofia_presence_chat_send; chat_interface->interface_name
= "sip"; break; }
;
6830
6831 crtp_init(*module_interface);
6832
6833 sofia_stir_shaken_create_services();
6834
6835 /* indicate that the module should continue to be loaded */
6836 return SWITCH_STATUS_SUCCESS;
6837
6838 err:
6839
6840 mod_sofia_shutdown_cleanup();
6841 return status;
6842}
6843
6844void mod_sofia_shutdown_cleanup() {
6845 int sanity = 0;
6846 int i;
6847 switch_status_t st;
6848
6849 switch_event_free_subclass(MY_EVENT_NOTIFY_REFER)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::notify_refer"
)
;
6850 switch_event_free_subclass(MY_EVENT_NOTIFY_WATCHED_HEADER)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::notify_watched_header"
)
;
6851 switch_event_free_subclass(MY_EVENT_UNREGISTER)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::unregister"
)
;
6852 switch_event_free_subclass(MY_EVENT_PROFILE_START)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::profile_start"
)
;
6853 switch_event_free_subclass(MY_EVENT_REINVITE)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::reinvite"
)
;
6854 switch_event_free_subclass(MY_EVENT_REPLACED)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::replaced"
)
;
6855 switch_event_free_subclass(MY_EVENT_TRANSFEROR)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::transferor"
)
;
6856 switch_event_free_subclass(MY_EVENT_TRANSFEREE)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::transferee"
)
;
6857 switch_event_free_subclass(MY_EVENT_ERROR)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::error"
)
;
6858 switch_event_free_subclass(MY_EVENT_INTERCEPTED)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::intercepted"
)
;
6859 switch_event_free_subclass(MY_EVENT_GATEWAY_STATE)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::gateway_state"
)
;
6860 switch_event_free_subclass(MY_EVENT_SIP_USER_STATE)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::sip_user_state"
)
;
6861 switch_event_free_subclass(MY_EVENT_GATEWAY_DEL)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::gateway_delete"
)
;
6862 switch_event_free_subclass(MY_EVENT_EXPIRE)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::expire"
)
;
6863 switch_event_free_subclass(MY_EVENT_REGISTER_ATTEMPT)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::register_attempt"
)
;
6864 switch_event_free_subclass(MY_EVENT_REGISTER_FAILURE)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::register_failure"
)
;
6865 switch_event_free_subclass(MY_EVENT_PRE_REGISTER)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::pre_register"
)
;
6866 switch_event_free_subclass(MY_EVENT_REGISTER)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::register"
)
;
6867 switch_event_free_subclass(MY_EVENT_GATEWAY_ADD)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::gateway_add"
)
;
6868 switch_event_free_subclass(MY_EVENT_BYE_RESPONSE)switch_event_free_subclass_detailed("mod_sofia.c", "sofia::bye_response"
)
;
6869
6870 switch_console_del_complete_func("::sofia::list_profiles");
6871 switch_console_set_complete("del sofia");
6872
6873 switch_mutex_lock(mod_sofia_globals.mutex);
6874 if (mod_sofia_globals.running == 1) {
6875 mod_sofia_globals.running = 0;
6876 }
6877 switch_mutex_unlock(mod_sofia_globals.mutex);
6878
6879 switch_event_unbind_callback(sofia_presence_event_handler);
6880
6881 switch_event_unbind_callback(general_queue_event_handler);
6882 switch_event_unbind_callback(event_handler);
6883
6884 if (mod_sofia_globals.presence_queue) {
6885 switch_queue_push(mod_sofia_globals.presence_queue, NULL((void*)0));
6886 switch_queue_interrupt_all(mod_sofia_globals.presence_queue);
6887 }
6888
6889 while (mod_sofia_globals.threads) {
6890 switch_cond_next();
6891 if (++sanity >= 60000) {
6892 break;
6893 }
6894 }
6895
6896 for (i = 0; mod_sofia_globals.msg_queue_thread[i]; i++) {
6897 switch_queue_push(mod_sofia_globals.msg_queue, NULL((void*)0));
6898 switch_queue_interrupt_all(mod_sofia_globals.msg_queue);
6899 }
6900
6901 for (i = 0; mod_sofia_globals.msg_queue_thread[i]; i++) {
6902 switch_thread_join(&st, mod_sofia_globals.msg_queue_thread[i]);
6903 }
6904
6905 if (mod_sofia_globals.presence_thread) {
6906 switch_thread_join(&st, mod_sofia_globals.presence_thread);
6907 }
6908
6909 su_deinit();
6910
6911 /*
6912 Release the clone of the default SIP parser
6913 created by `sip_update_default_mclass(sip_extend_mclass(NULL))` call with NULL argument
6914 */
6915 sip_cloned_parser_destroy();
6916
6917 switch_mutex_lock(mod_sofia_globals.hash_mutex);
6918 switch_core_hash_destroy(&mod_sofia_globals.profile_hash);
6919 switch_core_hash_destroy(&mod_sofia_globals.gateway_hash);
6920 switch_mutex_unlock(mod_sofia_globals.hash_mutex);
6921
6922 sofia_stir_shaken_destroy_services();
6923}
6924
6925SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sofia_shutdown)switch_status_t mod_sofia_shutdown (void)
6926{
6927 mod_sofia_shutdown_cleanup();
6928 return SWITCH_STATUS_SUCCESS;
6929}
6930
6931/* For Emacs:
6932 * Local Variables:
6933 * mode:c
6934 * indent-tabs-mode:t
6935 * tab-width:4
6936 * c-basic-offset:4
6937 * End:
6938 * For VIM:
6939 * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
6940 */