From 4cb0e2e5bd99054772ded049726bc1d9b9bd73ba Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 6 Sep 2012 10:59:39 -0500 Subject: [PATCH 01/12] protect against case with null sofia_private in callback --- src/mod/endpoints/mod_sofia/sofia.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index d1e4a09e73..21ff55d480 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1209,11 +1209,13 @@ static void our_sofia_event_callback(nua_event_t event, sofia_handle_sip_i_options(status, phrase, nua, profile, nh, sofia_private, sip, de, tags); break; case nua_i_invite: - if (session && sofia_private->is_call > 1) { - sofia_handle_sip_i_reinvite(session, nua, profile, nh, sofia_private, sip, de, tags); - } else { - sofia_private->is_call++; - sofia_handle_sip_i_invite(session, nua, profile, nh, sofia_private, sip, de, tags); + if (session && sofia_private) { + if (sofia_private->is_call > 1) { + sofia_handle_sip_i_reinvite(session, nua, profile, nh, sofia_private, sip, de, tags); + } else { + sofia_private->is_call++; + sofia_handle_sip_i_invite(session, nua, profile, nh, sofia_private, sip, de, tags); + } } break; case nua_i_publish: From d528ceee1927ff370cc424d55c95e34f9ce2a73d Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 6 Sep 2012 11:32:50 -0500 Subject: [PATCH 02/12] regression from a9d72bc35d0e021f8db1ea480b1ddb0744d73bac --- src/switch_ivr.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 95f0e901d8..92f6186934 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -631,8 +631,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se } } - if (!inner || switch_channel_test_flag(channel, CF_STOP_BROADCAST)) { - switch_channel_clear_flag(channel, CF_BROADCAST); + if (!inner) { + switch_channel_clear_flag(channel, CF_BROADCAST); + } + + if (switch_channel_test_flag(channel, CF_STOP_BROADCAST)) { + switch_channel_clear_flag(channel, CF_BROADCAST); switch_channel_set_flag(channel, CF_BREAK); } From cc73cb654403954d6bfe2ba9e7784e83ad0d52d9 Mon Sep 17 00:00:00 2001 From: Steve Underwood Date: Fri, 7 Sep 2012 00:41:41 +0800 Subject: [PATCH 03/12] Some tweaks to spandsp tests. Make spandsp write TIFF files more like the TIFF/FX spec says, even though no software seems to care. --- libs/spandsp/src/t31.c | 34 +++++++++---------- libs/spandsp/src/t4_rx.c | 12 ++++--- .../etsi/fax/generate_etsi_300_242_pages.c | 6 ++-- .../test-data/itu/fax/generate_dithered_tif.c | 1 + .../test-data/itu/fax/generate_sized_pages.c | 1 + .../itu/fax/generate_striped_pages.c | 1 + libs/spandsp/tests/t42_tests.c | 6 ++-- 7 files changed, 36 insertions(+), 25 deletions(-) diff --git a/libs/spandsp/src/t31.c b/libs/spandsp/src/t31.c index 8e747c4d0f..01d948e357 100644 --- a/libs/spandsp/src/t31.c +++ b/libs/spandsp/src/t31.c @@ -1689,6 +1689,16 @@ static int restart_modem(t31_state_t *s, int new_modem) } s->at_state.transmit = TRUE; break; + case FAX_MODEM_V21_RX: + if (s->t38_mode) + { + } + else + { + t31_v21_rx(s); + fax_modems_set_rx_handler(t, (span_rx_handler_t) &fsk_rx, &t->v21_rx, (span_rx_fillin_handler_t) &fsk_rx_fillin, &t->v21_rx); + } + break; case FAX_MODEM_V21_TX: if (s->t38_mode) { @@ -1712,15 +1722,16 @@ static int restart_modem(t31_state_t *s, int new_modem) s->dled = FALSE; s->at_state.transmit = TRUE; break; - case FAX_MODEM_V21_RX: - if (s->t38_mode) - { - } - else + case FAX_MODEM_V17_RX: + case FAX_MODEM_V27TER_RX: + case FAX_MODEM_V29_RX: + if (!s->t38_mode) { + fax_modems_start_fast_modem(t, s->modem, s->bit_rate, s->short_train, use_hdlc); + /* Allow for +FCERROR/+FRH:3 */ t31_v21_rx(s); - fax_modems_set_rx_handler(t, (span_rx_handler_t) &fsk_rx, &t->v21_rx, (span_rx_fillin_handler_t) &fsk_rx_fillin, &t->v21_rx); } + s->at_state.transmit = FALSE; break; case FAX_MODEM_V17_TX: if (s->t38_mode) @@ -1755,17 +1766,6 @@ static int restart_modem(t31_state_t *s, int new_modem) s->tx.data_started = FALSE; s->at_state.transmit = TRUE; break; - case FAX_MODEM_V17_RX: - case FAX_MODEM_V27TER_RX: - case FAX_MODEM_V29_RX: - if (!s->t38_mode) - { - fax_modems_start_fast_modem(t, s->modem, s->bit_rate, s->short_train, use_hdlc); - /* Allow for +FCERROR/+FRH:3 */ - t31_v21_rx(s); - } - s->at_state.transmit = FALSE; - break; case FAX_MODEM_V27TER_TX: if (s->t38_mode) { diff --git a/libs/spandsp/src/t4_rx.c b/libs/spandsp/src/t4_rx.c index f3b34167b2..c17c377630 100644 --- a/libs/spandsp/src/t4_rx.c +++ b/libs/spandsp/src/t4_rx.c @@ -172,7 +172,7 @@ static int set_tiff_directory_info(t4_rx_state_t *s) } #if defined(SPANDSP_SUPPORT_TIFF_FX) TIFFSetField(t->tiff_file, TIFFTAG_PROFILETYPE, PROFILETYPE_G3_FAX); - TIFFSetField(t->tiff_file, TIFFTAG_FAXPROFILE, FAXPROFILE_S); + TIFFSetField(t->tiff_file, TIFFTAG_FAXPROFILE, FAXPROFILE_F); TIFFSetField(t->tiff_file, TIFFTAG_CODINGMETHODS, CODINGMETHODS_T4_1D | CODINGMETHODS_T4_2D | CODINGMETHODS_T6); TIFFSetField(t->tiff_file, TIFFTAG_VERSIONYEAR, "1998"); /* TIFFSetField(t->tiff_file, TIFFTAG_MODENUMBER, 0); */ @@ -304,10 +304,14 @@ static int write_tiff_image(t4_rx_state_t *s) return -1; /* Set up the TIFF directory info... */ set_tiff_directory_info(s); - /* ...and then write the image... */ + /* ...Put the directory in the file before the image data, to get them in the order specified + for TIFF/F files... */ + if (!TIFFCheckpointDirectory(t->tiff_file)) + span_log(&s->logging, SPAN_LOG_WARNING, "%s: Failed to checkpoint directory for page %d.\n", t->file, s->current_page); + /* ...and write out the image... */ if (TIFFWriteEncodedStrip(t->tiff_file, 0, t->image_buffer, t->image_size) < 0) span_log(&s->logging, SPAN_LOG_WARNING, "%s: Error writing TIFF strip.\n", t->file); - /* ...then the directory entry, and libtiff is happy. */ + /* ...then finalise the directory entry, and libtiff is happy. */ if (!TIFFWriteDirectory(t->tiff_file)) span_log(&s->logging, SPAN_LOG_WARNING, "%s: Failed to write directory for page %d.\n", t->file, s->current_page); #if defined(SPANDSP_SUPPORT_TIFF_FX) @@ -316,7 +320,7 @@ static int write_tiff_image(t4_rx_state_t *s) if (!TIFFCreateCustomDirectory(t->tiff_file, &tiff_fx_field_array)) { TIFFSetField(t->tiff_file, TIFFTAG_FAXPROFILE, PROFILETYPE_G3_FAX); - TIFFSetField(t->tiff_file, TIFFTAG_PROFILETYPE, FAXPROFILE_S); + TIFFSetField(t->tiff_file, TIFFTAG_PROFILETYPE, FAXPROFILE_F); TIFFSetField(t->tiff_file, TIFFTAG_VERSIONYEAR, "1998"); offset = 0; diff --git a/libs/spandsp/test-data/etsi/fax/generate_etsi_300_242_pages.c b/libs/spandsp/test-data/etsi/fax/generate_etsi_300_242_pages.c index dda0d0fbc7..9a2a3e971e 100644 --- a/libs/spandsp/test-data/etsi/fax/generate_etsi_300_242_pages.c +++ b/libs/spandsp/test-data/etsi/fax/generate_etsi_300_242_pages.c @@ -623,6 +623,10 @@ int main(int argc, char *argv[]) tm->tm_sec); TIFFSetField(tiff_file, TIFFTAG_DATETIME, buf); image_length = sequence[i].length; + TIFFSetField(tiff_file, TIFFTAG_PAGENUMBER, 0, 1); + TIFFSetField(tiff_file, TIFFTAG_CLEANFAXDATA, CLEANFAXDATA_CLEAN); + TIFFSetField(tiff_file, TIFFTAG_IMAGELENGTH, image_length); + TIFFCheckpointDirectory(tiff_file); /* Write the image first.... */ switch (sequence[i].type) @@ -662,8 +666,6 @@ int main(int argc, char *argv[]) } /* ....then the directory entry, and libtiff is happy. */ TIFFSetField(tiff_file, TIFFTAG_IMAGELENGTH, image_length); - TIFFSetField(tiff_file, TIFFTAG_PAGENUMBER, 0, 1); - TIFFSetField(tiff_file, TIFFTAG_CLEANFAXDATA, CLEANFAXDATA_CLEAN); TIFFWriteDirectory(tiff_file); } diff --git a/libs/spandsp/test-data/itu/fax/generate_dithered_tif.c b/libs/spandsp/test-data/itu/fax/generate_dithered_tif.c index 31c8cb0cc8..03ae0e8602 100644 --- a/libs/spandsp/test-data/itu/fax/generate_dithered_tif.c +++ b/libs/spandsp/test-data/itu/fax/generate_dithered_tif.c @@ -137,6 +137,7 @@ int main(int argc, char *argv[]) TIFFSetField(tiff_file, TIFFTAG_PAGENUMBER, 0, 1); TIFFSetField(tiff_file, TIFFTAG_CLEANFAXDATA, CLEANFAXDATA_CLEAN); TIFFSetField(tiff_file, TIFFTAG_IMAGEWIDTH, image_width); + TIFFCheckpointDirectory(tiff_file); /* Write the image first.... */ for (row = 0; row < image_length; row++) diff --git a/libs/spandsp/test-data/itu/fax/generate_sized_pages.c b/libs/spandsp/test-data/itu/fax/generate_sized_pages.c index bd7e8cdc91..a075f622e5 100644 --- a/libs/spandsp/test-data/itu/fax/generate_sized_pages.c +++ b/libs/spandsp/test-data/itu/fax/generate_sized_pages.c @@ -367,6 +367,7 @@ int main(int argc, char *argv[]) TIFFSetField(tiff_file, TIFFTAG_PAGENUMBER, 0, 1); TIFFSetField(tiff_file, TIFFTAG_CLEANFAXDATA, CLEANFAXDATA_CLEAN); TIFFSetField(tiff_file, TIFFTAG_IMAGEWIDTH, sequence[i].width); + TIFFCheckpointDirectory(tiff_file); /* Write the image first.... */ for (row = 0; row < sequence[i].length; row++) diff --git a/libs/spandsp/test-data/itu/fax/generate_striped_pages.c b/libs/spandsp/test-data/itu/fax/generate_striped_pages.c index 0c3eafd149..63b8e755c7 100644 --- a/libs/spandsp/test-data/itu/fax/generate_striped_pages.c +++ b/libs/spandsp/test-data/itu/fax/generate_striped_pages.c @@ -103,6 +103,7 @@ int main(int argc, char *argv[]) TIFFSetField(tiff_file, TIFFTAG_IMAGEWIDTH, IMAGE_WIDTH); TIFFSetField(tiff_file, TIFFTAG_IMAGELENGTH, IMAGE_LENGTH); TIFFSetField(tiff_file, TIFFTAG_PAGENUMBER, 0, 1); + TIFFCheckpointDirectory(tiff_file); image_size = IMAGE_WIDTH*ROWS_PER_STRIPE/8; memset(image_buffer, 0x18, image_size); diff --git a/libs/spandsp/tests/t42_tests.c b/libs/spandsp/tests/t42_tests.c index 588bfdd3fe..8cddaa18cd 100644 --- a/libs/spandsp/tests/t42_tests.c +++ b/libs/spandsp/tests/t42_tests.c @@ -46,7 +46,7 @@ #include "spandsp.h" #if defined(SPANDSP_SUPPORT_TIFF_FX) -//#include +#include #endif //#define IN_FILE_NAME "../test-data/itu/t24/F21_200.TIF" @@ -156,7 +156,9 @@ int main(int argc, char *argv[]) logging = span_log_init(NULL, SPAN_LOG_FLOW, "T.42"); +#if defined(SPANDSP_SUPPORT_TIFF_FX) TIFF_FX_init(); +#endif set_lab_illuminant(&lab_param, 0.9638f, 1.0f, 0.8245f); set_lab_gamut(&lab_param, 0, 100, -85, 85, -75, 125, FALSE); @@ -189,7 +191,7 @@ int main(int argc, char *argv[]) YCbCrSubsampleHoriz = 0; YCbCrSubsampleVert = 0; TIFFGetField(tif, TIFFTAG_YCBCRSUBSAMPLING, &YCbCrSubsampleHoriz, &YCbCrSubsampleVert); - planar_config = 0; + planar_config = PLANARCONFIG_CONTIG; TIFFGetField(tif, TIFFTAG_PLANARCONFIG, &planar_config); off = 0; From cbefc9dae149be4fb0a3ee9f135ebc14fff2d126 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 6 Sep 2012 11:53:58 -0500 Subject: [PATCH 04/12] fix logic in dmachine parser for overlap bindings so they work regardless of the order they are bound --- src/switch_ivr_async.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index c684c8f14c..4ab523a3a5 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -311,9 +311,18 @@ static dm_match_t switch_ivr_dmachine_check_match(switch_ivr_dmachine_t *dmachin for(bp = dmachine->realm->binding_list; bp; bp = bp->next) { if (bp->is_regex) { - switch_status_t r_status = switch_regex_match(dmachine->digits, bp->digits); - pmatches = 1; + pmatches++; + } else { + if (!strncmp(dmachine->digits, bp->digits, strlen(dmachine->digits))) { + pmatches++; + } + } + } + for(bp = dmachine->realm->binding_list; bp; bp = bp->next) { + if (bp->is_regex) { + switch_status_t r_status = switch_regex_match(dmachine->digits, bp->digits); + if (r_status == SWITCH_STATUS_SUCCESS) { if (is_timeout || (bp == dmachine->realm->binding_list && !bp->next)) { best = DM_MATCH_EXACT; @@ -325,11 +334,7 @@ static dm_match_t switch_ivr_dmachine_check_match(switch_ivr_dmachine_t *dmachin } else { int pmatch = !strncmp(dmachine->digits, bp->digits, strlen(dmachine->digits)); - if (pmatch) { - pmatches++; - } - - if (!exact_bp && pmatch && !strcmp(bp->digits, dmachine->digits)) { + if (!exact_bp && pmatch && (pmatches == 1 || is_timeout) && !strcmp(bp->digits, dmachine->digits)) { best = DM_MATCH_EXACT; exact_bp = bp; if (dmachine->cur_digit_len == dmachine->max_digit_len) break; From a035182582f35ee2a7d44953240e1a05a22b9f54 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Fri, 7 Sep 2012 00:02:32 +0200 Subject: [PATCH 05/12] ftmod_libpri: Append new lpwrap timers in correct order. List is sorted in ascending order of expiration time, fix the if clause in lpwrap_start_timer(). Signed-off-by: Stefan Knoblich --- libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c index fb478901b3..09fed0b72a 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c @@ -201,7 +201,7 @@ int lpwrap_start_timer(struct lpwrap_pri *spri, struct lpwrap_timer *timer, cons ftdm_mutex_lock(spri->timer_mutex); for (prev = &spri->timer_list, cur = spri->timer_list; cur; prev = &(*prev)->next, cur = cur->next) { - if (cur->timeout < timer->timeout) { + if (cur->timeout > timer->timeout) { *prev = timer; timer->next = cur; break; From 17329d04ad4bfb9a0ec21aabfbf15f2a4dc3535c Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Fri, 7 Sep 2012 00:04:40 +0200 Subject: [PATCH 06/12] ftmod_libpri: Print warning message in lpwrap_stop_timer(), if timer is not on the active list Signed-off-by: Stefan Knoblich --- libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c index 09fed0b72a..748b70a42f 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/lpwrap_pri.c @@ -238,6 +238,10 @@ int lpwrap_stop_timer(struct lpwrap_pri *spri, struct lpwrap_timer *timer) ftdm_mutex_unlock(spri->timer_mutex); + if (!cur) { + ftdm_log_chan(spri->dchan, FTDM_LOG_WARNING, "-- Timer %p not found in list\n", timer); + } + timer->next = NULL; timer->timeout = 0; timer->callback = NULL; From a7c791d2de000c958723465f6647bf069fa85595 Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Thu, 6 Sep 2012 15:43:01 -0700 Subject: [PATCH 07/12] Update phrase_en.xml (to be recorded) --- docs/phrase/phrase_en.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/phrase/phrase_en.xml b/docs/phrase/phrase_en.xml index fa9f4f7cc8..c9fa47ec59 100644 --- a/docs/phrase/phrase_en.xml +++ b/docs/phrase/phrase_en.xml @@ -590,7 +590,7 @@ - + From cd8814844a6af0873601969e502df30cbc736b9a Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 7 Sep 2012 15:08:10 -0500 Subject: [PATCH 08/12] FS-4408 fix crash caused by missing or invalid call-id in sip invite --- src/mod/endpoints/mod_sofia/sofia.c | 53 +++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 21ff55d480..79a925f4f8 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1690,6 +1690,14 @@ static void sofia_queue_message(sofia_dispatch_event_t *de) switch_queue_push(mod_sofia_globals.msg_queue, de); } +static void set_call_id(private_object_t *tech_pvt, sip_t const *sip) +{ + if (!tech_pvt->call_id && tech_pvt->session && tech_pvt->channel && sip && sip->sip_call_id && sip->sip_call_id->i_id) { + tech_pvt->call_id = switch_core_session_strdup(tech_pvt->session, sip->sip_call_id->i_id); + switch_channel_set_variable(tech_pvt->channel, "sip_call_id", tech_pvt->call_id); + } +} + void sofia_event_callback(nua_event_t event, int status, @@ -1709,16 +1717,22 @@ void sofia_event_callback(nua_event_t event, if ((session = switch_core_session_locate(sofia_private->uuid))) { private_object_t *tech_pvt = switch_core_session_get_private(session); + switch_channel_t *channel = switch_core_session_get_channel(session); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "detaching session %s\n", sofia_private->uuid); - - tech_pvt->sofia_private = NULL; - tech_pvt->nh = NULL; - sofia_set_flag(tech_pvt, TFLAG_BYE); - switch_mutex_lock(profile->flag_mutex); - switch_core_hash_insert(profile->chat_hash, tech_pvt->call_id, strdup(switch_core_session_get_uuid(session))); - switch_mutex_unlock(profile->flag_mutex); - switch_core_session_rwunlock(session); + set_call_id(tech_pvt, sip); + + if (!zstr(tech_pvt->call_id)) { + tech_pvt->sofia_private = NULL; + tech_pvt->nh = NULL; + sofia_set_flag(tech_pvt, TFLAG_BYE); + switch_mutex_lock(profile->flag_mutex); + switch_core_hash_insert(profile->chat_hash, tech_pvt->call_id, strdup(switch_core_session_get_uuid(session))); + switch_mutex_unlock(profile->flag_mutex); + switch_core_session_rwunlock(session); + } else { + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + } } } goto end; @@ -1804,9 +1818,25 @@ void sofia_event_callback(nua_event_t event, } else { free(uuid); uuid = NULL; + sip = NULL; } } } + + if (!sip || !sip->sip_call_id || zstr(sip->sip_call_id->i_id)) { + nua_respond(nh, 503, "INVALID INVITE", TAG_END()); + nua_destroy_event(de->event); + su_free(nh->nh_home, de); + + switch_mutex_lock(profile->flag_mutex); + profile->queued_events--; + switch_mutex_unlock(profile->flag_mutex); + + nua_handle_unref(nh); + nua_stack_unref(nua); + + goto end; + } if (sofia_test_pflag(profile, PFLAG_CALLID_AS_UUID)) { session = switch_core_session_request_uuid(sofia_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL, sip->sip_call_id->i_id); @@ -1829,13 +1859,8 @@ void sofia_event_callback(nua_event_t event, } sofia_glue_attach_private(session, profile, tech_pvt, channel_name); - - if (!tech_pvt->call_id && sip->sip_call_id && sip->sip_call_id->i_id) { - switch_channel_t *channel = switch_core_session_get_channel(session); - tech_pvt->call_id = switch_core_session_strdup(session, sip->sip_call_id->i_id); - switch_channel_set_variable(channel, "sip_call_id", tech_pvt->call_id); - } + set_call_id(tech_pvt, sip); } else { nua_respond(nh, 503, "Maximum Calls In Progress", SIPTAG_RETRY_AFTER_STR("300"), TAG_END()); nua_destroy_event(de->event); From bfc46567c14332fc7bbdfd56f2f99e2db563eb5a Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 7 Sep 2012 15:33:09 -0500 Subject: [PATCH 09/12] add uuid_media_reneg api command to tell a channel to send a re-invite with optional list of new codecs --- src/include/switch_types.h | 1 + .../applications/mod_commands/mod_commands.c | 45 +++++++++++++++++++ src/mod/endpoints/mod_sofia/mod_sofia.c | 38 ++++++++++++++++ src/mod/endpoints/mod_sofia/sofia_glue.c | 11 +++-- 4 files changed, 91 insertions(+), 4 deletions(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 6104999c4c..db9cf5cb0e 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -906,6 +906,7 @@ typedef enum { SWITCH_MESSAGE_INDICATE_AUDIO_DATA, SWITCH_MESSAGE_INDICATE_BLIND_TRANSFER_RESPONSE, SWITCH_MESSAGE_INDICATE_STUN_ERROR, + SWITCH_MESSAGE_INDICATE_MEDIA_RENEG, SWITCH_MESSAGE_INVALID } switch_core_session_message_types_t; diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 19817c83c3..0a6c1d08ce 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -2739,6 +2739,49 @@ SWITCH_STANDARD_API(uuid_media_function) return SWITCH_STATUS_SUCCESS; } +#define MEDIA_RENEG_SYNTAX "[ ]" +SWITCH_STANDARD_API(uuid_media_neg_function) +{ + char *mycmd = NULL, *argv[2] = { 0 }; + int argc = 0; + switch_status_t status = SWITCH_STATUS_FALSE; + + if (!zstr(cmd) && (mycmd = strdup(cmd))) { + argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); + } + + if (zstr(cmd) || argc < 1 || zstr(argv[0])) { + stream->write_function(stream, "-USAGE: %s\n", MEDIA_RENEG_SYNTAX); + } else { + switch_core_session_message_t msg = { 0 }; + switch_core_session_t *lsession = NULL; + char *uuid = argv[0]; + + msg.message_id = SWITCH_MESSAGE_INDICATE_MEDIA_RENEG; + msg.string_arg = argv[1]; + msg.from = __FILE__; + + if (*uuid == '+') { + msg.numeric_arg++; + uuid++; + } + + if ((lsession = switch_core_session_locate(uuid))) { + status = switch_core_session_receive_message(lsession, &msg); + switch_core_session_rwunlock(lsession); + } + } + + if (status == SWITCH_STATUS_SUCCESS) { + stream->write_function(stream, "+OK Success\n"); + } else { + stream->write_function(stream, "-ERR Operation Failed\n"); + } + + switch_safe_free(mycmd); + return SWITCH_STATUS_SUCCESS; +} + SWITCH_STANDARD_API(uuid_early_ok_function) { char *uuid = (char *) cmd; @@ -5690,6 +5733,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) SWITCH_ADD_API(commands_api_interface, "uuid_limit_release", "Release limit resource", uuid_limit_release_function, LIMIT_RELEASE_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_loglevel", "set loglevel on session", uuid_loglevel, UUID_LOGLEVEL_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_media", "media", uuid_media_function, MEDIA_SYNTAX); + SWITCH_ADD_API(commands_api_interface, "uuid_media_reneg", "media negotiation", uuid_media_neg_function, MEDIA_RENEG_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_park", "Park Channel", park_function, PARK_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_phone_event", "Send and event to the phone", uuid_phone_event_function, PHONE_EVENT_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_pre_answer", "pre_answer", uuid_pre_answer_function, ""); @@ -5841,6 +5885,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) switch_console_set_complete("add uuid_media ::console::list_uuid"); switch_console_set_complete("add uuid_media off ::console::list_uuid"); switch_console_set_complete("add uuid_park ::console::list_uuid"); + switch_console_set_complete("add uuid_media_reneg ::console::list_uuid"); switch_console_set_complete("add uuid_phone_event ::console::list_uuid talk"); switch_console_set_complete("add uuid_phone_event ::console::list_uuid hold"); switch_console_set_complete("add uuid_preprocess ::console::list_uuid"); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index a5f8d8d11f..bd36346be1 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1547,6 +1547,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi case SWITCH_MESSAGE_INDICATE_RECOVERY_REFRESH: case SWITCH_MESSAGE_INDICATE_APPLICATION_EXEC: break; + case SWITCH_MESSAGE_INDICATE_PROXY_MEDIA: { if (switch_rtp_ready(tech_pvt->rtp_session)) { @@ -1849,6 +1850,43 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi } switch (msg->message_id) { + + case SWITCH_MESSAGE_INDICATE_MEDIA_RENEG: + { + switch_core_session_t *nsession; + + if (msg->string_arg) { + switch_channel_set_variable(channel, "absolute_codec_string", NULL); + if (*msg->string_arg == '=') { + switch_channel_set_variable(channel, "codec_string", msg->string_arg); + } else { + switch_channel_set_variable_printf(channel, "codec_string", "=%s%s%s,%s", + tech_pvt->video_rm_encoding ? tech_pvt->video_rm_encoding : "", + tech_pvt->video_rm_encoding ? "," : "", + tech_pvt->rm_encoding, msg->string_arg); + } + + + tech_pvt->num_codecs = 0; + tech_pvt->rm_encoding = NULL; + tech_pvt->video_rm_encoding = NULL; + sofia_clear_flag_locked(tech_pvt, TFLAG_VIDEO); + sofia_glue_tech_prepare_codecs(tech_pvt); + sofia_glue_check_video_codecs(tech_pvt); + sofia_glue_set_local_sdp(tech_pvt, NULL, 0, NULL, 1); + sofia_set_pflag(tech_pvt->profile, PFLAG_RENEG_ON_REINVITE); + } + + sofia_glue_do_invite(session); + + if (msg->numeric_arg && switch_core_session_get_partner(session, &nsession) == SWITCH_STATUS_SUCCESS) { + msg->numeric_arg = 0; + switch_core_session_receive_message(nsession, msg); + switch_core_session_rwunlock(nsession); + } + + } + break; case SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ: { const char *pl = ""; diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index c381ead0d4..453d58cea0 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -833,12 +833,14 @@ void sofia_glue_tech_prepare_codecs(private_object_t *tech_pvt) if (!(codec_string = switch_channel_get_variable(tech_pvt->channel, "codec_string"))) { codec_string = sofia_glue_get_codec_string(tech_pvt); - if (codec_string && *codec_string == '=') { - codec_string++; - goto ready; - } } + if (codec_string && *codec_string == '=') { + codec_string++; + goto ready; + } + + if ((ocodec = switch_channel_get_variable(tech_pvt->channel, SWITCH_ORIGINATOR_CODEC_VARIABLE))) { if (!codec_string || sofia_test_pflag(tech_pvt->profile, PFLAG_DISABLE_TRANSCODING)) { codec_string = ocodec; @@ -871,6 +873,7 @@ void sofia_glue_check_video_codecs(private_object_t *tech_pvt) int i; tech_pvt->video_count = 0; for (i = 0; i < tech_pvt->num_codecs; i++) { + if (tech_pvt->codecs[i]->codec_type == SWITCH_CODEC_TYPE_VIDEO) { tech_pvt->video_count++; } From e2544415ada2de4bf4f4cdd2bb386e69285c7f82 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 7 Sep 2012 16:50:50 -0500 Subject: [PATCH 10/12] add chan vars to tell sip to break the rfc and expect the codec payload the other side replies with rather than the one it offered which is the correct behaviour --- src/mod/endpoints/mod_sofia/sofia_glue.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 453d58cea0..97d9e06e07 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -5138,6 +5138,8 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s if (mimp) { char tmp[50]; + const char *mirror = switch_channel_get_variable(tech_pvt->channel, "sip_mirror_remote_audio_codec_payload"); + tech_pvt->rm_encoding = switch_core_session_strdup(session, (char *) map->rm_encoding); tech_pvt->iananame = switch_core_session_strdup(session, (char *) mimp->iananame); tech_pvt->pt = (switch_payload_t) map->rm_pt; @@ -5155,7 +5157,9 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s switch_channel_set_variable(tech_pvt->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp); tech_pvt->audio_recv_pt = (switch_payload_t)map->rm_pt; - if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && !sofia_test_flag(tech_pvt, TFLAG_REINVITE)) { + if (!switch_true(mirror) && + switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND && + (!sofia_test_flag(tech_pvt, TFLAG_REINVITE) || sofia_test_pflag(tech_pvt->profile, PFLAG_RENEG_ON_REINVITE))) { sofia_glue_get_offered_pt(tech_pvt, mimp, &tech_pvt->audio_recv_pt); } @@ -5278,6 +5282,8 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s if (mimp) { if ((tech_pvt->video_rm_encoding = switch_core_session_strdup(session, (char *) rm_encoding))) { char tmp[50]; + const char *mirror = switch_channel_get_variable(tech_pvt->channel, "sip_mirror_remote_video_codec_payload"); + tech_pvt->video_pt = (switch_payload_t) map->rm_pt; tech_pvt->video_rm_rate = map->rm_rate; tech_pvt->video_codec_ms = mimp->microseconds_per_packet / 1000; @@ -5295,7 +5301,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s tech_pvt->video_recv_pt = (switch_payload_t)map->rm_pt; - if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { + if (!switch_true(mirror) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { sofia_glue_get_offered_pt(tech_pvt, mimp, &tech_pvt->video_recv_pt); } From c2893801cb407826d177663c0eb23dfef2354c47 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 7 Sep 2012 18:17:57 -0500 Subject: [PATCH 11/12] add timestamps for on and off hold times to put in xml cdrs --- src/include/switch_channel.h | 1 + src/include/switch_core.h | 10 ++++++++++ src/switch_channel.c | 31 +++++++++++++++++++++++++++++++ src/switch_ivr.c | 35 +++++++++++++++++++++++++++++++++-- 4 files changed, 75 insertions(+), 2 deletions(-) diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index 2348a4cc54..f4655a23e6 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -642,6 +642,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_api_on(switch_channel_t *channel, SWITCH_DECLARE(switch_caller_extension_t *) switch_channel_get_queued_extension(switch_channel_t *channel); SWITCH_DECLARE(void) switch_channel_transfer_to_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension); SWITCH_DECLARE(const char *) switch_channel_get_partner_uuid(switch_channel_t *channel); +SWITCH_DECLARE(switch_hold_record_t *) switch_channel_get_hold_record(switch_channel_t *channel); SWITCH_END_EXTERN_C #endif diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 50ec7a965e..b340078f41 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -61,6 +61,16 @@ struct switch_app_log { struct switch_app_log *next; }; + +typedef struct switch_hold_record_s { + switch_time_t on; + switch_time_t off; + char *uuid; + struct switch_hold_record_s *next; +} switch_hold_record_t; + + + #define MESSAGE_STAMP_FFL(_m) _m->_file = __FILE__; _m->_func = __SWITCH_FUNC__; _m->_line = __LINE__ #define MESSAGE_STRING_ARG_MAX 10 diff --git a/src/switch_channel.c b/src/switch_channel.c index 38331f0be9..3f767ae21d 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -155,8 +155,13 @@ struct switch_channel { switch_event_t *app_list; switch_event_t *api_list; switch_event_t *var_list; + switch_hold_record_t *hold_record; }; +SWITCH_DECLARE(switch_hold_record_t *) switch_channel_get_hold_record(switch_channel_t *channel) +{ + return channel->hold_record; +} SWITCH_DECLARE(const char *) switch_channel_cause2str(switch_call_cause_t cause) { @@ -1611,9 +1616,24 @@ SWITCH_DECLARE(void) switch_channel_set_flag_value(switch_channel_t *channel, sw switch_mutex_unlock(channel->flag_mutex); if (HELD) { + switch_hold_record_t *hr; + const char *brto = switch_channel_get_partner_uuid(channel); + switch_channel_set_callstate(channel, CCS_HELD); switch_mutex_lock(channel->profile_mutex); channel->caller_profile->times->last_hold = switch_time_now(); + + hr = switch_core_session_alloc(channel->session, sizeof(*hr)); + hr->on = switch_time_now(); + if (brto) { + hr->uuid = switch_core_session_strdup(channel->session, brto); + } + + if (channel->hold_record) { + hr->next = channel->hold_record; + } + channel->hold_record = hr; + switch_mutex_unlock(channel->profile_mutex); } @@ -1763,6 +1783,11 @@ SWITCH_DECLARE(void) switch_channel_clear_flag(switch_channel_t *channel, switch if (channel->caller_profile->times->last_hold) { channel->caller_profile->times->hold_accum += (switch_time_now() - channel->caller_profile->times->last_hold); } + + if (channel->hold_record) { + channel->hold_record->off = switch_time_now(); + } + switch_mutex_unlock(channel->profile_mutex); } @@ -2905,6 +2930,12 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_hangup(switch_chan switch_event_t *event; const char *var; + switch_mutex_lock(channel->profile_mutex); + if (channel->hold_record && !channel->hold_record->off) { + channel->hold_record->off = switch_time_now(); + } + switch_mutex_unlock(channel->profile_mutex); + switch_mutex_lock(channel->state_mutex); last_state = channel->state; channel->state = CS_HANGUP; diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 92f6186934..63721e66fd 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -2195,11 +2195,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_generate_xml_cdr(switch_core_session_ switch_channel_t *channel = switch_core_session_get_channel(session); switch_caller_profile_t *caller_profile; switch_xml_t variables, cdr, x_main_cp, x_caller_profile, x_caller_extension, x_times, time_tag, - x_application, x_callflow, x_inner_extension, x_apps, x_o, x_channel_data, x_field; + x_application, x_callflow, x_inner_extension, x_apps, x_o, x_channel_data, x_field, xhr, x_hold; switch_app_log_t *app_log; char tmp[512], *f; int cdr_off = 0, v_off = 0, cd_off = 0; - + switch_hold_record_t *hold_record = switch_channel_get_hold_record(channel), *hr; + if (*xml_cdr) { cdr = *xml_cdr; } else { @@ -2266,6 +2267,36 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_generate_xml_cdr(switch_core_session_ } } + if (hold_record) { + int cf_off = 0; + + if (!(xhr = switch_xml_add_child_d(cdr, "hold-record", cdr_off++))) { + goto error; + } + + for (hr = hold_record; hr; hr = hr->next) { + char *t = tmp; + if (!(x_hold = switch_xml_add_child_d(xhr, "hold", cf_off++))) { + goto error; + } + + switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, hr->on); + switch_xml_set_attr_d(x_hold, "on", t); + + switch_snprintf(tmp, sizeof(tmp), "%" SWITCH_TIME_T_FMT, hr->off); + switch_xml_set_attr_d(x_hold, "off", t); + + if (hr->uuid) { + switch_xml_set_attr_d(x_hold, "bridged-to", hr->uuid); + } + + + } + + + } + + caller_profile = switch_channel_get_caller_profile(channel); From 6de760992fe44eb30bb8ed128ab356806ba331b9 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Fri, 7 Sep 2012 18:28:06 -0500 Subject: [PATCH 12/12] FS-4591 --- src/mod/languages/mod_managed/managed/ManagedSession.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/mod/languages/mod_managed/managed/ManagedSession.cs b/src/mod/languages/mod_managed/managed/ManagedSession.cs index 9629215c70..bed7a03878 100644 --- a/src/mod/languages/mod_managed/managed/ManagedSession.cs +++ b/src/mod/languages/mod_managed/managed/ManagedSession.cs @@ -139,16 +139,13 @@ namespace FreeSWITCH.Native // The delegate needs to be stored so it doesn't get GC'd, so we can't just return GetFunctionPointerForDelegate right away. /// Wraps a nice handler into a delegate suitable for reverse P/Invoke. This only currently works well for hangup/reporting handlers. - public static switch_state_handler_t_delegate CreateStateHandlerDelegate(Action handler) { + public static switch_state_handler_t_delegate CreateStateHandlerDelegate(ManagedSession sess, Action handler) + { // We create a ManagedSession on top of the session so callbacks can use it "nicely" // Then we sort of dispose it. switch_state_handler_t_delegate del = ptr => { - using (var sess = new ManagedSession(new SWIGTYPE_p_switch_core_session(ptr, false))) { handler(sess); - sess.SetAutoHangup(false); - sess.destroy(); return switch_status_t.SWITCH_STATUS_SUCCESS; - } }; return del; } @@ -187,7 +184,7 @@ namespace FreeSWITCH.Native var bleg = new ManagedSession(); bleg.originate_ondestroy_delegate = bleg.originate_ondestroy_method; - bleg.originate_onhangup_delegate = CreateStateHandlerDelegate(sess_b => { + bleg.originate_onhangup_delegate = CreateStateHandlerDelegate(bleg, sess_b => { if (onHangup != null) { onHangup(sess_b); }