From 89f3f5e2986d24800e40064f9966675389f5f8a0 Mon Sep 17 00:00:00 2001 From: Brian West Date: Wed, 5 Nov 2014 12:18:47 -0600 Subject: [PATCH 01/43] FS-6961: [mod_erlang_event]: Add call UUID to call_hangup message --- src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index b1743eb716..dc465545d2 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -693,7 +693,10 @@ static switch_status_t check_attached_sessions(listener_t *listener, int *msgs_s sp->uuid_str, switch_channel_state_name(sp->channel_state)); ei_x_new_with_version(&ebuf); + ei_x_encode_tuple_header(&ebuf, 2); ei_x_encode_atom(&ebuf, "call_hangup"); + _ei_x_encode_string(&ebuf, sp->uuid_str); + switch_mutex_lock(listener->sock_mutex); ei_sendto(listener->ec, listener->sockfd, &sp->process, &ebuf); (*msgs_sent)++; From 441dd9128862ce741a56a01acfa3e862949d1347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Tue, 27 Jan 2015 17:14:54 +0100 Subject: [PATCH 02/43] FS-7204, Allow to force a per-account send-message-query-on-register --- src/mod/endpoints/mod_sofia/sofia_reg.c | 30 +++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 7e26470d73..9e574eb240 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1252,6 +1252,7 @@ uint8_t sofia_reg_handle_register_token(nua_t *nua, sofia_profile_t *profile, nu const char *agent = "unknown"; const char *pres_on_reg = NULL; int send_pres = 0; + int send_message_query = 0; int is_tls = 0, is_tcp = 0, is_ws = 0, is_wss = 0; char expbuf[35] = ""; time_t reg_time = switch_epoch_time_now(NULL); @@ -1265,6 +1266,7 @@ uint8_t sofia_reg_handle_register_token(nua_t *nua, sofia_profile_t *profile, nu char *sw_reg_host; char *token_val = NULL; + if (sofia_private_p) { sofia_private = *sofia_private_p; } @@ -1761,6 +1763,7 @@ uint8_t sofia_reg_handle_register_token(nua_t *nua, sofia_profile_t *profile, nu reg_meta = var; } + /* associated MWI account */ if (v_event && *v_event && (mwi_account = switch_event_get_header(*v_event, "mwi-account"))) { dup_mwi_account = strdup(mwi_account); switch_assert(dup_mwi_account != NULL); @@ -1774,6 +1777,26 @@ uint8_t sofia_reg_handle_register_token(nua_t *nua, sofia_profile_t *profile, nu mwi_host = (char *) reg_host; } + /* per-profile unsolicited MWI on register */ + if (sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER)) { + send_message_query = 2; + } else if (sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER)) { + send_message_query = 1; + } else { + send_message_query = 0; + } + + /* per-account unsolicited MWI on register */ + if (v_event && *v_event && (var = switch_event_get_header(*v_event, "send-message-query-on-register"))) { + if (switch_true(var)) { + send_message_query = 2; + } else if (!strcasecmp(var, "first-only")) { + send_message_query = 1; + } else { + send_message_query = 0; + } + } + if (regtype != REG_REGISTER) { switch_goto_int(r, 0, end); } @@ -2027,10 +2050,9 @@ uint8_t sofia_reg_handle_register_token(nua_t *nua, sofia_profile_t *profile, nu switch_snprintf(exp_param, sizeof(exp_param), "expires=%ld", exptime); sip_contact_add_param(nua_handle_home(nh), sip->sip_contact, exp_param); - - if ((sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_REGISTER) || - (reg_count == 1 && sofia_test_pflag(profile, PFLAG_MESSAGE_QUERY_ON_FIRST_REGISTER))) && debounce_ok) { - + + /* send unsolicited MWI if configured */ + if (send_message_query == 2 || (reg_count == 1 && send_message_query == 1 && debounce_ok)) { if (switch_event_create(&s_mwi_event, SWITCH_EVENT_MESSAGE_QUERY) == SWITCH_STATUS_SUCCESS) { switch_event_add_header(s_mwi_event, SWITCH_STACK_BOTTOM, "Message-Account", "%s:%s@%s", proto, mwi_user, mwi_host); switch_event_add_header_string(s_mwi_event, SWITCH_STACK_BOTTOM, "VM-Sofia-Profile", profile->name); From f135232ef5ab3f53f76cfa8ec2a1225f7700de90 Mon Sep 17 00:00:00 2001 From: Flavio Grossi Date: Mon, 2 Feb 2015 15:48:26 +0100 Subject: [PATCH 03/43] FS-7196: add recording_follow_transfer support for semi attended transfers --- src/mod/endpoints/mod_sofia/sofia.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 0f0f492e99..db0bf1467a 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -7916,6 +7916,7 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t if ((a_session = switch_core_session_locate(br_a))) { const char *moh = profile->hold_music; + switch_core_session_t *tmpsess = NULL; switch_channel_t *a_channel = switch_core_session_get_channel(a_session); switch_caller_profile_t *prof = switch_channel_get_caller_profile(channel_b); const char *tmp; @@ -7946,6 +7947,15 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t } else { switch_ivr_session_transfer(a_session, "park", "inline", NULL); } + if (switch_true(switch_channel_get_variable(channel_a, "recording_follow_transfer"))) { + switch_core_media_bug_transfer_recordings(session, a_session); + } + if (switch_true(switch_channel_get_variable(channel_b, "recording_follow_transfer")) && (tmpsess = switch_core_session_locate(br_a))) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, + "Early transfer detected with no media, moving recording bug to other leg\n"); + switch_core_media_bug_transfer_recordings(b_session, tmpsess); + switch_core_session_rwunlock(tmpsess); + } switch_core_session_rwunlock(a_session); From a4ef9d6ba3d210cb0589342a0e059cf9bca98ae7 Mon Sep 17 00:00:00 2001 From: Brian West Date: Wed, 1 Apr 2015 10:32:21 -0500 Subject: [PATCH 04/43] FS-7405: if all is required don't pass if total ne pass --- src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c b/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c index 71908b36f0..9fe1fbef42 100644 --- a/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c +++ b/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c @@ -380,6 +380,12 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t * if ((all && !fail) || (!all && pass)) { anti_action = SWITCH_FALSE; } + if (all && total != pass) { + proceed = 1; + pass = 0; + fail++; + anti_action = SWITCH_TRUE; + } } switch_safe_free(field_expanded); From f5e0a879b2c5e035075db2c9441a111020575dea Mon Sep 17 00:00:00 2001 From: Ognjen Seslija Date: Sun, 5 Apr 2015 16:21:38 +0200 Subject: [PATCH 05/43] JIRA FS-7412. Added new LDAP schema (fsaccount.schema) with relevant attributes to match FS directory params and variables. Changed mod_xml_ldap code to reflect new schema. Updated xml_ldap.conf.xml as well to reflect mapping of new attributes. --- .../conf/autoload_configs/xml_ldap.conf.xml | 54 +++++ src/mod/xml_int/mod_xml_ldap/fsaccount.schema | 225 ++++++++++++++++++ src/mod/xml_int/mod_xml_ldap/mod_xml_ldap.c | 186 ++++++++++++--- 3 files changed, 435 insertions(+), 30 deletions(-) create mode 100644 src/mod/xml_int/mod_xml_ldap/conf/autoload_configs/xml_ldap.conf.xml create mode 100644 src/mod/xml_int/mod_xml_ldap/fsaccount.schema diff --git a/src/mod/xml_int/mod_xml_ldap/conf/autoload_configs/xml_ldap.conf.xml b/src/mod/xml_int/mod_xml_ldap/conf/autoload_configs/xml_ldap.conf.xml new file mode 100644 index 0000000000..84a9673171 --- /dev/null +++ b/src/mod/xml_int/mod_xml_ldap/conf/autoload_configs/xml_ldap.conf.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mod/xml_int/mod_xml_ldap/fsaccount.schema b/src/mod/xml_int/mod_xml_ldap/fsaccount.schema new file mode 100644 index 0000000000..367741a903 --- /dev/null +++ b/src/mod/xml_int/mod_xml_ldap/fsaccount.schema @@ -0,0 +1,225 @@ +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.1 NAME 'fsUid' + DESC 'FreeSWITCH directory user id' + EQUALITY caseExactIA5Match + SUBSTR caseExactIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.2 NAME 'fsCIDR' + DESC 'FreeSWITCH directory user id cidr' + EQUALITY caseExactIA5Match + SUBSTR caseExactIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.3 NAME 'fsNumberAlias' + DESC 'FreeSWITCH directory user id number-alias' + EQUALITY numericStringMatch + SUBSTR numericStringSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.4 NAME 'fsDialString' + DESC 'FreeSWITCH directory dial-string param' + EQUALITY caseExactIA5Match + SUBSTR caseExactIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.5 NAME 'fsPassword' + DESC 'FreeSWITCH directory password param' + EQUALITY caseExactIA5Match + SUBSTR caseExactIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.6 NAME 'fsReverseAuthUser' + DESC 'FreeSWITCH directory reverse-auth-user param' + EQUALITY caseExactIA5Match + SUBSTR caseExactIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.7 NAME 'fsReverseAuthPass' + DESC 'FreeSWITCH directory reverse-auth-pass param' + EQUALITY caseExactIA5Match + SUBSTR caseExactIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.8 NAME 'fsA1Hash' + DESC 'FreeSWITCH directory a1-hash param' + EQUALITY caseExactIA5Match + SUBSTR caseExactIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.9 NAME 'fsVmPassword' + DESC 'FreeSWITCH directory vm-password param' + EQUALITY numericStringMatch + SUBSTR numericStringSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.10 NAME 'fsVmEnabled' + DESC 'FreeSWITCH directory vm-enabled param' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.11 NAME 'fsVmMailFrom' + DESC 'FreeSWITCH directory vm-mailfrom param' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.12 NAME 'fsVmMailTo' + DESC 'FreeSWITCH directory vm-mailto param' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.13 NAME 'fsVmNotifyMailTo' + DESC 'FreeSWITCH directory vm-notify-mailto param' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.14 NAME 'fsVmAttachFile' + DESC 'FreeSWITCH directory vm-attach-file param' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.15 NAME 'fsVmMessageExt' + DESC 'FreeSWITCH directory vm-message-ext param' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.16 NAME 'fsVmEmailAllMessages' + DESC 'FreeSWITCH directory vm-email-all-messages param' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.17 NAME 'fsVmKeepLocalAfterEmail' + DESC 'FreeSWITCH directory vm-keep-local-after-email param' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.18 NAME 'fsVmNotifyEmailAllMessages' + DESC 'FreeSWITCH directory vm-notify-email-all-messages param' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.19 NAME 'fsVmSkipInstructions' + DESC 'FreeSWITCH directory vm-skip-instructions param' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.20 NAME 'fsVmCc' + DESC 'FreeSWITCH directory vm-cc param' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.21 NAME 'fsVmDiskQuota' + DESC 'FreeSWITCH directory vm-disk-quota param' + EQUALITY numericStringMatch + SUBSTR numericStringSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.22 NAME 'fsAccountCode' + DESC 'FreeSWITCH directory accountcode variable' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.23 NAME 'fsUserContext' + DESC 'FreeSWITCH directory user_context variable' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.24 NAME 'fsVmMailbox' + DESC 'FreeSWITCH directory vm_mailbox variable' + EQUALITY numericStringMatch + SUBSTR numericStringSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.25 NAME 'fsCallGroup' + DESC 'FreeSWITCH directory callgroup variable' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.26 NAME ('fsTollAllow' 'fsRuleSet') + DESC 'FreeSWITCH directory toll_allow variable' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.27 NAME 'fsEffectiveCallerIDNumber' + DESC 'FreeSWITCH directory effective_caller_id_number variable' + EQUALITY numericStringMatch + SUBSTR numericStringSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.28 NAME 'fsEffectiveCallerIDName' + DESC 'FreeSWITCH directory effective_caller_id_name variable' + EQUALITY caseExactMatch + SUBSTR caseExactSubstringsMatch + ORDERING caseExactOrderingMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.29 NAME 'fsOutboundCallerIDNumber' + DESC 'FreeSWITCH directory outbound_caller_id_number variable' + EQUALITY numericStringMatch + SUBSTR numericStringSubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.36 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.30 NAME 'fsOutboundCallerIDName' + DESC 'FreeSWITCH directory outbound_caller_id_name variable' + EQUALITY caseExactMatch + SUBSTR caseExactSubstringsMatch + ORDERING caseExactOrderingMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 + SINGLE-VALUE ) + +attributetype ( 1.3.6.1.4.1.27880.1003.1.1.31 NAME 'fsDomainName' + DESC 'FreeSWITCH directory domain name' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 + SINGLE-VALUE ) + +objectclass (1.3.6.1.4.1.27880.1003.2.1 NAME 'FSAccount' + SUP top AUXILIARY + DESC 'FreeSWITCH Directory Account (v1.1)' + MAY ( fsUid $ fsCIDR $ fsNumberAlias $ fsDialString $ fsPassword $ + fsReverseAuthUser $ fsReverseAuthPass $ fsA1Hash $ fsVmMessageExt $ + fsVmPassword $ fsVmEnabled $ fsVmMailFrom $ fsVmMailTo $ + fsVmNotifyMailTo $ fsVmAttachFile $ fsVmMessageExt $ + fsVmEmailAllMessages $ fsVmKeepLocalAfterEmail $ fsVmNotifyEmailAllMessages $ + fsVmSkipInstructions $ fsVmCc $ fsVmDiskQuota $ fsAccountCode $ + fsUserContext $ fsVmMailbox $ fsCallGroup $ fsTollAllow $ + fsEffectiveCallerIDNumber $ fsEffectiveCallerIDName $ + fsOutboundCallerIDNumber $ fsOutboundCallerIDName $ fsDomainName )) diff --git a/src/mod/xml_int/mod_xml_ldap/mod_xml_ldap.c b/src/mod/xml_int/mod_xml_ldap/mod_xml_ldap.c index a3d805495c..2de9a72158 100644 --- a/src/mod/xml_int/mod_xml_ldap/mod_xml_ldap.c +++ b/src/mod/xml_int/mod_xml_ldap/mod_xml_ldap.c @@ -65,19 +65,36 @@ typedef struct xml_binding { typedef enum exten_types { LDAP_EXTEN_ID = 0, LDAP_EXTEN_CIDR, + LDAP_EXTEN_NUMBER_ALIAS, + LDAP_EXTEN_DIAL_STRING, LDAP_EXTEN_PASSWORD, - LDAP_EXTEN_VM_ENABLED, + LDAP_EXTEN_REV_AUTH_USER, + LDAP_EXTEN_REV_AUTH_PASS, + LDAP_EXTEN_A1_HASH, LDAP_EXTEN_VM_PASSWORD, + LDAP_EXTEN_VM_ENABLED, LDAP_EXTEN_VM_MAILFROM, LDAP_EXTEN_VM_MAILTO, - LDAP_EXTEN_VM_EMAILMSG, - LDAP_EXTEN_VM_NOTEMAILMSG, - LDAP_EXTEN_VM_ATTACHFILE, - LDAP_EXTEN_USER_CONTEXT, - LDAP_EXTEN_EFF_CLIDNAME, - LDAP_EXTEN_EFF_CLIDNUM, + LDAP_EXTEN_VM_NOTIFY_MAILTO, + LDAP_EXTEN_VM_ATTACH_FILE, + LDAP_EXTEN_VM_MESSAGE_EXT, + LDAP_EXTEN_VM_EMAIL_ALL_MSGS, + LDAP_EXTEN_VM_KEEP_LOCAL_AFTER_MAIL, + LDAP_EXTEN_VM_NOTIFY_EMAIL_ALL_MSGS, + LDAP_EXTEN_VM_SKIP_INSTRUCTIONS, + LDAP_EXTEN_VM_CC, + LDAP_EXTEN_VM_DISK_QUOTA, LDAP_EXTEN_ACCOUNTCODE, - LDAP_EXTEN_RULESET, + LDAP_EXTEN_USER_CONTEXT, + LDAP_EXTEN_VM_MAILBOX, + LDAP_EXTEN_CALLGROUP, + LDAP_EXTEN_TOLL_ALLOW, + LDAP_EXTEN_EFF_CLIDNUM, + LDAP_EXTEN_EFF_CLIDNAME, + LDAP_EXTEN_OUT_CLIDNUM, + LDAP_EXTEN_OUT_CLIDNAME, + LDAP_EXTEN_DOMAIN_NAME +/* not used now LDAP_EXTEN_AREACODE, LDAP_EXTEN_CID_EXTNAME, LDAP_EXTEN_CID_EXTNUM, @@ -99,6 +116,7 @@ typedef enum exten_types { LDAP_EXTEN_HOTLINE_ACTIVE, LDAP_EXTEN_HOTLINE_DEST, LDAP_EXTEN_CLASSOFSERVICE +*/ } exten_type_t; struct xml_ldap_attribute { @@ -236,6 +254,20 @@ static switch_status_t do_config(void) attr_list->next = malloc(sizeof(*attr_list)); attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); attr_list = attr_list->next; + } else if (!strncasecmp("number-alias", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_NUMBER_ALIAS; + attr_list->len = strlen(m); + attr_list->val = strdup(m); + attr_list->next = malloc(sizeof(*attr_list)); + attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); + attr_list = attr_list->next; + } else if (!strncasecmp("dial-string", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_DIAL_STRING; + attr_list->len = strlen(m); + attr_list->val = strdup(m); + attr_list->next = malloc(sizeof(*attr_list)); + attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); + attr_list = attr_list->next; } else if (!strncasecmp("password", n, strlen(n))) { attr_list->type = LDAP_EXTEN_PASSWORD; attr_list->len = strlen(m); @@ -243,8 +275,22 @@ static switch_status_t do_config(void) attr_list->next = malloc(sizeof(*attr_list)); attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); attr_list = attr_list->next; - } else if (!strncasecmp("vm-enabled", n, strlen(n))) { - attr_list->type = LDAP_EXTEN_VM_ENABLED; + } else if (!strncasecmp("reverse-auth-user", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_REV_AUTH_USER; + attr_list->len = strlen(m); + attr_list->val = strdup(m); + attr_list->next = malloc(sizeof(*attr_list)); + attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); + attr_list = attr_list->next; + } else if (!strncasecmp("reverse-auth-pass", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_REV_AUTH_PASS; + attr_list->len = strlen(m); + attr_list->val = strdup(m); + attr_list->next = malloc(sizeof(*attr_list)); + attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); + attr_list = attr_list->next; + } else if (!strncasecmp("a1-hash", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_A1_HASH; attr_list->len = strlen(m); attr_list->val = strdup(m); attr_list->next = malloc(sizeof(*attr_list)); @@ -257,6 +303,13 @@ static switch_status_t do_config(void) attr_list->next = malloc(sizeof(*attr_list)); attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); attr_list = attr_list->next; + } else if (!strncasecmp("vm-enabled", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_VM_ENABLED; + attr_list->len = strlen(m); + attr_list->val = strdup(m); + attr_list->next = malloc(sizeof(*attr_list)); + attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); + attr_list = attr_list->next; } else if (!strncasecmp("vm-mailfrom", n, strlen(n))) { attr_list->type = LDAP_EXTEN_VM_MAILFROM; attr_list->len = strlen(m); @@ -271,28 +324,77 @@ static switch_status_t do_config(void) attr_list->next = malloc(sizeof(*attr_list)); attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); attr_list = attr_list->next; - } else if (!strncasecmp("vm-email-all-messages", n, strlen(n))) { - attr_list->type = LDAP_EXTEN_VM_EMAILMSG; - attr_list->len = strlen(m); - attr_list->val = strdup(m); - attr_list->next = malloc(sizeof(*attr_list)); - attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); - attr_list = attr_list->next; - } else if (!strncasecmp("vm-notify-email-all-messages", n, strlen(n))) { - attr_list->type = LDAP_EXTEN_VM_NOTEMAILMSG; + } else if (!strncasecmp("vm-notify-mailto", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_VM_NOTIFY_MAILTO; attr_list->len = strlen(m); attr_list->val = strdup(m); attr_list->next = malloc(sizeof(*attr_list)); attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); attr_list = attr_list->next; } else if (!strncasecmp("vm-attach-file", n, strlen(n))) { - attr_list->type = LDAP_EXTEN_VM_ATTACHFILE; + attr_list->type = LDAP_EXTEN_VM_ATTACH_FILE; + attr_list->len = strlen(m); + attr_list->val = strdup(m); + attr_list->next = malloc(sizeof(*attr_list)); + attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); + attr_list = attr_list->next; + } else if (!strncasecmp("vm-message-ext", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_VM_MESSAGE_EXT; + attr_list->len = strlen(m); + attr_list->val = strdup(m); + attr_list->next = malloc(sizeof(*attr_list)); + attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); + attr_list = attr_list->next; + } else if (!strncasecmp("vm-email-all-messages", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_VM_EMAIL_ALL_MSGS; + attr_list->len = strlen(m); + attr_list->val = strdup(m); + attr_list->next = malloc(sizeof(*attr_list)); + attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); + attr_list = attr_list->next; + } else if (!strncasecmp("vm-keep-local-after-mail", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_VM_KEEP_LOCAL_AFTER_MAIL; + attr_list->len = strlen(m); + attr_list->val = strdup(m); + attr_list->next = malloc(sizeof(*attr_list)); + attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); + attr_list = attr_list->next; + } else if (!strncasecmp("vm-notify-email-all-messages", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_VM_NOTIFY_EMAIL_ALL_MSGS; + attr_list->len = strlen(m); + attr_list->val = strdup(m); + attr_list->next = malloc(sizeof(*attr_list)); + attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); + attr_list = attr_list->next; + } else if (!strncasecmp("vm-skip-instructions", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_VM_SKIP_INSTRUCTIONS; + attr_list->len = strlen(m); + attr_list->val = strdup(m); + attr_list->next = malloc(sizeof(*attr_list)); + attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); + attr_list = attr_list->next; + } else if (!strncasecmp("vm-cc", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_VM_CC; + attr_list->len = strlen(m); + attr_list->val = strdup(m); + attr_list->next = malloc(sizeof(*attr_list)); + attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); + attr_list = attr_list->next; + } else if (!strncasecmp("vm-disk-quota", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_VM_DISK_QUOTA; attr_list->len = strlen(m); attr_list->val = strdup(m); attr_list->next = malloc(sizeof(*attr_list)); attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); attr_list = attr_list->next; /* Variables */ + } else if (!strncasecmp("accountcode", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_ACCOUNTCODE; + attr_list->len = strlen(m); + attr_list->val = strdup(m); + attr_list->next = malloc(sizeof(*attr_list)); + attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); + attr_list = attr_list->next; } else if (!strncasecmp("user_context", n, strlen(n))) { attr_list->type = LDAP_EXTEN_USER_CONTEXT; attr_list->len = strlen(m); @@ -300,8 +402,22 @@ static switch_status_t do_config(void) attr_list->next = malloc(sizeof(*attr_list)); attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); attr_list = attr_list->next; - } else if (!strncasecmp("effective_caller_id_name", n, strlen(n))) { - attr_list->type = LDAP_EXTEN_EFF_CLIDNAME; + } else if (!strncasecmp("vm_mailbox", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_VM_MAILBOX; + attr_list->len = strlen(m); + attr_list->val = strdup(m); + attr_list->next = malloc(sizeof(*attr_list)); + attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); + attr_list = attr_list->next; + } else if (!strncasecmp("callgroup", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_CALLGROUP; + attr_list->len = strlen(m); + attr_list->val = strdup(m); + attr_list->next = malloc(sizeof(*attr_list)); + attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); + attr_list = attr_list->next; + } else if (!strncasecmp("toll_allow", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_TOLL_ALLOW; attr_list->len = strlen(m); attr_list->val = strdup(m); attr_list->next = malloc(sizeof(*attr_list)); @@ -314,15 +430,22 @@ static switch_status_t do_config(void) attr_list->next = malloc(sizeof(*attr_list)); attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); attr_list = attr_list->next; - } else if (!strncasecmp("accountcode", n, strlen(n))) { - attr_list->type = LDAP_EXTEN_ACCOUNTCODE; + } else if (!strncasecmp("effective_caller_id_name", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_EFF_CLIDNAME; attr_list->len = strlen(m); attr_list->val = strdup(m); attr_list->next = malloc(sizeof(*attr_list)); attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); attr_list = attr_list->next; - } else if (!strncasecmp("ruleset", n, strlen(n))) { - attr_list->type = LDAP_EXTEN_RULESET; + } else if (!strncasecmp("outbound_caller_id_number", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_OUT_CLIDNUM; + attr_list->len = strlen(m); + attr_list->val = strdup(m); + attr_list->next = malloc(sizeof(*attr_list)); + attr_list->next = memset(attr_list->next, 0, sizeof(*attr_list)); + attr_list = attr_list->next; + } else if (!strncasecmp("outbound_caller_id_name", n, strlen(n))) { + attr_list->type = LDAP_EXTEN_OUT_CLIDNAME; attr_list->len = strlen(m); attr_list->val = strdup(m); attr_list->next = malloc(sizeof(*attr_list)); @@ -365,10 +488,13 @@ static switch_status_t trydir(switch_xml_t *pxml, int *xoff, LDAP * ld, char *di LDAPMessage *msg, *entry; xml_ldap_attribute_t *attr = NULL; static char *fsattr[] = - { "id", "cidr", "password", "vm-enabled", "vm-password", "vm-mailfrom", "vm-mailto", - "vm-email-all-messages", "vm-notify-email-all-messages", "vm-attach-file", - "user_context", "effective_caller_id_name", "effective_caller_id_number", - "accountcode", "ruleset", NULL }; + { "id", "cidr", "number-alias", "dial-string", "password", "reverse-auth-user", + "reverse-auth-pass", "a1-hash", "vm-password", "vm-enabled", "vm-mailfrom", + "vm-mailto", "vm-notify-mailto", "vm-attach-file", "vm-message-ext", + "vm-email-all-messages", "vm-keep-local-after-mail", "vm-notify-email-all-messages", + "vm-skip-instructions", "vm-cc", "vm-disk-quota", "accountcode", "user_context", + "vm_mailbox", "callgroup", "effective_caller_id_number", "effective_caller_id_name", + "outbound_caller_id_number", "outbound_caller_id_name", "toll_allow", NULL }; basedn = switch_mprintf(binding->basedn, dir_domain); filter = switch_mprintf(binding->filter, dir_exten); From beeea0172411f6274effdac8b90f970fa317b159 Mon Sep 17 00:00:00 2001 From: Italo Rossi Date: Tue, 7 Apr 2015 22:11:27 -0300 Subject: [PATCH 06/43] FS-7242 Waiting for state CS_PARK when receiving REFER. --- src/mod/endpoints/mod_sofia/sofia.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index f8ccbd6f67..19ea978b01 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -8042,6 +8042,7 @@ void sofia_handle_sip_i_refer(nua_t *nua, sofia_profile_t *profile, nua_handle_t sofia_clear_flag_locked(tech_pvt, TFLAG_HOLD_LOCK); switch_channel_set_variable(channel_b, "park_timeout", "2:attended_transfer"); switch_channel_set_state(channel_b, CS_PARK); + switch_channel_wait_for_state_timeout(channel_b, CS_PARK, 5000); } else { if (!br_a && !br_b) { From 69d5333bfc18342e856cadccf668432948c45374 Mon Sep 17 00:00:00 2001 From: Victor Torres Date: Fri, 17 Apr 2015 18:50:16 -0300 Subject: [PATCH 07/43] FS-7445 fixes cc_outbound_cid_name_prefix --- .../mod_callcenter/mod_callcenter.c | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c index 6db5f8a2cd..7f44601fe2 100644 --- a/src/mod/applications/mod_callcenter/mod_callcenter.c +++ b/src/mod/applications/mod_callcenter/mod_callcenter.c @@ -1506,19 +1506,18 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa const char *cid_number = NULL; const char *cid_name_prefix = NULL; - if ((cid_name_prefix = switch_channel_get_variable(member_channel, "cc_outbound_cid_name_prefix"))) { - cid_name_freeable = switch_mprintf("%s%s", cid_name_prefix, h->member_cid_name); - cid_name = cid_name_freeable; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Setting outbound caller_id_name to: %s\n", cid_name); - } else { - if (!(cid_name = switch_channel_get_variable(member_channel, "effective_caller_id_name"))) { - cid_name = h->member_cid_name; - } - - if (!(cid_number = switch_channel_get_variable(member_channel, "effective_caller_id_number"))) { - cid_number = h->member_cid_number; - } + if (!(cid_name = switch_channel_get_variable(member_channel, "effective_caller_id_name"))) { + cid_name = h->member_cid_name; } + if (!(cid_number = switch_channel_get_variable(member_channel, "effective_caller_id_number"))) { + cid_number = h->member_cid_number; + } + if ((cid_name_prefix = switch_channel_get_variable(member_channel, "cc_outbound_cid_name_prefix"))) { + cid_name_freeable = switch_mprintf("%s%s", cid_name_prefix, cid_name); + cid_name = cid_name_freeable; + } + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_DEBUG, "Setting outbound caller_id_name to: %s\n", cid_name); + switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS); switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_queue", "%s", h->queue_name); switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_uuid", "%s", h->member_uuid); From b4250c87a53310d934052ef2226b9a5983ff9e6f Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Mon, 20 Apr 2015 18:23:57 -0400 Subject: [PATCH 08/43] Fix switch_ivr_parse_event() to not hangup a session when there is no media yet If the lead-frames header is set but there is no media ready yet do not attempt to read media from the channel and continue with command execution FS-7455 #resolve --- src/switch_ivr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_ivr.c b/src/switch_ivr.c index ad9b6b1139..9fb9b354d8 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -521,7 +521,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se elp = 1; } - if (lead_frames) { + if (lead_frames && switch_channel_media_ready(channel)) { switch_frame_t *read_frame; int frame_count = atoi(lead_frames); int max_frames = frame_count * 2; From 1bc241922e3136dda8067723a4d4c9ebdd51f101 Mon Sep 17 00:00:00 2001 From: Italo Rossi Date: Sun, 3 May 2015 20:25:42 -0300 Subject: [PATCH 09/43] FS-7464 mod_callcenter moh-sound needs to be expanded when containing variables. --- src/mod/applications/mod_callcenter/mod_callcenter.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c index 6db5f8a2cd..fcf89a6845 100644 --- a/src/mod/applications/mod_callcenter/mod_callcenter.c +++ b/src/mod/applications/mod_callcenter/mod_callcenter.c @@ -25,7 +25,7 @@ * * Marc Olivier Chouinard * Emmanuel Schmidbauer - * + * Ítalo Rossi * * mod_callcenter.c -- Call Center Module * @@ -2518,6 +2518,7 @@ SWITCH_STANDARD_APP(callcenter_function) const char *cc_base_score = switch_channel_get_variable(member_channel, "cc_base_score"); int cc_base_score_int = 0; const char *cur_moh = NULL; + char *moh_expanded = NULL; char start_epoch[64]; switch_event_t *event; switch_time_t t_member_called = local_epoch_time_now(NULL); @@ -2679,6 +2680,7 @@ SWITCH_STANDARD_APP(callcenter_function) cur_moh = switch_core_session_strdup(member_session, queue->moh); } queue_rwunlock(queue); + moh_expanded = switch_channel_expand_variables(member_channel, cur_moh); while (switch_channel_ready(member_channel)) { switch_input_args_t args = { 0 }; @@ -2701,9 +2703,8 @@ SWITCH_STANDARD_APP(callcenter_function) switch_core_session_flush_private_events(member_session); - if (moh_valid && cur_moh) { - switch_status_t status = switch_ivr_play_file(member_session, NULL, cur_moh, &args); - + if (moh_valid && moh_expanded) { + switch_status_t status = switch_ivr_play_file(member_session, NULL, moh_expanded, &args); if (status == SWITCH_STATUS_FALSE /* Invalid Recording */ && SWITCH_READ_ACCEPTABLE(status)) { /* Sadly, there doesn't seem to be a return to switch_ivr_play_file that tell you the file wasn't found. FALSE also mean that the channel got switch to BRAKE state, so we check for read acceptable */ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member_session), SWITCH_LOG_WARNING, "Couldn't play file '%s', continuing wait with no audio\n", cur_moh); @@ -2724,6 +2725,9 @@ SWITCH_STANDARD_APP(callcenter_function) } switch_yield(1000); } + if (moh_expanded != cur_moh) { + switch_safe_free(moh_expanded); + } /* Make sure an agent was found, as we might break above without setting it */ if (!agent_found && (p = switch_channel_get_variable(member_channel, "cc_agent_found"))) { From 890991cd28bb2b2860c988476f8641d7b32f02c8 Mon Sep 17 00:00:00 2001 From: Italo Rossi Date: Mon, 25 May 2015 14:55:57 -0300 Subject: [PATCH 10/43] FS-7569 mod_callcenter - Tracking queue strategy changes to avoid stuck members --- .../mod_callcenter/mod_callcenter.c | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c index 6db5f8a2cd..e33ec98d03 100644 --- a/src/mod/applications/mod_callcenter/mod_callcenter.c +++ b/src/mod/applications/mod_callcenter/mod_callcenter.c @@ -2108,6 +2108,7 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName agent_callback_t cbt; const char *member_state = NULL; const char *member_abandoned_epoch = NULL; + const char *serving_agent = NULL; memset(&cbt, 0, sizeof(cbt)); cbt.queue_name = argv[0]; @@ -2119,6 +2120,7 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName cbt.member_score = argv[6]; member_state = argv[7]; member_abandoned_epoch = argv[8]; + serving_agent = argv[9]; if (!cbt.queue_name || !(queue = get_queue(cbt.queue_name))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Queue %s not found locally, skip this member\n", cbt.queue_name); @@ -2153,7 +2155,23 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName } /* Skip this member */ goto end; - } + } + + /* Tracking queue strategy changes */ + /* member is ring-all but not the queue */ + if (!strcasecmp(serving_agent, "ring-all") && (strcasecmp(queue_strategy, "ring-all") != 0)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Queue '%s' changed strategy, adjusting member parameters", queue_name); + sql = switch_mprintf("UPDATE members SET serving_agent = '', state = '%s' WHERE uuid = '%s' AND state = '%s' AND serving_agent = 'ring-all'", cc_member_state2str(CC_MEMBER_STATE_WAITING), cbt.member_uuid, cc_member_state2str(CC_MEMBER_STATE_TRYING)); + cc_execute_sql(NULL, sql, NULL); + switch_safe_free(sql); + } + /* Queue is now ring-all and not the member */ + else if (!strcasecmp(queue_strategy, "ring-all") && (strcasecmp(serving_agent, "ring-all") != 0)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Queue '%s' changed strategy, adjusting member parameters", queue_name); + sql = switch_mprintf("UPDATE members SET serving_agent = 'ring-all', state = '%s' WHERE uuid = '%s' AND state = '%s' AND serving_agent = ''", cc_member_state2str(CC_MEMBER_STATE_TRYING), cbt.member_uuid, cc_member_state2str(CC_MEMBER_STATE_WAITING)); + cc_execute_sql(NULL, sql, NULL); + switch_safe_free(sql); + } /* Check if member is in the queue waiting */ if (zstr(cbt.member_session_uuid)) { @@ -2307,7 +2325,7 @@ void *SWITCH_THREAD_FUNC cc_agent_dispatch_thread_run(switch_thread_t *thread, v while (globals.running == 1) { char *sql = NULL; - sql = switch_mprintf("SELECT queue,uuid,session_uuid,cid_number,cid_name,joined_epoch,(%" SWITCH_TIME_T_FMT "-joined_epoch)+base_score+skill_score AS score, state, abandoned_epoch FROM members" + sql = switch_mprintf("SELECT queue,uuid,session_uuid,cid_number,cid_name,joined_epoch,(%" SWITCH_TIME_T_FMT "-joined_epoch)+base_score+skill_score AS score, state, abandoned_epoch, serving_agent FROM members" " WHERE state = '%q' OR state = '%q' OR (serving_agent = 'ring-all' AND state = '%q') ORDER BY score DESC", local_epoch_time_now(NULL), cc_member_state2str(CC_MEMBER_STATE_WAITING), cc_member_state2str(CC_MEMBER_STATE_ABANDONED), cc_member_state2str(CC_MEMBER_STATE_TRYING)); From 15f6699aaac516caafaee55ee9a3b57a331c46fe Mon Sep 17 00:00:00 2001 From: Steve Underwood Date: Mon, 1 Jun 2015 05:38:33 +0800 Subject: [PATCH 11/43] V.27ter modem modified to make it a little less tolerant of poor SNR, and a little more tolerant of big timing errors between the symbols at the far end, and as they are received by us. --- libs/spandsp/src/v27ter_rx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/spandsp/src/v27ter_rx.c b/libs/spandsp/src/v27ter_rx.c index 6959d27ef2..93d3b4680d 100644 --- a/libs/spandsp/src/v27ter_rx.c +++ b/libs/spandsp/src/v27ter_rx.c @@ -497,14 +497,14 @@ static __inline__ void symbol_sync(v27ter_rx_state_t *s) s->gardner_integrate += (p + q > 0) ? s->gardner_step : -s->gardner_step; - if (abs(s->gardner_integrate) >= 256) + if (abs(s->gardner_integrate) >= 128) { /* This integrate and dump approach avoids rapid changes of the equalizer put step. Rapid changes, without hysteresis, are bad. They degrade the equalizer performance when the true symbol boundary is close to a sample boundary. */ //span_log(&s->logging, SPAN_LOG_FLOW, "Hop %d\n", s->gardner_integrate); - s->eq_put_step += (s->gardner_integrate/256); - s->total_baud_timing_correction += (s->gardner_integrate/256); + s->eq_put_step += (s->gardner_integrate/128); + s->total_baud_timing_correction += (s->gardner_integrate/128); if (s->qam_report) s->qam_report(s->qam_user_data, NULL, NULL, s->gardner_integrate); s->gardner_integrate = 0; From 8131f210b34c818e24911869b125b3b98c88fd10 Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 1 Jun 2015 09:16:25 -0500 Subject: [PATCH 12/43] FS-7579 --resolve --- src/mod/applications/mod_conference/mod_conference.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 532e827c3c..b4cc3e829d 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -11479,7 +11479,7 @@ static void clear_eflags(char *events, uint32_t *f) } else if (!strcmp(event, "play-file")) { *f &= ~EFLAG_PLAY_FILE; } else if (!strcmp(event, "play-file-done")) { - *f &= ~EFLAG_PLAY_FILE; + *f &= ~EFLAG_PLAY_FILE_DONE; } else if (!strcmp(event, "play-file-member")) { *f &= ~EFLAG_PLAY_FILE_MEMBER; } else if (!strcmp(event, "speak-text")) { From 0c4f85111f491b4929609ad42505167b6621183d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Zaprza=C5=82a?= Date: Tue, 3 Mar 2015 13:05:23 +0100 Subject: [PATCH 13/43] FS-7337: Add support for Remote-Party-ID header in UPDATE request. --- src/mod/endpoints/mod_sofia/sofia.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 230f3789be..4dc4557542 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1136,6 +1136,7 @@ void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *pro } if (!fs) { + sip_remote_party_id_t *rpid; if ((passerted = sip_p_asserted_identity(sip))) { if (passerted->paid_url->url_user) { number = passerted->paid_url->url_user; @@ -1151,6 +1152,21 @@ void sofia_update_callee_id(switch_core_session_t *session, sofia_profile_t *pro end_of(name) = '\0'; } } + } else if ((rpid = sip_remote_party_id(sip))) { + if (rpid->rpid_url->url_user) { + number = rpid->rpid_url->url_user; + } + if (!zstr(rpid->rpid_display)) { + dup = strdup(rpid->rpid_display); + if (*dup == '"') { + name = dup + 1; + } else { + name = dup; + } + if (end_of(name) == '"') { + end_of(name) = '\0'; + } + } } } @@ -1510,6 +1526,7 @@ static void our_sofia_event_callback(nua_event_t event, sofia_handle_sip_i_info(nua, profile, nh, session, sip, de, tags); break; case nua_i_update: + sofia_update_callee_id(session, profile, sip, SWITCH_TRUE); break; case nua_r_update: if (session && tech_pvt && locked) { From f792f9de9ee0bf0a0d601fb5236268aa054cb16d Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Mon, 1 Jun 2015 12:51:26 -0400 Subject: [PATCH 14/43] FS-7570: fix status variable reference that is breaking compile w/ zrtp enabled --- src/switch_rtp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 438a3dabd5..07a407d6e8 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -7746,7 +7746,7 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_write_raw(switch_rtp_t *rtp_session, break; case zrtp_status_drop: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: zRTP protection drop with code %d\n", stat); - ret = SWITCH_STATUS_SUCCESS; + status = SWITCH_STATUS_SUCCESS; goto end; break; case zrtp_status_fail: From f82dd1e9eabd185729fd09dc86035840e4617534 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 1 Jun 2015 11:54:43 -0500 Subject: [PATCH 15/43] FS-7513 add video-auto-floor-msec param to control how long a member must have the audio floor before also taking the video floor %NEEDS_DOC --- .../autoload_configs/conference.conf.xml | 1 + .../mod_conference/mod_conference.c | 34 +++++++++++++++---- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/conf/vanilla/autoload_configs/conference.conf.xml b/conf/vanilla/autoload_configs/conference.conf.xml index ccde59f7f1..9dfb75b22d 100644 --- a/conf/vanilla/autoload_configs/conference.conf.xml +++ b/conf/vanilla/autoload_configs/conference.conf.xml @@ -185,6 +185,7 @@ + diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index b4cc3e829d..73237bc7b8 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -594,6 +594,7 @@ typedef struct conference_obj { struct conf_fps video_fps; int playing_video_file; int recording_members; + uint32_t video_floor_packets; } conference_obj_t; /* Relationship with another member */ @@ -682,6 +683,7 @@ struct conference_member { switch_frame_buffer_t *fb; switch_image_t *avatar_png_img; switch_image_t *video_mute_img; + uint32_t floor_packets; int blanks; int managed_kps; int blackouts; @@ -4531,6 +4533,7 @@ static void conference_set_floor_holder(conference_obj_t *conference, conference if (old_member) { old_id = old_member->id; member_update_status_field(old_member); + old_member->floor_packets = 0; } switch_set_flag(conference, CFLAG_FLOOR_CHANGE); @@ -6330,6 +6333,7 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v check_agc_levels(member); clear_avg(member); member->score_iir = 0; + member->floor_packets = 0; if (test_eflag(member->conference, EFLAG_STOP_TALKING) && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { @@ -6369,7 +6373,7 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v if (member->volume_in_level) { switch_change_sln_volume(read_frame->data, (read_frame->datalen / 2) * member->conference->channels, member->volume_in_level); } - + if (member->agc_volume_in_level) { switch_change_sln_volume_granular(read_frame->data, (read_frame->datalen / 2) * member->conference->channels, member->agc_volume_in_level); } @@ -6428,10 +6432,6 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v member->score_iir = SCORE_MAX_IIR; } - if (member == member->conference->floor_holder && member->id != member->conference->video_floor_holder) { - conference_set_video_floor_holder(member->conference, member, SWITCH_FALSE); - } - if (noise_gate_check(member)) { uint32_t diff = member->score - member->energy_level; if (hangover_hits) { @@ -6442,6 +6442,10 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v member->nt_tally = 0; } + if (member == member->conference->floor_holder) { + member->floor_packets++; + } + if (diff >= diff_level || ++hangunder_hits >= hangunder) { hangover_hits = hangunder_hits = 0; @@ -6504,6 +6508,13 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v member->last_score = member->score; + + if (member == member->conference->floor_holder) { + if (member->id != member->conference->video_floor_holder && + (member->floor_packets > member->conference->video_floor_packets || member->energy_level == 0)) { + conference_set_video_floor_holder(member->conference, member, SWITCH_FALSE); + } + } } loops++; @@ -12573,7 +12584,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c switch_codec_implementation_t read_impl = { 0 }; switch_channel_t *channel = NULL; const char *force_rate = NULL, *force_interval = NULL, *force_channels = NULL, *presence_id = NULL; - uint32_t force_rate_i = 0, force_interval_i = 0, force_channels_i = 0; + uint32_t force_rate_i = 0, force_interval_i = 0, force_channels_i = 0, video_auto_floor_msec = 0; /* Validate the conference name */ if (zstr(name)) { @@ -12790,6 +12801,13 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c } else if (switch_true(val)) { comfort_noise_level = 1400; } + } else if (!strcasecmp(var, "video-auto-floor-msec") && !zstr(val)) { + int tmp; + tmp = atoi(val); + + if (tmp > 0) { + video_auto_floor_msec = tmp; + } } else if (!strcasecmp(var, "sound-prefix") && !zstr(val)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "override sound-prefix with: %s\n", val); sound_prefix = val; @@ -13170,6 +13188,10 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c conference->ivr_dtmf_timeout = ivr_dtmf_timeout; conference->ivr_input_timeout = ivr_input_timeout; + if (video_auto_floor_msec) { + conference->video_floor_packets = video_auto_floor_msec / conference->interval; + } + conference->eflags = 0xFFFFFFFF; if (!zstr(suppress_events)) { From 3702ce5a8e82b881b7b2b007145948c923fca571 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 1 Jun 2015 12:44:21 -0500 Subject: [PATCH 16/43] squash --- .../applications/mod_conference/mod_conference.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 73237bc7b8..f59adc9c49 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -4498,15 +4498,6 @@ static void conference_set_floor_holder(conference_obj_t *conference, conference conference_member_t *old_member = NULL; int old_id = 0; - - if (((conference->video_floor_holder && !member && !switch_test_flag(conference, CFLAG_VID_FLOOR_LOCK)) || - (member && member->channel && (switch_channel_test_flag(member->channel, CF_VIDEO) || member->avatar_png_img)))) { - - if (member && member->id != conference->video_floor_holder) { - conference_set_video_floor_holder(conference, member, SWITCH_FALSE); - } - } - if (conference->floor_holder) { if (conference->floor_holder == member) { return; @@ -6451,11 +6442,11 @@ static void *SWITCH_THREAD_FUNC conference_loop_input(switch_thread_t *thread, v hangover_hits = hangunder_hits = 0; member->last_talking = switch_epoch_time_now(NULL); - if (!switch_test_flag(member, MFLAG_TALKING)) { switch_set_flag_locked(member, MFLAG_TALKING); member_update_status_field(member); - + member->floor_packets = 0; + if (test_eflag(member->conference, EFLAG_START_TALKING) && switch_test_flag(member, MFLAG_CAN_SPEAK) && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) { conference_add_event_member_data(member, event); From 022fddbe6a6ef7775da61aa3a1afeb9447eb7bae Mon Sep 17 00:00:00 2001 From: Alexander Traud Date: Tue, 19 May 2015 12:43:43 +0200 Subject: [PATCH 17/43] Add Perfect Forward Secrecy (DHE PFS) to mod_sofia Ephemeral ECDH (ECDHE) was supported already. This patch adds Ephemeral DH (DHE). To enable it, add DH parameters into the private-key file of your server (agent.pem). For example via: openssl dhparam -out dh.pem 2048 FS-7561 #resolve --- conf/vanilla/vars.xml | 2 -- .../libsofia-sip-ua/tport/tport_tls.c | 21 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/conf/vanilla/vars.xml b/conf/vanilla/vars.xml index 89c8a95f3b..c3e216361a 100644 --- a/conf/vanilla/vars.xml +++ b/conf/vanilla/vars.xml @@ -413,8 +413,6 @@ openssl ciphers -v 'ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH' Will show you what is available in your verion of openssl. - Freeswitch does not support non-Elliptic Curve Diffie Hellman key - exchange. --> diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c b/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c index 5689d582c8..976a88dede 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/tport_tls.c @@ -381,6 +381,27 @@ int tls_init_context(tls_t *tls, tls_issues_t const *ti) #if require_client_certificate errno = EIO; return -1; +#endif +#ifndef OPENSSL_NO_DH + } else { + BIO *bio = BIO_new_file(ti->key, "r"); + if (bio != NULL) { + DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + if (dh != NULL) { + if (!SSL_CTX_set_tmp_dh(tls->ctx, dh)) { + SU_DEBUG_1(("%s: invalid DH parameters (PFS) because %s: %s\n", + "tls_init_context", + ERR_reason_error_string(ERR_get_error()), + ti->key)); + } else { + long options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_DH_USE; + options = SSL_CTX_set_options(tls->ctx, options); + SU_DEBUG_3(("%s\n", "tls: initialized DHE")); + } + DH_free(dh); + } + BIO_free(bio); + } #endif } From 8d98bc27ef67f44579ea593e36a48a53816844f3 Mon Sep 17 00:00:00 2001 From: doancea Date: Wed, 22 Apr 2015 16:04:07 +0200 Subject: [PATCH 18/43] FS-7462: fix FMTP in the INVITE - make it use values from opus.conf.xml --- src/mod/codecs/mod_opus/mod_opus.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c index 21dc569c6b..8a950aab22 100644 --- a/src/mod/codecs/mod_opus/mod_opus.c +++ b/src/mod/codecs/mod_opus/mod_opus.c @@ -490,8 +490,14 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_opus_load) codec_interface->parse_fmtp = switch_opus_fmtp_parse; settings = default_codec_settings; - - + + if (opus_prefs.maxaveragebitrate){ + settings.maxaveragebitrate = opus_prefs.maxaveragebitrate; + } + if (opus_prefs.maxplaybackrate) { + settings.maxplaybackrate = opus_prefs.maxplaybackrate; + } + for (x = 0; x < 3; x++) { settings.ptime = mss / 1000; From d7a1f3d424a6beda761a6950aeadd2010a4769c0 Mon Sep 17 00:00:00 2001 From: Nathan Neulinger Date: Mon, 1 Jun 2015 12:22:08 -0500 Subject: [PATCH 19/43] FS-7593 --resolve add locking keyed on device name around any database updates adding/removing the device --- src/mod/endpoints/mod_skinny/mod_skinny.c | 91 +++++++++++++++++++- src/mod/endpoints/mod_skinny/mod_skinny.h | 27 ++++++ src/mod/endpoints/mod_skinny/skinny_server.c | 12 ++- 3 files changed, 127 insertions(+), 3 deletions(-) diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index 7ef5aec3e2..59d1b4ef69 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -1464,6 +1464,86 @@ static int flush_listener_callback(void *pArg, int argc, char **argv, char **col return 0; } +void skinny_lock_device_name(listener_t *listener, char *device_name) +{ + switch_time_t started = 0; + unsigned int elapsed = 0; + device_name_lock_t *dnl; + + if ( listener->profile->debug >= 9 ) { + skinny_log_l(listener, SWITCH_LOG_DEBUG, "lock device name '%s'\n", device_name); + } + + started = switch_micro_time_now(); + + /* global mutex on hash operations */ + switch_mutex_lock(listener->profile->device_name_lock_mutex); + + dnl = (device_name_lock_t *) switch_core_hash_find(listener->profile->device_name_lock_hash, device_name); + if ( ! dnl ) { + if ( listener->profile->debug >= 9 ) { + skinny_log_l(listener, SWITCH_LOG_DEBUG, "creating device name lock for device name '%s'\n", device_name); + } + dnl = switch_core_alloc(listener->profile->pool, sizeof(*dnl)); + switch_mutex_init(&dnl->flag_mutex, SWITCH_MUTEX_NESTED, listener->profile->pool); + switch_core_hash_insert(listener->profile->device_name_lock_hash, device_name, dnl); + } + + switch_mutex_unlock(listener->profile->device_name_lock_mutex); + + if ( listener->profile->debug >= 9 ) { + skinny_log_l(listener, SWITCH_LOG_DEBUG, "setting device name lock for device name '%s'\n", device_name); + } + switch_set_flag_locked(dnl, DNLFLAG_INUSE); + + if ((elapsed = (unsigned int) ((switch_micro_time_now() - started) / 1000)) > 5) { + skinny_log_l(listener, SWITCH_LOG_DEBUG, "device name lock took more than 5ms for '%s' (%d)\n", device_name, elapsed); + } + + if ( listener->profile->debug >= 9 ) { + skinny_log_l(listener, SWITCH_LOG_DEBUG, "locked device name '%s'\n", device_name); + } +} + +void skinny_unlock_device_name(listener_t *listener, char *device_name) +{ + switch_time_t started = 0; + unsigned int elapsed = 0; + device_name_lock_t *dnl; + + if ( listener->profile->debug >= 9 ) { + skinny_log_l(listener, SWITCH_LOG_DEBUG, "unlock device name '%s'\n", device_name); + } + + started = switch_micro_time_now(); + + /* global mutex on hash operations */ + switch_mutex_lock(listener->profile->device_name_lock_mutex); + dnl = (device_name_lock_t *) switch_core_hash_find(listener->profile->device_name_lock_hash, device_name); + switch_mutex_unlock(listener->profile->device_name_lock_mutex); + + if ( ! dnl ) { + skinny_log_l(listener, SWITCH_LOG_WARNING, "request to unlock and no lock structure for '%s'\n", device_name); + /* since it didn't exist, nothing to unlock, don't bother creating structure now */ + } else { + if ( listener->profile->debug >= 9 ) { + skinny_log_l(listener, SWITCH_LOG_DEBUG, "clearing device name lock on '%s'\n", device_name); + } + switch_clear_flag_locked(dnl, DNLFLAG_INUSE); + } + + /* Should we clean up the lock structure here, or does it ever get reclaimed? I don't think memory is released + so attempting to clear it up here likely would just result in a leak. */ + + if ((elapsed = (unsigned int) ((switch_micro_time_now() - started) / 1000)) > 5) { + skinny_log_l(listener, SWITCH_LOG_DEBUG, "device name unlock took more than 5ms for '%s' (%d)\n", device_name, elapsed); + } + + if ( listener->profile->debug >= 9 ) { + skinny_log_l(listener, SWITCH_LOG_DEBUG, "unlocked device name '%s'\n", device_name); + } +} + void skinny_clean_device_from_db(listener_t *listener, char *device_name) { if(!zstr(device_name)) { @@ -1579,7 +1659,9 @@ static void flush_listener(listener_t *listener) switch_safe_free(sql); } + skinny_lock_device_name(listener, listener->device_name); skinny_clean_listener_from_db(listener); + skinny_unlock_device_name(listener, listener->device_name); strcpy(listener->device_name, ""); } @@ -1658,7 +1740,7 @@ switch_status_t kill_listener(listener_t *listener, void *pvt) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Killing listener %s:%d.\n", listener->device_name, listener->device_instance); - switch_clear_flag(listener, LFLAG_RUNNING); + switch_clear_flag_locked(listener, LFLAG_RUNNING); close_socket(&listener->sock, listener->profile); return SWITCH_STATUS_SUCCESS; } @@ -1740,11 +1822,12 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj) skinny_log_l_msg(listener, SWITCH_LOG_DEBUG, "Connection Open\n"); } + listener->connect_time = switch_epoch_time_now(NULL); + switch_set_flag_locked(listener, LFLAG_RUNNING); keepalive_listener(listener, NULL); add_listener(listener); - while (listener_is_ready(listener)) { status = skinny_read_packet(listener, &request); @@ -2116,6 +2199,8 @@ static switch_status_t load_skinny_config(void) switch_mutex_init(&profile->sock_mutex, SWITCH_MUTEX_NESTED, profile->pool); switch_mutex_init(&profile->flag_mutex, SWITCH_MUTEX_NESTED, profile->pool); + switch_mutex_init(&profile->device_name_lock_mutex, SWITCH_MUTEX_NESTED, profile->pool); + for (param = switch_xml_child(xsettings, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); char *val = (char *) switch_xml_attr_soft(param, "value"); @@ -2233,6 +2318,8 @@ static switch_status_t load_skinny_config(void) continue; } + /* Device Name Locks */ + switch_core_hash_init(&profile->device_name_lock_hash); /* Device types */ switch_core_hash_init(&profile->device_type_params_hash); diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.h b/src/mod/endpoints/mod_skinny/mod_skinny.h index 425710dae4..b0f6abf1be 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.h +++ b/src/mod/endpoints/mod_skinny/mod_skinny.h @@ -127,6 +127,9 @@ struct skinny_profile { int non_blocking; switch_hash_t *soft_key_set_sets_hash; switch_hash_t *device_type_params_hash; + /* lock on device names for multiple connection handling */ + switch_mutex_t *device_name_lock_mutex; + switch_hash_t *device_name_lock_hash; /* extensions */ char *ext_voicemail; char *ext_redial; @@ -169,6 +172,23 @@ typedef enum { SKINNY_ACTION_WAIT } skinny_action_t; + + +/*****************************************************************************/ +/* DEVICE NAME LOCK TYPES */ +/*****************************************************************************/ +typedef enum { + DNLFLAG_INUSE = (1 << 0), +} device_name_lock_flag_t; + +struct device_name_lock { + char device_name[16]; + switch_mutex_t *flag_mutex; + uint32_t flags; +}; + +typedef struct device_name_lock device_name_lock_t; + /*****************************************************************************/ /* LISTENERS TYPES */ /*****************************************************************************/ @@ -197,6 +217,7 @@ struct listener { switch_mutex_t *flag_mutex; uint32_t flags; time_t expire_time; + time_t connect_time; switch_time_t digit_timeout_time; struct listener *next; char *ext_voicemail; @@ -301,6 +322,12 @@ switch_status_t keepalive_listener(listener_t *listener, void *pvt); void skinny_clean_listener_from_db(listener_t *listener); void skinny_clean_device_from_db(listener_t *listener, char *device_name); +/*****************************************************************************/ +/* DEVICE NAME LOCK FUNCTIONS */ +/*****************************************************************************/ +void skinny_lock_device_name(listener_t *listener, char *device_name); +void skinny_unlock_device_name(listener_t *listener, char *device_name); + /*****************************************************************************/ /* CHANNEL FUNCTIONS */ /*****************************************************************************/ diff --git a/src/mod/endpoints/mod_skinny/skinny_server.c b/src/mod/endpoints/mod_skinny/skinny_server.c index 5a581de463..7d4facfcf7 100644 --- a/src/mod/endpoints/mod_skinny/skinny_server.c +++ b/src/mod/endpoints/mod_skinny/skinny_server.c @@ -1113,12 +1113,17 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "action", "skinny-auth"); /* clean up all traces before adding to database */ + skinny_lock_device_name(listener, request->data.reg.device_name); skinny_clean_device_from_db(listener, request->data.reg.device_name); if (switch_xml_locate_user("id", request->data.reg.device_name, profile->domain, "", &xroot, &xdomain, &xuser, &xgroup, params) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Can't find device [%s@%s]\n" "You must define a domain called '%s' in your directory and add a user with id=\"%s\".\n" , request->data.reg.device_name, profile->domain, profile->domain, request->data.reg.device_name); + + /* unlock before trying to send response in case socket blocks */ + skinny_unlock_device_name(listener, request->data.reg.device_name); + send_register_reject(listener, "Device not found"); status = SWITCH_STATUS_FALSE; goto end; @@ -1135,6 +1140,10 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Device %s:%d is already registered on another listener.\n", request->data.reg.device_name, request->data.reg.instance); + + /* unlock before trying to send response in case socket blocks */ + skinny_unlock_device_name(listener, request->data.reg.device_name); + send_register_reject(listener, "Device is already registered on another listener"); status = SWITCH_STATUS_FALSE; goto end; @@ -1156,11 +1165,12 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r switch_safe_free(sql); } - switch_copy_string(listener->device_name, request->data.reg.device_name, 16); listener->device_instance = request->data.reg.instance; listener->device_type = request->data.reg.device_type; + skinny_unlock_device_name(listener, request->data.reg.device_name); + xskinny = switch_xml_child(xuser, "skinny"); if (xskinny) { if ((xparams = switch_xml_child(xskinny, "params"))) { From 8f343939dc7f63f6a1686941e7d34e1cbf27a1c3 Mon Sep 17 00:00:00 2001 From: Andrew Cassidy Date: Mon, 4 May 2015 12:52:08 +0100 Subject: [PATCH 20/43] Added new options to nibble bill for minimum charges and rounding #FS-7560 These options are: 1) nibble_rounding: The number of decimal places to round the cost of the call to 2) nibble_minimum: The minimum charge to apply to a call Rounding is applied before the minimum charging, and these steps only occur at call end to make sure they're accurate. Checks for minimum_charge before call starts "Billing done" flag to the data struct, and used that to exit early in the event processing during hangup has already occured. --- .../mod_nibblebill/mod_nibblebill.c | 61 +++++++++++++++++-- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/src/mod/applications/mod_nibblebill/mod_nibblebill.c b/src/mod/applications/mod_nibblebill/mod_nibblebill.c index 39a799c1ec..a06e0c8d94 100644 --- a/src/mod/applications/mod_nibblebill/mod_nibblebill.c +++ b/src/mod/applications/mod_nibblebill/mod_nibblebill.c @@ -50,6 +50,7 @@ */ #include +#include typedef struct { switch_time_t lastts; /* Last time we did any billing */ @@ -59,6 +60,7 @@ typedef struct { double bill_adjustments; /* Adjustments to make to the next billing, based on pause/resume events */ int lowbal_action_executed; /* Set to 1 once lowbal_action has been executed */ + int final_bill_done; /* Set to 1 one the final rounding has been done on a call to prevent spurious rebills on hangup */ } nibble_data_t; @@ -454,6 +456,12 @@ static switch_status_t do_billing(switch_core_session_t *session) double nobal_amt = globals.nobal_amt; double lowbal_amt = globals.lowbal_amt; double balance; + double minimum_charge = 0; + double rounding_factor = 1; + double excess = 0; + double rounded_billed = 0; + int billsecs = 0; + double balance_check = 0; if (!session) { /* Why are we here? */ @@ -480,6 +488,16 @@ static switch_status_t do_billing(switch_core_session_t *session) lowbal_amt = atof(switch_channel_get_variable(channel, "lowbal_amt")); } + if (!zstr(switch_channel_get_variable(channel, "nibble_rounding"))) { + rounding_factor = pow(10, atof(switch_channel_get_variable(channel, "nibble_rounding"))); + } + + if (!zstr(switch_channel_get_variable(channel, "nibble_minimum"))) { + minimum_charge = atof(switch_channel_get_variable(channel, "nibble_minimum")); + } + + + /* Return if there's no billing information on this session */ if (!billrate || !billaccount) { return SWITCH_STATUS_SUCCESS; @@ -501,8 +519,9 @@ static switch_status_t do_billing(switch_core_session_t *session) /* See if this person has enough money left to continue the call */ balance = get_balance(billaccount, channel); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Comparing %f to hangup balance of %f\n", balance, nobal_amt); - if (balance <= nobal_amt) { + balance_check = balance - minimum_charge; + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Comparing %f to hangup balance of %f, taking into account minimum charge of %f\n", balance, nobal_amt, minimum_charge); + if (balance_check <= nobal_amt) { /* Not enough money - reroute call to nobal location */ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Balance of %f fell below allowed amount of %f! (Account %s)\n", balance, nobal_amt, billaccount); @@ -530,6 +549,12 @@ static switch_status_t do_billing(switch_core_session_t *session) return SWITCH_STATUS_SUCCESS; } + if (nibble_data && nibble_data->final_bill_done) { + switch_mutex_lock(globals.mutex); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Received heartbeat, but final bill has been committed - ignoring\n"); + return SWITCH_STATUS_SUCCESS; + } + /* Have we done any billing on this channel yet? If no, set up vars for doing so */ if (!nibble_data) { nibble_data = switch_core_session_alloc(session, sizeof(*nibble_data)); @@ -543,8 +568,10 @@ static switch_status_t do_billing(switch_core_session_t *session) switch_time_exp_lt(&tm, nibble_data->lastts); switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm); + billsecs = (int) ((ts - nibble_data->lastts) / 1000000); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%d seconds passed since last bill time of %s\n", - (int) ((ts - nibble_data->lastts) / 1000000), date); + billsecs, date); if ((ts - nibble_data->lastts) >= 0) { /* If billincrement is set we bill by it and not by time elapsed */ @@ -576,6 +603,29 @@ static switch_status_t do_billing(switch_core_session_t *session) } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failed to log to database!\n"); } + + /* Do Rounding and minimum charge during hangup */ + if (switch_channel_get_state(channel) == CS_HANGUP) { + /* we're going to make an assumption that final billing is done here. So we'll see how this goes. */ + /* round total billed up as required */ + + rounded_billed = ceilf(nibble_data->total * rounding_factor) / rounding_factor; + + if (rounded_billed < minimum_charge) + { + excess = minimum_charge - nibble_data->total; + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Applying minimum charge of %f (%f excess)\n", minimum_charge, excess); + } + else if (nibble_data->total < rounded_billed) + { + excess = rounded_billed - nibble_data->total; + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Rounding to precision %f, total %f (%f excess)\n", rounding_factor, rounded_billed, excess); + } + bill_event(excess, billaccount, channel); + nibble_data->total += excess; + switch_channel_set_variable_printf(channel, "nibble_total_billed", "%f", nibble_data->total); + nibble_data->final_bill_done = 1; + } } else { if (switch_strlen_zero(billincrement)) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Just tried to bill %s negative minutes! That should be impossible.\n", uuid); @@ -951,10 +1001,11 @@ static switch_status_t process_hangup(switch_core_session_t *session) do_billing(session); billaccount = switch_channel_get_variable(channel, globals.var_name_account); + if (billaccount) { switch_channel_set_variable_printf(channel, "nibble_current_balance", "%f", get_balance(billaccount, channel)); - } - + } + return SWITCH_STATUS_SUCCESS; } From 3b2d00f3e65061393da10a4ba286ac72cdb3c16e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 28 May 2015 18:02:21 -0500 Subject: [PATCH 21/43] FS-7587 Add ipv6 support to Verto / Websockets --- conf/vanilla/autoload_configs/verto.conf.xml | 29 ++- src/include/switch_core_media.h | 3 + src/include/switch_rtp.h | 1 + src/mod/endpoints/mod_verto/mcast/mcast.c | 105 ++++++-- src/mod/endpoints/mod_verto/mcast/mcast.h | 3 + src/mod/endpoints/mod_verto/mod_verto.c | 255 ++++++++++++------- src/mod/endpoints/mod_verto/mod_verto.h | 18 +- src/mod/endpoints/mod_verto/ws.c | 15 +- src/switch_core.c | 27 +- src/switch_core_media.c | 216 +++++++++++----- src/switch_utils.c | 5 +- 11 files changed, 489 insertions(+), 188 deletions(-) diff --git a/conf/vanilla/autoload_configs/verto.conf.xml b/conf/vanilla/autoload_configs/verto.conf.xml index a62fd706d7..b69777ac0a 100644 --- a/conf/vanilla/autoload_configs/verto.conf.xml +++ b/conf/vanilla/autoload_configs/verto.conf.xml @@ -5,9 +5,9 @@ - - - + + + @@ -21,7 +21,28 @@ - + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/include/switch_core_media.h b/src/include/switch_core_media.h index 37631fce70..bc25817225 100644 --- a/src/include/switch_core_media.h +++ b/src/include/switch_core_media.h @@ -125,6 +125,9 @@ typedef struct switch_core_media_params_s { char *extrtpip; char *rtpip; + char *rtpip4; + char *rtpip6; + char *remote_ip; int remote_port; diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h index 6dfa1e2531..4bb140c83d 100644 --- a/src/include/switch_rtp.h +++ b/src/include/switch_rtp.h @@ -105,6 +105,7 @@ typedef struct ice_s { icand_t cands[MAX_CAND][2]; int cand_idx; int chosen[2]; + int is_chosen[2]; char *ufrag; char *pwd; char *options; diff --git a/src/mod/endpoints/mod_verto/mcast/mcast.c b/src/mod/endpoints/mod_verto/mcast/mcast.c index e37ac08efc..617553bcc4 100644 --- a/src/mod/endpoints/mod_verto/mcast/mcast.c +++ b/src/mod/endpoints/mod_verto/mcast/mcast.c @@ -58,16 +58,29 @@ int mcast_socket_create(const char *host, int16_t port, mcast_handle_t *handle, mcast_flag_t flags) { uint32_t one = 1; + int family = AF_INET; memset(handle, 0, sizeof(*handle)); - if ((!(flags & MCAST_SEND) && !(flags & MCAST_RECV)) || (handle->sock = socket(AF_INET, SOCK_DGRAM, 0)) <= 0 ) { - return -1; + if (strchr(host, ':')) { + family = AF_INET6; } - handle->send_addr.sin_family = AF_INET; - handle->send_addr.sin_addr.s_addr = inet_addr(host); - handle->send_addr.sin_port = htons(port); + if ((!(flags & MCAST_SEND) && !(flags & MCAST_RECV)) || (handle->sock = socket(family, SOCK_DGRAM, 0)) <= 0 ) { + return -1; + } + + if (family == AF_INET6) { + handle->send_addr6.sin6_family = AF_INET6; + handle->send_addr6.sin6_port = htons(port); + inet_pton(AF_INET6, host, &(handle->send_addr6.sin6_addr)); + handle->family = AF_INET6; + } else { + handle->send_addr.sin_family = AF_INET; + handle->send_addr.sin_addr.s_addr = inet_addr(host); + handle->send_addr.sin_port = htons(port); + handle->family = AF_INET; + } if ( setsockopt(handle->sock, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one)) != 0 ) { close(handle->sock); @@ -76,28 +89,61 @@ int mcast_socket_create(const char *host, int16_t port, mcast_handle_t *handle, if ((flags & MCAST_RECV)) { - struct ip_mreq mreq; + if (handle->family == AF_INET) { + struct ip_mreq mreq; + + handle->recv_addr.sin_family = AF_INET; + handle->recv_addr.sin_addr.s_addr = htonl(INADDR_ANY); + handle->recv_addr.sin_port = htons(port); - handle->recv_addr.sin_family = AF_INET; - handle->recv_addr.sin_addr.s_addr = htonl(INADDR_ANY); - handle->recv_addr.sin_port = htons(port); + mreq.imr_multiaddr.s_addr = inet_addr(host); + mreq.imr_interface.s_addr = htonl(INADDR_ANY); - mreq.imr_multiaddr.s_addr = inet_addr(host); - mreq.imr_interface.s_addr = htonl(INADDR_ANY); + if (setsockopt(handle->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof(mreq)) < 0) { + close(handle->sock); + handle->sock = -1; + return -1; + } - if (setsockopt(handle->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mreq, sizeof(mreq)) < 0) { - close(handle->sock); - handle->sock = -1; - return -1; + if (bind(handle->sock, (struct sockaddr *) &handle->recv_addr, sizeof(handle->recv_addr)) < 0) { + close(handle->sock); + handle->sock = -1; + return -1; + } + + } else { + struct ipv6_mreq mreq; + struct addrinfo addr_criteria; + struct addrinfo *mcast_addr; + char service[80] = ""; + + memset(&addr_criteria, 0, sizeof(addr_criteria)); + addr_criteria.ai_family = AF_UNSPEC; + addr_criteria.ai_socktype = SOCK_DGRAM; + addr_criteria.ai_protocol = IPPROTO_UDP; + addr_criteria.ai_flags |= AI_NUMERICHOST; + + snprintf(service, sizeof(service), "%d", port); + getaddrinfo(host, service, &addr_criteria, &mcast_addr); + + + memset(&handle->recv_addr6, 0, sizeof(handle->recv_addr6)); + handle->recv_addr6.sin6_family = AF_INET6; + handle->recv_addr6.sin6_port = htons(port); + inet_pton(AF_INET6, "::0", &(handle->recv_addr6.sin6_addr)); + + memcpy(&mreq.ipv6mr_multiaddr, &((struct sockaddr_in6 *)mcast_addr->ai_addr)->sin6_addr, sizeof(struct in6_addr)); + + mreq.ipv6mr_interface = 0; + setsockopt(handle->sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); + + if (bind(handle->sock, (struct sockaddr *) &handle->recv_addr6, sizeof(handle->recv_addr6)) < 0) { + printf("FUCK (%s) %s\n", host, strerror(errno)); + close(handle->sock); + handle->sock = -1; + return -1; + } } - - if (bind(handle->sock, (struct sockaddr *) &handle->recv_addr, sizeof(handle->recv_addr)) < 0) { - close(handle->sock); - handle->sock = -1; - return -1; - } - - } handle->ttl = 1; @@ -155,7 +201,11 @@ ssize_t mcast_socket_send(mcast_handle_t *handle, void *data, size_t datalen) datalen = sizeof(handle->buffer); } - return sendto(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->send_addr, sizeof(handle->send_addr)); + if (handle->family == AF_INET6) { + return sendto(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->send_addr6, sizeof(handle->send_addr6)); + } else { + return sendto(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->send_addr, sizeof(handle->send_addr)); + } } ssize_t mcast_socket_recv(mcast_handle_t *handle, void *data, size_t datalen, int ms) @@ -175,6 +225,9 @@ ssize_t mcast_socket_recv(mcast_handle_t *handle, void *data, size_t datalen, in } } - - return recvfrom(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->recv_addr, &addrlen); + if (handle->family == AF_INET6) { + return recvfrom(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->recv_addr6, &addrlen); + } else { + return recvfrom(handle->sock, data, datalen, 0, (struct sockaddr *) &handle->recv_addr, &addrlen); + } } diff --git a/src/mod/endpoints/mod_verto/mcast/mcast.h b/src/mod/endpoints/mod_verto/mcast/mcast.h index 915f803fe8..bc9114abce 100644 --- a/src/mod/endpoints/mod_verto/mcast/mcast.h +++ b/src/mod/endpoints/mod_verto/mcast/mcast.h @@ -71,6 +71,9 @@ typedef struct { unsigned char ttl; struct sockaddr_in send_addr; struct sockaddr_in recv_addr; + struct sockaddr_in6 send_addr6; + struct sockaddr_in6 recv_addr6; + int family; unsigned char buffer[65536]; int ready; } mcast_handle_t; diff --git a/src/mod/endpoints/mod_verto/mod_verto.c b/src/mod/endpoints/mod_verto/mod_verto.c index 1d422a53ad..57faa8e38a 100644 --- a/src/mod/endpoints/mod_verto/mod_verto.c +++ b/src/mod/endpoints/mod_verto/mod_verto.c @@ -1803,12 +1803,6 @@ error: static void client_run(jsock_t *jsock) { - - jsock->local_addr.sin_family = AF_INET; - jsock->local_addr.sin_addr.s_addr = htonl(INADDR_ANY); - jsock->local_addr.sin_port = 0; - - if (ws_init(&jsock->ws, jsock->client_socket, (jsock->ptype & PTYPE_CLIENT_SSL) ? jsock->profile->ssl_ctx : NULL, 0, 1, !!jsock->profile->vhosts) < 0) { if (jsock->profile->vhosts) { http_run(jsock); @@ -2259,10 +2253,30 @@ static void verto_set_media_options(verto_pvt_t *tech_pvt, verto_profile_t *prof { uint32_t i; - tech_pvt->mparams->rtpip = switch_core_session_strdup(tech_pvt->session, profile->rtpip[profile->rtpip_cur++]); + if (!zstr(profile->rtpip[profile->rtpip_cur])) { + tech_pvt->mparams->rtpip4 = switch_core_session_strdup(tech_pvt->session, profile->rtpip[profile->rtpip_cur++]); + tech_pvt->mparams->rtpip = tech_pvt->mparams->rtpip4; + if (profile->rtpip_cur == profile->rtpip_index) { + profile->rtpip_cur = 0; + } + } - if (profile->rtpip_cur == profile->rtpip_index) { - profile->rtpip_cur = 0; + if (!zstr(profile->rtpip6[profile->rtpip_cur6])) { + tech_pvt->mparams->rtpip6 = switch_core_session_strdup(tech_pvt->session, profile->rtpip6[profile->rtpip_cur6++]); + + if (zstr(tech_pvt->mparams->rtpip)) { + tech_pvt->mparams->rtpip = tech_pvt->mparams->rtpip6; + } + + if (profile->rtpip_cur6 == profile->rtpip_index6) { + profile->rtpip_cur6 = 0; + } + } + + if (zstr(tech_pvt->mparams->rtpip)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "%s has no media ip, check your configuration\n", + switch_channel_get_name(tech_pvt->channel)); + switch_channel_hangup(tech_pvt->channel, SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL); } tech_pvt->mparams->extrtpip = tech_pvt->mparams->extsipip = profile->extrtpip; @@ -3376,7 +3390,7 @@ static switch_bool_t verto__invite_func(const char *method, cJSON *params, jsock switch_either(jsock->dialplan, jsock->profile->dialplan), caller_id_name, caller_id_number, - inet_ntoa(jsock->remote_addr.sin_addr), + jsock->remote_host, cJSON_GetObjectCstr(dialog, "ani"), cJSON_GetObjectCstr(dialog, "aniii"), cJSON_GetObjectCstr(dialog, "rdnis"), @@ -3778,7 +3792,7 @@ static void jrpc_init(void) -static int start_jsock(verto_profile_t *profile, ws_socket_t sock) +static int start_jsock(verto_profile_t *profile, ws_socket_t sock, int family) { jsock_t *jsock = NULL; int flag = 1; @@ -3798,11 +3812,20 @@ static int start_jsock(verto_profile_t *profile, ws_socket_t sock) jsock = (jsock_t *) switch_core_alloc(pool, sizeof(*jsock)); jsock->pool = pool; + jsock->family = family; - len = sizeof(jsock->remote_addr); + if (family == PF_INET) { + len = sizeof(jsock->remote_addr); - if ((jsock->client_socket = accept(sock, (struct sockaddr *) &jsock->remote_addr, &len)) < 0) { - die("ACCEPT FAILED\n"); + if ((jsock->client_socket = accept(sock, (struct sockaddr *) &jsock->remote_addr, &len)) < 0) { + die("ACCEPT FAILED\n"); + } + } else { + len = sizeof(jsock->remote_addr6); + + if ((jsock->client_socket = accept(sock, (struct sockaddr *) &jsock->remote_addr6, &len)) < 0) { + die("ACCEPT FAILED\n"); + } } for (i = 0; i < profile->i; i++) { @@ -3818,7 +3841,15 @@ static int start_jsock(verto_profile_t *profile, ws_socket_t sock) jsock->profile = profile; if (zstr(jsock->name)) { - jsock->name = switch_core_sprintf(pool, "%s:%d", inet_ntoa(jsock->remote_addr.sin_addr), ntohs(jsock->remote_addr.sin_port)); + if (family == PF_INET) { + jsock->remote_port = ntohs(jsock->remote_addr.sin_port); + inet_ntop(AF_INET, &jsock->remote_addr.sin_addr, jsock->remote_host, sizeof(jsock->remote_host)); + jsock->name = switch_core_sprintf(pool, "%s:%d", jsock->remote_host, jsock->remote_port); + } else { + jsock->remote_port = ntohs(jsock->remote_addr6.sin6_port); + inet_ntop(AF_INET6, &jsock->remote_addr6.sin6_addr, jsock->remote_host, sizeof(jsock->remote_host)); + jsock->name = switch_core_sprintf(pool, "%s:%d", jsock->remote_host, jsock->remote_port); + } } jsock->ptype = ptype; @@ -3826,7 +3857,7 @@ static int start_jsock(verto_profile_t *profile, ws_socket_t sock) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s Client Connect.\n", jsock->name); if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_CLIENT_CONNECT) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "verto_profile_name", profile->name); - switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "verto_client_address", "%s:%d", inet_ntoa(jsock->remote_addr.sin_addr), ntohs(jsock->remote_addr.sin_port)); + switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "verto_client_address", "%s:%d", jsock->remote_host, jsock->remote_port); switch_event_fire(&s_event); } @@ -3873,7 +3904,7 @@ static int start_jsock(verto_profile_t *profile, ws_socket_t sock) return -1; } -static ws_socket_t prepare_socket(int ip, uint16_t port) +static ws_socket_t prepare_socket(ips_t *ips) { ws_socket_t sock = ws_sock_invalid; #ifndef WIN32 @@ -3881,29 +3912,48 @@ static ws_socket_t prepare_socket(int ip, uint16_t port) #else char reuse_addr = 1; #endif + int family; struct sockaddr_in addr; + struct sockaddr_in6 addr6; - if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + if (strchr(ips->local_ip, ':')) { + family = PF_INET6; + } else { + family = PF_INET; + } + + if ((sock = socket(family, SOCK_STREAM, IPPROTO_TCP)) < 0) { die("Socket Error!\n"); } if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr)) < 0 ) { die("Socket setsockopt Error!\n"); } - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = ip; - addr.sin_port = htons(port); - - if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - die("Bind Error!\n"); - } + if (family == PF_INET) { + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr(ips->local_ip); + addr.sin_port = htons(ips->local_port); + if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + die("Bind Error!\n"); + } + } else { + memset(&addr6, 0, sizeof(addr6)); + addr6.sin6_family = AF_INET6; + addr6.sin6_port = htons(ips->local_port); + inet_pton(AF_INET6, ips->local_ip, &(addr6.sin6_addr)); + if (bind(sock, (struct sockaddr *) &addr6, sizeof(addr6)) < 0) { + die("Bind Error!\n"); + } + } + if (listen(sock, MAXPENDING) < 0) { die("Listen error\n"); } + ips->family = family; + return sock; error: @@ -3979,7 +4029,7 @@ static int profile_one_loop(verto_profile_t *profile) if (profile->mcast_ip && pfds[x].sock == (switch_os_socket_t)profile->mcast_sub.sock) { handle_mcast_sub(profile); } else { - start_jsock(profile, pfds[x].sock); + start_jsock(profile, pfds[x].sock, profile->ip[x].family); } } } @@ -3991,52 +4041,6 @@ static int profile_one_loop(verto_profile_t *profile) } -static int runtime(verto_profile_t *profile) -{ - int i; - - for (i = 0; i < profile->i; i++) { - if ((profile->server_socket[i] = prepare_socket(profile->ip[i].local_ip_addr, profile->ip[i].local_port)) < 0) { - die("Client Socket Error!\n"); - } - } - - if (profile->mcast_ip) { - if (mcast_socket_create(profile->mcast_ip, profile->mcast_port, &profile->mcast_sub, MCAST_RECV | MCAST_TTL_HOST) < 0) { - die("mcast recv socket create"); - } - - if (mcast_socket_create(profile->mcast_ip, profile->mcast_port + 1, &profile->mcast_pub, MCAST_SEND | MCAST_TTL_HOST) > 0) { - mcast_socket_close(&profile->mcast_sub); - die("mcast send socket create"); - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MCAST Bound to %s:%d/%d\n", profile->mcast_ip, profile->mcast_port, profile->mcast_port + 1); - } - - - while(profile->running) { - if (profile_one_loop(profile) < 0) { - goto error; - } - } - - if (profile->mcast_sub.sock > -1) { - mcast_socket_close(&profile->mcast_sub); - } - - if (profile->mcast_pub.sock > -1) { - mcast_socket_close(&profile->mcast_pub); - } - - return 0; - - error: - - return -1; - -} - static void kill_profile(verto_profile_t *profile) { jsock_t *p; @@ -4092,6 +4096,58 @@ static void kill_profiles(void) } +static int runtime(verto_profile_t *profile) +{ + int i; + int r = 0; + + for (i = 0; i < profile->i; i++) { + //if ((profile->server_socket[i] = prepare_socket(profile->ip[i].local_ip_addr, profile->ip[i].local_port)) < 0) { + if ((profile->server_socket[i] = prepare_socket(&profile->ip[i])) < 0) { + die("Client Socket Error!\n"); + } + } + + if (profile->mcast_ip) { + if (mcast_socket_create(profile->mcast_ip, profile->mcast_port, &profile->mcast_sub, MCAST_RECV | MCAST_TTL_HOST) < 0) { + r = -1; + die("mcast recv socket create\n"); + } + + if (mcast_socket_create(profile->mcast_ip, profile->mcast_port + 1, &profile->mcast_pub, MCAST_SEND | MCAST_TTL_HOST) > 0) { + mcast_socket_close(&profile->mcast_sub); + r = -1; + die("mcast send socket create\n"); + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MCAST Bound to %s:%d/%d\n", profile->mcast_ip, profile->mcast_port, profile->mcast_port + 1); + } + + + while(profile->running) { + if (profile_one_loop(profile) < 0) { + goto error; + } + } + + error: + + if (profile->mcast_sub.sock > -1) { + mcast_socket_close(&profile->mcast_sub); + } + + if (profile->mcast_pub.sock > -1) { + mcast_socket_close(&profile->mcast_pub); + } + + if (r) { + kill_profile(profile); + } + + return r; + +} + static void do_shutdown(void) { globals.running = 0; @@ -4105,20 +4161,35 @@ static void do_shutdown(void) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Done\n"); } -static void parse_ip(char *host, uint16_t *port, in_addr_t *addr, char *input) + +static void parse_ip(char *host, switch_size_t host_len, uint16_t *port, char *input) { char *p; - struct hostent *hent; + //struct hostent *hent; - strncpy(host, input, 255); - - host[255] = 0; - - if ((p = strchr(host, ':')) != NULL) { - *p++ = '\0'; - *port = (uint16_t)atoi(p); + if ((p = strchr(input, '['))) { + char *end = switch_find_end_paren(p, '[', ']'); + if (end) { + p++; + strncpy(host, p, end - p); + if (*(end+1) == ':' && end + 2 < end_of_p(input)) { + end += 2; + if (end) { + *port = (uint16_t)atoi(end); + } + } + } else { + strncpy(host, "::", host_len); + } + } else { + strncpy(host, input, host_len); + if ((p = strrchr(host, ':')) != NULL) { + *p++ = '\0'; + *port = (uint16_t)atoi(p); + } } +#if 0 if ( host[0] < '0' || host[0] > '9' ) { // Non-numeric host (at least it doesn't start with one). Convert it to ip addr first if ((hent = gethostbyname(host)) != NULL) { @@ -4130,8 +4201,10 @@ static void parse_ip(char *host, uint16_t *port, in_addr_t *addr, char *input) } else { *addr = inet_addr(host); } +#endif } + static verto_profile_t *find_profile(const char *name) { verto_profile_t *p, *r = NULL; @@ -4264,7 +4337,7 @@ static switch_status_t parse_config(const char *cf) if (!strcasecmp(var, "bind-local")) { const char *secure = switch_xml_attr_soft(param, "secure"); if (i < MAX_BIND) { - parse_ip(profile->ip[profile->i].local_ip, &profile->ip[profile->i].local_port, &profile->ip[profile->i].local_ip_addr, val); + parse_ip(profile->ip[profile->i].local_ip, sizeof(profile->ip[profile->i].local_ip), &profile->ip[profile->i].local_port, val); if (switch_true(secure)) { profile->ip[profile->i].secure = 1; } @@ -4316,10 +4389,18 @@ static switch_status_t parse_config(const char *cf) if (zstr(val)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid RTP IP.\n"); } else { - if (profile->rtpip_index < MAX_RTPIP -1) { - profile->rtpip[profile->rtpip_index++] = switch_core_strdup(profile->pool, val); + if (strchr(val, ':')) { + if (profile->rtpip_index6 < MAX_RTPIP -1) { + profile->rtpip6[profile->rtpip_index6++] = switch_core_strdup(profile->pool, val); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Too many RTP IP.\n"); + } } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Too many RTP IP.\n"); + if (profile->rtpip_index < MAX_RTPIP -1) { + profile->rtpip[profile->rtpip_index++] = switch_core_strdup(profile->pool, val); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Too many RTP IP.\n"); + } } } } else if (!strcasecmp(var, "ext-rtp-ip")) { diff --git a/src/mod/endpoints/mod_verto/mod_verto.h b/src/mod/endpoints/mod_verto/mod_verto.h index 11614926a6..eccd095369 100644 --- a/src/mod/endpoints/mod_verto/mod_verto.h +++ b/src/mod/endpoints/mod_verto/mod_verto.h @@ -106,9 +106,8 @@ struct jsock_s { unsigned char buf[65535]; char *name; jsock_type_t ptype; - struct sockaddr_in local_addr; struct sockaddr_in remote_addr; - struct sockaddr_in send_addr; + struct sockaddr_in6 remote_addr6; #ifndef WIN32 struct passwd pw; #endif @@ -132,6 +131,11 @@ struct jsock_s { char *dialplan; char *context; + + char remote_host[256]; + int remote_port; + int family; + struct verto_profile_s *profile; switch_thread_rwlock_t *rwlock; @@ -155,12 +159,12 @@ typedef struct jsock_s jsock_t; #define MAX_BIND 25 #define MAX_RTPIP 25 -struct ips { +typedef struct ips { char local_ip[256]; - in_addr_t local_ip_addr; uint16_t local_port; int secure; -}; + int family; +} ips_t; typedef enum { TFLAG_SENT_MEDIA = (1 << 0), @@ -240,6 +244,10 @@ struct verto_profile_s { int rtpip_index; int rtpip_cur; + char *rtpip6[MAX_RTPIP]; + int rtpip_index6; + int rtpip_cur6; + char *cand_acl[SWITCH_MAX_CAND_ACL]; uint32_t cand_acl_count; diff --git a/src/mod/endpoints/mod_verto/ws.c b/src/mod/endpoints/mod_verto/ws.c index 8a46b65502..6e9a69d025 100644 --- a/src/mod/endpoints/mod_verto/ws.c +++ b/src/mod/endpoints/mod_verto/ws.c @@ -691,6 +691,7 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data) ssize_t need = 2; char *maskp; int ll = 0; + int frag = 0; again: need = 2; @@ -741,8 +742,16 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data) case WSOC_PING: case WSOC_PONG: { - //int fin = (wsh->buffer[0] >> 7) & 1; + int fin = (wsh->buffer[0] >> 7) & 1; int mask = (wsh->buffer[1] >> 7) & 1; + + if (fin) { + if (*oc == WSOC_CONTINUATION) { + frag = 1; + } else { + frag = 0; + } + } if (mask) { need += 4; @@ -837,6 +846,10 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data) ws_write_frame(wsh, WSOC_PONG, wsh->payload, wsh->rplen); goto again; } + + if (frag) { + goto again; + } *(wsh->payload+wsh->rplen) = '\0'; diff --git a/src/switch_core.c b/src/switch_core.c index 753dfa5a26..5ed8ad83a1 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1331,7 +1331,12 @@ SWITCH_DECLARE(switch_bool_t) switch_check_network_list_ip_token(const char *ip_ free(list_name_dup); } else { switch_parse_cidr(list_name, &net, &mask, &bits); - ok = switch_test_subnet(ip.v4, net.v4, mask.v4); + + if (ipv6) { + ok = switch_testv6_subnet(ip, net, mask); + } else { + ok = switch_test_subnet(ip.v4, net.v4, mask.v4); + } } } switch_mutex_unlock(runtime.global_mutex); @@ -1395,6 +1400,26 @@ SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload) switch_network_list_add_cidr(rfc_list, "fe80::/10", SWITCH_FALSE); switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); + tmp_name = "wan_v6.auto"; + switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name); + switch_network_list_add_cidr(rfc_list, "0.0.0.0/0", SWITCH_FALSE); + switch_network_list_add_cidr(rfc_list, "fe80::/10", SWITCH_FALSE); + switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); + + + tmp_name = "wan_v4.auto"; + switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name); + switch_network_list_add_cidr(rfc_list, "0.0.0.0/8", SWITCH_FALSE); + switch_network_list_add_cidr(rfc_list, "10.0.0.0/8", SWITCH_FALSE); + switch_network_list_add_cidr(rfc_list, "172.16.0.0/12", SWITCH_FALSE); + switch_network_list_add_cidr(rfc_list, "192.168.0.0/16", SWITCH_FALSE); + switch_network_list_add_cidr(rfc_list, "169.254.0.0/16", SWITCH_FALSE); + switch_network_list_add_cidr(rfc_list, "::/0", SWITCH_FALSE); + switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); + + tmp_name = "nat.auto"; switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); diff --git a/src/switch_core_media.c b/src/switch_core_media.c index 7a469575d4..d20af51290 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -2885,6 +2885,8 @@ static void clear_ice(switch_core_session_t *session, switch_media_type_t type) engine->ice_in.chosen[0] = 0; engine->ice_in.chosen[1] = 0; + engine->ice_in.is_chosen[0] = 0; + engine->ice_in.is_chosen[1] = 0; engine->ice_in.cand_idx = 0; memset(&engine->ice_in, 0, sizeof(engine->ice_in)); engine->remote_rtcp_port = 0; @@ -3047,6 +3049,52 @@ SWITCH_DECLARE(switch_call_direction_t) switch_ice_direction(switch_core_session return r; } +//? +static switch_status_t ip_choose_family(switch_media_handle_t *smh, const char *ip) +{ + switch_status_t status = SWITCH_STATUS_FALSE; + + if (zstr(ip)) { + return status; + } + + if (strchr(ip, ':')) { + if (!zstr(smh->mparams->rtpip6)) { + smh->mparams->rtpip = smh->mparams->rtpip6; + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s choosing family v6\n", + switch_channel_get_name(smh->session->channel)); + status = SWITCH_STATUS_SUCCESS; + } + } else { + if (!zstr(smh->mparams->rtpip4)) { + smh->mparams->rtpip = smh->mparams->rtpip4; + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s choosing family v4\n", + switch_channel_get_name(smh->session->channel)); + status = SWITCH_STATUS_SUCCESS; + } + } + + return status; +} + +//? +static switch_bool_t ip_possible(switch_media_handle_t *smh, const char *ip) +{ + switch_bool_t r = SWITCH_FALSE; + + if (zstr(ip)) { + return r; + } + + if (strchr(ip, ':')) { + r = (switch_bool_t) !zstr(smh->mparams->rtpip6); + } else { + r = (switch_bool_t) !zstr(smh->mparams->rtpip4); + } + + return r; +} + //? static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_session_t *sdp, sdp_media_t *m) { @@ -3055,12 +3103,14 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ int i = 0, got_rtcp_mux = 0; const char *val; - if (engine->ice_in.chosen[0] && engine->ice_in.chosen[1] && !switch_channel_test_flag(smh->session->channel, CF_REINVITE)) { + if (engine->ice_in.is_chosen[0] && engine->ice_in.is_chosen[1] && !switch_channel_test_flag(smh->session->channel, CF_REINVITE)) { return; } engine->ice_in.chosen[0] = 0; engine->ice_in.chosen[1] = 0; + engine->ice_in.is_chosen[0] = 0; + engine->ice_in.is_chosen[1] = 0; engine->ice_in.cand_idx = 0; if (m) { @@ -3074,6 +3124,7 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ char *fields[15]; int argc = 0, j = 0; int cid = 0; + int pass_acl = 0; if (zstr(attr->a_name)) { continue; @@ -3150,55 +3201,61 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Checking Candidate cid: %d proto: %s type: %s addr: %s:%s\n", cid+1, fields[2], fields[7], fields[4], fields[5]); - - - engine->ice_in.cand_idx++; + + pass_acl = 0; for (i = 0; i < engine->cand_acl_count; i++) { - if (!engine->ice_in.chosen[cid] && !strchr(fields[4], ':') && switch_check_network_list_ip(fields[4], engine->cand_acl[i])) { - engine->ice_in.chosen[cid] = engine->ice_in.cand_idx; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, - "Choose %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n", - type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio", - cid+1, fields[2], fields[7], fields[4], fields[5]); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, - "Save %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n", - type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio", - cid+1, fields[2], fields[7], fields[4], fields[5]); + if (switch_check_network_list_ip(fields[4], engine->cand_acl[i])) { + pass_acl = 1; + break; } - - engine->ice_in.cands[engine->ice_in.cand_idx][cid].foundation = switch_core_session_strdup(smh->session, fields[0]); - engine->ice_in.cands[engine->ice_in.cand_idx][cid].component_id = atoi(fields[1]); - engine->ice_in.cands[engine->ice_in.cand_idx][cid].transport = switch_core_session_strdup(smh->session, fields[2]); - engine->ice_in.cands[engine->ice_in.cand_idx][cid].priority = atol(fields[3]); - engine->ice_in.cands[engine->ice_in.cand_idx][cid].con_addr = switch_core_session_strdup(smh->session, fields[4]); - engine->ice_in.cands[engine->ice_in.cand_idx][cid].con_port = (switch_port_t)atoi(fields[5]); - - - j = 6; - - while(j < argc && fields[j+1]) { - if (!strcasecmp(fields[j], "typ")) { - engine->ice_in.cands[engine->ice_in.cand_idx][cid].cand_type = switch_core_session_strdup(smh->session, fields[j+1]); - } else if (!strcasecmp(fields[j], "raddr")) { - engine->ice_in.cands[engine->ice_in.cand_idx][cid].raddr = switch_core_session_strdup(smh->session, fields[j+1]); - } else if (!strcasecmp(fields[j], "rport")) { - engine->ice_in.cands[engine->ice_in.cand_idx][cid].rport = (switch_port_t)atoi(fields[j+1]); - } else if (!strcasecmp(fields[j], "generation")) { - engine->ice_in.cands[engine->ice_in.cand_idx][cid].generation = switch_core_session_strdup(smh->session, fields[j+1]); - } - - j += 2; - } - - - if (engine->ice_in.chosen[cid]) { - engine->ice_in.cands[engine->ice_in.chosen[cid]][cid].ready++; - } - - break; } + + if (!engine->ice_in.is_chosen[cid] && ip_possible(smh, fields[4]) && pass_acl) { + engine->ice_in.chosen[cid] = engine->ice_in.cand_idx; + engine->ice_in.is_chosen[cid] = 1; + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, + "Choose %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n", + type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio", + cid+1, fields[2], fields[7], fields[4], fields[5]); + ip_choose_family(smh, fields[4]); + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, + "Save %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n", + type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio", + cid+1, fields[2], fields[7], fields[4], fields[5]); + } + + engine->ice_in.cands[engine->ice_in.cand_idx][cid].foundation = switch_core_session_strdup(smh->session, fields[0]); + engine->ice_in.cands[engine->ice_in.cand_idx][cid].component_id = atoi(fields[1]); + engine->ice_in.cands[engine->ice_in.cand_idx][cid].transport = switch_core_session_strdup(smh->session, fields[2]); + engine->ice_in.cands[engine->ice_in.cand_idx][cid].priority = atol(fields[3]); + engine->ice_in.cands[engine->ice_in.cand_idx][cid].con_addr = switch_core_session_strdup(smh->session, fields[4]); + engine->ice_in.cands[engine->ice_in.cand_idx][cid].con_port = (switch_port_t)atoi(fields[5]); + + j = 6; + + while(j < argc && fields[j+1]) { + if (!strcasecmp(fields[j], "typ")) { + engine->ice_in.cands[engine->ice_in.cand_idx][cid].cand_type = switch_core_session_strdup(smh->session, fields[j+1]); + } else if (!strcasecmp(fields[j], "raddr")) { + engine->ice_in.cands[engine->ice_in.cand_idx][cid].raddr = switch_core_session_strdup(smh->session, fields[j+1]); + } else if (!strcasecmp(fields[j], "rport")) { + engine->ice_in.cands[engine->ice_in.cand_idx][cid].rport = (switch_port_t)atoi(fields[j+1]); + } else if (!strcasecmp(fields[j], "generation")) { + engine->ice_in.cands[engine->ice_in.cand_idx][cid].generation = switch_core_session_strdup(smh->session, fields[j+1]); + } + + j += 2; + } + + + if (engine->ice_in.is_chosen[cid]) { + engine->ice_in.cands[engine->ice_in.chosen[cid]][cid].ready++; + } + + engine->ice_in.cand_idx++; } } @@ -3206,18 +3263,23 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ /* still no candidates, so start searching for some based on sane deduction */ /* look for candidates on the same network */ - if (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]) { - for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]); i++) { - if (!engine->ice_in.chosen[0] && engine->ice_in.cands[i][0].component_id == 1 && - !engine->ice_in.cands[i][0].rport && switch_check_network_list_ip(engine->ice_in.cands[i][0].con_addr, "localnet.auto")) { + if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) { + for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]); i++) { + if (!engine->ice_in.is_chosen[0] && engine->ice_in.cands[i][0].component_id == 1 && + !engine->ice_in.cands[i][0].rport && ip_possible(smh, engine->ice_in.cands[i][0].con_addr) && + switch_check_network_list_ip(engine->ice_in.cands[i][0].con_addr, "localnet.auto")) { engine->ice_in.chosen[0] = i; + engine->ice_in.is_chosen[0] = 1; engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++; + ip_choose_family(smh, engine->ice_in.cands[i][0].con_addr); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, "No %s RTP candidate found; defaulting to the first local one.\n", type2str(type)); } - if (!engine->ice_in.chosen[1] && engine->ice_in.cands[i][1].component_id == 2 && - !engine->ice_in.cands[i][1].rport && switch_check_network_list_ip(engine->ice_in.cands[i][1].con_addr, "localnet.auto")) { + if (!engine->ice_in.is_chosen[1] && engine->ice_in.cands[i][1].component_id == 2 && + !engine->ice_in.cands[i][1].rport && ip_possible(smh, engine->ice_in.cands[i][1].con_addr) && + switch_check_network_list_ip(engine->ice_in.cands[i][1].con_addr, "localnet.auto")) { engine->ice_in.chosen[1] = i; + engine->ice_in.is_chosen[1] = 1; engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session),SWITCH_LOG_NOTICE, "No %s RTCP candidate found; defaulting to the first local one.\n", type2str(type)); @@ -3226,16 +3288,21 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ } /* look for candidates with srflx */ - if (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]) { - for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]); i++) { - if (!engine->ice_in.chosen[0] && engine->ice_in.cands[i][0].component_id == 1 && engine->ice_in.cands[i][0].rport) { + if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) { + for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]); i++) { + if (!engine->ice_in.is_chosen[0] && + engine->ice_in.cands[i][0].component_id == 1 && engine->ice_in.cands[i][0].rport && ip_possible(smh, engine->ice_in.cands[i][0].con_addr)) { engine->ice_in.chosen[0] = i; + engine->ice_in.chosen[1] = 1; engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++; + ip_choose_family(smh, engine->ice_in.cands[i][0].con_addr); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, "No %s RTP candidate found; defaulting to the first srflx one.\n", type2str(type)); } - if (!engine->ice_in.chosen[1] && engine->ice_in.cands[i][1].component_id == 2 && engine->ice_in.cands[i][1].rport) { + if (!engine->ice_in.is_chosen[1] && engine->ice_in.cands[i][1].component_id == 2 && engine->ice_in.cands[i][1].rport && + ip_possible(smh, engine->ice_in.cands[i][1].con_addr)) { engine->ice_in.chosen[1] = i; + engine->ice_in.is_chosen[1] = 1; engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session),SWITCH_LOG_NOTICE, "No %s RTCP candidate found; defaulting to the first srflx one.\n", type2str(type)); @@ -3244,8 +3311,9 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ } /* Got RTP but not RTCP, probably mux */ - if (engine->ice_in.chosen[0] && !engine->ice_in.chosen[1] && got_rtcp_mux) { + if (engine->ice_in.is_chosen[0] && !engine->ice_in.is_chosen[1] && got_rtcp_mux) { engine->ice_in.chosen[1] = engine->ice_in.chosen[0]; + engine->ice_in.is_chosen[1] = 1; memcpy(&engine->ice_in.cands[engine->ice_in.chosen[1]][1], &engine->ice_in.cands[engine->ice_in.chosen[0]][0], sizeof(engine->ice_in.cands[engine->ice_in.chosen[0]][0])); @@ -3257,16 +3325,19 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ } /* look for any candidates and hope for auto-adjust */ - if (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]) { - for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.chosen[0] || !engine->ice_in.chosen[1]); i++) { - if (!engine->ice_in.chosen[0] && engine->ice_in.cands[i][0].component_id == 1) { + if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) { + for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]); i++) { + if (!engine->ice_in.is_chosen[0] && engine->ice_in.cands[i][0].component_id == 1 && ip_possible(smh, engine->ice_in.cands[i][0].con_addr)) { engine->ice_in.chosen[0] = i; + engine->ice_in.is_chosen[0] = 1; engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++; + ip_choose_family(smh, engine->ice_in.cands[i][0].con_addr); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, "No %s RTP candidate found; defaulting to the first one.\n", type2str(type)); } - if (!engine->ice_in.chosen[1] && engine->ice_in.cands[i][1].component_id == 2) { + if (!engine->ice_in.is_chosen[1] && engine->ice_in.cands[i][1].component_id == 2) { engine->ice_in.chosen[1] = i; + engine->ice_in.is_chosen[1] = 1; engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, "No %s RTCP candidate found; defaulting to the first one.\n", type2str(type)); @@ -3274,6 +3345,13 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ } } + if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) { + /* PUNT */ + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s no suitable candidates found.\n", + switch_channel_get_name(smh->session->channel)); + return; + } + for (i = 0; i < 2; i++) { if (engine->ice_in.cands[engine->ice_in.chosen[i]][i].ready) { if (zstr(engine->ice_in.ufrag) || zstr(engine->ice_in.pwd)) { @@ -5476,6 +5554,20 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_choose_port(switch_core_sessio SWITCH_DECLARE(switch_status_t) switch_core_media_choose_ports(switch_core_session_t *session, switch_bool_t audio, switch_bool_t video) { switch_status_t status = SWITCH_STATUS_SUCCESS; + switch_media_handle_t *smh; + + if (!(smh = session->media_handle)) { + return SWITCH_STATUS_FALSE; + } + + if (zstr(smh->mparams->rtpip)) { + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s has no media ip\n", + switch_channel_get_name(smh->session->channel)); + switch_channel_hangup(smh->session->channel, SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL); + + return SWITCH_STATUS_FALSE; + } if (audio && (status = switch_core_media_choose_port(session, SWITCH_MEDIA_TYPE_AUDIO, 0)) == SWITCH_STATUS_SUCCESS) { if (video) { @@ -6316,7 +6408,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%sVIDEO RTP [%s] %s:%d->%s:%d codec: %u ms: %d [%s]\n", switch_channel_test_flag(session->channel, CF_PROXY_MEDIA) ? "PROXY " : "", switch_channel_get_name(session->channel), - a_engine->cur_payload_map->remote_sdp_ip, + a_engine->local_sdp_ip, v_engine->local_sdp_port, v_engine->cur_payload_map->remote_sdp_ip, v_engine->cur_payload_map->remote_sdp_port, v_engine->cur_payload_map->agreed_pt, diff --git a/src/switch_utils.c b/src/switch_utils.c index e53c66d079..59b474045c 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -431,7 +431,8 @@ SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip6_token(switch_netw for (node = list->node_head; node; node = node->next) { if (node->family == AF_INET) continue; - if (node->bits > bits && switch_testv6_subnet(ip, node->ip, node->mask)) { + + if (node->bits >= bits && switch_testv6_subnet(ip, node->ip, node->mask)) { if (node->ok) { ok = SWITCH_TRUE; } else { @@ -457,7 +458,7 @@ SWITCH_DECLARE(switch_bool_t) switch_network_list_validate_ip_token(switch_netwo for (node = list->node_head; node; node = node->next) { if (node->family == AF_INET6) continue; /* want AF_INET */ - if (node->bits > bits && switch_test_subnet(ip, node->ip.v4, node->mask.v4)) { + if (node->bits >= bits && switch_test_subnet(ip, node->ip.v4, node->mask.v4)) { if (node->ok) { ok = SWITCH_TRUE; } else { From 69ea6a444adc8a9b5ff26201c0736c5560a01b06 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Mon, 1 Jun 2015 15:27:45 -0400 Subject: [PATCH 22/43] FS-7587: keep sofia-sip ws lib in sync --- libs/sofia-sip/libsofia-sip-ua/tport/ws.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/libs/sofia-sip/libsofia-sip-ua/tport/ws.c b/libs/sofia-sip/libsofia-sip-ua/tport/ws.c index 8a46b65502..6e9a69d025 100644 --- a/libs/sofia-sip/libsofia-sip-ua/tport/ws.c +++ b/libs/sofia-sip/libsofia-sip-ua/tport/ws.c @@ -691,6 +691,7 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data) ssize_t need = 2; char *maskp; int ll = 0; + int frag = 0; again: need = 2; @@ -741,8 +742,16 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data) case WSOC_PING: case WSOC_PONG: { - //int fin = (wsh->buffer[0] >> 7) & 1; + int fin = (wsh->buffer[0] >> 7) & 1; int mask = (wsh->buffer[1] >> 7) & 1; + + if (fin) { + if (*oc == WSOC_CONTINUATION) { + frag = 1; + } else { + frag = 0; + } + } if (mask) { need += 4; @@ -837,6 +846,10 @@ ssize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data) ws_write_frame(wsh, WSOC_PONG, wsh->payload, wsh->rplen); goto again; } + + if (frag) { + goto again; + } *(wsh->payload+wsh->rplen) = '\0'; From 651c312a7596e53e3c9464b61558b07f972b37f7 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Mon, 1 Jun 2015 15:28:33 -0400 Subject: [PATCH 23/43] FS-7499: fix build error on 32bit platforms --- src/switch_rtp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 07a407d6e8..3905e57cb6 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -5705,7 +5705,7 @@ static switch_status_t process_rtcp_packet(switch_rtp_t *rtp_session, switch_siz if (msg->header.version != 2 || !(msg->header.type > 199 && msg->header.type < 208)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_WARNING, - "INVALID RTCP PACKET TYPE %d VER %d LEN %ld\n", msg->header.type, + "INVALID RTCP PACKET TYPE %d VER %d LEN %" SWITCH_SIZE_T_FMT "\n", msg->header.type, msg->header.version, len); status = SWITCH_STATUS_BREAK; break; From 83923660577cac053deeac3b9901df45e0cf8487 Mon Sep 17 00:00:00 2001 From: doancea Date: Mon, 1 Jun 2015 18:22:45 +0200 Subject: [PATCH 24/43] Fixed encoded_data_len for MODE 2400, it should be 6 bytes. Also replaced 2550 bps bitrate (obsoleted operation mode) by 2400 --- src/mod/codecs/mod_codec2/mod_codec2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mod/codecs/mod_codec2/mod_codec2.c b/src/mod/codecs/mod_codec2/mod_codec2.c index bb70bf8c46..cee954499a 100644 --- a/src/mod/codecs/mod_codec2/mod_codec2.c +++ b/src/mod/codecs/mod_codec2/mod_codec2.c @@ -152,7 +152,7 @@ static switch_status_t switch_codec2_encode(switch_codec_t *codec, switch_codec_ fflush(context->encoder_out); #endif - *encoded_data_len = 8; + *encoded_data_len = 6; return SWITCH_STATUS_SUCCESS; } @@ -230,7 +230,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_codec2_load) *module_interface = switch_loadable_module_create_module_interface(pool, modname); - SWITCH_ADD_CODEC(codec_interface, "CODEC2 2550bps"); + SWITCH_ADD_CODEC(codec_interface, "CODEC2 2400bps"); switch_core_codec_add_implementation(pool, codec_interface, SWITCH_CODEC_TYPE_AUDIO, @@ -239,7 +239,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_codec2_load) NULL, 8000, /* samples/sec */ 8000, /* samples/sec */ - 2550, /* bps */ + 2400, /* bps */ 20000, /* ptime */ CODEC2_SAMPLES_PER_FRAME, /* samples decoded */ CODEC2_SAMPLES_PER_FRAME*2, /* bytes decoded */ From 69d4e1d53a7ad3393a66a025fcab762b3cc54333 Mon Sep 17 00:00:00 2001 From: William King Date: Mon, 1 Jun 2015 17:51:15 -0700 Subject: [PATCH 25/43] FS-7426 shouuld not be disabled on all, only squeeze and wheezy --- debian/bootstrap.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index b77589baf1..a4dc996f2c 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -30,7 +30,6 @@ avoid_mods=( endpoints/mod_opal endpoints/mod_reference endpoints/mod_unicall - event_handlers/mod_amqp sdk/autotools xml_int/mod_xml_ldap xml_int/mod_xml_radius From 3df55b9bb5325ed0f7273576264c5aa94a8a6810 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 15 Jan 2013 00:50:28 -0500 Subject: [PATCH 26/43] Add sip_watched_headers variable to launch events when a SIP message contains a given SIP header FS-6801 #resolve --- src/mod/endpoints/mod_sofia/mod_sofia.c | 18 +++++++ src/mod/endpoints/mod_sofia/mod_sofia.h | 2 + src/mod/endpoints/mod_sofia/sofia.c | 65 +++++++++++++++++++++++++ 3 files changed, 85 insertions(+) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 33f4e0f855..0971e66088 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -72,6 +72,7 @@ static switch_status_t sofia_kill_channel(switch_core_session_t *session, int si */ static switch_status_t sofia_on_init(switch_core_session_t *session) { + const char *hval = NULL; switch_channel_t *channel = switch_core_session_get_channel(session); private_object_t *tech_pvt = (private_object_t *) switch_core_session_get_private(session); switch_status_t status = SWITCH_STATUS_SUCCESS; @@ -89,6 +90,23 @@ static switch_status_t sofia_on_init(switch_core_session_t *session) switch_core_media_absorb_sdp(session); } + if ((hval = switch_channel_get_variable(channel, "sip_watch_headers"))) { + char *dupvar = NULL; + char *watch_headers[10]; + unsigned int numhdrs = 0; + int i = 0; + dupvar = switch_core_session_strdup(session, hval); + numhdrs = switch_separate_string(dupvar, ',', watch_headers, switch_arraylen(watch_headers)); + if (numhdrs) { + char **wheaders = switch_core_session_alloc(session, ((numhdrs+1) * sizeof(wheaders[0]))); + for (i = 0; i < numhdrs; i++) { + wheaders[i] = watch_headers[i]; + } + wheaders[i] = NULL; + tech_pvt->watch_headers = wheaders; + } + } + if (switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING) || switch_channel_test_flag(tech_pvt->channel, CF_RECOVERING_BRIDGE)) { sofia_set_flag(tech_pvt, TFLAG_RECOVERED); } diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 577ff07bbc..06a4c739bc 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -93,6 +93,7 @@ typedef struct private_object private_object_t; #define MY_EVENT_RECOVERY_RECOVERED "sofia::recovery_recovered" #define MY_EVENT_ERROR "sofia::error" #define MY_EVENT_PROFILE_START "sofia::profile_start" +#define MY_EVENT_NOTIFY_WATCHED_HEADER "sofia::notify_watched_header" #define MULTICAST_EVENT "multicast::event" #define SOFIA_REPLACES_HEADER "_sofia_replaces_" @@ -784,6 +785,7 @@ struct private_object { sofia_cid_type_t cid_type; uint32_t session_timeout; enum nua_session_refresher session_refresher; + char **watch_headers; char *respond_phrase; int respond_code; char *respond_dest; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index edc15cf69b..ef3d9381fa 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -1251,6 +1251,21 @@ static void tech_send_ack(nua_handle_t *nh, private_object_t *tech_pvt) } +static void notify_watched_header(switch_core_session_t *session, const char *msgline, const char *hdrname, const char *hdrval) +{ + switch_event_t *event = NULL; + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Found known watched header in message '%s', %s: %s\n", msgline, hdrname, hdrval); + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_NOTIFY_WATCHED_HEADER) == SWITCH_STATUS_SUCCESS) { + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "SIP-Message", msgline); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Header-Name", hdrname); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Header-Value", hdrval); + switch_channel_event_set_data(channel, event); + switch_event_fire(&event); + } else { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failed creating event of type %s!\n", MY_EVENT_NOTIFY_WATCHED_HEADER); + } +} //sofia_dispatch_event_t *de static void our_sofia_event_callback(nua_event_t event, @@ -1326,6 +1341,56 @@ static void our_sofia_event_callback(nua_event_t event, } } + if (session && tech_pvt && tech_pvt->watch_headers && sip) { + char msgline[512]; + int hi; + msg_header_t *h = NULL; + if (sip->sip_request) { + h = (msg_header_t *)sip->sip_request; + msg_header_field_e(msgline, sizeof(msgline), h, 0); + } else if (sip->sip_status) { + h = (msg_header_t *)sip->sip_status; + msg_header_field_e(msgline, sizeof(msgline), h, 0); + } + if (h) { + sip_unknown_t *un = NULL; + char buf[512]; + char *c = NULL; + + msgline[sizeof(msgline)-1] = '\0'; + c = strchr(msgline, '\r'); + if (c) { + *c = '\0'; + } + + /* Faster (ie hash-based) search here would be nice? ie, make watch_headers a hash? */ + + /* Search first in the valid headers */ + for (h = h->sh_succ; h; h = h->sh_succ) { + sip_header_t *sh = (sip_header_t *)h; + if (!sh->sh_class->hc_name) { + continue; + } + for (hi = 0; tech_pvt->watch_headers[hi]; hi++) { + if (!strcasecmp(tech_pvt->watch_headers[hi], sh->sh_class->hc_name)) { + msg_header_field_e(buf, sizeof(buf), h, 0); + buf[sizeof(buf)-1] = '\0'; + notify_watched_header(session, msgline, sh->sh_class->hc_name, buf); + } + } + } + + /* Search now in the unknown headers */ + for (un = sip->sip_unknown; un; un = un->un_next) { + for (hi = 0; tech_pvt->watch_headers[hi]; hi++) { + if (!strcasecmp(tech_pvt->watch_headers[hi], un->un_name)) { + notify_watched_header(session, msgline, un->un_name, un->un_value); + } + } + } + } + } + if (sofia_test_pflag(profile, PFLAG_AUTH_ALL) && tech_pvt && tech_pvt->key && sip && (event < nua_r_set_params || event > nua_r_authenticate)) { sip_authorization_t const *authorization = NULL; From 6bfa2992166f17e9c649edd6d037ad23334bbdd4 Mon Sep 17 00:00:00 2001 From: Seven Du Date: Tue, 2 Jun 2015 18:46:29 +0800 Subject: [PATCH 27/43] set affected_rows also for non-SELECT queries --- src/switch_pgsql.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/switch_pgsql.c b/src/switch_pgsql.c index 4d955f1f45..d51312e866 100644 --- a/src/switch_pgsql.c +++ b/src/switch_pgsql.c @@ -25,6 +25,7 @@ * * Anthony Minessale II * Eliot Gable + * Seven Du * * switch_pgsql.c -- PGSQL Driver * @@ -465,7 +466,17 @@ SWITCH_DECLARE(switch_pgsql_status_t) switch_pgsql_finish_results_real(const cha switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_ERROR, "Error executing query:\n%s\n", res->err); final_status = SWITCH_PGSQL_FAIL; } - if (!res) done = 1; + + if (!res) { + done = 1; + } else if (res->result) { + char *affected_rows = PQcmdTuples(res->result); + + if (!zstr(affected_rows)) { + handle->affected_rows = atoi(affected_rows); + } + } + switch_pgsql_free_result(&res); } while (!done); return final_status; From d04e1f03ff4fb2a80ea0aa98d78366936561f4c5 Mon Sep 17 00:00:00 2001 From: Chris Rienzo Date: Tue, 2 Jun 2015 10:48:57 -0400 Subject: [PATCH 28/43] FS-7564 #resolve #comment [mod_rayo] Added new algorithms for offering calls to clients. Two new params added to autoload_configs/rayo.conf.xml offer-algorithm all: offer to all clients (default and old behavior) first: offer to first client, fails over to next client in list random: offer to random client, fails over to next random client offer-timeout-ms 0: disable > 0 and < 120000: time to wait for reply from offer. On timeout, next client is offered call. If no other clients available, call is rejected. 5000 is default. --- conf/rayo/autoload_configs/rayo.conf.xml | 5 + .../conf/autoload_configs/rayo.conf.xml | 5 + src/mod/event_handlers/mod_rayo/mod_rayo.c | 234 ++++++++++++++++-- 3 files changed, 228 insertions(+), 16 deletions(-) diff --git a/conf/rayo/autoload_configs/rayo.conf.xml b/conf/rayo/autoload_configs/rayo.conf.xml index 54aa388675..2ebcdbcffd 100644 --- a/conf/rayo/autoload_configs/rayo.conf.xml +++ b/conf/rayo/autoload_configs/rayo.conf.xml @@ -8,6 +8,11 @@ + + + + diff --git a/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml b/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml index 54aa388675..2ebcdbcffd 100644 --- a/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml +++ b/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml @@ -8,6 +8,11 @@ + + + + diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.c b/src/mod/event_handlers/mod_rayo/mod_rayo.c index aa213ff168..28d7ae1013 100644 --- a/src/mod/event_handlers/mod_rayo/mod_rayo.c +++ b/src/mod/event_handlers/mod_rayo/mod_rayo.c @@ -1,6 +1,6 @@ /* * mod_rayo for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application - * Copyright (C) 2013-2014, Grasshopper + * Copyright (C) 2013-2015, Grasshopper * * Version: MPL 1.1 * @@ -61,6 +61,10 @@ SWITCH_MODULE_DEFINITION(mod_rayo, mod_rayo_load, mod_rayo_shutdown, mod_rayo_ru #define JOINED_CALL 1 #define JOINED_MIXER 2 +#define OFFER_ALL 0 +#define OFFER_FIRST 1 +#define OFFER_RANDOM 2 + struct rayo_actor; struct rayo_client; struct rayo_call; @@ -123,8 +127,12 @@ struct rayo_call { struct rayo_actor base; /** Definitive controlling party JID */ char *dcp_jid; - /** Potential controlling parties */ + /** Potential controlling parties (have sent offers to) */ switch_hash_t *pcps; + /** Available controlling parties (not sent offers to) */ + switch_hash_t *acps; + /** Number of available controlling parties */ + int num_acps; /** current idle start time */ switch_time_t idle_start_time; /** true if fax is in progress */ @@ -223,6 +231,8 @@ static struct { int num_message_threads; /** message delivery queue */ switch_queue_t *msg_queue; + /** in progress offer queue */ + switch_queue_t *offer_queue; /** shutdown flag */ int shutdown; /** prevents context shutdown until all threads are finished */ @@ -237,6 +247,10 @@ static struct { int add_variables_to_offer; /** if true, channel variables are added to answered, ringing, end events */ int add_variables_to_events; + /** How to distribute offers to clients */ + int offer_algorithm; + /** How long to wait for offer response before retrying */ + int offer_timeout_us; } globals; /** @@ -866,12 +880,13 @@ static void start_deliver_message_thread(switch_memory_pool_t *pool) } /** - * Stop all message threads + * Stop all threads */ -static void stop_deliver_message_threads(void) +static void stop_all_threads(void) { globals.shutdown = 1; switch_queue_interrupt_all(globals.msg_queue); + switch_queue_interrupt_all(globals.offer_queue); switch_thread_rwlock_wrlock(globals.shutdown_rwlock); } @@ -1219,6 +1234,7 @@ done: switch_event_destroy(&call->answer_event); } switch_core_hash_destroy(&call->pcps); + switch_core_hash_destroy(&call->acps); } /** @@ -1404,6 +1420,8 @@ static struct rayo_call *rayo_call_init(struct rayo_call *call, switch_memory_po call->rayo_app_started = 0; call->answer_event = NULL; switch_core_hash_init(&call->pcps); + switch_core_hash_init(&call->acps); + call->num_acps = 0; } switch_safe_free(call_jid); @@ -3825,6 +3843,171 @@ static int should_offer_to_client(struct rayo_client *rclient, char **offer_filt return 0; } +/** + * Offered call information + */ +struct offered_call_info { + /** Call JID */ + char *call_jid; + /** Time this offer expires */ + switch_time_t offer_time; +}; + +/** + * Deliver offer message to next available client(s) + */ +static int send_offer_to_clients(struct rayo_call *from_call, switch_core_session_t *session) +{ + int i = 0; + int selection = 0; + int sent = 0; + switch_hash_index_t *hi = NULL; + iks *offer = NULL; + + if (from_call->num_acps <= 0) { + return 0; + } + + if (globals.offer_algorithm == OFFER_RANDOM) { + /* pick client at (not really) random */ + selection = rand() % from_call->num_acps; + } else if (globals.offer_algorithm == OFFER_FIRST) { + /* send to first client */ + selection = 0; + } else { + /* send to all clients */ + selection = -1; + } + + for (hi = switch_core_hash_first(from_call->acps); hi; hi = switch_core_hash_next(&hi)) { + if (i++ == selection || selection == -1) { + const char *to_client_jid = NULL; + const void *key; + void *val; + + /* get client jid to send to */ + switch_core_hash_this(hi, &key, NULL, &val); + to_client_jid = (const char *)key; + switch_assert(to_client_jid); + + /* send offer to client, remembering jid as PCP */ + if (!offer) { + offer = rayo_create_offer(from_call, session); + } + switch_core_hash_insert(from_call->pcps, to_client_jid, "1"); + iks_insert_attrib(offer, "to", to_client_jid); + RAYO_SEND_MESSAGE_DUP(from_call, to_client_jid, offer); + + /* remove client JID from list of available clients */ + switch_core_hash_delete(from_call->acps, to_client_jid); + from_call->num_acps--; + sent = 1; + + if (selection != -1) { + break; + } + } + } + switch_safe_free(hi); + + /* queue offer information */ + if (globals.offer_timeout_us > 0 && sent) { + struct offered_call_info *offered_call; + switch_zmalloc(offered_call, sizeof(*offered_call)); + offered_call->offer_time = switch_micro_time_now(); + offered_call->call_jid = strdup(RAYO_JID(from_call)); + if (switch_queue_trypush(globals.offer_queue, offered_call) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Failed to queue offered call info! Offer timeout won't work on this call\n"); + switch_safe_free(offered_call->call_jid); + switch_safe_free(offered_call); + } + } + + if (offer) { + iks_delete(offer); + } + + return sent; +} + +/** + * Thread that monitors for timed out offers + * @param thread this thread + * @param obj unused + * @return NULL + */ +static void *SWITCH_THREAD_FUNC offer_timeout_thread(switch_thread_t *thread, void *obj) +{ + struct offered_call_info *next_offer; + switch_thread_rwlock_rdlock(globals.shutdown_rwlock); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "New offer timeout thread\n"); + while (!globals.shutdown) { + if (switch_queue_pop(globals.offer_queue, (void *)&next_offer) == SWITCH_STATUS_SUCCESS) { + switch_time_t now = switch_micro_time_now(); + switch_time_t offer_timeout = next_offer->offer_time + globals.offer_timeout_us; + + /* wait for timeout */ + while (offer_timeout > now && !globals.shutdown) { + switch_time_t remain = offer_timeout - now; + remain = remain > 500000 ? 500000 : remain; + switch_sleep(remain); + now = switch_micro_time_now(); + } + + /* check if offer was accepted - it is accepted if the call has a DCP (definitive controlling party) */ + if (!globals.shutdown) { + struct rayo_call *call = RAYO_CALL_LOCATE(next_offer->call_jid); + if (call) { + switch_mutex_lock(RAYO_ACTOR(call)->mutex); + if (zstr(rayo_call_get_dcp_jid(call))) { + switch_core_session_t *session = switch_core_session_locate(rayo_call_get_uuid(call)); + if (session) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, offer timeout\n", RAYO_JID(call)); + if (!send_offer_to_clients(call, session)) { + /* nobody to offer to, end call */ + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s, no more clients to offer, ending call\n", RAYO_JID(call)); + switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE); + } + switch_core_session_rwunlock(session); + } + } + switch_mutex_unlock(RAYO_ACTOR(call)->mutex); + RAYO_RELEASE(call); + } + } + + switch_safe_free(next_offer->call_jid); + switch_safe_free(next_offer); + } + } + + /* clean up queue */ + while(switch_queue_trypop(globals.offer_queue, (void *)&next_offer) == SWITCH_STATUS_SUCCESS) { + switch_safe_free(next_offer->call_jid); + switch_safe_free(next_offer); + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Offer timeout thread finished\n"); + switch_thread_rwlock_unlock(globals.shutdown_rwlock); + + return NULL; +} + +/** + * Create a new offer timeout thread + * @param pool to use + */ +static void start_offer_timeout_thread(switch_memory_pool_t *pool) +{ + switch_thread_t *thread; + switch_threadattr_t *thd_attr = NULL; + switch_threadattr_create(&thd_attr, pool); + switch_threadattr_detach_set(thd_attr, 1); + switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); + switch_thread_create(&thread, thd_attr, offer_timeout_thread, NULL, pool); +} + #define RAYO_USAGE "[client username 1,client username n]" /** * Offer call and park channel @@ -3874,7 +4057,6 @@ SWITCH_STANDARD_APP(rayo_app) if (!call) { /* offer control */ switch_hash_index_t *hi = NULL; - iks *offer = NULL; char *clients_to_offer[16] = { 0 }; int clients_to_offer_count = 0; @@ -3888,7 +4070,6 @@ SWITCH_STANDARD_APP(rayo_app) switch_channel_set_variable(switch_core_session_get_channel(session), "rayo_call_jid", RAYO_JID(call)); - offer = rayo_create_offer(call, session); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Offering call for Rayo 3PCC\n"); if (!zstr(data)) { @@ -3904,7 +4085,6 @@ SWITCH_STANDARD_APP(rayo_app) } /* Offer call to all (or specified) ONLINE clients */ - /* TODO load balance offers so first session doesn't always get offer first? */ switch_mutex_lock(globals.clients_mutex); for (hi = switch_core_hash_first(globals.clients_roster); hi; hi = switch_core_hash_next(&hi)) { struct rayo_client *rclient; @@ -3914,16 +4094,15 @@ SWITCH_STANDARD_APP(rayo_app) rclient = (struct rayo_client *)val; switch_assert(rclient); - /* is session available to take call? */ + /* find clients available to take calls */ if (should_offer_to_client(rclient, clients_to_offer, clients_to_offer_count)) { - ok = 1; - switch_core_hash_insert(call->pcps, RAYO_JID(rclient), "1"); - iks_insert_attrib(offer, "to", RAYO_JID(rclient)); - RAYO_SEND_MESSAGE_DUP(call, RAYO_JID(rclient), offer); + switch_core_hash_insert(call->acps, RAYO_JID(rclient), "1"); + call->num_acps++; } } + ok = send_offer_to_clients(call, session); + switch_mutex_unlock(globals.clients_mutex); - iks_delete(offer); /* nobody to offer to */ if (!ok) { @@ -4158,6 +4337,8 @@ static switch_status_t do_config(switch_memory_pool_t *pool, const char *config_ globals.pause_when_offline = 0; globals.add_variables_to_offer = 0; globals.add_variables_to_events = 0; + globals.offer_timeout_us = 5000000; + globals.offer_algorithm = OFFER_ALL; /* get params */ { @@ -4203,6 +4384,25 @@ static switch_status_t do_config(switch_memory_pool_t *pool, const char *config_ globals.add_variables_to_offer = 1; globals.add_variables_to_events = 1; } + } else if (!strcasecmp(var, "offer-timeout-ms")) { + int offer_timeout_ms = 0; + if (switch_is_number(val) && (offer_timeout_ms = atoi(val)) >= 0 && offer_timeout_ms < 120000) { + globals.offer_timeout_us = offer_timeout_ms * 1000; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring invalid value for offer-timeout-ms \"%s\"\n", val); + } + } else if (!strcasecmp(var, "offer-algorithm")) { + if (zstr(val)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No value for offer-algorithm\n"); + } else if (!strcasecmp(val, "all")) { + globals.offer_algorithm = OFFER_ALL; + } else if (!strcasecmp(val, "first")) { + globals.offer_algorithm = OFFER_FIRST; + } else if (!strcasecmp(val, "random")) { + globals.offer_algorithm = OFFER_RANDOM; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Ignoring invalid value for offer-algorithm \"%s\"\n", val); + } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unsupported param: %s\n", var); } @@ -4881,6 +5081,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_rayo_load) switch_core_hash_init(&globals.cmd_aliases); switch_thread_rwlock_create(&globals.shutdown_rwlock, pool); switch_queue_create(&globals.msg_queue, 25000, pool); + switch_queue_create(&globals.offer_queue, 25000, pool); globals.offline_logged = 1; /* server commands */ @@ -4930,6 +5131,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_rayo_load) start_deliver_message_thread(pool); } } + start_offer_timeout_thread(pool); /* create admin client */ globals.console = rayo_console_client_create(); @@ -4979,9 +5181,9 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_rayo_shutdown) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for XMPP threads to stop\n"); xmpp_stream_context_destroy(globals.xmpp_context); - /* stop message threads */ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for message threads to stop\n"); - stop_deliver_message_threads(); + /* stop threads */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for message and offer timeout threads to stop\n"); + stop_all_threads(); if (globals.console) { RAYO_RELEASE(globals.console); From bd3589a2fbb56486f3c76548a4197716ebcce8c7 Mon Sep 17 00:00:00 2001 From: doancea Date: Tue, 2 Jun 2015 01:17:20 +0200 Subject: [PATCH 29/43] FS-7436: added FEC support for mod_opus You need an enabled jitter buffer for FEC to work. If a packet is missing we look in the jitter buffer for the next one, if the next packet is present we pass it to the decoder to extract the FEC info from it. If there's no FEC inside the packet, the Opus decoder will return PLC. --- src/mod/codecs/mod_opus/mod_opus.c | 31 ++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c index 8a950aab22..fbfc159527 100644 --- a/src/mod/codecs/mod_opus/mod_opus.c +++ b/src/mod/codecs/mod_opus/mod_opus.c @@ -74,6 +74,7 @@ struct opus_context { OpusDecoder *decoder_object; uint32_t enc_frame_size; uint32_t dec_frame_size; + uint32_t counter_plc_fec; }; struct { @@ -338,7 +339,7 @@ static switch_status_t switch_opus_init(switch_codec_t *codec, switch_codec_flag return SWITCH_STATUS_GENERR; } - + context->counter_plc_fec = 0; } codec->private_info = context; @@ -352,6 +353,7 @@ static switch_status_t switch_opus_destroy(switch_codec_t *codec) if (context) { if (context->decoder_object) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"tried PLC or FEC %d times \n",context->counter_plc_fec); opus_decoder_destroy(context->decoder_object); context->decoder_object = NULL; } @@ -400,9 +402,13 @@ static switch_status_t switch_opus_decode(switch_codec_t *codec, unsigned int *flag) { struct opus_context *context = codec->private_info; + switch_core_session_t *session = codec->session; + stfu_instance_t *jb = NULL; + stfu_frame_t next_frame; int samples = 0; uint32_t frame_size; uint32_t frame_samples; + uint32_t found_frame; if (!context) { return SWITCH_STATUS_FALSE; @@ -411,7 +417,28 @@ static switch_status_t switch_opus_decode(switch_codec_t *codec, frame_samples = *decoded_data_len / 2 / codec->implementation->number_of_channels; frame_size = frame_samples - (frame_samples % (codec->implementation->actual_samples_per_second / 400)); - samples = opus_decode(context->decoder_object, (*flag & SFF_PLC) ? NULL : encoded_data, encoded_data_len, decoded_data, frame_size, !!(*flag & SFF_PLC)); + /*FEC: shameless rip-off from mod_silk.c . OPUS only supports n+1 FEC , SILK is supposed to work with n+1, n+2*/ + if (*flag & SFF_PLC) { + context->counter_plc_fec; + if (session) { + jb = switch_core_session_get_jb(session, SWITCH_MEDIA_TYPE_AUDIO); + } + if (jb && codec->cur_frame) { + found_frame = stfu_n_copy_next_frame(jb, (uint32_t)codec->cur_frame->timestamp, codec->cur_frame->seq, 1, &next_frame); + if (found_frame) { + samples = opus_decode(context->decoder_object, next_frame.data, next_frame.dlen, decoded_data, frame_size, 1); /* opus_decode() does PLC if there's no FEC in the packet*/ + if (samples < 0 ) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Decoder Error (FEC): %s!\n", opus_strerror(samples)); + return SWITCH_STATUS_FALSE; + } else { + *decoded_data_len = samples * 2 * codec->implementation->number_of_channels; + return SWITCH_STATUS_SUCCESS; + } + } + } + } + + samples = opus_decode(context->decoder_object, (*flag & SFF_PLC) ? NULL : encoded_data, encoded_data_len, decoded_data, frame_size, 0); if (samples < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Decoder Error: %s fs:%u plc:%d!\n", opus_strerror(samples), frame_size, !!(*flag & SFF_PLC)); From e21a423d9f0589f845e18b1beb04fc8f2060e80e Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Tue, 2 Jun 2015 13:23:43 -0400 Subject: [PATCH 30/43] FS-7436: [mod_opus] fix the plc counter to actually count --- src/mod/codecs/mod_opus/mod_opus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod/codecs/mod_opus/mod_opus.c b/src/mod/codecs/mod_opus/mod_opus.c index fbfc159527..38f6981665 100644 --- a/src/mod/codecs/mod_opus/mod_opus.c +++ b/src/mod/codecs/mod_opus/mod_opus.c @@ -353,7 +353,7 @@ static switch_status_t switch_opus_destroy(switch_codec_t *codec) if (context) { if (context->decoder_object) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"tried PLC or FEC %d times \n",context->counter_plc_fec); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "tried PLC or FEC %d times \n", context->counter_plc_fec); opus_decoder_destroy(context->decoder_object); context->decoder_object = NULL; } @@ -419,7 +419,7 @@ static switch_status_t switch_opus_decode(switch_codec_t *codec, /*FEC: shameless rip-off from mod_silk.c . OPUS only supports n+1 FEC , SILK is supposed to work with n+1, n+2*/ if (*flag & SFF_PLC) { - context->counter_plc_fec; + context->counter_plc_fec++; if (session) { jb = switch_core_session_get_jb(session, SWITCH_MEDIA_TYPE_AUDIO); } From d961aad2c2c81459e0841c58b75b3f98e93088c7 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 2 Jun 2015 13:16:53 -0500 Subject: [PATCH 31/43] FS-7604 #resolve --- libs/esl/fs_cli.c | 43 +++++++++++++++++++++++++++++++++++++------ libs/esl/src/esl.c | 4 ++-- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c index 32fb77111c..7a74a042c4 100644 --- a/libs/esl/fs_cli.c +++ b/libs/esl/fs_cli.c @@ -99,6 +99,9 @@ static History *myhistory; static HistEvent ev; #endif + +static esl_mutex_t *MUTEX = NULL; + static void _sleep_ns(int secs, long nsecs) { #ifndef WIN32 if (nsecs > 999999999) { @@ -720,8 +723,15 @@ static void *msg_thread_run(esl_thread_t *me, void *obj) thread_running = 1; while(thread_running && handle->connected) { int aok = 1; - esl_status_t status = esl_recv_event_timed(handle, 10, 1, NULL); - if (status == ESL_FAIL) { + esl_status_t status; + + esl_mutex_lock(MUTEX); + status = esl_recv_event_timed(handle, 10, 1, NULL); + esl_mutex_unlock(MUTEX); + + if (status == ESL_BREAK) { + sleep_ms(1); + } else if (status == ESL_FAIL) { esl_log(ESL_LOG_WARNING, "Disconnected.\n"); running = -1; thread_running = 0; } else if (status == ESL_SUCCESS) { @@ -851,8 +861,11 @@ static const char *cli_usage = static int process_command(esl_handle_t *handle, const char *cmd) { + int r = 0; + while (*cmd == ' ') cmd++; + esl_mutex_lock(MUTEX); if ((*cmd == '/' && cmd++) || !strncasecmp(cmd, "...", 3)) { if (!strcasecmp(cmd, "help")) { @@ -865,7 +878,7 @@ static int process_command(esl_handle_t *handle, const char *cmd) !strcasecmp(cmd, "bye") ) { esl_log(ESL_LOG_INFO, "Goodbye!\nSee you at ClueCon http://www.cluecon.com/\n"); - return -1; + r = -1; goto end; } else if (!strncasecmp(cmd, "logfilter", 9)) { cmd += 9; while (*cmd && *cmd == ' ') { @@ -922,7 +935,7 @@ static int process_command(esl_handle_t *handle, const char *cmd) snprintf(cmd_str, sizeof(cmd_str), "api %s\nconsole_execute: true\n\n", cmd); if (esl_send_recv(handle, cmd_str)) { output_printf("Socket interrupted, bye!\n"); - return -1; + r = -1; goto end; } if (handle->last_sr_event) { if (handle->last_sr_event->body) { @@ -932,8 +945,12 @@ static int process_command(esl_handle_t *handle, const char *cmd) } } } + end: - return 0; + + esl_mutex_unlock(MUTEX); + + return r; } static int get_profile(const char *name, cli_profile_t **profile) @@ -1142,7 +1159,9 @@ static unsigned char esl_console_complete(const char *buffer, const char *cursor } else { snprintf(cmd_str, sizeof(cmd_str), "api console_complete %s\n\n", buf); } + esl_send_recv(global_handle, cmd_str); + if (global_handle->last_sr_event && global_handle->last_sr_event->body) { char *r = global_handle->last_sr_event->body; char *w, *p1; @@ -1183,7 +1202,13 @@ static unsigned char esl_console_complete(const char *buffer, const char *cursor static unsigned char complete(EditLine *el, int ch) { const LineInfo *lf = el_line(el); - return esl_console_complete(lf->buffer, lf->cursor, lf->lastchar); + int r; + + esl_mutex_lock(MUTEX); + r = esl_console_complete(lf->buffer, lf->cursor, lf->lastchar); + esl_mutex_unlock(MUTEX); + + return r; } #endif @@ -1378,6 +1403,9 @@ int main(int argc, char *argv[]) int loops = 2, reconnect = 0; char *ccheck; + + esl_mutex_create(&MUTEX); + #if HAVE_DECL_EL_PROMPT_ESC feature_level = 1; #else @@ -1755,6 +1783,9 @@ int main(int argc, char *argv[]) esl_disconnect(&handle); global_handle = NULL; thread_running = 0; + + esl_mutex_destroy(&MUTEX); + return 0; } diff --git a/libs/esl/src/esl.c b/libs/esl/src/esl.c index 6ac5bcf8ce..ab89b4c822 100644 --- a/libs/esl/src/esl.c +++ b/libs/esl/src/esl.c @@ -933,9 +933,9 @@ ESL_DECLARE(int) esl_wait_sock(esl_socket_t sock, uint32_t ms, esl_poll_t flags) if ((flags & ESL_POLL_ERROR)) { pfds[0].events |= POLLERR; } - - s = poll(pfds, 1, ms); + s = poll(pfds, 1, ms); + if (s < 0) { r = s; } else if (s > 0) { From 72897018156e0eff4c61b567ef655a433f55b199 Mon Sep 17 00:00:00 2001 From: ico Date: Sun, 4 Jan 2015 13:56:30 +0200 Subject: [PATCH 32/43] FS-7603: Implement failover for socket application --- .../mod_event_socket/mod_event_socket.c | 79 +++++++++++-------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c index 99a6415469..5199163797 100644 --- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c +++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c @@ -400,8 +400,12 @@ SWITCH_STANDARD_APP(socket_function) listener_t *listener; int argc = 0, x = 0; char *argv[80] = { 0 }; + char *hosts[50] = { 0 }; + unsigned int hosts_count = 0; + switch_status_t connected = SWITCH_STATUS_FALSE; char *mydata; switch_channel_t *channel = NULL; + char errbuf[512] = {0}; channel = switch_core_session_get_channel(session); @@ -414,47 +418,58 @@ SWITCH_STANDARD_APP(socket_function) return; } - host = argv[0]; + hosts_count = switch_split(argv[0], '|', hosts); - if (zstr(host)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Missing Host!\n"); - return; - } + for(x = 0; x < hosts_count; x++) { + host = hosts[x]; - if ((port_name = strrchr(host, ':'))) { - *port_name++ = '\0'; - port = (switch_port_t) atoi(port_name); - } + if (zstr(host)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Missing Host!\n"); + continue; + } - if ((path = strchr((port_name ? port_name : host), '/'))) { - *path++ = '\0'; - switch_channel_set_variable(channel, "socket_path", path); - } + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "Trying host: %s\n", host); - switch_channel_set_variable(channel, "socket_host", host); + if ((port_name = strrchr(host, ':'))) { + *port_name++ = '\0'; + port = (switch_port_t) atoi(port_name); + } - if (switch_sockaddr_info_get(&sa, host, SWITCH_UNSPEC, port, 0, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { + if ((path = strchr((port_name ? port_name : host), '/'))) { + *path++ = '\0'; + switch_channel_set_variable(channel, "socket_path", path); + } + + switch_channel_set_variable(channel, "socket_host", host); + + if (switch_sockaddr_info_get(&sa, host, SWITCH_UNSPEC, port, 0, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Socket Error!\n"); + continue; + } + + if (switch_socket_create(&new_sock, switch_sockaddr_get_family(sa), SOCK_STREAM, SWITCH_PROTO_TCP, switch_core_session_get_pool(session)) + != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Socket Error!\n"); + continue; + } + + switch_socket_opt_set(new_sock, SWITCH_SO_KEEPALIVE, 1); + switch_socket_opt_set(new_sock, SWITCH_SO_TCP_NODELAY, 1); + switch_socket_opt_set(new_sock, SWITCH_SO_TCP_KEEPIDLE, 30); + switch_socket_opt_set(new_sock, SWITCH_SO_TCP_KEEPINTVL, 30); + + if ((connected = switch_socket_connect(new_sock, sa)) == SWITCH_STATUS_SUCCESS) { + break; + } + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Socket Error: %s\n", switch_strerror(errno, errbuf, sizeof(errbuf))); + }//end hosts loop + + if (connected != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Socket Error!\n"); return; } - if (switch_socket_create(&new_sock, switch_sockaddr_get_family(sa), SOCK_STREAM, SWITCH_PROTO_TCP, switch_core_session_get_pool(session)) - != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Socket Error!\n"); - return; - } - - switch_socket_opt_set(new_sock, SWITCH_SO_KEEPALIVE, 1); - switch_socket_opt_set(new_sock, SWITCH_SO_TCP_NODELAY, 1); - switch_socket_opt_set(new_sock, SWITCH_SO_TCP_KEEPIDLE, 30); - switch_socket_opt_set(new_sock, SWITCH_SO_TCP_KEEPINTVL, 30); - - if (switch_socket_connect(new_sock, sa) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Socket Error!\n"); - return; - } - - if (!(listener = switch_core_session_alloc(session, sizeof(*listener)))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Memory Error\n"); return; From 22cb3f708f6c0a5cd056db0ccb30690f3adcf136 Mon Sep 17 00:00:00 2001 From: Seven Du Date: Wed, 3 Jun 2015 05:47:08 +0800 Subject: [PATCH 33/43] FS-7585 increasing AMF buffer for larger picture --- src/mod/endpoints/mod_rtmp/mod_rtmp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_rtmp/mod_rtmp.h b/src/mod/endpoints/mod_rtmp/mod_rtmp.h index e53cb95d94..8571aedafa 100644 --- a/src/mod/endpoints/mod_rtmp/mod_rtmp.h +++ b/src/mod/endpoints/mod_rtmp/mod_rtmp.h @@ -47,7 +47,7 @@ #define RTMP_DEFAULT_PORT 1935 #define RTMP_TCP_READ_BUF 2048 * 16 -#define AMF_MAX_SIZE 2048 * 16 +#define AMF_MAX_SIZE 2048 * 16 * 2 #define SUPPORT_SND_NONE 0x0000 #define SUPPORT_SND_ADPCM 0x0002 From 49778c34e5aeb2506ad83286aa21ba353727c751 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Tue, 2 Jun 2015 19:26:28 -0400 Subject: [PATCH 34/43] FS-7258, FS-7571: [mod_xml_cdr] properly encode xml cdr for post to web server --- src/include/switch_utils.h | 1 + src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c | 2 +- src/switch_utils.c | 9 +++++++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index 5d85353669..c6768d5860 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -1052,6 +1052,7 @@ static inline int switch_needs_url_encode(const char *s) return 0; } +SWITCH_DECLARE(char *) switch_url_encode_opt(const char *url, char *buf, size_t len, switch_bool_t double_encode); SWITCH_DECLARE(char *) switch_url_encode(const char *url, char *buf, size_t len); SWITCH_DECLARE(char *) switch_url_decode(char *s); SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, diff --git a/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c b/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c index 71f51d30ce..968e16e4ad 100644 --- a/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c +++ b/src/mod/xml_int/mod_xml_cdr/mod_xml_cdr.c @@ -272,7 +272,7 @@ static switch_status_t my_on_reporting(switch_core_session_t *session) memset(xml_text_escaped, 0, need_bytes); if (globals.encode == ENCODING_DEFAULT) { headers = switch_curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded"); - switch_url_encode(xml_text, xml_text_escaped, need_bytes); + switch_url_encode_opt(xml_text, xml_text_escaped, need_bytes, SWITCH_TRUE); } else { headers = switch_curl_slist_append(headers, "Content-Type: application/x-www-form-base64-encoded"); switch_b64_encode((unsigned char *) xml_text, need_bytes / 3, (unsigned char *) xml_text_escaped, need_bytes); diff --git a/src/switch_utils.c b/src/switch_utils.c index 59b474045c..0b415492dc 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -3162,7 +3162,7 @@ SWITCH_DECLARE(int) switch_socket_waitfor(switch_pollfd_t *poll, int ms) return nsds; } -SWITCH_DECLARE(char *) switch_url_encode(const char *url, char *buf, size_t len) +SWITCH_DECLARE(char *) switch_url_encode_opt(const char *url, char *buf, size_t len, switch_bool_t double_encode) { const char *p, *e = end_of_p(url); size_t x = 0; @@ -3185,7 +3185,7 @@ SWITCH_DECLARE(char *) switch_url_encode(const char *url, char *buf, size_t len) break; } - if (*p == '%' && e-p > 1) { + if (!double_encode && *p == '%' && e-p > 1) { if (strchr(hex, *(p+1)) && strchr(hex, *(p+2))) { ok = 1; } @@ -3207,6 +3207,11 @@ SWITCH_DECLARE(char *) switch_url_encode(const char *url, char *buf, size_t len) return buf; } +SWITCH_DECLARE(char *) switch_url_encode(const char *url, char *buf, size_t len) +{ + return switch_url_encode_opt(url, buf, len, SWITCH_FALSE); +} + SWITCH_DECLARE(char *) switch_url_decode(char *s) { char *o; From 51c6a6f7b55ac7168ba899dcc61d9e5e91f122a8 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 2 Jun 2015 21:09:45 -0500 Subject: [PATCH 35/43] add a bit to 2db8f94ab6543018df1792663b809e77d521cab9 --- src/switch_core_media.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/switch_core_media.c b/src/switch_core_media.c index d20af51290..bd0b1c23a1 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -3390,6 +3390,8 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ if (engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port) { if (engine->rtcp_mux) { + engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port = engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port; + engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr = engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, "Asked by candidate to set remote rtcp %s addr to %s:%d but this is rtcp-mux so no thanks\n", type2str(type), engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port); From c9065a85b6ac92ef3318df2abe30395df1f3c99f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 2 Jun 2015 21:20:03 -0500 Subject: [PATCH 36/43] FS-7602 add some of 3b2d00f3e65061393da10a4ba286ac72cdb3c16e from verto to sip and refactor some code to keep sip working like verto --- src/include/switch_core_media.h | 1 + src/include/switch_stun.h | 2 ++ src/mod/endpoints/mod_sofia/mod_sofia.c | 11 ++++++++++- src/mod/endpoints/mod_sofia/mod_sofia.h | 3 +++ src/mod/endpoints/mod_sofia/sofia.c | 20 +++++++++++++++----- src/mod/endpoints/mod_sofia/sofia_glue.c | 22 +++++++++++++++++++--- src/switch_core_media.c | 17 ++--------------- src/switch_core_state_machine.c | 4 ++++ src/switch_rtp.c | 10 +++++++++- src/switch_stun.c | 1 + 10 files changed, 66 insertions(+), 25 deletions(-) diff --git a/src/include/switch_core_media.h b/src/include/switch_core_media.h index bc25817225..31bf08387b 100644 --- a/src/include/switch_core_media.h +++ b/src/include/switch_core_media.h @@ -332,6 +332,7 @@ SWITCH_DECLARE(switch_media_flow_t) switch_core_session_media_flow(switch_core_s SWITCH_DECLARE(switch_status_t) switch_core_media_get_vid_params(switch_core_session_t *session, switch_vid_params_t *vid_params); SWITCH_DECLARE(switch_status_t) switch_core_media_set_video_file(switch_core_session_t *session, switch_file_handle_t *fh, switch_rw_t rw); SWITCH_DECLARE(switch_bool_t) switch_core_session_in_video_thread(switch_core_session_t *session); +SWITCH_DECLARE(switch_bool_t) switch_core_media_check_dtls(switch_core_session_t *session); SWITCH_END_EXTERN_C #endif diff --git a/src/include/switch_stun.h b/src/include/switch_stun.h index eb4274457b..9db0aadd84 100644 --- a/src/include/switch_stun.h +++ b/src/include/switch_stun.h @@ -197,6 +197,8 @@ SWITCH_DECLARE(char *) switch_stun_host_lookup(const char *host, switch_memory_p \return true or false */ SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_get_mapped_address(switch_stun_packet_attribute_t *attribute, char *ipstr, uint16_t *port); +SWITCH_DECLARE(uint8_t) switch_stun_packet_attribute_get_xor_mapped_address(switch_stun_packet_attribute_t *attribute, uint32_t cookie, char *ipstr, uint16_t *port); + /*! \brief Extract a username from a packet attribute diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 4917cd8824..f80318f459 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -2676,9 +2676,15 @@ static switch_status_t cmd_status(char **argv, int argc, switch_stream_handle_t stream->write_function(stream, "Dialplan \t%s\n", switch_str_nil(profile->dialplan)); stream->write_function(stream, "Context \t%s\n", switch_str_nil(profile->context)); stream->write_function(stream, "Challenge Realm \t%s\n", zstr(profile->challenge_realm) ? "auto_to" : profile->challenge_realm); + for (x = 0; x < profile->rtpip_index; x++) { stream->write_function(stream, "RTP-IP \t%s\n", switch_str_nil(profile->rtpip[x])); } + + for (x = 0; x < profile->rtpip_index6; x++) { + stream->write_function(stream, "RTP-IP \t%s\n", switch_str_nil(profile->rtpip6[x])); + } + if (profile->extrtpip) { stream->write_function(stream, "Ext-RTP-IP \t%s\n", profile->extrtpip); } @@ -2980,6 +2986,9 @@ static switch_status_t cmd_xml_status(char **argv, int argc, switch_stream_handl for (x = 0; x < profile->rtpip_index; x++) { stream->write_function(stream, " %s\n", switch_str_nil(profile->rtpip[x])); } + for (x = 0; x < profile->rtpip_index6; x++) { + stream->write_function(stream, " %s\n", switch_str_nil(profile->rtpip6[x])); + } if (profile->extrtpip) { stream->write_function(stream, " %s\n", profile->extrtpip); } @@ -5467,7 +5476,7 @@ static void general_event_handler(switch_event_t *event) } if (!strcmp(profile->rtpip[x], old_ip6)) { - profile->rtpip[x] = switch_core_strdup(profile->pool, new_ip6); + profile->rtpip6[x] = switch_core_strdup(profile->pool, new_ip6); rb++; } } diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 864eff79ac..df52655ab2 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -575,11 +575,14 @@ struct sofia_profile { char *shutdown_type; char *extrtpip; char *rtpip[MAX_RTPIP]; + char *rtpip6[MAX_RTPIP]; char *jb_msec; switch_payload_t te; switch_payload_t recv_te; uint32_t rtpip_index; uint32_t rtpip_next; + uint32_t rtpip_index6; + uint32_t rtpip_next6; char *rtcp_audio_interval_msec; char *rtcp_video_interval_msec; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index cf461262d3..b6b597f61e 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -4219,6 +4219,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) profile->ob_failed_calls = 0; profile->shutdown_type = "false"; profile->rtpip_index = 0; + profile->rtpip_index6 = 0; if (xprofiledomain) { profile->domain_name = switch_core_strdup(profile->pool, xprofiledomain); @@ -4717,10 +4718,19 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) } else { ip = strcasecmp(val, "auto") ? val : mod_sofia_globals.guess_ip; } - if (profile->rtpip_index < MAX_RTPIP) { - profile->rtpip[profile->rtpip_index++] = switch_core_strdup(profile->pool, ip); + + if (strchr(ip, ':')) { + if (profile->rtpip_index < MAX_RTPIP) { + profile->rtpip6[profile->rtpip_index6++] = switch_core_strdup(profile->pool, ip); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Max IPs configured for profile %s.\n", profile->name); + } } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Max IPs configured for profile %s.\n", profile->name); + if (profile->rtpip_index6 < MAX_RTPIP) { + profile->rtpip[profile->rtpip_index++] = switch_core_strdup(profile->pool, ip); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Max IPs configured for profile %s.\n", profile->name); + } } } else if (!strcasecmp(var, "sip-ip")) { char *ip = mod_sofia_globals.guess_ip; @@ -5455,7 +5465,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) profile->sipip = switch_core_strdup(profile->pool, mod_sofia_globals.guess_ip); } - if (!profile->rtpip[0]) { + if (!profile->rtpip[0] && !profile->rtpip6[0]) { profile->rtpip[profile->rtpip_index++] = switch_core_strdup(profile->pool, mod_sofia_globals.guess_ip); } @@ -5488,7 +5498,7 @@ switch_status_t config_sofia(sofia_config_t reload, char *profile_name) profile->sdp_username = switch_core_strdup(profile->pool, "FreeSWITCH"); } - if (!profile->rtpip[0]) { + if (!profile->rtpip[0] && !profile->rtpip6[0]) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Setting ip to '127.0.0.1'\n"); profile->rtpip[profile->rtpip_index++] = switch_core_strdup(profile->pool, "127.0.0.1"); } diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index cfa01c34f2..52b8b5256f 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -92,9 +92,25 @@ void sofia_glue_attach_private(switch_core_session_t *session, sofia_profile_t * tech_pvt->profile = profile; - tech_pvt->mparams.rtpip = switch_core_session_strdup(session, profile->rtpip[profile->rtpip_next++]); - if (profile->rtpip_next >= profile->rtpip_index) { - profile->rtpip_next = 0; + if (!zstr(profile->rtpip[profile->rtpip_next])) { + tech_pvt->mparams.rtpip4 = switch_core_session_strdup(session, profile->rtpip[profile->rtpip_next++]); + tech_pvt->mparams.rtpip = tech_pvt->mparams.rtpip4; + + if (profile->rtpip_next >= profile->rtpip_index) { + profile->rtpip_next = 0; + } + } + + if (!zstr(profile->rtpip[profile->rtpip_next6])) { + tech_pvt->mparams.rtpip6 = switch_core_session_strdup(session, profile->rtpip[profile->rtpip_next6++]); + + if (zstr(tech_pvt->mparams.rtpip)) { + tech_pvt->mparams.rtpip = tech_pvt->mparams.rtpip6; + } + + if (profile->rtpip_next6 >= profile->rtpip_index6) { + profile->rtpip_next6 = 0; + } } profile->inuse++; diff --git a/src/switch_core_media.c b/src/switch_core_media.c index bd0b1c23a1..cd725ab3db 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -216,8 +216,6 @@ struct switch_media_handle_s { }; -static switch_bool_t check_dtls(switch_core_session_t *session); - static switch_srtp_crypto_suite_t SUITES[CRYPTO_INVALID] = { { "AEAD_AES_256_GCM_8", AEAD_AES_256_GCM_8, 44}, { "AEAD_AES_128_GCM_8", AEAD_AES_128_GCM_8, 28}, @@ -6589,13 +6587,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_activate_rtp(switch_core_sessi end: - switch_channel_clear_flag(session->channel, CF_REINVITE); switch_core_recovery_track(session); - - return status; } @@ -8649,7 +8644,7 @@ static int check_engine(switch_rtp_engine_t *engine) return 1; } -static switch_bool_t check_dtls(switch_core_session_t *session) +SWITCH_DECLARE(switch_bool_t) switch_core_media_check_dtls(switch_core_session_t *session) { switch_media_handle_t *smh; switch_rtp_engine_t *a_engine, *v_engine; @@ -8661,7 +8656,7 @@ static switch_bool_t check_dtls(switch_core_session_t *session) return SWITCH_FALSE; } - if (switch_channel_down(session->channel)) { + if (!switch_channel_media_up(session->channel)) { return SWITCH_FALSE; } @@ -8715,14 +8710,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_media_receive_message(switch_core_se } break; - case SWITCH_MESSAGE_INDICATE_ANSWER: - case SWITCH_MESSAGE_INDICATE_PROGRESS: - case SWITCH_MESSAGE_ANSWER_EVENT: - case SWITCH_MESSAGE_PROGRESS_EVENT: - { - check_dtls(session); - } - break; case SWITCH_MESSAGE_INDICATE_VIDEO_REFRESH_REQ: { if (v_engine->rtp_session) { diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index c066cd00b7..26750ff58e 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -486,6 +486,10 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session_t *session) } } } + + if (state > CS_INIT && switch_channel_media_up(session->channel)) { + switch_core_media_check_dtls(session); + } switch (state) { case CS_NEW: /* Just created, Waiting for first instructions */ diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 3905e57cb6..b0b9f2f9e6 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -887,7 +887,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG8, "STUN PACKET TYPE: %s\n", switch_stun_value_to_name(SWITCH_STUN_TYPE_PACKET_TYPE, packet->header.type)); do { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG8, "|---: STUN ATTR %s\n", + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG8, "|---: STUN ATTR %d %x %s\n", attr->type, attr->type, switch_stun_value_to_name(SWITCH_STUN_TYPE_ATTRIBUTE, attr->type)); switch (attr->type) { @@ -928,6 +928,14 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG8, "|------: %s:%d\n", ip, port); } break; + case SWITCH_STUN_ATTR_XOR_MAPPED_ADDRESS: + if (attr->type) { + char ip[16]; + uint16_t port; + switch_stun_packet_attribute_get_xor_mapped_address(attr, packet->header.cookie, ip, &port); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG8, "|------: %s:%d\n", ip, port); + } + break; case SWITCH_STUN_ATTR_USERNAME: if (attr->type) { switch_stun_packet_attribute_get_username(attr, username, sizeof(username)); diff --git a/src/switch_stun.c b/src/switch_stun.c index 1dd35d9bc5..d1f43c3244 100644 --- a/src/switch_stun.c +++ b/src/switch_stun.c @@ -60,6 +60,7 @@ static const struct value_mapping PACKET_TYPES[] = { static const struct value_mapping ATTR_TYPES[] = { {SWITCH_STUN_ATTR_MAPPED_ADDRESS, "MAPPED_ADDRESS"}, + {SWITCH_STUN_ATTR_XOR_MAPPED_ADDRESS, "XOR_MAPPED_ADDRESS"}, {SWITCH_STUN_ATTR_RESPONSE_ADDRESS, "RESPONSE_ADDRESS"}, {SWITCH_STUN_ATTR_CHANGE_REQUEST, "CHANGE_REQUEST"}, {SWITCH_STUN_ATTR_SOURCE_ADDRESS, "SOURCE_ADDRESS"}, From 581c104753bdbd11d2680625f6f77f5d63047170 Mon Sep 17 00:00:00 2001 From: William King Date: Wed, 3 Jun 2015 09:16:48 -0700 Subject: [PATCH 37/43] FS-7586 Change the default min-required-recording-participants option for mod_conference from 2 to 1. #NEEDSDOCS --- src/mod/applications/mod_conference/mod_conference.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index f59adc9c49..7a94dc82eb 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -12565,7 +12565,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c char *suppress_events = NULL; char *verbose_events = NULL; char *auto_record = NULL; - int min_recording_participants = 2; + int min_recording_participants = 1; char *conference_log_dir = NULL; char *cdr_event_mode = NULL; char *terminate_on_silence = NULL; @@ -12828,9 +12828,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_c } else if (!strcasecmp(var, "auto-record") && !zstr(val)) { auto_record = val; } else if (!strcasecmp(var, "min-required-recording-participants") && !zstr(val)) { - if (!strcmp(val, "1")) { - min_recording_participants = 1; - } else if (!strcmp(val, "2")) { + if (!strcmp(val, "2")) { min_recording_participants = 2; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "min-required-recording-participants is invalid, leaving set to %d\n", min_recording_participants); From fc075a75e540add3cc94c8e3028452e58abdef3e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 3 Jun 2015 15:52:48 -0500 Subject: [PATCH 38/43] FS-7513 make sure user does not have auto avatar when not visible --- .../mod_conference/mod_conference.c | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index 7a94dc82eb..30272d92d4 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -1884,6 +1884,26 @@ static void check_avatar(conference_member_t *member, switch_bool_t force) } } +static void check_flush(conference_member_t *member) +{ + int flushed; + + if (!member->channel || !switch_channel_test_flag(member->channel, CF_VIDEO)) { + return; + } + + flushed = flush_video_queue(member->video_queue); + + if (flushed && member->auto_avatar) { + switch_channel_video_sync(member->channel); + + switch_img_free(&member->avatar_png_img); + member->avatar_patched = 0; + reset_video_bitrate_counters(member); + member->blanks = 0; + member->auto_avatar = 0; + } +} static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread_t *thread, void *obj) { @@ -2030,7 +2050,7 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread size = switch_queue_size(imember->video_queue); } while(size > 0); - if (switch_test_flag(imember, MFLAG_CAN_BE_SEEN) && imember->video_flow != SWITCH_MEDIA_FLOW_SENDONLY) { + if (switch_test_flag(imember, MFLAG_CAN_BE_SEEN) && imember->video_layer_id > -1 && imember->video_flow != SWITCH_MEDIA_FLOW_SENDONLY) { if (img) { imember->good_img++; if ((imember->good_img % (int)(conference->video_fps.fps * 10)) == 0) { @@ -2054,31 +2074,14 @@ static void *SWITCH_THREAD_FUNC conference_video_muxing_thread_run(switch_thread //if (layer) { //layer->is_avatar = 1; //} - + imember->auto_avatar = 1; } } } } } else { - int flushed = flush_video_queue(imember->video_queue); - - if (flushed && imember->auto_avatar) { - switch_channel_video_sync(imember->channel); - - switch_img_free(&imember->avatar_png_img); - imember->avatar_patched = 0; - reset_video_bitrate_counters(imember); - - if (layer) { - layer->is_avatar = 0; - imember->auto_avatar = 0; - } - - imember->blanks = 0; - } else { - - } + check_flush(imember); } layer = NULL; @@ -4441,6 +4444,7 @@ static void conference_set_video_floor_holder(conference_obj_t *conference, conf switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Adding video floor %s\n", switch_channel_get_name(member->channel)); + check_flush(member); switch_core_session_video_reinit(member->session); conference->video_floor_holder = member->id; member_update_status_field(member); From 6c135e15c183e1472e64818be6e72a1f16c51c1f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 3 Jun 2015 15:54:15 -0500 Subject: [PATCH 39/43] FS-7602 FS-7499 FS-7587 #comment another refactoring pass on candidate parsing and ipv4/6 parsing --- src/include/switch_rtp.h | 2 +- src/mod/endpoints/mod_verto/mod_verto.c | 47 +++-- src/switch_apr.c | 8 +- src/switch_core.c | 14 ++ src/switch_core_media.c | 257 +++++++++--------------- src/switch_rtp.c | 41 ++-- 6 files changed, 171 insertions(+), 198 deletions(-) diff --git a/src/include/switch_rtp.h b/src/include/switch_rtp.h index 4bb140c83d..5a9e3d6003 100644 --- a/src/include/switch_rtp.h +++ b/src/include/switch_rtp.h @@ -103,7 +103,7 @@ typedef struct icand_s { typedef struct ice_s { icand_t cands[MAX_CAND][2]; - int cand_idx; + int cand_idx[2]; int chosen[2]; int is_chosen[2]; char *ufrag; diff --git a/src/mod/endpoints/mod_verto/mod_verto.c b/src/mod/endpoints/mod_verto/mod_verto.c index 57faa8e38a..68b75d505a 100644 --- a/src/mod/endpoints/mod_verto/mod_verto.c +++ b/src/mod/endpoints/mod_verto/mod_verto.c @@ -143,7 +143,7 @@ static void verto_deinit_ssl(verto_profile_t *profile) static void close_file(ws_socket_t *sock) { - if (*sock > -1) { + if (*sock != ws_sock_invalid) { #ifndef WIN32 close(*sock); #else @@ -155,7 +155,7 @@ static void close_file(ws_socket_t *sock) static void close_socket(ws_socket_t *sock) { - if (*sock > -1) { + if (*sock != ws_sock_invalid) { shutdown(*sock, 2); close_file(sock); } @@ -1914,7 +1914,7 @@ static void *SWITCH_THREAD_FUNC client_thread(switch_thread_t *thread, void *obj switch_event_destroy(&jsock->vars); switch_event_destroy(&jsock->user_vars); - if (jsock->client_socket > -1) { + if (jsock->client_socket != ws_sock_invalid) { close_socket(&jsock->client_socket); } @@ -3655,7 +3655,7 @@ static switch_bool_t verto__broadcast_func(const char *method, cJSON *params, js jevent = cJSON_Duplicate(params, 1); switch_event_channel_broadcast(event_channel, &jevent, modname, globals.event_channel_id); - if (jsock->profile->mcast_pub.sock > -1) { + if (jsock->profile->mcast_pub.sock != ws_sock_invalid) { if ((json_text = cJSON_PrintUnformatted(params))) { if ( mcast_socket_send(&jsock->profile->mcast_pub, json_text, strlen(json_text) + 1) < 0 ) { @@ -3894,7 +3894,7 @@ static int start_jsock(verto_profile_t *profile, ws_socket_t sock, int family) error: if (jsock) { - if (jsock->client_socket > -1) { + if (jsock->client_socket != ws_sock_invalid) { close_socket(&jsock->client_socket); } @@ -3965,7 +3965,13 @@ static ws_socket_t prepare_socket(ips_t *ips) static void handle_mcast_sub(verto_profile_t *profile) { - int bytes = mcast_socket_recv(&profile->mcast_sub, NULL, 0, 0); + int bytes; + + if (profile->mcast_sub.sock == ws_sock_invalid) { + return; + } + + bytes = mcast_socket_recv(&profile->mcast_sub, NULL, 0, 0); if (bytes > 0) { cJSON *json; @@ -4100,27 +4106,36 @@ static int runtime(verto_profile_t *profile) { int i; int r = 0; + int listeners = 0; for (i = 0; i < profile->i; i++) { //if ((profile->server_socket[i] = prepare_socket(profile->ip[i].local_ip_addr, profile->ip[i].local_port)) < 0) { - if ((profile->server_socket[i] = prepare_socket(&profile->ip[i])) < 0) { - die("Client Socket Error!\n"); + if ((profile->server_socket[i] = prepare_socket(&profile->ip[i])) != ws_sock_invalid) { + listeners++; } } + if (!listeners) { + die("Client Socket Error! No Listeners!\n"); + } + if (profile->mcast_ip) { + int ok = 1; + if (mcast_socket_create(profile->mcast_ip, profile->mcast_port, &profile->mcast_sub, MCAST_RECV | MCAST_TTL_HOST) < 0) { - r = -1; - die("mcast recv socket create\n"); + ok++; } - if (mcast_socket_create(profile->mcast_ip, profile->mcast_port + 1, &profile->mcast_pub, MCAST_SEND | MCAST_TTL_HOST) > 0) { + if (ok && mcast_socket_create(profile->mcast_ip, profile->mcast_port + 1, &profile->mcast_pub, MCAST_SEND | MCAST_TTL_HOST) > 0) { mcast_socket_close(&profile->mcast_sub); - r = -1; - die("mcast send socket create\n"); + ok = 0; } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MCAST Bound to %s:%d/%d\n", profile->mcast_ip, profile->mcast_port, profile->mcast_port + 1); + if (ok) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MCAST Bound to %s:%d/%d\n", profile->mcast_ip, profile->mcast_port, profile->mcast_port + 1); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MCAST Disabled\n"); + } } @@ -4132,11 +4147,11 @@ static int runtime(verto_profile_t *profile) error: - if (profile->mcast_sub.sock > -1) { + if (profile->mcast_sub.sock != ws_sock_invalid) { mcast_socket_close(&profile->mcast_sub); } - if (profile->mcast_pub.sock > -1) { + if (profile->mcast_pub.sock != ws_sock_invalid) { mcast_socket_close(&profile->mcast_pub); } diff --git a/src/switch_apr.c b/src/switch_apr.c index 5e7dc52dbd..a2ce5074b2 100644 --- a/src/switch_apr.c +++ b/src/switch_apr.c @@ -864,11 +864,15 @@ SWITCH_DECLARE(const char *) switch_get_addr(char *buf, switch_size_t len, switc return SWITCH_BLANK_STRING; } + memset(buf, 0, len); + if (in->family == AF_INET) { - return get_addr(buf, len, (struct sockaddr *) &in->sa, in->salen); + get_addr(buf, len, (struct sockaddr *) &in->sa, in->salen); + return buf; } - return get_addr6(buf, len, (struct sockaddr_in6 *) &in->sa, in->salen); + get_addr6(buf, len, (struct sockaddr_in6 *) &in->sa, in->salen); + return buf; } SWITCH_DECLARE(uint16_t) switch_sockaddr_get_port(switch_sockaddr_t *sa) diff --git a/src/switch_core.c b/src/switch_core.c index 5ed8ad83a1..d585addbd3 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1420,6 +1420,20 @@ SWITCH_DECLARE(void) switch_load_network_lists(switch_bool_t reload) switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); + tmp_name = "any_v6.auto"; + switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name); + switch_network_list_add_cidr(rfc_list, "0.0.0.0/0", SWITCH_FALSE); + switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); + + + tmp_name = "any_v4.auto"; + switch_network_list_create(&rfc_list, tmp_name, SWITCH_TRUE, IP_LIST.pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (allow)\n", tmp_name); + switch_network_list_add_cidr(rfc_list, "::/0", SWITCH_FALSE); + switch_core_hash_insert(IP_LIST.hash, tmp_name, rfc_list); + + tmp_name = "nat.auto"; switch_network_list_create(&rfc_list, tmp_name, SWITCH_FALSE, IP_LIST.pool); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Created ip list %s default (deny)\n", tmp_name); diff --git a/src/switch_core_media.c b/src/switch_core_media.c index cd725ab3db..f9698841a8 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -339,6 +339,9 @@ SWITCH_DECLARE(uint32_t) switch_core_media_get_video_fps(switch_core_session_t * fps = switch_round_to_step(smh->vid_frames / (now - smh->vid_started), 5); if (fps < 15) fps = 15; + smh->vid_started = switch_epoch_time_now(NULL); + smh->vid_frames = 1; + return fps; } @@ -2885,7 +2888,8 @@ static void clear_ice(switch_core_session_t *session, switch_media_type_t type) engine->ice_in.chosen[1] = 0; engine->ice_in.is_chosen[0] = 0; engine->ice_in.is_chosen[1] = 0; - engine->ice_in.cand_idx = 0; + engine->ice_in.cand_idx[0] = 0; + engine->ice_in.cand_idx[1] = 0; memset(&engine->ice_in, 0, sizeof(engine->ice_in)); engine->remote_rtcp_port = 0; @@ -3094,22 +3098,24 @@ static switch_bool_t ip_possible(switch_media_handle_t *smh, const char *ip) } //? -static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_session_t *sdp, sdp_media_t *m) +static switch_status_t check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_session_t *sdp, sdp_media_t *m) { switch_rtp_engine_t *engine = &smh->engines[type]; sdp_attribute_t *attr; int i = 0, got_rtcp_mux = 0; const char *val; + int ice_seen = 0, cid = 0, ai = 0; if (engine->ice_in.is_chosen[0] && engine->ice_in.is_chosen[1] && !switch_channel_test_flag(smh->session->channel, CF_REINVITE)) { - return; + return SWITCH_STATUS_SUCCESS; } engine->ice_in.chosen[0] = 0; engine->ice_in.chosen[1] = 0; engine->ice_in.is_chosen[0] = 0; engine->ice_in.is_chosen[1] = 0; - engine->ice_in.cand_idx = 0; + engine->ice_in.cand_idx[0] = 0; + engine->ice_in.cand_idx[1] = 0; if (m) { attr = m->m_attributes; @@ -3121,8 +3127,6 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ char *data; char *fields[15]; int argc = 0, j = 0; - int cid = 0; - int pass_acl = 0; if (zstr(attr->a_name)) { continue; @@ -3130,6 +3134,7 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ if (!strcasecmp(attr->a_name, "ice-ufrag")) { engine->ice_in.ufrag = switch_core_session_strdup(smh->session, attr->a_value); + ice_seen++; } else if (!strcasecmp(attr->a_name, "ice-pwd")) { engine->ice_in.pwd = switch_core_session_strdup(smh->session, attr->a_value); } else if (!strcasecmp(attr->a_name, "ice-options")) { @@ -3182,172 +3187,108 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ } data = switch_core_session_strdup(smh->session, attr->a_value); - + argc = switch_split(data, ' ', fields); - if (argc < 5 || engine->ice_in.cand_idx >= MAX_CAND - 1) { + cid = fields[1] ? atoi(fields[1]) - 1 : 0; + + if (argc < 5 || engine->ice_in.cand_idx[cid] >= MAX_CAND - 1) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_WARNING, "Invalid data\n"); continue; } - cid = atoi(fields[1]) - 1; - - for (i = 0; i < argc; i++) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG1, "CAND %d [%s]\n", i, fields[i]); } - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, - "Checking Candidate cid: %d proto: %s type: %s addr: %s:%s\n", cid+1, fields[2], fields[7], fields[4], fields[5]); - - pass_acl = 0; - - for (i = 0; i < engine->cand_acl_count; i++) { - if (switch_check_network_list_ip(fields[4], engine->cand_acl[i])) { - pass_acl = 1; - break; - } - } - - if (!engine->ice_in.is_chosen[cid] && ip_possible(smh, fields[4]) && pass_acl) { - engine->ice_in.chosen[cid] = engine->ice_in.cand_idx; - engine->ice_in.is_chosen[cid] = 1; - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, - "Choose %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n", + if (!ip_possible(smh, fields[4])) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, + "Drop %s Candidate cid: %d proto: %s type: %s addr: %s:%s (no network path)\n", type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio", cid+1, fields[2], fields[7], fields[4], fields[5]); - ip_choose_family(smh, fields[4]); } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Save %s Candidate cid: %d proto: %s type: %s addr: %s:%s\n", type == SWITCH_MEDIA_TYPE_VIDEO ? "video" : "audio", cid+1, fields[2], fields[7], fields[4], fields[5]); } - - engine->ice_in.cands[engine->ice_in.cand_idx][cid].foundation = switch_core_session_strdup(smh->session, fields[0]); - engine->ice_in.cands[engine->ice_in.cand_idx][cid].component_id = atoi(fields[1]); - engine->ice_in.cands[engine->ice_in.cand_idx][cid].transport = switch_core_session_strdup(smh->session, fields[2]); - engine->ice_in.cands[engine->ice_in.cand_idx][cid].priority = atol(fields[3]); - engine->ice_in.cands[engine->ice_in.cand_idx][cid].con_addr = switch_core_session_strdup(smh->session, fields[4]); - engine->ice_in.cands[engine->ice_in.cand_idx][cid].con_port = (switch_port_t)atoi(fields[5]); - + + + engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].foundation = switch_core_session_strdup(smh->session, fields[0]); + engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].component_id = atoi(fields[1]); + engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].transport = switch_core_session_strdup(smh->session, fields[2]); + engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].priority = atol(fields[3]); + engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].con_addr = switch_core_session_strdup(smh->session, fields[4]); + engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].con_port = (switch_port_t)atoi(fields[5]); + j = 6; while(j < argc && fields[j+1]) { if (!strcasecmp(fields[j], "typ")) { - engine->ice_in.cands[engine->ice_in.cand_idx][cid].cand_type = switch_core_session_strdup(smh->session, fields[j+1]); + engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].cand_type = switch_core_session_strdup(smh->session, fields[j+1]); } else if (!strcasecmp(fields[j], "raddr")) { - engine->ice_in.cands[engine->ice_in.cand_idx][cid].raddr = switch_core_session_strdup(smh->session, fields[j+1]); + engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].raddr = switch_core_session_strdup(smh->session, fields[j+1]); } else if (!strcasecmp(fields[j], "rport")) { - engine->ice_in.cands[engine->ice_in.cand_idx][cid].rport = (switch_port_t)atoi(fields[j+1]); + engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].rport = (switch_port_t)atoi(fields[j+1]); } else if (!strcasecmp(fields[j], "generation")) { - engine->ice_in.cands[engine->ice_in.cand_idx][cid].generation = switch_core_session_strdup(smh->session, fields[j+1]); + engine->ice_in.cands[engine->ice_in.cand_idx[cid]][cid].generation = switch_core_session_strdup(smh->session, fields[j+1]); } - - j += 2; - } - - if (engine->ice_in.is_chosen[cid]) { - engine->ice_in.cands[engine->ice_in.chosen[cid]][cid].ready++; - } - - engine->ice_in.cand_idx++; - } - - } - - /* still no candidates, so start searching for some based on sane deduction */ - - /* look for candidates on the same network */ - if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) { - for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]); i++) { - if (!engine->ice_in.is_chosen[0] && engine->ice_in.cands[i][0].component_id == 1 && - !engine->ice_in.cands[i][0].rport && ip_possible(smh, engine->ice_in.cands[i][0].con_addr) && - switch_check_network_list_ip(engine->ice_in.cands[i][0].con_addr, "localnet.auto")) { - engine->ice_in.chosen[0] = i; - engine->ice_in.is_chosen[0] = 1; - engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++; - ip_choose_family(smh, engine->ice_in.cands[i][0].con_addr); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, - "No %s RTP candidate found; defaulting to the first local one.\n", type2str(type)); - } - if (!engine->ice_in.is_chosen[1] && engine->ice_in.cands[i][1].component_id == 2 && - !engine->ice_in.cands[i][1].rport && ip_possible(smh, engine->ice_in.cands[i][1].con_addr) && - switch_check_network_list_ip(engine->ice_in.cands[i][1].con_addr, "localnet.auto")) { - engine->ice_in.chosen[1] = i; - engine->ice_in.is_chosen[1] = 1; - engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session),SWITCH_LOG_NOTICE, - "No %s RTCP candidate found; defaulting to the first local one.\n", type2str(type)); + j += 2; } + + engine->ice_in.cand_idx[cid]++; } } - /* look for candidates with srflx */ - if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) { - for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]); i++) { - if (!engine->ice_in.is_chosen[0] && - engine->ice_in.cands[i][0].component_id == 1 && engine->ice_in.cands[i][0].rport && ip_possible(smh, engine->ice_in.cands[i][0].con_addr)) { - engine->ice_in.chosen[0] = i; - engine->ice_in.chosen[1] = 1; - engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++; - ip_choose_family(smh, engine->ice_in.cands[i][0].con_addr); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, - "No %s RTP candidate found; defaulting to the first srflx one.\n", type2str(type)); - } - if (!engine->ice_in.is_chosen[1] && engine->ice_in.cands[i][1].component_id == 2 && engine->ice_in.cands[i][1].rport && - ip_possible(smh, engine->ice_in.cands[i][1].con_addr)) { - engine->ice_in.chosen[1] = i; - engine->ice_in.is_chosen[1] = 1; - engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session),SWITCH_LOG_NOTICE, - "No %s RTCP candidate found; defaulting to the first srflx one.\n", type2str(type)); + for (cid = 0; cid < 2; cid++) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Searching for %s candidate.\n", cid ? "rtcp" : "rtp"); + + for (ai = 0; ai < engine->cand_acl_count; ai++) { + for (i = 0; i < engine->ice_in.cand_idx[cid]; i++) { + if (switch_check_network_list_ip(engine->ice_in.cands[i][cid].con_addr, engine->cand_acl[ai])) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, + "Choose %s candidate, index %d, %s:%d\n", cid ? "rtcp" : "rtp", i, + engine->ice_in.cands[i][cid].con_addr, engine->ice_in.cands[i][cid].con_port); + + engine->ice_in.chosen[cid] = i; + engine->ice_in.is_chosen[cid] = 1; + engine->ice_in.cands[i][cid].ready++; + ip_choose_family(smh, engine->ice_in.cands[i][cid].con_addr); + + if (cid == 0 && got_rtcp_mux && engine->ice_in.cand_idx[1] < MAX_CAND) { + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, + "Choose same candidate, index %d, for rtcp based on rtcp-mux attribute %s:%d\n", engine->ice_in.cand_idx[1], + engine->ice_in.cands[i][cid].con_addr, engine->ice_in.cands[i][cid].con_port); + + + engine->ice_in.cands[engine->ice_in.cand_idx[1]][1] = engine->ice_in.cands[i][0]; + engine->ice_in.chosen[1] = engine->ice_in.cand_idx[1]; + engine->ice_in.is_chosen[1] = 1; + engine->ice_in.cand_idx[1]++; + + goto done_choosing; + } + + goto next_cid; + } } } + + next_cid: + + continue; } - /* Got RTP but not RTCP, probably mux */ - if (engine->ice_in.is_chosen[0] && !engine->ice_in.is_chosen[1] && got_rtcp_mux) { - engine->ice_in.chosen[1] = engine->ice_in.chosen[0]; - engine->ice_in.is_chosen[1] = 1; + done_choosing: - memcpy(&engine->ice_in.cands[engine->ice_in.chosen[1]][1], &engine->ice_in.cands[engine->ice_in.chosen[0]][0], - sizeof(engine->ice_in.cands[engine->ice_in.chosen[0]][0])); - engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++; - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, - "No %s RTCP candidate found; defaulting to the same as RTP [%s:%d]\n", type2str(type), - engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port); - } - - /* look for any candidates and hope for auto-adjust */ - if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) { - for (i = 0; i <= engine->ice_in.cand_idx && (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]); i++) { - if (!engine->ice_in.is_chosen[0] && engine->ice_in.cands[i][0].component_id == 1 && ip_possible(smh, engine->ice_in.cands[i][0].con_addr)) { - engine->ice_in.chosen[0] = i; - engine->ice_in.is_chosen[0] = 1; - engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++; - ip_choose_family(smh, engine->ice_in.cands[i][0].con_addr); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, - "No %s RTP candidate found; defaulting to the first one.\n", type2str(type)); - } - if (!engine->ice_in.is_chosen[1] && engine->ice_in.cands[i][1].component_id == 2) { - engine->ice_in.chosen[1] = i; - engine->ice_in.is_chosen[1] = 1; - engine->ice_in.cands[engine->ice_in.chosen[1]][1].ready++; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, - "No %s RTCP candidate found; defaulting to the first one.\n", type2str(type)); - } - } - } if (!engine->ice_in.is_chosen[0] || !engine->ice_in.is_chosen[1]) { /* PUNT */ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "%s no suitable candidates found.\n", switch_channel_get_name(smh->session->channel)); - return; + return SWITCH_STATUS_FALSE; } for (i = 0; i < 2; i++) { @@ -3362,8 +3303,8 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ if (engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr && engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port) { char tmp[80] = ""; engine->cur_payload_map->remote_sdp_ip = switch_core_session_strdup(smh->session, (char *) engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, - "setting remote %s ice addr to %s:%d based on candidate\n", type2str(type), + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, + "setting remote %s ice addr to index %d %s:%d based on candidate\n", type2str(type), engine->ice_in.chosen[0], engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port); engine->ice_in.cands[engine->ice_in.chosen[0]][0].ready++; @@ -3377,31 +3318,19 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ smh->mparams->remote_ip = engine->cur_payload_map->remote_sdp_ip; } - if (engine->remote_rtcp_port) { - engine->remote_rtcp_port = engine->cur_payload_map->remote_sdp_port; - } - - switch_snprintf(tmp, sizeof(tmp), "%d", engine->cur_payload_map->remote_sdp_port); - switch_channel_set_variable(smh->session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, engine->cur_payload_map->remote_sdp_ip); + switch_snprintf(tmp, sizeof(tmp), "%d", engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port); + switch_channel_set_variable(smh->session->channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE, engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr); switch_channel_set_variable(smh->session->channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE, tmp); } if (engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port) { - if (engine->rtcp_mux) { - engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port = engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_port; - engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr = engine->ice_in.cands[engine->ice_in.chosen[0]][0].con_addr; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, - "Asked by candidate to set remote rtcp %s addr to %s:%d but this is rtcp-mux so no thanks\n", type2str(type), - engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_NOTICE, - "Setting remote rtcp %s addr to %s:%d based on candidate\n", type2str(type), - engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port); - engine->remote_rtcp_ice_port = engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port; - engine->remote_rtcp_ice_addr = switch_core_session_strdup(smh->session, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr); - - engine->remote_rtcp_port = engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port; - } + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, + "Setting remote rtcp %s addr to %s:%d based on candidate\n", type2str(type), + engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port); + engine->remote_rtcp_ice_port = engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port; + engine->remote_rtcp_ice_addr = switch_core_session_strdup(smh->session, engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_addr); + + engine->remote_rtcp_port = engine->ice_in.cands[engine->ice_in.chosen[1]][1].con_port; } @@ -3489,6 +3418,9 @@ static void check_ice(switch_media_handle_t *smh, switch_media_type_t type, sdp_ } } + + + return ice_seen ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_BREAK; } #ifdef _MSC_VER #pragma warning(pop) @@ -3581,7 +3513,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s const char *tmp; int m_idx = 0; int nm_idx = 0; - + switch_assert(session); if (!(smh = session->media_handle)) { @@ -4358,8 +4290,11 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s } if (switch_core_media_set_codec(session, 0, smh->mparams->codec_flags) == SWITCH_STATUS_SUCCESS) { - got_audio = 1; - check_ice(smh, SWITCH_MEDIA_TYPE_AUDIO, sdp, m); + if (check_ice(smh, SWITCH_MEDIA_TYPE_AUDIO, sdp, m) == SWITCH_STATUS_FALSE) { + match = 0; + } else { + got_audio = 1; + } } else { match = 0; } @@ -4632,7 +4567,9 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s } if (switch_core_media_set_video_codec(session, 0) == SWITCH_STATUS_SUCCESS) { - check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, m); + if (check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, m) != SWITCH_STATUS_SUCCESS) { + vmatch = 0; + } } } } @@ -5067,7 +5004,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_start_video_thread(switch_co return SWITCH_STATUS_FALSE; } - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "%s Starting Video thread\n", switch_core_session_get_name(session)); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Starting Video thread\n", switch_core_session_get_name(session)); if (v_engine->rtp_session) { switch_rtp_set_default_payload(v_engine->rtp_session, v_engine->cur_payload_map->agreed_pt); diff --git a/src/switch_rtp.c b/src/switch_rtp.c index b0b9f2f9e6..46f3dca55d 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -1038,7 +1038,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d if (!icep[j] || !icep[j]->ice_params) { continue; } - for (i = 0; i < icep[j]->ice_params->cand_idx; i++) { + for (i = 0; i < icep[j]->ice_params->cand_idx[icep[j]->proto]; i++) { if (icep[j]->ice_params && icep[j]->ice_params->cands[i][icep[j]->proto].priority == *pri) { if (j == IPR_RTP) { icep[j]->ice_params->chosen[j] = i; @@ -1191,7 +1191,7 @@ static void handle_ice(switch_rtp_t *rtp_session, switch_rtp_ice_t *ice, void *d - for (i = 0; i <= ice->ice_params->cand_idx; i++) { + for (i = 0; i <= ice->ice_params->cand_idx[ice->proto]; i++) { if (ice->ice_params->cands[i][ice->proto].con_port == port) { if (!strcmp(ice->ice_params->cands[i][ice->proto].con_addr, host) && !strcmp(ice->ice_params->cands[i][ice->proto].cand_type, "relay")) { @@ -2404,7 +2404,7 @@ static switch_status_t enable_remote_rtcp_socket(switch_rtp_t *rtp_session, cons host = switch_get_addr(bufa, sizeof(bufa), rtp_session->rtcp_remote_addr); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(rtp_session->session), SWITCH_LOG_DEBUG, - "Setting RTCP remote addr to %s:%d\n", host, rtp_session->remote_rtcp_port); + "Setting RTCP remote addr to %s:%d %d\n", host, rtp_session->remote_rtcp_port, rtp_session->rtcp_remote_addr->family); } if (rtp_session->rtcp_sock_input && switch_sockaddr_get_family(rtp_session->rtcp_remote_addr) == @@ -2846,23 +2846,24 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_set_remote_address(switch_rtp_t *rtp_ } - if (rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP] && !rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) { - if (remote_rtcp_port) { - rtp_session->remote_rtcp_port = remote_rtcp_port; + if (rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP]) { + if (rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) { + rtp_session->rtcp_remote_addr = rtp_session->remote_addr; + rtp_session->rtcp_sock_output = rtp_session->sock_output; } else { - rtp_session->remote_rtcp_port = rtp_session->eff_remote_port + 1; + if (remote_rtcp_port) { + rtp_session->remote_rtcp_port = remote_rtcp_port; + } else { + rtp_session->remote_rtcp_port = rtp_session->eff_remote_port + 1; + } + status = enable_remote_rtcp_socket(rtp_session, err); + + if (rtp_session->rtcp_dtls) { + //switch_sockaddr_info_get(&rtp_session->rtcp_dtls->remote_addr, host, SWITCH_UNSPEC, port, 0, rtp_session->pool); + rtp_session->rtcp_dtls->remote_addr = rtp_session->rtcp_remote_addr; + rtp_session->rtcp_dtls->sock_output = rtp_session->rtcp_sock_output; + } } - status = enable_remote_rtcp_socket(rtp_session, err); - - if (rtp_session->rtcp_dtls) { - //switch_sockaddr_info_get(&rtp_session->rtcp_dtls->remote_addr, host, SWITCH_UNSPEC, port, 0, rtp_session->pool); - rtp_session->rtcp_dtls->remote_addr = rtp_session->rtcp_remote_addr; - rtp_session->rtcp_dtls->sock_output = rtp_session->rtcp_sock_output; - } - } - - if (rtp_session->flags[SWITCH_RTP_FLAG_ENABLE_RTCP] && rtp_session->flags[SWITCH_RTP_FLAG_RTCP_MUX]) { - rtp_session->rtcp_remote_addr = rtp_session->remote_addr; } switch_mutex_unlock(rtp_session->write_mutex); @@ -4112,8 +4113,10 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_rtcp(switch_rtp_t *rtp_sessi rtp_session->rtcp_sock_output = rtp_session->sock_output; rtp_session->rtcp_recv_msg_p = (rtcp_msg_t *) &rtp_session->recv_msg; + + return SWITCH_STATUS_SUCCESS; - return enable_remote_rtcp_socket(rtp_session, &err); + //return enable_remote_rtcp_socket(rtp_session, &err); } else { rtp_session->rtcp_recv_msg_p = (rtcp_msg_t *) &rtp_session->rtcp_recv_msg; } From 4dc7e2a2bbc1c039c2ee4066dd79c0b11e751dcb Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 3 Jun 2015 15:56:26 -0500 Subject: [PATCH 40/43] FS-7587 #comment one profile to rule them all --- conf/vanilla/autoload_configs/verto.conf.xml | 28 +++++--------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/conf/vanilla/autoload_configs/verto.conf.xml b/conf/vanilla/autoload_configs/verto.conf.xml index b69777ac0a..e55359aa6d 100644 --- a/conf/vanilla/autoload_configs/verto.conf.xml +++ b/conf/vanilla/autoload_configs/verto.conf.xml @@ -8,25 +8,6 @@ - - - - - - - - - - - - - - - - - - - @@ -35,17 +16,22 @@ - + + + + + + + - From 150ebff5d4e9362a36ec98bd4b873b12ffde246e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 3 Jun 2015 16:04:51 -0500 Subject: [PATCH 41/43] FS-7602 FS-7499 FS-7587 #comment another refactoring pass on candidate parsing and ipv4/6 parsing (part 2) --- src/switch_core_media.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/switch_core_media.c b/src/switch_core_media.c index f9698841a8..df872dfa30 100644 --- a/src/switch_core_media.c +++ b/src/switch_core_media.c @@ -3241,6 +3241,11 @@ static switch_status_t check_ice(switch_media_handle_t *smh, switch_media_type_t } } + if (!ice_seen) { + return SWITCH_STATUS_SUCCESS; + } + + for (cid = 0; cid < 2; cid++) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(smh->session), SWITCH_LOG_DEBUG, "Searching for %s candidate.\n", cid ? "rtcp" : "rtp"); @@ -3419,7 +3424,6 @@ static switch_status_t check_ice(switch_media_handle_t *smh, switch_media_type_t } - return ice_seen ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_BREAK; } #ifdef _MSC_VER @@ -4567,7 +4571,7 @@ SWITCH_DECLARE(uint8_t) switch_core_media_negotiate_sdp(switch_core_session_t *s } if (switch_core_media_set_video_codec(session, 0) == SWITCH_STATUS_SUCCESS) { - if (check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, m) != SWITCH_STATUS_SUCCESS) { + if (check_ice(smh, SWITCH_MEDIA_TYPE_VIDEO, sdp, m) == SWITCH_STATUS_FALSE) { vmatch = 0; } } From 9d46b63742084fe007618c9539548c4c5e502cc5 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 3 Jun 2015 16:09:02 -0500 Subject: [PATCH 42/43] FS-7587 #comment one profile to rule them all (part 2) --- conf/vanilla/autoload_configs/verto.conf.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/vanilla/autoload_configs/verto.conf.xml b/conf/vanilla/autoload_configs/verto.conf.xml index e55359aa6d..73037325cd 100644 --- a/conf/vanilla/autoload_configs/verto.conf.xml +++ b/conf/vanilla/autoload_configs/verto.conf.xml @@ -5,7 +5,7 @@ - + From 564393cf27618ddf3140ef05f35901d6beb6dbcd Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 3 Jun 2015 16:21:12 -0500 Subject: [PATCH 43/43] refresh checkboxes in demo --- html5/verto/video_demo/verto.js | 1 + 1 file changed, 1 insertion(+) diff --git a/html5/verto/video_demo/verto.js b/html5/verto/video_demo/verto.js index b53e5eee70..b9e458f3c9 100644 --- a/html5/verto/video_demo/verto.js +++ b/html5/verto/video_demo/verto.js @@ -795,6 +795,7 @@ function refresh_devices() //$("input[type='radio']).checkboxradio({}); $("input[type='radio']").checkboxradio("refresh"); + $("input[type='checkbox']").checkboxradio("refresh"); //console.error($("#usecamera").find(":selected").val()); }