diff options
-rw-r--r-- | CHANGES | 30 | ||||
-rw-r--r-- | Makefile.moddir_rules | 2 | ||||
-rw-r--r-- | UPGRADE-15.txt | 23 | ||||
-rw-r--r-- | UPGRADE.txt | 16 | ||||
-rw-r--r-- | apps/app_followme.c | 24 | ||||
-rwxr-xr-x | build_tools/download_externals | 6 | ||||
-rw-r--r-- | cel/cel_odbc.c | 2 | ||||
-rw-r--r-- | configs/samples/followme.conf.sample | 12 | ||||
-rw-r--r-- | configs/samples/pjsip.conf.sample | 11 | ||||
-rwxr-xr-x | configure | 11 | ||||
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | contrib/ast-db-manage/config/versions/52798ad97bdf_add_pjsip_identify_by_header.py | 57 | ||||
-rw-r--r-- | include/asterisk/res_pjsip.h | 2 | ||||
-rw-r--r-- | res/res_pjsip.c | 11 | ||||
-rw-r--r-- | res/res_pjsip/pjsip_configuration.c | 5 | ||||
-rw-r--r-- | res/res_pjsip_endpoint_identifier_ip.c | 57 | ||||
-rw-r--r-- | third-party/pjproject/patches/0060-sip_msg-Prevent-crash-on-header-without-vptr.patch | 47 |
17 files changed, 265 insertions, 53 deletions
@@ -57,6 +57,36 @@ cdr_syslog built. ------------------------------------------------------------------------------ +--- Functionality changes from Asterisk 15.2.0 to Asterisk 15.3.0 ------------ +------------------------------------------------------------------------------ + +app_followme +------------------ + * Added a new prompt, connecting-prompt, which will be played + (if configured) to the "winner" callee before connecting the call. + +res_pjsip +------------------ + * Users who are matching endpoints by SIP header need to reevaluate their + global "endpoint_identifier_order" option in light of the "ip" endpoint + identifier method split into the "ip" and "header" endpoint identifier + methods. + +res_pjsip_endpoint_identifier_ip +------------------ + * The endpoint identifier "ip" method previously recognized endpoints either + by IP address or a matching SIP header. The "ip" endpoint identifier method + is now split into the "ip" and "header" endpoint identifier methods. The + "ip" endpoint identifier method only matches by IP address and the "header" + endpoint identifier method only matches by SIP header. The split allows the + user to control the relative priority of the IP address and the SIP header + identification methods in the global "endpoint_identifier_order" option. + e.g., If you have two type=identify sections where one matches by IP address + for endpoint alice and the other matches by SIP header for endpoint bob then + you can now predict which endpoint is matched when a request comes in that + matches both. + +------------------------------------------------------------------------------ --- Functionality changes from Asterisk 15.1.0 to Asterisk 15.2.0 ------------ ------------------------------------------------------------------------------ diff --git a/Makefile.moddir_rules b/Makefile.moddir_rules index 917c8e08c..5d82088a9 100644 --- a/Makefile.moddir_rules +++ b/Makefile.moddir_rules @@ -115,7 +115,7 @@ ifneq ($(findstring :,$(XMLSTARLET)$(BASH)),:) @if [ -f .moduleinfo ] ; then \ declare -A DISABLED_MODS ;\ for x in $(MENUSELECT_$(MENUSELECT_CATEGORY)) ; do DISABLED_MODS[$${x}]=1 ; done ;\ - EXTERNAL_MODS=$$(xmlstarlet sel -t -m "/category/member[support_level = 'external']" -v "@name" -n .moduleinfo) ;\ + EXTERNAL_MODS=$$($(XMLSTARLET) sel -t -m "/category/member[support_level = 'external']" -v "@name" -n .moduleinfo) ;\ for x in $${EXTERNAL_MODS} ; do \ if [ -z "$${DISABLED_MODS[$${x}]}" ] ; then \ $(ASTTOPDIR)/build_tools/download_externals $${x} ;\ diff --git a/UPGRADE-15.txt b/UPGRADE-15.txt index 30dc5d04c..d47bbe38a 100644 --- a/UPGRADE-15.txt +++ b/UPGRADE-15.txt @@ -23,6 +23,29 @@ === UPGRADE-14.txt -- Upgrade info for 13 to 14 =========================================================== +From 15.2.0 to 15.3.0: + +res_pjsip +------------------ + * Users who are matching endpoints by SIP header need to reevaluate their + global "endpoint_identifier_order" option in light of the "ip" endpoint + identifier method split into the "ip" and "header" endpoint identifier + methods. + +res_pjsip_endpoint_identifier_ip +------------------ + * The endpoint identifier "ip" method previously recognized endpoints either + by IP address or a matching SIP header. The "ip" endpoint identifier method + is now split into the "ip" and "header" endpoint identifier methods. The + "ip" endpoint identifier method only matches by IP address and the "header" + endpoint identifier method only matches by SIP header. The split allows the + user to control the relative priority of the IP address and the SIP header + identification methods in the global "endpoint_identifier_order" option. + e.g., If you have two type=identify sections where one matches by IP address + for endpoint alice and the other matches by SIP header for endpoint bob then + you can now predict which endpoint is matched when a request comes in that + matches both. + New in 15.0.0: Build System: diff --git a/UPGRADE.txt b/UPGRADE.txt index b2c75fbb5..8f45742af 100644 --- a/UPGRADE.txt +++ b/UPGRADE.txt @@ -43,19 +43,3 @@ ARI: cdr_syslog: - The cdr_syslog module is now deprecated and by default it is no longer built. - -New in 15.0.0: - -Build System: - - '--with-pjproject-bundled' is now the default when running ./configure - It can be disabled with '--without-pjproject-bundled'. - -Core: - - Multi-stream support has been added so a channel can have multiple - streams of the same type such as audio and video. - - - The 'Data Retrieval API' has been removed. This API was not actively - maintained, was not added to new modules (such as res_pjsip), and there - exist better alternatives to acquire the same information, such as the - ARI. As a result, the 'DataGet' AMI action as well as the 'data get' - CLI command have been removed. diff --git a/apps/app_followme.c b/apps/app_followme.c index 7b47f4dbb..dbb11ee26 100644 --- a/apps/app_followme.c +++ b/apps/app_followme.c @@ -176,6 +176,7 @@ struct call_followme { char plsholdprompt[PATH_MAX]; /*!< Sound prompt name and path */ char statusprompt[PATH_MAX]; /*!< Sound prompt name and path */ char sorryprompt[PATH_MAX]; /*!< Sound prompt name and path */ + char connprompt[PATH_MAX]; /*!< Sound prompt name and path */ AST_LIST_HEAD_NOLOCK(numbers, number) numbers; /*!< Head of the list of follow-me numbers */ AST_LIST_HEAD_NOLOCK(blnumbers, number) blnumbers; /*!< Head of the list of black-listed numbers */ @@ -212,6 +213,7 @@ struct fm_args { char plsholdprompt[PATH_MAX]; /*!< Sound prompt name and path */ char statusprompt[PATH_MAX]; /*!< Sound prompt name and path */ char sorryprompt[PATH_MAX]; /*!< Sound prompt name and path */ + char connprompt[PATH_MAX]; /*!< Sound prompt name and path */ struct ast_flags followmeflags; }; @@ -277,6 +279,7 @@ static char optionsprompt[PATH_MAX] = "followme/options"; static char plsholdprompt[PATH_MAX] = "followme/pls-hold-while-try"; static char statusprompt[PATH_MAX] = "followme/status"; static char sorryprompt[PATH_MAX] = "followme/sorry"; +static char connprompt[PATH_MAX] = ""; static AST_RWLIST_HEAD_STATIC(followmes, call_followme); @@ -333,6 +336,7 @@ static void init_profile(struct call_followme *f, int activate) ast_copy_string(f->plsholdprompt, plsholdprompt, sizeof(f->plsholdprompt)); ast_copy_string(f->statusprompt, statusprompt, sizeof(f->statusprompt)); ast_copy_string(f->sorryprompt, sorryprompt, sizeof(f->sorryprompt)); + ast_copy_string(f->connprompt, connprompt, sizeof(f->connprompt)); if (activate) { f->active = 1; } @@ -366,7 +370,9 @@ static void profile_set_param(struct call_followme *f, const char *param, const ast_copy_string(f->statusprompt, val, sizeof(f->statusprompt)); else if (!strcasecmp(param, "followme-sorry-prompt") || !strcasecmp(param, "sorry_prompt")) ast_copy_string(f->sorryprompt, val, sizeof(f->sorryprompt)); - else if (failunknown) { + else if (!strcasecmp(param, "followme-connecting-prompt") || !strcasecmp(param, "connecting_prompt")) { + ast_copy_string(f->connprompt, val, sizeof(f->connprompt)); + } else if (failunknown) { if (linenum >= 0) ast_log(LOG_WARNING, "Unknown keyword in profile '%s': %s at line %d of followme.conf\n", f->name, param, linenum); else @@ -489,6 +495,13 @@ static int reload_followme(int reload) ast_copy_string(sorryprompt, tmpstr, sizeof(sorryprompt)); } + if ((tmpstr = ast_variable_retrieve(cfg, "general", "connecting-prompt")) && !ast_strlen_zero(tmpstr)) { + ast_copy_string(connprompt, tmpstr, sizeof(connprompt)); + } else if ((tmpstr = ast_variable_retrieve(cfg, "general", "connecting_prompt")) && !ast_strlen_zero(tmpstr)) { + ast_copy_string(connprompt, tmpstr, sizeof(connprompt)); + } + + /* Chug through config file */ while ((cat = ast_category_browse(cfg, cat))) { int new = 0; @@ -1408,6 +1421,7 @@ static int app_exec(struct ast_channel *chan, const char *data) ast_copy_string(targs->plsholdprompt, f->plsholdprompt, sizeof(targs->plsholdprompt)); ast_copy_string(targs->statusprompt, f->statusprompt, sizeof(targs->statusprompt)); ast_copy_string(targs->sorryprompt, f->sorryprompt, sizeof(targs->sorryprompt)); + ast_copy_string(targs->connprompt, f->connprompt, sizeof(targs->connprompt)); /* Copy the numbers we're going to use into another list in case the master list should get modified (and locked) while we're trying to do a follow-me */ AST_LIST_HEAD_INIT_NOLOCK(&targs->cnumbers); @@ -1495,6 +1509,14 @@ static int app_exec(struct ast_channel *chan, const char *data) res = 0; } else { caller = chan; + + /* Play "connecting" message to the winner, if configured. */ + if (!ast_strlen_zero(targs->connprompt)) { + ast_autoservice_start(caller); + ast_stream_and_wait(outbound, targs->connprompt, ""); + ast_autoservice_stop(caller); + } + /* Bridge the two channels. */ memset(&config, 0, sizeof(config)); diff --git a/build_tools/download_externals b/build_tools/download_externals index efeb6c53c..f27271fd5 100755 --- a/build_tools/download_externals +++ b/build_tools/download_externals @@ -165,7 +165,7 @@ if [[ -f ${DESTDIR}${ASTMODDIR}/${module_name}.manifest.xml ]] ; then fi fi - cs=$(md5sum ${f} | cut -b1-32) + cs=$(${MD5} ${f} | cut -b1-32) if [[ "${cs}" != "${sum}" ]] ; then echo Checksum mismatch: ${f} need_install=1 @@ -214,7 +214,7 @@ trap "rm -rf ${cache_dir}/${module_dir} ; rm -rf ${tmpdir}" EXIT echo "${full_name}: Installing." if [[ $EUID == 0 ]] ; then - install_params="--group=0 --owner=0" + install_params="-g 0 -o 0" fi names=$(${XMLSTARLET} sel -t -m "//file" -v "@name" -n ${cache_dir}/${module_dir}/manifest.xml) @@ -229,7 +229,7 @@ for name in ${names} ; do mode=0644 fi - ${INSTALL} -Dp ${install_params} --mode=${mode} ${source_path} ${install_path} + ${INSTALL} -Dp ${install_params} -m ${mode} ${source_path} ${install_path} done ${INSTALL} -Dp ${install_params} --mode=0644 ${cache_dir}/${module_dir}/manifest.xml ${DESTDIR}${ASTMODDIR}/${module_name}.manifest.xml diff --git a/cel/cel_odbc.c b/cel/cel_odbc.c index a289b877c..05c1095cb 100644 --- a/cel/cel_odbc.c +++ b/cel/cel_odbc.c @@ -849,7 +849,7 @@ static int reload(void) return AST_MODULE_LOAD_SUCCESS; } -AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, ODBC_BACKEND_NAME, +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "ODBC CEL backend", .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, diff --git a/configs/samples/followme.conf.sample b/configs/samples/followme.conf.sample index 487554d81..25421e651 100644 --- a/configs/samples/followme.conf.sample +++ b/configs/samples/followme.conf.sample @@ -39,7 +39,11 @@ status_prompt=>followme/status sorry_prompt=>followme/sorry ; The global default for 'I'm sorry, but we were unable to locate your party' message. ; -; +connecting_prompt=> +; The global default sound file name for 'Please say hello to the caller' message. +; Setting to an empty string skips playing the prompt. The default is no prompt +; file name. + [default] musicclass=>default ; The moh class that should be used for the caller while they are waiting to be connected. @@ -95,3 +99,9 @@ status_prompt=>followme/status sorry_prompt=>followme/sorry ; The 'I'm sorry, but we were unable to locate your party' message prompt. Default ; is the global default. +; +connecting_prompt=> +; The sound file name for 'Please say hello to the caller' message. Default is the +; global default. +; + diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample index 849932069..a39a8675a 100644 --- a/configs/samples/pjsip.conf.sample +++ b/configs/samples/pjsip.conf.sample @@ -635,6 +635,7 @@ ; "username": Identify by the From or To username and domain ; "auth_username": Identify by the Authorization username and realm ; "ip": Identify by the source IP address + ; "header": Identify by a configured SIP header value. ; In the username and auth_username cases, if an exact match ; on both username and domain/realm fails, the match is ; retried with just the username. @@ -993,11 +994,11 @@ ; (default: "no") ;endpoint_identifier_order=ip,username,anonymous ; The order by which endpoint identifiers are given priority. - ; Currently, "ip", "username", "auth_username" and "anonymous" are valid - ; identifiers as registered by the res_pjsip_endpoint_identifier_* modules. - ; Some modules like res_pjsip_endpoint_identifier_user register more than - ; one identifier. Use the CLI command "pjsip show identifiers" to see the - ; identifiers currently available. + ; Currently, "ip", "header", "username", "auth_username" and "anonymous" + ; are valid identifiers as registered by the res_pjsip_endpoint_identifier_* + ; modules. Some modules like res_pjsip_endpoint_identifier_user register + ; more than one identifier. Use the CLI command "pjsip show identifiers" + ; to see the identifiers currently available. ; (default: ip,username,anonymous) ;max_initial_qualify_time=4 ; The maximum amount of time (in seconds) from ; startup that qualifies should be attempted on all @@ -7604,8 +7604,10 @@ $as_echo "no" >&6; } fi -# Extract the first word of "xmlstarlet", so it can be a program name with args. -set dummy xmlstarlet; ac_word=$2 +for ac_prog in xmlstarlet xml +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_XMLSTARLET+:} false; then : @@ -7631,7 +7633,6 @@ done done IFS=$as_save_IFS - test -z "$ac_cv_path_XMLSTARLET" && ac_cv_path_XMLSTARLET=":" ;; esac fi @@ -7645,6 +7646,10 @@ $as_echo "no" >&6; } fi + test -n "$XMLSTARLET" && break +done +test -n "$XMLSTARLET" || XMLSTARLET=":" + # Extract the first word of "bash", so it can be a program name with args. set dummy bash; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 diff --git a/configure.ac b/configure.ac index f68338b2d..64ecbfab3 100644 --- a/configure.ac +++ b/configure.ac @@ -281,7 +281,7 @@ AC_PATH_PROG([RUBBER], [rubber], :) AC_PATH_PROG([CATDVI], [catdvi], :) AC_PATH_PROG([KPATHSEA], [kpsewhich], :) AC_PATH_PROG([XMLLINT], [xmllint], :) -AC_PATH_PROG([XMLSTARLET], [xmlstarlet], :) +AC_PATH_PROGS([XMLSTARLET], [xmlstarlet xml], :) AC_PATH_PROG([BASH], [bash], :) AC_PATH_PROG([GIT], [git], :) AC_PATH_PROG([ALEMBIC], [alembic], :) diff --git a/contrib/ast-db-manage/config/versions/52798ad97bdf_add_pjsip_identify_by_header.py b/contrib/ast-db-manage/config/versions/52798ad97bdf_add_pjsip_identify_by_header.py new file mode 100644 index 000000000..ab5939cfe --- /dev/null +++ b/contrib/ast-db-manage/config/versions/52798ad97bdf_add_pjsip_identify_by_header.py @@ -0,0 +1,57 @@ +"""add pjsip identify by header + +Revision ID: 52798ad97bdf +Revises: e2f04d309071 +Create Date: 2018-01-08 12:16:02.782277 + +""" + +# revision identifiers, used by Alembic. +revision = '52798ad97bdf' +down_revision = 'e2f04d309071' + +from alembic import op +import sqlalchemy as sa + + +def column_upgrade(table_name, column_name, enum_name): + if op.get_context().bind.dialect.name != 'postgresql': + if op.get_context().bind.dialect.name == 'mssql': + op.drop_constraint('ck_ps_endpoints_identify_by_pjsip_identify_by_values', + table_name) + op.alter_column(table_name, column_name, type_=sa.String(80)) + return + + # Postgres requires a few more steps + op.execute('ALTER TABLE ' + table_name + ' ALTER COLUMN ' + column_name + + ' TYPE varchar(80) USING identify_by::text::' + enum_name) + + op.execute('DROP TYPE ' + enum_name) + + +def column_downgrade(table_name, column_name, enum_name, enum_values): + if op.get_context().bind.dialect.name != 'postgresql': + op.alter_column(table_name, column_name, + type_=sa.Enum(*enum_values, name=enum_name)) + return + + # Postgres requires a few more steps + updated = sa.Enum(*enum_values, name=enum_name) + updated.create(op.get_bind(), checkfirst=False) + + op.execute('ALTER TABLE ' + table_name + ' ALTER COLUMN ' + column_name + + ' TYPE ' + enum_name + ' USING identify_by::text::' + enum_name) + + +def upgrade(): + # The ps_endpoints identify_by column has always been a comma separated + # list of enum values. This is better represented as a string anyway to + # avoid database compatibility issues. Also future changes are likely + # to allow loadable endpoint identifier names and negating fixed enum + # benefits. + column_upgrade('ps_endpoints', 'identify_by', 'pjsip_identify_by_values') + + +def downgrade(): + column_downgrade('ps_endpoints', 'identify_by', 'pjsip_identify_by_values', + ['username', 'auth_username', 'ip']) diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h index 6c48d2e84..66b99b8f7 100644 --- a/include/asterisk/res_pjsip.h +++ b/include/asterisk/res_pjsip.h @@ -443,6 +443,8 @@ enum ast_sip_endpoint_identifier_type { AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME = (1 << 1), /*! Identify based on source IP address */ AST_SIP_ENDPOINT_IDENTIFY_BY_IP = (1 << 2), + /*! Identify based on arbitrary headers */ + AST_SIP_ENDPOINT_IDENTIFY_BY_HEADER = (1 << 3), }; AST_VECTOR(ast_sip_identify_by_vector, enum ast_sip_endpoint_identifier_type); diff --git a/res/res_pjsip.c b/res/res_pjsip.c index 3f9574d2a..07fc980ef 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -323,6 +323,17 @@ endpoint identification. </para> </enum> + <enum name="header"> + <para>Matches the endpoint based on a configured SIP header + value. + </para> + <para>This method of identification is not configured here + but simply allowed by this configuration option. See the + documentation for the <literal>identify</literal> + configuration section for more details on this method of + endpoint identification. + </para> + </enum> </enumlist> </description> </configOption> diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c index c79877a85..d1bfdfe01 100644 --- a/res/res_pjsip/pjsip_configuration.c +++ b/res/res_pjsip/pjsip_configuration.c @@ -594,6 +594,9 @@ static const char *sip_endpoint_identifier_type2str(enum ast_sip_endpoint_identi case AST_SIP_ENDPOINT_IDENTIFY_BY_IP: str = "ip"; break; + case AST_SIP_ENDPOINT_IDENTIFY_BY_HEADER: + str = "header"; + break; } return str; } @@ -617,6 +620,8 @@ static int sip_endpoint_identifier_str2type(const char *str) method = AST_SIP_ENDPOINT_IDENTIFY_BY_AUTH_USERNAME; } else if (!strcasecmp(str, "ip")) { method = AST_SIP_ENDPOINT_IDENTIFY_BY_IP; + } else if (!strcasecmp(str, "header")) { + method = AST_SIP_ENDPOINT_IDENTIFY_BY_HEADER; } else { method = -1; } diff --git a/res/res_pjsip_endpoint_identifier_ip.c b/res/res_pjsip_endpoint_identifier_ip.c index 58e462460..ee47e4d4e 100644 --- a/res/res_pjsip_endpoint_identifier_ip.c +++ b/res/res_pjsip_endpoint_identifier_ip.c @@ -186,7 +186,7 @@ static int header_identify_match_check(void *obj, void *arg, int flags) return 0; } - return CMP_MATCH | CMP_STOP; + return CMP_MATCH; } /*! \brief Comparator function for matching an object by IP address */ @@ -201,7 +201,7 @@ static int ip_identify_match_check(void *obj, void *arg, int flags) ast_debug(3, "Source address %s matches identify '%s'\n", ast_sockaddr_stringify(addr), ast_sorcery_object_get_id(identify)); - return CMP_MATCH | CMP_STOP; + return CMP_MATCH; } else { ast_debug(3, "Source address %s does not match identify '%s'\n", ast_sockaddr_stringify(addr), @@ -210,48 +210,62 @@ static int ip_identify_match_check(void *obj, void *arg, int flags) } } -static struct ast_sip_endpoint *ip_identify(pjsip_rx_data *rdata) +static struct ast_sip_endpoint *common_identify(ao2_callback_fn *identify_match_cb, void *arg) { - struct ast_sockaddr addr = { { 0, } }; RAII_VAR(struct ao2_container *, candidates, NULL, ao2_cleanup); - RAII_VAR(struct ip_identify_match *, match, NULL, ao2_cleanup); + struct ip_identify_match *match; struct ast_sip_endpoint *endpoint; /* If no possibilities exist return early to save some time */ - if (!(candidates = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "identify", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL)) || - !ao2_container_count(candidates)) { + candidates = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "identify", + AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); + if (!candidates || !ao2_container_count(candidates)) { ast_debug(3, "No identify sections to match against\n"); return NULL; } - ast_sockaddr_parse(&addr, rdata->pkt_info.src_name, PARSE_PORT_FORBID); - ast_sockaddr_set_port(&addr, rdata->pkt_info.src_port); - - match = ao2_callback(candidates, 0, ip_identify_match_check, &addr); + match = ao2_callback(candidates, 0, identify_match_cb, arg); if (!match) { - ast_debug(3, "Identify checks by IP address failed to find match: '%s' did not match any identify section rules\n", - ast_sockaddr_stringify(&addr)); - match = ao2_callback(candidates, 0, header_identify_match_check, rdata); - if (!match) { - return NULL; - } + return NULL; } - endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", match->endpoint_name); + endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", + match->endpoint_name); if (endpoint) { - ast_debug(3, "Retrieved endpoint %s\n", ast_sorcery_object_get_id(endpoint)); + ast_debug(3, "Identify '%s' SIP message matched to endpoint %s\n", + ast_sorcery_object_get_id(match), match->endpoint_name); } else { - ast_log(LOG_WARNING, "Identify section '%s' points to endpoint '%s' but endpoint could not be looked up\n", - ast_sorcery_object_get_id(match), match->endpoint_name); + ast_log(LOG_WARNING, "Identify '%s' points to endpoint '%s' but endpoint could not be found\n", + ast_sorcery_object_get_id(match), match->endpoint_name); } + ao2_ref(match, -1); return endpoint; } +static struct ast_sip_endpoint *ip_identify(pjsip_rx_data *rdata) +{ + struct ast_sockaddr addr = { { 0, } }; + + ast_sockaddr_parse(&addr, rdata->pkt_info.src_name, PARSE_PORT_FORBID); + ast_sockaddr_set_port(&addr, rdata->pkt_info.src_port); + + return common_identify(ip_identify_match_check, &addr); +} + static struct ast_sip_endpoint_identifier ip_identifier = { .identify_endpoint = ip_identify, }; +static struct ast_sip_endpoint *header_identify(pjsip_rx_data *rdata) +{ + return common_identify(header_identify_match_check, rdata); +} + +static struct ast_sip_endpoint_identifier header_identifier = { + .identify_endpoint = header_identify, +}; + /*! \brief Helper function which performs a host lookup and adds result to identify match */ static int ip_identify_match_host_lookup(struct ip_identify_match *identify, const char *host) { @@ -720,6 +734,7 @@ static int load_module(void) ast_sorcery_load_object(ast_sip_get_sorcery(), "identify"); ast_sip_register_endpoint_identifier_with_name(&ip_identifier, "ip"); + ast_sip_register_endpoint_identifier_with_name(&header_identifier, "header"); ast_sip_register_endpoint_formatter(&endpoint_identify_formatter); cli_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL); diff --git a/third-party/pjproject/patches/0060-sip_msg-Prevent-crash-on-header-without-vptr.patch b/third-party/pjproject/patches/0060-sip_msg-Prevent-crash-on-header-without-vptr.patch new file mode 100644 index 000000000..c96292a95 --- /dev/null +++ b/third-party/pjproject/patches/0060-sip_msg-Prevent-crash-on-header-without-vptr.patch @@ -0,0 +1,47 @@ +From cf6b662b8fe450ea7dc6eb5adb2b878971ce0d67 Mon Sep 17 00:00:00 2001 +From: George Joseph <gjoseph@digium.com> +Date: Wed, 10 Jan 2018 08:48:32 -0700 +Subject: [PATCH] sip_msg: Prevent crash on header without vptr + +Occasionally a header with no vptr gets into the list of header. This +causes a crash when printing them. We still need to figure out how +the header got there but this patch at least prevents the crash by checking +for a non-NULL vptr before attempting to call its print function. +--- + pjsip/src/pjsip/sip_msg.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/pjsip/src/pjsip/sip_msg.c b/pjsip/src/pjsip/sip_msg.c +index 76d07b563..194b5ee01 100644 +--- a/pjsip/src/pjsip/sip_msg.c ++++ b/pjsip/src/pjsip/sip_msg.c +@@ -26,6 +26,7 @@ + #include <pj/string.h> + #include <pj/pool.h> + #include <pj/assert.h> ++#include <pj/log.h> + #include <pjlib-util/string.h> + + PJ_DEF_DATA(const pjsip_method) pjsip_invite_method = +@@ -469,6 +470,8 @@ PJ_DEF(pj_ssize_t) pjsip_msg_print( const pjsip_msg *msg, + + *p++ = '\r'; + *p++ = '\n'; ++ } else { ++ PJ_LOG(1, ("sip_msg", "Header with no vptr encountered!! Current buffer: %.*s", (int)(p-buf), buf)); + } + } + +@@ -576,6 +579,9 @@ PJ_DEF(void*) pjsip_hdr_shallow_clone( pj_pool_t *pool, const void *hdr_ptr ) + PJ_DEF(int) pjsip_hdr_print_on( void *hdr_ptr, char *buf, pj_size_t len) + { + pjsip_hdr *hdr = (pjsip_hdr*) hdr_ptr; ++ if (!hdr->vptr) { ++ return 0; ++ } + return (*hdr->vptr->print_on)(hdr_ptr, buf, len); + } + +-- +2.14.3 + |