diff --git a/conf/lang/en/vm/sounds.xml b/conf/lang/en/vm/sounds.xml index 976fcde32d..449ad55f2d 100644 --- a/conf/lang/en/vm/sounds.xml +++ b/conf/lang/en/vm/sounds.xml @@ -315,7 +315,7 @@ - + @@ -331,9 +331,17 @@ + + + + + - + + + + diff --git a/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c b/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c index 9673549f79..06caeef7ae 100644 --- a/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c +++ b/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c @@ -25,6 +25,15 @@ * NOTE: This is intended as a Layer 1 interface only, signaling * is handled by other modules (e.g. ftmod_libpri or ftmod_isdn). */ +/* + * TODO: + * - Use a fifo and PH_DATA_CNF for b-channel write polling (drop timerfd) + * + * - Disable L1 idle deactivation on BRI PTMP with IMGL1HOLD ioctl(? optional) + * + * - Add hfcsusb specific state + flag defines and try to do something useful with + * it in misdn_handle_mph_information_ind(). + */ #include #include @@ -91,23 +100,33 @@ typedef enum { #define MISDN_IS_RAW(x) (x & MISDN_CAPS_RAW) #define MISDN_IS_HDLC(x) (x & MISDN_CAPS_HDLC) +#define MISDN_MSG_DATA(x) ((void *)((unsigned char *)(x) + MISDN_HEADER_LEN)) const static struct { const int id; const char *name; } misdn_event_types[] = { - { PH_DATA_REQ, "PH_DATA_REQ" }, - { PH_DATA_IND, "PH_DATA_IND" }, - { PH_DATA_CNF, "PH_DATA_CNF" }, - { PH_CONTROL_REQ, "PH_CONTROL_REQ" }, - { PH_CONTROL_IND, "PH_CONTROL_IND" }, - { PH_CONTROL_CNF, "PH_CONTROL_CNF" }, - { PH_ACTIVATE_REQ, "PH_ACTIVATE_REQ" }, - { PH_ACTIVATE_IND, "PH_ACTIVATE_IND" }, - { PH_ACTIVATE_CNF, "PH_ACTIVATE_CNF" }, - { PH_DEACTIVATE_REQ, "PH_DEACTIVATE_REQ" }, - { PH_DEACTIVATE_IND, "PH_DEACTIVATE_IND" }, - { PH_DEACTIVATE_CNF, "PH_DEACTIVATE_CNF" }, +#define MISDN_EVENT_TYPE(x) { x, #x } + MISDN_EVENT_TYPE(PH_DATA_REQ), + MISDN_EVENT_TYPE(PH_DATA_IND), + MISDN_EVENT_TYPE(PH_DATA_CNF), + MISDN_EVENT_TYPE(PH_DATA_E_IND), + MISDN_EVENT_TYPE(PH_CONTROL_REQ), + MISDN_EVENT_TYPE(PH_CONTROL_IND), + MISDN_EVENT_TYPE(PH_CONTROL_CNF), + MISDN_EVENT_TYPE(PH_ACTIVATE_REQ), + MISDN_EVENT_TYPE(PH_ACTIVATE_IND), + MISDN_EVENT_TYPE(PH_ACTIVATE_CNF), + MISDN_EVENT_TYPE(PH_DEACTIVATE_REQ), + MISDN_EVENT_TYPE(PH_DEACTIVATE_IND), + MISDN_EVENT_TYPE(PH_DEACTIVATE_CNF), + MISDN_EVENT_TYPE(MPH_ACTIVATE_REQ), + MISDN_EVENT_TYPE(MPH_ACTIVATE_IND), + MISDN_EVENT_TYPE(MPH_DEACTIVATE_REQ), + MISDN_EVENT_TYPE(MPH_DEACTIVATE_IND), + MISDN_EVENT_TYPE(MPH_INFORMATION_REQ), + MISDN_EVENT_TYPE(MPH_INFORMATION_IND), +#undef MISDN_EVENT_TYPE }; static const char *misdn_event2str(const int event) @@ -128,6 +147,7 @@ const static struct { } misdn_control_types[] = { #define MISDN_CONTROL_TYPE(x) { x, #x } MISDN_CONTROL_TYPE(DTMF_HFC_COEF), +#undef MISDN_CONTROL_TYPE }; #if 0 /* unused for now */ @@ -189,6 +209,7 @@ struct misdn_chan_private { #define ftdm_span_io_private(x) ((x)->io_data) static ftdm_status_t misdn_handle_incoming(ftdm_channel_t *ftdmchan, const char *rbuf, const int size); +static int misdn_handle_mph_information_ind(ftdm_channel_t *chan, const struct mISDNhead *hh, const void *data, const int data_len); /*********************************************************************************** * mISDN interface functions @@ -432,8 +453,8 @@ static ftdm_status_t misdn_activate_channel(ftdm_channel_t *chan, int activate) return FTDM_FAIL; } //#ifdef MISDN_DEBUG_EVENTS - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN got event '%s' while waiting for %s confirmation\n", - misdn_event2str(hh->prim), (activate) ? "activation" : "deactivation"); + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN got event '%s (%#x)' while waiting for %s confirmation\n", + misdn_event2str(hh->prim), hh->prim, (activate) ? "activation" : "deactivation"); //#endif switch (hh->prim) { case PH_ACTIVATE_IND: /* success (or not): save last response, */ @@ -451,9 +472,14 @@ static ftdm_status_t misdn_activate_channel(ftdm_channel_t *chan, int activate) ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN got '%s' echo while waiting for %s confirmation (id: %#x)\n", misdn_event2str(hh->prim), (activate) ? "activation" : "deactivation", hh->id); break; + case MPH_INFORMATION_IND: + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN ignoring event '%s (%#x)' while waiting for %s confirmation\n", + misdn_event2str(hh->prim), hh->prim, (activate) ? "activation" : "deactivation"); + misdn_handle_mph_information_ind(chan, hh, MISDN_MSG_DATA(buf), retval - MISDN_HEADER_LEN); + break; default: /* other messages, ignore */ - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN ignoring event '%s' while waiting for %s confirmation\n", - misdn_event2str(hh->prim), (activate) ? "activation" : "deactivation"); + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN ignoring event '%s (%#x)' while waiting for %s confirmation\n", + misdn_event2str(hh->prim), hh->prim, (activate) ? "activation" : "deactivation"); break; } } @@ -605,50 +631,88 @@ static int misdn_handle_ph_control_ind(ftdm_channel_t *chan, const struct mISDNh static int misdn_handle_mph_information_ind(ftdm_channel_t *chan, const struct mISDNhead *hh, const void *data, const int data_len) { struct misdn_chan_private *priv = ftdm_chan_io_private(chan); - int alarm_flags, value; - if (data_len < sizeof(value)) { - ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "mISDN MPH_INFORMATION_IND message is too short\n"); + /* + * mISDN has some inconsistency issues here. + * + * There are only two drivers that emit MPH_INFORMATION_IND messages, + * hfcsusb and hfcmulti. The former sends a set of ph_info and ph_info_ch structures, + * while the latter just sends an int containing the current L1_SIGNAL_* event id. + * + * The flags and state information in the ph_info and ph_info_ch structures + * are defined in kernel internal hw-specific headers (mISDNhw.h). + * + * Use the payload size to guess the type of message. + */ + if (data_len >= sizeof(struct ph_info)) { + /* complete port status, hfcsusb sends this */ + struct ph_info *info = (struct ph_info *)data; + struct ph_info_ch *bch_info = NULL; + + if (data_len < (sizeof(*info) + info->dch.num_bch * sizeof(*bch_info))) { + ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "mISDN MPH_INFORMATION_IND message is too short\n"); + return FTDM_FAIL; + } + bch_info = &info->bch[0]; + + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN port state:\n\tD-Chan state:\t%hu\n\tD-Chan flags:\t%#x\n\tD-Chan proto:\t%hu\n\tD-Chan active:\t%s\n", + info->dch.state, info->dch.ch.Flags, info->dch.ch.protocol, info->dch.ch.Flags & (1 << 6) ? "yes" : "no"); + + /* TODO: try to translate this to a usable set of alarm flags */ + + } else if (data_len == sizeof(int)) { + /* alarm info, sent by hfcmulti */ + int value = *(int *)data; + int alarm_flags = chan->alarm_flags; + + if (data_len < sizeof(value)) { + ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "mISDN MPH_INFORMATION_IND message is too short\n"); + return FTDM_FAIL; + } + + switch (value) { + case L1_SIGNAL_LOS_ON: + alarm_flags |= FTDM_ALARM_RED; + break; + case L1_SIGNAL_LOS_OFF: + alarm_flags &= ~FTDM_ALARM_RED; + break; + case L1_SIGNAL_AIS_ON: + alarm_flags |= FTDM_ALARM_AIS; + break; + case L1_SIGNAL_AIS_OFF: + alarm_flags &= ~FTDM_ALARM_AIS; + break; + case L1_SIGNAL_RDI_ON: + alarm_flags |= FTDM_ALARM_YELLOW; + break; + case L1_SIGNAL_RDI_OFF: + alarm_flags &= ~FTDM_ALARM_YELLOW; + break; + case L1_SIGNAL_SLIP_RX: + priv->slip_rx_cnt++; + break; + case L1_SIGNAL_SLIP_TX: + priv->slip_tx_cnt++; + break; + default: + ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN unknown MPH_INFORMATION_IND signal: %#04x\n", + value); + return FTDM_FAIL; + } + + /* check whether alarm status has changed, update channel flags if it has */ + if ((value = (alarm_flags ^ chan->alarm_flags))) { + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN alarm flags have changed %#x -> %#x\n", + chan->alarm_flags, alarm_flags); + chan->alarm_flags ^= value; + } + } else { + ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN sent MPH_INFORMATION_IND message with unknown size %d\n", + data_len); return FTDM_FAIL; } - value = *(int *)data; - alarm_flags = chan->alarm_flags; - switch (value) { - case L1_SIGNAL_LOS_ON: - alarm_flags |= FTDM_ALARM_RED; - break; - case L1_SIGNAL_LOS_OFF: - alarm_flags &= ~FTDM_ALARM_RED; - break; - case L1_SIGNAL_AIS_ON: - alarm_flags |= FTDM_ALARM_AIS; - break; - case L1_SIGNAL_AIS_OFF: - alarm_flags &= ~FTDM_ALARM_AIS; - break; - case L1_SIGNAL_RDI_ON: - alarm_flags |= FTDM_ALARM_YELLOW; - break; - case L1_SIGNAL_RDI_OFF: - alarm_flags &= ~FTDM_ALARM_YELLOW; - break; - case L1_SIGNAL_SLIP_RX: - priv->slip_rx_cnt++; - break; - case L1_SIGNAL_SLIP_TX: - priv->slip_tx_cnt++; - break; - default: - ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN unknown MPH_INFORMATION_IND message: %d\n", - value); - return FTDM_FAIL; - } - if ((value = (alarm_flags ^ chan->alarm_flags))) { - ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN alarm flags have changed %#x -> %#x\n", - chan->alarm_flags, alarm_flags); - chan->alarm_flags ^= value; - } return FTDM_SUCCESS; } diff --git a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c index f1d56a92c5..7cb0982591 100644 --- a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c +++ b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c @@ -341,6 +341,7 @@ static int phase_b_handler(t30_state_t *s, void *user_data, int result) /* Fire event */ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, pvt->app_mode == FUNCTION_TX ? SPANDSP_EVENT_TXFAXNEGOCIATERESULT : SPANDSP_EVENT_RXFAXNEGOCIATERESULT) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "uuid", switch_core_session_get_uuid(session)); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-transfer-rate", fax_transfer_rate); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-ecm-used", (t30_stats.error_correcting_mode) ? "on" : "off"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-local-station-id", local_ident); @@ -437,6 +438,7 @@ static int phase_d_handler(t30_state_t *s, void *user_data, int msg) switch_channel_execute_on(channel, "execute_on_fax_phase_d"); if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, pvt->app_mode == FUNCTION_TX ? SPANDSP_EVENT_TXFAXPAGERESULT : SPANDSP_EVENT_RXFAXPAGERESULT) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "uuid", switch_core_session_get_uuid(session)); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-document-transferred-pages", fax_document_transferred_pages); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-resolution", fax_image_resolution); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "fax-image-size", fax_image_size); diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 8461f480bc..df68f28166 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -1544,8 +1544,6 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t char cid_buf[1024] = ""; if (switch_channel_ready(channel)) { - const char *vm_announce_cid = NULL; - switch_snprintf(cid_buf, sizeof(cid_buf), "%s|%s", cbt->cid_number, cbt->cid_name); msg.from = __FILE__; @@ -1556,10 +1554,8 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t cid_buf, switch_channel_get_name(channel)); switch_core_session_receive_message(session, &msg); - if (!zstr(cbt->cid_number) && (vm_announce_cid = switch_channel_get_variable(channel, "vm_announce_cid"))) { - switch_ivr_play_file(session, NULL, vm_announce_cid, NULL); - switch_ivr_sleep(session, 500, SWITCH_TRUE, NULL); - switch_ivr_say(session, cbt->cid_number, NULL, "name_spelled", "pronounced", NULL, NULL); + if (!zstr(cbt->cid_number) && (switch_true(switch_channel_get_variable(channel, "vm_announce_cid")))) { + TRY_CODE(switch_ivr_phrase_macro(session, VM_SAY_PHONE_NUMBER_MACRO, cbt->cid_number, NULL, NULL)); } args.input_callback = cancel_on_dtmf; diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 1860c08290..0a2f672df6 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -262,6 +262,7 @@ typedef enum { PFLAG_SHUTDOWN, PFLAG_PRESENCE_MAP, PFLAG_OPTIONS_RESPOND_503_ON_BUSY, + PFLAG_PRESENCE_DISABLE_EARLY, /* No new flags below this line */ PFLAG_MAX } PFLAGS; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 3dd28d7f60..0668eedf57 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -3035,6 +3035,12 @@ switch_status_t reconfig_sofia(sofia_profile_t *profile) } else { sofia_clear_pflag(profile, PFLAG_T38_PASSTHRU); } + } else if (!strcasecmp(var, "presence-disable-early")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_PRESENCE_DISABLE_EARLY); + } else { + sofia_clear_pflag(profile, PFLAG_PRESENCE_DISABLE_EARLY); + } } else if (!strcasecmp(var, "ignore-183nosdp")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_IGNORE_183NOSDP); @@ -3809,6 +3815,12 @@ switch_status_t config_sofia(int reload, char *profile_name) } else { sofia_clear_pflag(profile, PFLAG_T38_PASSTHRU); } + } else if (!strcasecmp(var, "presence-disable-early")) { + if (switch_true(val)) { + sofia_set_pflag(profile, PFLAG_PRESENCE_DISABLE_EARLY); + } else { + sofia_clear_pflag(profile, PFLAG_PRESENCE_DISABLE_EARLY); + } } else if (!strcasecmp(var, "ignore-183nosdp")) { if (switch_true(val)) { sofia_set_pflag(profile, PFLAG_IGNORE_183NOSDP); diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 75c663ef07..683903fc66 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -2499,11 +2499,17 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char * if (!strcasecmp(astate, "answered")) { astate = "confirmed"; } - + if (!strcasecmp(astate, "hangup")) { astate = "terminated"; } + if (!sofia_test_pflag(profile, PFLAG_PRESENCE_DISABLE_EARLY)) { + if (!strcasecmp(astate, "ringing") || !strcasecmp(astate, "early")) { + astate = "confirmed"; + } + } + if (is_dialog) { if (!strcasecmp(astate, "ringing")) { diff --git a/src/mod/timers/mod_posix_timer/mod_posix_timer.c b/src/mod/timers/mod_posix_timer/mod_posix_timer.c index f5b9a61a1f..425e98c93d 100644 --- a/src/mod/timers/mod_posix_timer/mod_posix_timer.c +++ b/src/mod/timers/mod_posix_timer/mod_posix_timer.c @@ -28,8 +28,8 @@ * */ #include -#include -#include +#include +#include SWITCH_MODULE_LOAD_FUNCTION(mod_posix_timer_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_posix_timer_shutdown); @@ -59,7 +59,7 @@ static struct { /** * Notified by POSIX timer of a tick */ -static void posix_timer_notify(sigval_t data) +static void posix_timer_notify(union sigval data) { interval_timer_t *it = (interval_timer_t *)data.sival_ptr; switch_mutex_lock(it->mutex); diff --git a/src/switch_event.c b/src/switch_event.c index 7e8a8676ba..25bab3185a 100644 --- a/src/switch_event.c +++ b/src/switch_event.c @@ -85,6 +85,7 @@ static switch_mutex_t *EVENT_QUEUE_MUTEX = NULL; static switch_hash_t *CUSTOM_HASH = NULL; static int THREAD_COUNT = 0; static int SYSTEM_RUNNING = 0; +static uint64_t EVENT_SEQUENCE_NR = 0; #ifdef SWITCH_EVENT_RECYCLE static switch_queue_t *EVENT_RECYCLE_QUEUE = NULL; static switch_queue_t *EVENT_HEADER_RECYCLE_QUEUE = NULL; @@ -1740,6 +1741,10 @@ SWITCH_DECLARE(void) switch_event_prep_for_delivery_detailed(const char *file, c switch_size_t retsize; switch_time_t ts = switch_micro_time_now(); + switch_mutex_lock(EVENT_QUEUE_MUTEX); + EVENT_SEQUENCE_NR++; + switch_mutex_unlock(EVENT_QUEUE_MUTEX); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Event-Name", switch_event_name(event->event_id)); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Core-UUID", switch_core_get_uuid()); @@ -1757,6 +1762,7 @@ SWITCH_DECLARE(void) switch_event_prep_for_delivery_detailed(const char *file, c switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Event-Calling-File", switch_cut_path(file)); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Event-Calling-Function", func); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Calling-Line-Number", "%d", line); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Event-Sequence", "%" SWITCH_UINT64_T_FMT, (uint64_t) EVENT_SEQUENCE_NR); }