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