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') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
48 | SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load)switch_status_t mod_sofia_load (switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool); | |||
49 | SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sofia_shutdown)switch_status_t mod_sofia_shutdown (void); | |||
50 | SWITCH_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 | ||||
52 | struct mod_sofia_globals mod_sofia_globals; | |||
53 | switch_endpoint_interface_t *sofia_endpoint_interface; | |||
54 | ||||
55 | #define STRLEN15 15 | |||
56 | ||||
57 | void mod_sofia_shutdown_cleanup(); | |||
58 | static switch_status_t sofia_on_init(switch_core_session_t *session); | |||
59 | ||||
60 | static switch_status_t sofia_on_exchange_media(switch_core_session_t *session); | |||
61 | static switch_status_t sofia_on_soft_execute(switch_core_session_t *session); | |||
62 | static switch_status_t sofia_acknowledge_call(switch_core_session_t *session); | |||
63 | static 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); | |||
66 | static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); | |||
67 | static switch_status_t sofia_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); | |||
68 | static switch_status_t sofia_read_video_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); | |||
69 | static switch_status_t sofia_write_video_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); | |||
70 | static switch_status_t sofia_read_text_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); | |||
71 | static switch_status_t sofia_write_text_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); | |||
72 | static 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 | */ | |||
82 | static 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 | ||||
139 | static 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 | ||||
165 | static 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 | ||||
184 | static 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 | ||||
202 | static 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 | ||||
219 | char *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 | ||||
284 | static 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 */ | |||
292 | static 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 | ||||
374 | switch_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 | ||||
413 | switch_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 | ||||
669 | static 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 | ||||
675 | static 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 | ||||
681 | static 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 | ||||
695 | static 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 | ||||
1019 | static 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 | ||||
1075 | static 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 | ||||
1098 | static 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 | ||||
1125 | static 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 | ||||
1159 | static 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 | ||||
1192 | static 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 | ||||
1249 | static 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 | ||||
1283 | static 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 | ||||
1331 | static 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 | ||||
2721 | static 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 | ||||
2746 | typedef switch_status_t (*sofia_command_t) (char **argv, int argc, switch_stream_handle_t *stream); | |||
2747 | ||||
2748 | const 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 | ||||
2763 | const char *sofia_state_string(int state) | |||
2764 | { | |||
2765 | if (state >= REG_STATE_LAST) return ""; | |||
2766 | ||||
2767 | return sofia_state_names[state]; | |||
2768 | } | |||
2769 | ||||
2770 | struct cb_helper_sql2str { | |||
2771 | char *buf; | |||
2772 | size_t len; | |||
2773 | int matches; | |||
2774 | }; | |||
2775 | ||||
2776 | struct 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 | ||||
2785 | static 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 | ||||
2826 | static 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 | ||||
2868 | static 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 | ||||
2877 | uint32_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 | ||||
2890 | static const char *status_names[] = { "DOWN", "UP", NULL((void*)0) }; | |||
2891 | ||||
2892 | static 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 | ||||
3205 | static 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 | ||||
3252 | static 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 | ||||
3520 | static 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 | ||||
3817 | static 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 | ||||
3843 | SWITCH_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 | ||||
3944 | SWITCH_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 | ||||
4034 | static 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 | ||||
4075 | SWITCH_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 | ||||
4208 | struct list_result { | |||
4209 | int row_process; | |||
4210 | int single_col; | |||
4211 | switch_stream_handle_t *stream; | |||
4212 | ||||
4213 | }; | |||
4214 | static 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 | ||||
4243 | static 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 */ | |||
4277 | SWITCH_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> */ | |||
4383 | SWITCH_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 | ||||
4435 | SWITCH_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 | ||||
4633 | switch_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 | ||||
4650 | switch_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 | ||||
4665 | static 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 | ||||
4670 | static 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 | ||||
4726 | static 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)) { | |||
| ||||
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))) { | |||
4753 | mod = protect_dest_uri(outbound_profile); | |||
4754 | } | |||
4755 | ||||
4756 | if (!(nsession = switch_core_session_request_uuid(sofia_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, | |||
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, '^'))) { | |||
4766 | *dest_to++ = '\0'; | |||
4767 | } | |||
4768 | profile_name = data; | |||
4769 | ||||
4770 | nchannel = switch_core_session_get_channel(nsession); | |||
4771 | ||||
4772 | if (session) { | |||
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))) { | |||
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)) { | |||
4782 | char *gw, *params; | |||
4783 | ||||
4784 | if (!(gw = strchr(profile_name, '/'))) { | |||
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, '/'))) { | |||
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))) { | |||
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; | |||
4807 | ||||
4808 | if (gateway_ptr->status != SOFIA_GATEWAY_UP) { | |||
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, ';'))) { | |||
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) { | |||
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)) { | |||
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)) { | |||
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, '@')) { | |||
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))) { | |||
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) { | |||
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); | |||
| ||||
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 | ||||
5235 | static 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 | ||||
5307 | static 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 | ||||
5363 | void 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 | ||||
5915 | static 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 | ||||
5923 | void 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 | ||||
5975 | switch_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 | ||||
6008 | switch_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 | ||||
6013 | static 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 | ||||
6046 | static 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 | ||||
6086 | SWITCH_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 | |||
6128 | static stir_shaken_as_t *sofia_stir_shaken_as = NULL((void*)0); | |||
6129 | static stir_shaken_vs_t *sofia_stir_shaken_vs = NULL((void*)0); | |||
6130 | ||||
6131 | static 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 | ||||
6147 | static 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 | ||||
6165 | static 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 | ||||
6178 | static 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 | |||
6188 | static 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 | ||||
6205 | static 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 | */ | |||
6277 | static 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 */ | |||
6353 | SWITCH_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 | ||||
6486 | done: | |||
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 */ | |||
6498 | char *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 | ||||
6531 | SWITCH_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 | ||||
6844 | void 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 | ||||
6925 | SWITCH_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 | */ |