diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 2a0fa83706..8fea822101 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -47,7 +47,6 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span); static ftdm_status_t ftdm_sangoma_isdn_dtmf(ftdm_channel_t *ftdmchan, const char* dtmf); ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event); -static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span); static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event); static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan); static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event); @@ -313,28 +312,6 @@ static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_eve } } -static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span) -{ - ftdm_status_t ret_status; - - ret_status = ftdm_span_poll_event(span, 0, NULL); - switch(ret_status) { - case FTDM_SUCCESS: - { - ftdm_event_t *event; - while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) { - ftdm_sangoma_isdn_process_phy_events(span, event->enum_id); - } - } - break; - case FTDM_TIMEOUT: - /* No events pending */ - break; - default: - ftdm_log(FTDM_LOG_WARNING, "%s:Failed to poll span event\n", span->name); - } -} - static void ftdm_sangoma_isdn_dchan_set_queue_size(ftdm_channel_t *dchan) { ftdm_status_t ret_status; @@ -374,6 +351,7 @@ static void *ftdm_sangoma_isdn_io_run(ftdm_thread_t *me, void *obj) unsigned waitms = 10000; ftdm_iterator_t *chaniter = NULL; ftdm_iterator_t *citer = NULL; + ftdm_event_t *event; short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count); /* Initialize the d-channel */ @@ -394,6 +372,8 @@ static void *ftdm_sangoma_isdn_io_run(ftdm_thread_t *me, void *obj) wflags = FTDM_READ; memset(poll_events, 0, sizeof(short)*span->chan_count); + poll_events[i] |= FTDM_EVENTS; + for (i = 0, citer = ftdm_span_get_chan_iterator(span, chaniter); citer; citer = ftdm_iterator_next(citer), i++) { ftdmchan = ftdm_iterator_current(citer); @@ -416,6 +396,7 @@ static void *ftdm_sangoma_isdn_io_run(ftdm_thread_t *me, void *obj) case FTDM_TIMEOUT: break; case FTDM_SUCCESS: + /* Check if there are any channels that have data available */ for (citer = ftdm_span_get_chan_iterator(span, chaniter); citer; citer = ftdm_iterator_next(citer)) { len = 1000; ftdmchan = ftdm_iterator_current(citer); @@ -444,6 +425,12 @@ static void *ftdm_sangoma_isdn_io_run(ftdm_thread_t *me, void *obj) } } } + + /* Check if there are any channels that have events available */ + while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) { + ftdm_sangoma_isdn_process_phy_events(span, event->enum_id); + } + break; default: ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Unhandled IO event\n"); @@ -487,7 +474,6 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) } while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) { - /* Check if there are any timers to process */ ftdm_sched_run(signal_data->sched); ftdm_span_trigger_signals(span); @@ -525,9 +511,6 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) ftdm_log(FTDM_LOG_ERROR, "%s: ftdm_interrupt_wait returned with unknown code\n", span->name); break; } - - /* Poll for events, e.g HW DTMF */ - ftdm_sangoma_isdn_poll_events(span); } /* clear the IN_THREAD flag so that we know the thread is done */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index c5256d08fc..44538bba61 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -1143,7 +1143,7 @@ static ftdm_status_t sngisdn_force_down(ftdm_channel_t *ftdmchan) sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data; ftdm_status_t status = FTDM_SUCCESS; - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Forcing channel to DOWN state (%s)\n", ftdm_channel_state2str(ftdmchan->state)); + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Forcing channel to DOWN state (%s)\n", ftdm_channel_state2str(ftdmchan->state)); switch (ftdmchan->state) { case FTDM_CHANNEL_STATE_DOWN: /* Do nothing */ diff --git a/libs/libdingaling/src/libdingaling.c b/libs/libdingaling/src/libdingaling.c index bbf26ca5c9..76b19f118f 100644 --- a/libs/libdingaling/src/libdingaling.c +++ b/libs/libdingaling/src/libdingaling.c @@ -1908,6 +1908,8 @@ void ldl_handle_send_msg(ldl_handle_t *handle, char *from, char *to, const char int on = 0; int len = 0; char *my_body = strdup(body); + char *my_body_base = my_body; + assert(handle != NULL); assert(body != NULL); @@ -1952,7 +1954,9 @@ void ldl_handle_send_msg(ldl_handle_t *handle, char *from, char *to, const char free(bdup); } - free(my_body); + if (my_body_base) { + free(my_body_base); + } apr_queue_push(handle->queue, msg); msg = NULL; diff --git a/src/include/switch_apr.h b/src/include/switch_apr.h index 2306075e1f..c7279b6a8c 100644 --- a/src/include/switch_apr.h +++ b/src/include/switch_apr.h @@ -1202,6 +1202,8 @@ SWITCH_DECLARE(switch_status_t) switch_socket_send(switch_socket_t *sock, const */ SWITCH_DECLARE(switch_status_t) switch_socket_sendto(switch_socket_t *sock, switch_sockaddr_t *where, int32_t flags, const char *buf, switch_size_t *len); + +SWITCH_DECLARE(switch_status_t) switch_socket_send_nonblock(switch_socket_t *sock, const char *buf, switch_size_t *len); /** * @param from The apr_sockaddr_t to fill in the recipient info diff --git a/src/include/switch_buffer.h b/src/include/switch_buffer.h index 75b5929b9b..751439d1ad 100644 --- a/src/include/switch_buffer.h +++ b/src/include/switch_buffer.h @@ -109,6 +109,8 @@ SWITCH_DECLARE(switch_size_t) switch_buffer_read(_In_ switch_buffer_t *buffer, _ */ SWITCH_DECLARE(switch_size_t) switch_buffer_peek(_In_ switch_buffer_t *buffer, _In_ void *data, _In_ switch_size_t datalen); +SWITCH_DECLARE(switch_size_t) switch_buffer_peek_zerocopy(_In_ switch_buffer_t *buffer, _Out_ const void **ptr); + /*! \brief Read data endlessly from a switch_buffer_t * \param buffer any buffer of type switch_buffer_t * \param data pointer to the read data to be returned diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 681fbf4dc6..9e16346199 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1227,7 +1227,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_insert(_In_ switch_hash_t *hash \note the string key must be a constant or a dynamic string */ SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_locked(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_opt_ const void *data, - _In_ switch_mutex_t *mutex); + _In_opt_ switch_mutex_t *mutex); +/*! + \brief Retrieve data from a given hash + \param hash the hash to retrieve from + \param key the key to retrieve + \param mutex optional rwlock to wrlock + \return a pointer to the data held in the key +*/ +SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_wrlock(switch_hash_t *hash, const char *key, const void *data, switch_thread_rwlock_t *rwlock); /*! \brief Delete data from a hash based on desired key @@ -1244,7 +1252,16 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_delete(_In_ switch_hash_t *hash \param mutex optional mutex to lock \return SWITCH_STATUS_SUCCESS if the data is deleted */ -SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_locked(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_ switch_mutex_t *mutex); +SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_locked(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_opt_ switch_mutex_t *mutex); + +/*! + \brief Delete data from a hash based on desired key + \param hash the hash to delete from + \param key the key from which to delete the data + \param mutex optional rwlock to wrlock + \return SWITCH_STATUS_SUCCESS if the data is deleted +*/ +SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_wrlock(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_opt_ switch_thread_rwlock_t *rwlock); /*! \brief Delete data from a hash based on callback function @@ -1272,6 +1289,15 @@ SWITCH_DECLARE(void *) switch_core_hash_find(_In_ switch_hash_t *hash, _In_z_ co */ SWITCH_DECLARE(void *) switch_core_hash_find_locked(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_ switch_mutex_t *mutex); +/*! + \brief Retrieve data from a given hash + \param hash the hash to retrieve from + \param key the key to retrieve + \param mutex optional rwlock to rdlock + \return a pointer to the data held in the key +*/ +SWITCH_DECLARE(void *) switch_core_hash_find_rdlock(_In_ switch_hash_t *hash, _In_z_ const char *key, _In_ switch_thread_rwlock_t *rwlock); + /*! \brief Gets the first element of a hashtable \param depricate_me [deprecated] NULL diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 2b2b3de45d..bf5d5d88ea 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1120,7 +1120,9 @@ typedef enum { typedef enum { CF_APP_TAGGED = (1 << 0), - CF_APP_T38 = (1 << 1) + CF_APP_T38 = (1 << 1), + CF_APP_T38_REQ = (1 << 2), + CF_APP_T38_FAIL = (1 << 3) } switch_channel_app_flag_t; diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index bd8559f95a..572fdf0c85 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -141,7 +141,9 @@ typedef enum { MFLAG_MINTWO = (1 << 13), MFLAG_MUTE_DETECT = (1 << 14), MFLAG_DIST_DTMF = (1 << 15), - MFLAG_MOD = (1 << 16) + MFLAG_MOD = (1 << 16), + MFLAG_INDICATE_MUTE = (1 << 17), + MFLAG_INDICATE_UNMUTE = (1 << 18) } member_flag_t; typedef enum { @@ -2494,6 +2496,7 @@ static void conference_loop_output(conference_member_t *member) uint32_t low_count, bytes; call_list_t *call_list, *cp; switch_codec_implementation_t read_impl = { 0 }; + int sanity; switch_core_session_get_read_impl(member->session, &read_impl); @@ -2594,6 +2597,13 @@ static void conference_loop_output(conference_member_t *member) switch_channel_answer(channel); } + + sanity = 2000; + while(!switch_test_flag(member, MFLAG_ITHREAD) && sanity > 0) { + switch_cond_next(); + sanity--; + } + /* Fair WARNING, If you expect the caller to hear anything or for digit handling to be processed, */ /* you better not block this thread loop for more than the duration of member->conference->timer_name! */ while (switch_test_flag(member, MFLAG_RUNNING) && switch_test_flag(member, MFLAG_ITHREAD) @@ -2745,6 +2755,30 @@ static void conference_loop_output(conference_member_t *member) switch_mutex_unlock(member->write_mutex); + if (switch_test_flag(member, MFLAG_INDICATE_MUTE)) { + if (!zstr(member->conference->muted_sound)) { + conference_member_play_file(member, member->conference->muted_sound, 0); + } else { + char msg[512]; + + switch_snprintf(msg, sizeof(msg), "Muted"); + conference_member_say(member, msg, 0); + } + switch_clear_flag(member, MFLAG_INDICATE_MUTE); + } + + if (switch_test_flag(member, MFLAG_INDICATE_UNMUTE)) { + if (!zstr(member->conference->unmuted_sound)) { + conference_member_play_file(member, member->conference->unmuted_sound, 0); + } else { + char msg[512]; + + switch_snprintf(msg, sizeof(msg), "Un-Muted"); + conference_member_say(member, msg, 0); + } + switch_clear_flag(member, MFLAG_INDICATE_UNMUTE); + } + if (switch_core_session_private_event_count(member->session)) { switch_channel_set_app_flag(channel, CF_APP_TAGGED); switch_ivr_parse_all_events(member->session); @@ -3608,18 +3642,12 @@ static switch_status_t conf_api_sub_mute(conference_member_t *member, switch_str switch_clear_flag_locked(member, MFLAG_CAN_SPEAK); switch_clear_flag_locked(member, MFLAG_TALKING); + switch_set_flag(member, MFLAG_INDICATE_MUTE); - if (!zstr(member->conference->muted_sound)) { - conference_member_play_file(member, member->conference->muted_sound, 0); - } else { - char msg[512]; - - switch_snprintf(msg, sizeof(msg), "Muted"); - conference_member_say(member, msg, 0); - } if (stream != NULL) { stream->write_function(stream, "OK mute %u\n", member->id); } + if (test_eflag(member->conference, EFLAG_MUTE_MEMBER) && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { conference_add_event_member_data(member, event); @@ -3684,17 +3712,12 @@ static switch_status_t conf_api_sub_unmute(conference_member_t *member, switch_s return SWITCH_STATUS_GENERR; switch_set_flag_locked(member, MFLAG_CAN_SPEAK); + switch_set_flag(member, MFLAG_INDICATE_UNMUTE); + if (stream != NULL) { stream->write_function(stream, "OK unmute %u\n", member->id); } - if (!zstr(member->conference->unmuted_sound)) { - conference_member_play_file(member, member->conference->unmuted_sound, 0); - } else { - char msg[512]; - switch_snprintf(msg, sizeof(msg), "Un-Muted"); - conference_member_say(member, msg, 0); - } if (test_eflag(member->conference, EFLAG_UNMUTE_MEMBER) && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { conference_add_event_member_data(member, event); diff --git a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c index 119294f4bd..e4457bd5b9 100644 --- a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c +++ b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c @@ -904,6 +904,7 @@ static t38_mode_t request_t38(pvt_t *pvt) switch_channel_set_private(channel, "t38_options", t38_options); pvt->t38_mode = T38_MODE_REQUESTED; + switch_channel_set_app_flag_key("T38", channel, CF_APP_T38_REQ); /* This will send a request for t.38 mode */ msg.from = __FILE__; @@ -1173,7 +1174,10 @@ void mod_spandsp_fax_process_fax(switch_core_session_t *session, const char *dat switch (pvt->t38_mode) { case T38_MODE_REQUESTED: { - if (switch_channel_test_app_flag_key("T38", channel, CF_APP_T38)) { + if (switch_channel_test_app_flag_key("T38", channel, CF_APP_T38_FAIL)) { + pvt->t38_mode = T38_MODE_REFUSED; + continue; + } else if (switch_channel_test_app_flag_key("T38", channel, CF_APP_T38)) { switch_core_session_message_t msg = { 0 }; pvt->t38_mode = T38_MODE_NEGOTIATED; spanfax_init(pvt, T38_MODE); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 31d437d7b0..86fa140046 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -524,6 +524,12 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session) if (!sofia_test_flag(tech_pvt, TFLAG_BYE)) { char *cid = generate_pai_str(tech_pvt); + if (sip_cause > 299) { + switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38); + switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_REQ); + switch_channel_set_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_FAIL); + } + nua_respond(tech_pvt->nh, sip_cause, sip_status_phrase(sip_cause), TAG_IF(!zstr(reason), SIPTAG_REASON_STR(reason)), TAG_IF(cid, SIPTAG_HEADER_STR(cid)), TAG_IF(!zstr(bye_headers), SIPTAG_HEADER_STR(bye_headers)), TAG_END()); @@ -3273,6 +3279,19 @@ static switch_status_t cmd_profile(char **argv, int argc, switch_stream_handle_t goto done; } + if (!strcasecmp(argv[1], "check_sync")) { + if (argc > 2) { + sofia_reg_check_call_id(profile, argv[2]); + stream->write_function(stream, "+OK syncing all registrations matching specified call_id\n"); + } else { + sofia_reg_check_sync(profile); + stream->write_function(stream, "+OK syncing all registrations\n"); + } + + goto done; + } + + if (!strcasecmp(argv[1], "flush_inbound_reg")) { int reboot = 0; @@ -3853,6 +3872,7 @@ SWITCH_STANDARD_API(sofia_function) " watchdog <on|off>\n\n" "sofia profile <name> [start | stop | restart | rescan]\n" " flush_inbound_reg [<call_id> | <[user]@domain>] [reboot]\n" + " check_sync [<call_id> | <[user]@domain>]\n" " [register | unregister] [<gateway name> | all]\n" " killgw <gateway name>\n" " [stun-auto-disable | stun-enabled] [true | false]]\n" @@ -5158,6 +5178,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sofia_load) switch_console_set_complete("add sofia profile ::sofia::list_profiles restart"); switch_console_set_complete("add sofia profile ::sofia::list_profiles flush_inbound_reg"); + switch_console_set_complete("add sofia profile ::sofia::list_profiles check_sync"); switch_console_set_complete("add sofia profile ::sofia::list_profiles register ::sofia::list_profile_gateway"); switch_console_set_complete("add sofia profile ::sofia::list_profiles unregister ::sofia::list_profile_gateway"); switch_console_set_complete("add sofia profile ::sofia::list_profiles killgw ::sofia::list_profile_gateway"); diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 4b41189a02..b996167074 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -295,6 +295,7 @@ typedef enum { TFLAG_NOTIMER_DURING_BRIDGE, TFLAG_JB_PAUSED, TFLAG_3PCC_INVITE, + TFLAG_NOREPLY, /* No new flags below this line */ TFLAG_MAX } TFLAGS; @@ -983,6 +984,8 @@ void sofia_glue_tech_patch_sdp(private_object_t *tech_pvt); switch_status_t sofia_glue_tech_proxy_remote_addr(private_object_t *tech_pvt); void sofia_presence_event_thread_start(void); void sofia_reg_expire_call_id(sofia_profile_t *profile, const char *call_id, int reboot); +void sofia_reg_check_call_id(sofia_profile_t *profile, const char *call_id); +void sofia_reg_check_sync(sofia_profile_t *profile); switch_status_t sofia_glue_tech_choose_video_port(private_object_t *tech_pvt, int force); switch_status_t sofia_glue_tech_set_video_codec(private_object_t *tech_pvt, int force); char *sofia_glue_get_register_host(const char *uri); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 12b0280974..5b130850b2 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -4161,6 +4161,16 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status tech_pvt->last_sdp_str = switch_core_session_strdup(session, sip->sip_payload->pl_data); } + + if (status > 299 && switch_channel_test_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_REQ)) { + switch_channel_set_private(channel, "t38_options", NULL); + switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38); + switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_REQ); + switch_channel_set_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_FAIL); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s T38 invite failed\n", switch_channel_get_name(tech_pvt->channel)); + } + + if (sofia_test_pflag(profile, PFLAG_MANAGE_SHARED_APPEARANCE)) { if (channel && sip->sip_call_info) { char *p; @@ -4462,6 +4472,9 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status switch_channel_set_private(other_channel, "t38_options", NULL); sofia_clear_flag(tech_pvt, TFLAG_T38_PASSTHRU); sofia_clear_flag(other_tech_pvt, TFLAG_T38_PASSTHRU); + switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38); + switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_REQ); + switch_channel_set_app_flag_key("T38", tech_pvt->channel, CF_APP_T38_FAIL); } else if (status == 200 && sofia_test_flag(tech_pvt, TFLAG_T38_PASSTHRU) && has_t38 && sip->sip_payload && sip->sip_payload->pl_data) { switch_t38_options_t *t38_options = sofia_glue_extract_t38_options(session, sip->sip_payload->pl_data); @@ -5231,8 +5244,9 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, if (tech_pvt->num_codecs) { match = sofia_glue_negotiate_sdp(session, r_sdp); } - - if (match && switch_channel_test_app_flag_key("T38", tech_pvt->channel, CF_APP_T38)) { + + if (match && sofia_test_flag(tech_pvt, TFLAG_NOREPLY)) { + sofia_clear_flag(tech_pvt, TFLAG_NOREPLY); goto done; } diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index b308b6038e..dba65d2aac 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -4389,8 +4389,13 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s if (got_udptl && m->m_type == sdp_media_image && m->m_port) { switch_t38_options_t *t38_options = tech_process_udptl(tech_pvt, sdp, m); + + if (switch_channel_test_app_flag_key("T38", tech_pvt->channel, CF_APP_T38)) { + sofia_set_flag(tech_pvt, TFLAG_NOREPLY); + } if (switch_true(switch_channel_get_variable(channel, "refuse_t38"))) { + switch_channel_clear_app_flag_key("T38", tech_pvt->channel, CF_APP_T38); match = 0; goto done; } else { diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 1d65a15081..a7490f6a8b 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -396,9 +396,30 @@ static void actual_sofia_presence_mwi_event_handler(switch_event_t *event) if (!profile) { if (!host || !(profile = sofia_glue_find_profile(host))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find profile %s\n", switch_str_nil(host)); - switch_safe_free(dup_account); - return; + char *sql; + switch_hash_index_t *hi; + void *val; + const void *vvar; + char buf[512] = ""; + + sql = switch_mprintf("select profile_name from sip_registrations where sip_host='%s' or mwi_host='%s'", host, host); + + switch_mutex_lock(mod_sofia_globals.hash_mutex); + for (hi = switch_hash_first(NULL, mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) { + switch_hash_this(hi, &vvar, NULL, &val); + profile = (sofia_profile_t *) val; + sofia_glue_execute_sql2str(profile, profile->ireg_mutex, sql, buf, sizeof(buf)); + if (!zstr(buf)) { + break; + } + } + switch_mutex_unlock(mod_sofia_globals.hash_mutex); + + if (!(profile = sofia_glue_find_profile(buf))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find profile %s\n", switch_str_nil(host)); + switch_safe_free(dup_account); + return; + } } } diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index fa837eb830..df02436ecd 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -733,6 +733,92 @@ void sofia_reg_check_expire(sofia_profile_t *profile, time_t now, int reboot) } + +int sofia_reg_check_callback(void *pArg, int argc, char **argv, char **columnNames) +{ + sofia_profile_t *profile = (sofia_profile_t *) pArg; + + sofia_reg_send_reboot(profile, argv[1], argv[2], argv[3], argv[7], argv[11]); + + return 0; +} + +void sofia_reg_check_call_id(sofia_profile_t *profile, const char *call_id) +{ + char *sql = NULL; + char *sqlextra = NULL; + char *dup = strdup(call_id); + char *host = NULL, *user = NULL; + + switch_assert(dup); + + if ((host = strchr(dup, '@'))) { + *host++ = '\0'; + user = dup; + } else { + host = dup; + } + + if (!host) { + host = "none"; + } + + if (zstr(user)) { + sqlextra = switch_mprintf(" or (sip_host='%q')", host); + } else { + sqlextra = switch_mprintf(" or (sip_user='%q' and sip_host='%q')", user, host); + } + + sql = switch_mprintf("select call_id,sip_user,sip_host,contact,status,rpid,expires" + ",user_agent,server_user,server_host,profile_name,network_ip" + " from sip_registrations where call_id='%q' %s", call_id, sqlextra); + + switch_mutex_lock(profile->ireg_mutex); + sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_check_callback, profile); + switch_mutex_unlock(profile->ireg_mutex); + + switch_safe_free(sql); + switch_safe_free(sqlextra); + switch_safe_free(dup); + +} + +void sofia_reg_check_sync(sofia_profile_t *profile) +{ + char sql[1024]; + + switch_mutex_lock(profile->ireg_mutex); + + switch_snprintf(sql, sizeof(sql), "select call_id,sip_user,sip_host,contact,status,rpid,expires" + ",user_agent,server_user,server_host,profile_name,network_ip" + " from sip_registrations where expires > 0"); + + + sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_reg_del_callback, profile); + switch_snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and hostname='%s'", mod_sofia_globals.hostname); + sofia_glue_actually_execute_sql(profile, sql, NULL); + + + switch_snprintf(sql, sizeof(sql), "delete from sip_presence where expires > 0 and hostname='%s'", mod_sofia_globals.hostname); + sofia_glue_actually_execute_sql(profile, sql, NULL); + + switch_snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and hostname='%s'", mod_sofia_globals.hostname); + sofia_glue_actually_execute_sql(profile, sql, NULL); + + switch_snprintf(sql, sizeof(sql), "select sub_to_user,sub_to_host,call_id from sip_subscriptions where expires >= -1 and hostname='%s'", + mod_sofia_globals.hostname); + sofia_glue_execute_sql_callback(profile, NULL, sql, sofia_sub_del_callback, profile); + + switch_snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname); + sofia_glue_actually_execute_sql(profile, sql, NULL); + + switch_snprintf(sql, sizeof(sql), "delete from sip_dialogs where expires >= -1 and hostname='%s'", mod_sofia_globals.hostname); + sofia_glue_actually_execute_sql(profile, sql, NULL); + + switch_mutex_unlock(profile->ireg_mutex); + +} + char *sofia_reg_find_reg_url(sofia_profile_t *profile, const char *user, const char *host, char *val, switch_size_t len) { struct callback_t cbt = { 0 }; diff --git a/src/switch_apr.c b/src/switch_apr.c index fe7442b57f..b592fc7c3e 100644 --- a/src/switch_apr.c +++ b/src/switch_apr.c @@ -716,6 +716,15 @@ SWITCH_DECLARE(switch_status_t) switch_socket_send(switch_socket_t *sock, const return status; } +SWITCH_DECLARE(switch_status_t) switch_socket_send_nonblock(switch_socket_t *sock, const char *buf, switch_size_t *len) +{ + if (!sock || !buf || !len) { + return SWITCH_STATUS_GENERR; + } + + return apr_socket_send(sock, buf, len); +} + SWITCH_DECLARE(switch_status_t) switch_socket_sendto(switch_socket_t *sock, switch_sockaddr_t *where, int32_t flags, const char *buf, switch_size_t *len) { diff --git a/src/switch_buffer.c b/src/switch_buffer.c index 39d7bf04a1..0f104f5500 100644 --- a/src/switch_buffer.c +++ b/src/switch_buffer.c @@ -224,6 +224,22 @@ SWITCH_DECLARE(switch_size_t) switch_buffer_peek(switch_buffer_t *buffer, void * return reading; } +SWITCH_DECLARE(switch_size_t) switch_buffer_peek_zerocopy(switch_buffer_t *buffer, const void **ptr) +{ + switch_size_t reading = 0; + + if (buffer->used < 1) { + buffer->used = 0; + return 0; + } else { + reading = buffer->used; + } + + *ptr = buffer->head; + + return reading; +} + SWITCH_DECLARE(switch_size_t) switch_buffer_write(switch_buffer_t *buffer, const void *data, switch_size_t datalen) { switch_size_t freespace, actual_freespace; diff --git a/src/switch_core_hash.c b/src/switch_core_hash.c index 8d04e9c5f3..c47281db97 100644 --- a/src/switch_core_hash.c +++ b/src/switch_core_hash.c @@ -96,6 +96,21 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_locked(switch_hash_t *ha return SWITCH_STATUS_SUCCESS; } +SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_wrlock(switch_hash_t *hash, const char *key, const void *data, switch_thread_rwlock_t *rwlock) +{ + if (rwlock) { + switch_thread_rwlock_wrlock(rwlock); + } + + sqlite3HashInsert(&hash->table, key, (int) strlen(key) + 1, (void *) data); + + if (rwlock) { + switch_thread_rwlock_unlock(rwlock); + } + + return SWITCH_STATUS_SUCCESS; +} + SWITCH_DECLARE(switch_status_t) switch_core_hash_delete(switch_hash_t *hash, const char *key) { sqlite3HashInsert(&hash->table, key, (int) strlen(key) + 1, NULL); @@ -117,6 +132,21 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_locked(switch_hash_t *ha return SWITCH_STATUS_SUCCESS; } +SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_wrlock(switch_hash_t *hash, const char *key, switch_thread_rwlock_t *rwlock) +{ + if (rwlock) { + switch_thread_rwlock_wrlock(rwlock); + } + + sqlite3HashInsert(&hash->table, key, (int) strlen(key) + 1, NULL); + + if (rwlock) { + switch_thread_rwlock_unlock(rwlock); + } + + return SWITCH_STATUS_SUCCESS; +} + SWITCH_DECLARE(switch_status_t) switch_core_hash_delete_multi(switch_hash_t *hash, switch_hash_delete_callback_t callback, void *pData) { switch_hash_index_t *hi = NULL; @@ -175,6 +205,23 @@ SWITCH_DECLARE(void *) switch_core_hash_find_locked(switch_hash_t *hash, const c return val; } +SWITCH_DECLARE(void *) switch_core_hash_find_rdlock(switch_hash_t *hash, const char *key, switch_thread_rwlock_t *rwlock) +{ + void *val; + + if (rwlock) { + switch_thread_rwlock_rdlock(rwlock); + } + + val = sqlite3HashFind(&hash->table, key, (int) strlen(key) + 1); + + if (rwlock) { + switch_thread_rwlock_unlock(rwlock); + } + + return val; +} + SWITCH_DECLARE(switch_hash_index_t *) switch_hash_first(char *depricate_me, switch_hash_t *hash) { return (switch_hash_index_t *) sqliteHashFirst(&hash->table);