summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES30
-rw-r--r--Makefile.moddir_rules2
-rw-r--r--UPGRADE-15.txt23
-rw-r--r--UPGRADE.txt16
-rw-r--r--apps/app_followme.c24
-rwxr-xr-xbuild_tools/download_externals6
-rw-r--r--cel/cel_odbc.c2
-rw-r--r--configs/samples/followme.conf.sample12
-rw-r--r--configs/samples/pjsip.conf.sample11
-rwxr-xr-xconfigure11
-rw-r--r--configure.ac2
-rw-r--r--contrib/ast-db-manage/config/versions/52798ad97bdf_add_pjsip_identify_by_header.py57
-rw-r--r--include/asterisk/res_pjsip.h2
-rw-r--r--res/res_pjsip.c11
-rw-r--r--res/res_pjsip/pjsip_configuration.c5
-rw-r--r--res/res_pjsip_endpoint_identifier_ip.c57
-rw-r--r--third-party/pjproject/patches/0060-sip_msg-Prevent-crash-on-header-without-vptr.patch47
17 files changed, 265 insertions, 53 deletions
diff --git a/CHANGES b/CHANGES
index ec533e831..c30b4caad 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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
diff --git a/configure b/configure
index 749b2fc68..988f75808 100755
--- a/configure
+++ b/configure
@@ -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
+