summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES25
-rw-r--r--apps/app_voicemail.c20
-rw-r--r--channels/chan_sip.c1
-rw-r--r--channels/pjsip/cli_commands.c16
-rw-r--r--configs/samples/hep.conf.sample10
-rw-r--r--configs/samples/voicemail.conf.sample2
-rw-r--r--contrib/ast-db-manage/config/versions/465e70e8c337_add_match_header_attribute_to_identify.py21
-rw-r--r--funcs/func_devstate.c2
-rw-r--r--main/stasis_cache.c2
-rw-r--r--menuselect/menuselect.c8
-rw-r--r--menuselect/menuselect.h3
-rw-r--r--res/res_pjsip.c22
-rw-r--r--res/res_pjsip_endpoint_identifier_ip.c96
-rw-r--r--res/res_pjsip_outbound_registration.c18
-rw-r--r--res/res_pjsip_transport_websocket.c30
-rw-r--r--third-party/pjproject/Makefile2
-rw-r--r--third-party/pjproject/patches/0014-Add-pjsip-transport-register-type-ipv6.patch62
17 files changed, 283 insertions, 57 deletions
diff --git a/CHANGES b/CHANGES
index 85658a4ec..ad1ff237b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -12,6 +12,14 @@
--- Functionality changes from Asterisk 13.14.0 to Asterisk 13.15.0 ----------
------------------------------------------------------------------------------
+AMI
+------------------
+ * The 'PJSIPShowEndpoint' command's respone event of 'IdentifyDetail' now
+ contains a new optional parameter, 'MatchHeader', mapping to the new
+ configuration option 'match_header' for the corresponding 'identify' object.
+ It should be noted that since 'match_header' takes in a key: value pair, the
+ event parameter will contain a ':' as well.
+
app_record
------------------
* Added new 'u' option to Record() application which prevents Asterisk from
@@ -30,6 +38,9 @@ app_voicemail
* The 'Comedian Mail' prompts can now be overriden using the 'vm-login' and
'vm-newuser' configuration options in voicemail.conf.
+ * Added 'fromstring' field to the voicemail boxes. If set, it will override
+ the global 'fromstring' field on a per-mailbox basis.
+
res_pjsip_transport_websocket
------------------
* Removed non-secure websocket support. Firefox and Chrome have not allowed
@@ -38,6 +49,20 @@ res_pjsip_transport_websocket
when Asterisk attempts to send SIP requests to do something like initiate
call hangup.
+res_pjsip_endpoint_identifier_ip
+------------------
+ * A new option has been added to the 'identify' configuration object,
+ 'match_header'. The 'match_header' attribute should contain a SIP
+ header: value pair that, When set, will cause inbound requests that contain
+ the matching SIP header/value pair to be associated with the corresponding
+ endpoint. This option is cumulative with the 'match' option, so that if
+ either option matches the request, the request is associated with the
+ endpoint.
+
+ In a future release, this module will be renamed to something more
+ appropriate, as it now matches inbound requests on more than just IP
+ address.
+
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 13.13.0 to Asterisk 13.14.0 ----------
------------------------------------------------------------------------------
diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c
index 608977952..6fad47c9e 100644
--- a/apps/app_voicemail.c
+++ b/apps/app_voicemail.c
@@ -805,6 +805,7 @@ struct ast_vm_user {
char *emailbody; /*!< E-mail body */
char pager[80]; /*!< E-mail address to pager (no attachment) */
char serveremail[80]; /*!< From: Mail address */
+ char fromstring[100]; /*!< From: Username */
char language[MAX_LANGUAGE]; /*!< Config: Language setting */
char zonetag[80]; /*!< Time zone */
char locale[20]; /*!< The locale (for presentation of date/time) */
@@ -813,7 +814,7 @@ struct ast_vm_user {
char uniqueid[80]; /*!< Unique integer identifier */
char exit[80];
char attachfmt[20]; /*!< Attachment format */
- unsigned int flags; /*!< VM_ flags */
+ unsigned int flags; /*!< VM_ flags */
int saydurationm;
int minsecs; /*!< Minimum number of seconds per message for this mailbox */
int maxmsg; /*!< Maximum number of msgs per folder for this mailbox */
@@ -1310,6 +1311,8 @@ static void apply_option(struct ast_vm_user *vmu, const char *var, const char *v
ast_copy_string(vmu->attachfmt, value, sizeof(vmu->attachfmt));
} else if (!strcasecmp(var, "serveremail")) {
ast_copy_string(vmu->serveremail, value, sizeof(vmu->serveremail));
+ } else if (!strcasecmp(var, "fromstring")) {
+ ast_copy_string(vmu->fromstring, value, sizeof(vmu->fromstring));
} else if (!strcasecmp(var, "emailbody")) {
ast_free(vmu->emailbody);
vmu->emailbody = ast_strdup(substitute_escapes(value));
@@ -5116,12 +5119,13 @@ static void make_email_file(FILE *p,
/* Set date format for voicemail mail */
ast_strftime_locale(date, sizeof(date), emaildateformat, &tm, S_OR(vmu->locale, NULL));
- if (!ast_strlen_zero(fromstring)) {
+ if (!ast_strlen_zero(fromstring) || !ast_strlen_zero(vmu->fromstring)) {
struct ast_channel *ast;
+ char *e_fromstring = !ast_strlen_zero(vmu->fromstring) ? vmu->fromstring : fromstring;
if ((ast = ast_dummy_channel_alloc())) {
char *ptr;
prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, fromfolder, enc_cidnum, enc_cidname, dur, date, category, flag);
- ast_str_substitute_variables(&str1, 0, ast, fromstring);
+ ast_str_substitute_variables(&str1, 0, ast, e_fromstring);
if (check_mime(ast_str_buffer(str1))) {
first_line = 1;
@@ -12234,7 +12238,7 @@ AST_TEST_DEFINE(test_voicemail_vmuser)
struct ast_vm_user *vmu;
/* language parameter seems to only be used for display in manager action */
static const char options_string[] = "attach=yes|attachfmt=wav49|"
- "serveremail=someguy@digium.com|tz=central|delete=yes|saycid=yes|"
+ "serveremail=someguy@digium.com|fromstring=Voicemail System|tz=central|delete=yes|saycid=yes|"
"sendvoicemail=yes|review=yes|tempgreetwarn=yes|messagewrap=yes|operator=yes|"
"envelope=yes|moveheard=yes|sayduration=yes|saydurationm=5|forcename=yes|"
"forcegreetings=yes|callback=somecontext|dialout=somecontext2|"
@@ -12275,6 +12279,10 @@ AST_TEST_DEFINE(test_voicemail_vmuser)
ast_test_status_update(test, "Parse failure for attachftm option\n");
res = 1;
}
+ if (strcasecmp(vmu->fromstring, "Voicemail System")) {
+ ast_test_status_update(test, "Parse failure for fromstring option\n");
+ res = 1;
+ }
if (strcasecmp(vmu->serveremail, "someguy@digium.com")) {
ast_test_status_update(test, "Parse failure for serveremail option\n");
res = 1;
@@ -12834,6 +12842,7 @@ static struct ast_cli_entry cli_voicemail[] = {
USER(ast_vm_user, emailbody, AST_DATA_STRING) \
USER(ast_vm_user, pager, AST_DATA_STRING) \
USER(ast_vm_user, serveremail, AST_DATA_STRING) \
+ USER(ast_vm_user, fromstring, AST_DATA_STRING) \
USER(ast_vm_user, language, AST_DATA_STRING) \
USER(ast_vm_user, zonetag, AST_DATA_STRING) \
USER(ast_vm_user, callback, AST_DATA_STRING) \
@@ -12861,6 +12870,7 @@ static struct ast_cli_entry cli_voicemail[] = {
USER(ast_vm_user, emailbody, AST_DATA_STRING) \
USER(ast_vm_user, pager, AST_DATA_STRING) \
USER(ast_vm_user, serveremail, AST_DATA_STRING) \
+ USER(ast_vm_user, fromstring, AST_DATA_STRING) \
USER(ast_vm_user, language, AST_DATA_STRING) \
USER(ast_vm_user, zonetag, AST_DATA_STRING) \
USER(ast_vm_user, callback, AST_DATA_STRING) \
@@ -13250,6 +13260,7 @@ static int manager_list_voicemail_users(struct mansession *s, const struct messa
"Email: %s\r\n"
"Pager: %s\r\n"
"ServerEmail: %s\r\n"
+ "FromString: %s\r\n"
"MailCommand: %s\r\n"
"Language: %s\r\n"
"TimeZone: %s\r\n"
@@ -13284,6 +13295,7 @@ static int manager_list_voicemail_users(struct mansession *s, const struct messa
vmu->email,
vmu->pager,
ast_strlen_zero(vmu->serveremail) ? serveremail : vmu->serveremail,
+ ast_strlen_zero(vmu->fromstring) ? fromstring : vmu->fromstring,
mailcmd,
vmu->language,
vmu->zonetag,
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index a0d414483..85796a073 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -23917,6 +23917,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, const char *rest
case 422: /* Session-Timers: Session interval too small */
xmitres = transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE);
ast_string_field_set(p, theirtag, NULL);
+ p->invitestate = INV_CALLING;
proc_422_rsp(p, req);
break;
diff --git a/channels/pjsip/cli_commands.c b/channels/pjsip/cli_commands.c
index 8d99379ff..1d2fbb9ad 100644
--- a/channels/pjsip/cli_commands.c
+++ b/channels/pjsip/cli_commands.c
@@ -346,11 +346,10 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags)
struct ast_sip_channel_pvt *cpvt = channel ? ast_channel_tech_pvt(channel) : NULL;
struct chan_pjsip_pvt *pvt = cpvt ? cpvt->pvt : NULL;
struct ast_sip_session_media *media = pvt ? pvt->media[SIP_MEDIA_AUDIO] : NULL;
- struct ast_rtp_codecs *codecs = media && media->rtp ? ast_rtp_instance_get_codecs(media->rtp) : NULL;
- struct ast_format *format = codecs ? ast_rtp_codecs_get_payload_format(codecs, 0) : NULL;
struct ast_rtp_instance_stats stats;
char *print_name = NULL;
char *print_time = alloca(32);
+ char codec_in_use[7];
ast_assert(context->output_buffer != NULL);
@@ -360,6 +359,16 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags)
return -1;
}
+ codec_in_use[0] = '\0';
+
+ if (channel) {
+ ast_channel_lock(channel);
+ if (ast_channel_rawreadformat(channel)) {
+ ast_copy_string(codec_in_use, ast_format_get_name(ast_channel_rawreadformat(channel)), sizeof(codec_in_use));
+ }
+ ast_channel_unlock(channel);
+ }
+
print_name = ast_strdupa(snapshot->name);
/* Skip the PJSIP/. We know what channel type it is and we need the space. */
print_name += 6;
@@ -374,7 +383,7 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags)
snapshot->bridgeid,
print_name,
print_time,
- format ? ast_format_get_name(format) : "",
+ codec_in_use,
stats.rxcount > 100000 ? stats.rxcount / 1000 : stats.rxcount,
stats.rxcount > 100000 ? "K": " ",
stats.rxploss > 100000 ? stats.rxploss / 1000 : stats.rxploss,
@@ -391,7 +400,6 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags)
);
}
- ao2_cleanup(format);
ao2_cleanup(channel);
return 0;
diff --git a/configs/samples/hep.conf.sample b/configs/samples/hep.conf.sample
index e1cd52ebb..3d1e74139 100644
--- a/configs/samples/hep.conf.sample
+++ b/configs/samples/hep.conf.sample
@@ -2,6 +2,15 @@
; res_hep Module configuration for Asterisk
;
+;
+; Note that this configuration file is consumed by res_hep, which is responsible
+; for the HEPv3 protocol manipulation and managing the connection to the Homer
+; capture server. Additional modules provide specific messages to be sent to
+; the Homer server:
+; - res_hep_pjsip: Send SIP messages transmitted/received by the PJSIP stack
+; - res_hep_rtcp: Send RTCP information (all channels)
+;
+
; All settings are currently set in the general section.
[general]
enabled = no ; Enable/disable forwarding of packets to a
@@ -17,4 +26,3 @@ uuid_type = call-id ; Specify the preferred source for the Homer
; correlation UUID. Valid options are:
; - 'call-id' for the PJSIP SIP Call-ID
; - 'channel' for the Asterisk channel name
-
diff --git a/configs/samples/voicemail.conf.sample b/configs/samples/voicemail.conf.sample
index 1c91ffb34..f8221eebe 100644
--- a/configs/samples/voicemail.conf.sample
+++ b/configs/samples/voicemail.conf.sample
@@ -439,7 +439,7 @@ european=Europe/Copenhagen|'vm-received' a d b 'digits/at' HM
; Note: The rest of the system must reference mailboxes defined here as mailbox@default.
1234 => 4242,Example Mailbox,root@localhost
-;4200 => 9855,Mark Spencer,markster@linux-support.net,mypager@digium.com,attach=no|serveremail=myaddy@digium.com|tz=central|maxmsg=10
+;4200 => 9855,Mark Spencer,markster@linux-support.net,mypager@digium.com,attach=no|serveremail=myaddy@digium.com|fromstring=MySystem|tz=central|maxmsg=10
;4300 => 3456,Ben Rigas,ben@american-computer.net
;4310 => -5432,Sales,sales@marko.net
;4069 => 6522,Matt Brooks,matt@marko.net,,|tz=central|attach=yes|saycid=yes|dialout=fromvm|callback=fromvm|review=yes|operator=yes|envelope=yes|moveheard=yes|sayduration=yes|saydurationm=1
diff --git a/contrib/ast-db-manage/config/versions/465e70e8c337_add_match_header_attribute_to_identify.py b/contrib/ast-db-manage/config/versions/465e70e8c337_add_match_header_attribute_to_identify.py
new file mode 100644
index 000000000..343b5cba9
--- /dev/null
+++ b/contrib/ast-db-manage/config/versions/465e70e8c337_add_match_header_attribute_to_identify.py
@@ -0,0 +1,21 @@
+"""Add match_header attribute to identify
+
+Revision ID: 465e70e8c337
+Revises: 28ab27a7826d
+Create Date: 2017-03-14 08:13:53.986681
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '465e70e8c337'
+down_revision = '28ab27a7826d'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+ op.add_column('ps_endpoint_id_ips', sa.Column('match_header', sa.String(255)))
+
+def downgrade():
+ op.drop_column('ps_endpoint_id_ips', 'match_header')
diff --git a/funcs/func_devstate.c b/funcs/func_devstate.c
index 88a5c5c71..21759bc33 100644
--- a/funcs/func_devstate.c
+++ b/funcs/func_devstate.c
@@ -341,7 +341,7 @@ static int load_module(void)
if (dev_name <= (const char *) 1)
continue;
ast_devstate_changed(ast_devstate_val(db_entry->data),
- AST_DEVSTATE_CACHABLE, "Custom:%s\n", dev_name);
+ AST_DEVSTATE_CACHABLE, "Custom:%s", dev_name);
}
ast_db_freetree(db_tree);
db_tree = NULL;
diff --git a/main/stasis_cache.c b/main/stasis_cache.c
index 9129c0064..b0973b984 100644
--- a/main/stasis_cache.c
+++ b/main/stasis_cache.c
@@ -842,7 +842,7 @@ static void caching_topic_exec(void *data, struct stasis_subscription *sub,
}
ao2_cleanup(update);
} else {
- ast_log(LOG_ERROR,
+ ast_debug(1,
"Attempting to remove an item from the %s cache that isn't there: %s %s\n",
stasis_topic_name(caching_topic->topic),
stasis_message_type_name(msg_type), msg_id);
diff --git a/menuselect/menuselect.c b/menuselect/menuselect.c
index da972d8b1..689cebf62 100644
--- a/menuselect/menuselect.c
+++ b/menuselect/menuselect.c
@@ -238,6 +238,10 @@ static enum support_level_values string_to_support_level(const char *support_lev
return SUPPORT_EXTERNAL;
}
+ if (!strcasecmp(support_level, "option")) {
+ return SUPPORT_OPTION;
+ }
+
return SUPPORT_UNSPECIFIED;
}
@@ -253,6 +257,8 @@ static const char *support_level_to_string(enum support_level_values support_lev
return "Deprecated";
case SUPPORT_EXTERNAL:
return "External";
+ case SUPPORT_OPTION:
+ return "Module Options";
default:
return "Unspecified";
}
@@ -461,7 +467,7 @@ static int process_xml_member_node(xmlNode *node, struct category *cat)
process_process_xml_category_child_node(cur, mem);
}
- if (!cat->positive_output) {
+ if (!cat->positive_output && strcasecmp(mem->support_level, "option")) {
mem->enabled = 1;
if (!mem->defaultenabled || strcasecmp(mem->defaultenabled, "no")) {
mem->was_enabled = 1;
diff --git a/menuselect/menuselect.h b/menuselect/menuselect.h
index bf2bf4c4f..78ae8eff6 100644
--- a/menuselect/menuselect.h
+++ b/menuselect/menuselect.h
@@ -108,7 +108,8 @@ enum support_level_values {
SUPPORT_DEPRECATED = 2,
SUPPORT_UNSPECIFIED = 3,
SUPPORT_EXTERNAL = 4,
- SUPPORT_COUNT = 5, /* Keep this item at the end of the list. Tracks total number of support levels. */
+ SUPPORT_OPTION = 5,
+ SUPPORT_COUNT = 6, /* Keep this item at the end of the list. Tracks total number of support levels. */
};
AST_LIST_HEAD_NOLOCK(support_level_bucket, member);
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 54a0a5f39..347658f9c 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -2755,7 +2755,7 @@ static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *u
pj_str_t tmp, local_addr;
pjsip_uri *uri;
pjsip_sip_uri *sip_uri;
- pjsip_transport_type_e type = PJSIP_TRANSPORT_UNSPECIFIED;
+ pjsip_transport_type_e type;
int local_port;
char default_user[PJSIP_MAX_URL_SIZE];
@@ -2775,21 +2775,21 @@ static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *u
sip_uri = pjsip_uri_get_uri(uri);
/* Determine the transport type to use */
+ type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
- type = PJSIP_TRANSPORT_TLS;
+ if (type == PJSIP_TRANSPORT_UNSPECIFIED
+ || !(pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE)) {
+ type = PJSIP_TRANSPORT_TLS;
+ }
} else if (!sip_uri->transport_param.slen) {
type = PJSIP_TRANSPORT_UDP;
- } else {
- type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
- }
-
- if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
+ } else if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
return -1;
}
/* If the host is IPv6 turn the transport into an IPv6 version */
- if (pj_strchr(&sip_uri->host, ':') && type < PJSIP_TRANSPORT_START_OTHER) {
- type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
+ if (pj_strchr(&sip_uri->host, ':')) {
+ type |= PJSIP_TRANSPORT_IPV6;
}
if (!ast_strlen_zero(domain)) {
@@ -2813,8 +2813,8 @@ static int sip_dialog_create_from(pj_pool_t *pool, pj_str_t *from, const char *u
}
/* If IPv6 was specified in the transport, set the proper type */
- if (pj_strchr(&local_addr, ':') && type < PJSIP_TRANSPORT_START_OTHER) {
- type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
+ if (pj_strchr(&local_addr, ':')) {
+ type |= PJSIP_TRANSPORT_IPV6;
}
from->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
diff --git a/res/res_pjsip_endpoint_identifier_ip.c b/res/res_pjsip_endpoint_identifier_ip.c
index 6fc724a1e..1bd7e892d 100644
--- a/res/res_pjsip_endpoint_identifier_ip.c
+++ b/res/res_pjsip_endpoint_identifier_ip.c
@@ -35,20 +35,33 @@
/*** DOCUMENTATION
<configInfo name="res_pjsip_endpoint_identifier_ip" language="en_US">
- <synopsis>Module that identifies endpoints via source IP address</synopsis>
+ <synopsis>Module that identifies endpoints</synopsis>
<configFile name="pjsip.conf">
<configObject name="identify">
- <synopsis>Identifies endpoints via source IP address</synopsis>
+ <synopsis>Identifies endpoints via some criteria.</synopsis>
+ <description>
+ <para>This module provides alternatives to matching inbound requests to
+ a configured endpoint. At least one of the matching mechanisms
+ must be provided, or the object configuration will be invalid.</para>
+ <para>If multiple criteria are provided, an inbound request will
+ be matched if it matches <emphasis>any</emphasis> of the criteria.</para>
+ <para>The matching mechanisms are provided by the following
+ configuration options:</para>
+ <enumlist>
+ <enum name="match"><para>Match by source IP address.</para></enum>
+ <enum name="match_header"><para>Match by SIP header.</para></enum>
+ </enumlist>
+ </description>
<configOption name="endpoint">
<synopsis>Name of Endpoint</synopsis>
</configOption>
<configOption name="match">
- <synopsis>IP addresses or networks to match against</synopsis>
+ <synopsis>IP addresses or networks to match against.</synopsis>
<description><para>
The value is a comma-delimited list of IP addresses. IP addresses may
have a subnet mask appended. The subnet mask may be written in either
CIDR or dot-decimal notation. Separate the IP address and subnet
- mask with a slash ('/')
+ mask with a slash ('/').
</para></description>
</configOption>
<configOption name="srv_lookups" default="yes">
@@ -57,7 +70,15 @@
perform SRV lookups for _sip._udp, _sip._tcp, and _sips._tcp of the given
hostnames to determine additional addresses that traffic may originate from.
</para></description>
- </configOption>
+ </configOption>
+ <configOption name="match_header">
+ <synopsis>Header/value pair to match against.</synopsis>
+ <description><para>A SIP header who value is used to match against. SIP
+ requests containing the header, along with the specified value, will be
+ mapped to the specified endpoint. The header must be specified with a
+ <literal>:</literal>, as in <literal>match_header = SIPHeader: value</literal>.
+ </para></description>
+ </configOption>
<configOption name="type">
<synopsis>Must be of type 'identify'.</synopsis>
</configOption>
@@ -77,6 +98,8 @@ struct ip_identify_match {
AST_DECLARE_STRING_FIELDS(
/*! The name of the endpoint */
AST_STRING_FIELD(endpoint_name);
+ /*! If matching by header, the header/value to match against */
+ AST_STRING_FIELD(match_header);
);
/*! \brief Networks or addresses that should match this */
struct ast_ha *matches;
@@ -109,7 +132,48 @@ static void *ip_identify_alloc(const char *name)
return identify;
}
-/*! \brief Comparator function for a matching object */
+/*! \brief Comparator function for matching an object by header */
+static int header_identify_match_check(void *obj, void *arg, int flags)
+{
+ struct ip_identify_match *identify = obj;
+ struct pjsip_rx_data *rdata = arg;
+ pjsip_generic_string_hdr *header;
+ pj_str_t pj_header_name;
+ pj_str_t pj_header_value;
+ char *c_header = ast_strdupa(identify->match_header);
+ char *c_value;
+
+ c_value = strchr(c_header, ':');
+ if (!c_value) {
+ ast_log(LOG_WARNING, "Identify '%s' has invalid header_match: No ':' separator found!\n",
+ ast_sorcery_object_get_id(identify));
+ return 0;
+ }
+ *c_value = '\0';
+ c_value++;
+ c_value = ast_strip(c_value);
+
+ pj_header_name = pj_str(c_header);
+ header = pjsip_msg_find_hdr_by_name(rdata->msg_info.msg, &pj_header_name, NULL);
+ if (!header) {
+ ast_debug(3, "SIP message does not contain header '%s'\n", c_header);
+ return 0;
+ }
+
+ pj_header_value = pj_str(c_value);
+ if (pj_strcmp(&pj_header_value, &header->hvalue)) {
+ ast_debug(3, "SIP message contains header '%s' but value '%.*s' does not match value '%s' for endpoint '%s'\n",
+ c_header,
+ (int) pj_strlen(&header->hvalue), pj_strbuf(&header->hvalue),
+ c_value,
+ identify->endpoint_name);
+ return 0;
+ }
+
+ return CMP_MATCH | CMP_STOP;
+}
+
+/*! \brief Comparator function for matching an object by IP address */
static int ip_identify_match_check(void *obj, void *arg, int flags)
{
struct ip_identify_match *identify = obj;
@@ -147,10 +211,14 @@ static struct ast_sip_endpoint *ip_identify(pjsip_rx_data *rdata)
ast_sockaddr_parse(&addr, rdata->pkt_info.src_name, PARSE_PORT_FORBID);
ast_sockaddr_set_port(&addr, rdata->pkt_info.src_port);
- if (!(match = ao2_callback(candidates, 0, ip_identify_match_check, &addr))) {
- ast_debug(3, "'%s' did not match any identify section rules\n",
+ match = ao2_callback(candidates, 0, ip_identify_match_check, &addr);
+ 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));
- return NULL;
+ match = ao2_callback(candidates, 0, header_identify_match_check, rdata);
+ if (!match) {
+ return NULL;
+ }
}
endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", match->endpoint_name);
@@ -495,7 +563,7 @@ static int cli_print_header(void *obj, void *arg, int flags)
filler = CLI_LAST_TABSTOP - indent - 24;
ast_str_append(&context->output_buffer, 0,
- "%*s: <ip/cidr%*.*s>\n",
+ "%*s: <criteria%*.*s>\n",
indent, "Match", filler, filler, CLI_HEADER_FILLER);
context->indent_level--;
@@ -532,6 +600,13 @@ static int cli_print_body(void *obj, void *arg, int flags)
addr, ast_sockaddr_cidr_bits(&match->netmask));
}
+ if (!ast_strlen_zero(ident->match_header)) {
+ ast_str_append(&context->output_buffer, 0, "%*s: %s\n",
+ indent,
+ "Match",
+ ident->match_header);
+ }
+
context->indent_level--;
if (context->indent_level == 0) {
@@ -592,6 +667,7 @@ static int load_module(void)
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "type", "", OPT_NOOP_T, 0, 0);
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "endpoint", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ip_identify_match, endpoint_name));
ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "identify", "match", "", ip_identify_match_handler, match_to_str, match_to_var_list, 0, 0);
+ ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "match_header", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ip_identify_match, match_header));
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "identify", "srv_lookups", "yes", OPT_BOOL_T, 1, FLDSET(struct ip_identify_match, srv_lookups));
ast_sorcery_load_object(ast_sip_get_sorcery(), "identify");
diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c
index 7a0b60ac8..ee1894ffb 100644
--- a/res/res_pjsip_outbound_registration.c
+++ b/res/res_pjsip_outbound_registration.c
@@ -1087,7 +1087,7 @@ static int sip_dialog_create_contact(pj_pool_t *pool, pj_str_t *contact, const c
pj_str_t tmp, local_addr;
pjsip_uri *uri;
pjsip_sip_uri *sip_uri;
- pjsip_transport_type_e type = PJSIP_TRANSPORT_UNSPECIFIED;
+ pjsip_transport_type_e type;
int local_port;
pj_strdup_with_null(pool, &tmp, target);
@@ -1099,20 +1099,20 @@ static int sip_dialog_create_contact(pj_pool_t *pool, pj_str_t *contact, const c
sip_uri = pjsip_uri_get_uri(uri);
+ type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
if (PJSIP_URI_SCHEME_IS_SIPS(sip_uri)) {
- type = PJSIP_TRANSPORT_TLS;
+ if (type == PJSIP_TRANSPORT_UNSPECIFIED
+ || !(pjsip_transport_get_flag_from_type(type) & PJSIP_TRANSPORT_SECURE)) {
+ type = PJSIP_TRANSPORT_TLS;
+ }
} else if (!sip_uri->transport_param.slen) {
type = PJSIP_TRANSPORT_UDP;
- } else {
- type = pjsip_transport_get_type_from_name(&sip_uri->transport_param);
- }
-
- if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
+ } else if (type == PJSIP_TRANSPORT_UNSPECIFIED) {
return -1;
}
if (pj_strchr(&sip_uri->host, ':')) {
- type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
+ type |= PJSIP_TRANSPORT_IPV6;
}
if (pjsip_tpmgr_find_local_addr(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()),
@@ -1121,7 +1121,7 @@ static int sip_dialog_create_contact(pj_pool_t *pool, pj_str_t *contact, const c
}
if (!pj_strchr(&sip_uri->host, ':') && pj_strchr(&local_addr, ':')) {
- type = (pjsip_transport_type_e)(((int)type) + PJSIP_TRANSPORT_IPV6);
+ type |= PJSIP_TRANSPORT_IPV6;
}
contact->ptr = pj_pool_alloc(pool, PJSIP_MAX_URL_SIZE);
diff --git a/res/res_pjsip_transport_websocket.c b/res/res_pjsip_transport_websocket.c
index ff8e346f4..1b9d616de 100644
--- a/res/res_pjsip_transport_websocket.c
+++ b/res/res_pjsip_transport_websocket.c
@@ -39,6 +39,7 @@
#include "asterisk/taskprocessor.h"
static int transport_type_wss;
+static int transport_type_wss_ipv6;
/*!
* \brief Wrapper for pjsip_transport, for storing the WebSocket session
@@ -198,15 +199,20 @@ static int transport_create(void *data)
newtransport->transport.type_name, ws_addr_str);
pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ws_addr_str), &newtransport->transport.key.rem_addr);
- newtransport->transport.key.rem_addr.addr.sa_family = pj_AF_INET();
- newtransport->transport.key.type = transport_type_wss;
+ if (newtransport->transport.key.rem_addr.addr.sa_family == pj_AF_INET6()) {
+ newtransport->transport.key.type = transport_type_wss_ipv6;
+ newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, PJ_INET6_ADDRSTRLEN);
+ pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, PJ_INET6_ADDRSTRLEN, 0);
+ } else {
+ newtransport->transport.key.type = transport_type_wss;
+ newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, PJ_INET_ADDRSTRLEN);
+ pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, PJ_INET_ADDRSTRLEN, 0);
+ }
newtransport->transport.addr_len = pj_sockaddr_get_len(&newtransport->transport.key.rem_addr);
pj_sockaddr_cp(&newtransport->transport.local_addr, &newtransport->transport.key.rem_addr);
- newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, newtransport->transport.addr_len+4);
- pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, newtransport->transport.addr_len+4, 0);
newtransport->transport.local_name.host.slen = pj_ansi_strlen(newtransport->transport.local_name.host.ptr);
newtransport->transport.local_name.port = pj_sockaddr_get_port(&newtransport->transport.key.rem_addr);
@@ -271,8 +277,6 @@ static int transport_read(void *data)
rdata->pkt_info.zero = 0;
pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ast_sockaddr_stringify(ast_websocket_remote_address(session))), &rdata->pkt_info.src_addr);
- rdata->pkt_info.src_addr.addr.sa_family = pj_AF_INET();
-
rdata->pkt_info.src_addr_len = sizeof(rdata->pkt_info.src_addr);
pj_ansi_strcpy(rdata->pkt_info.src_name, ast_sockaddr_stringify_host(ast_websocket_remote_address(session)));
@@ -395,7 +399,7 @@ static pj_bool_t websocket_on_rx_msg(pjsip_rx_data *rdata)
long type = rdata->tp_info.transport->key.type;
- if (type != (long) transport_type_wss) {
+ if (type != (long) transport_type_wss && type != (long) transport_type_wss_ipv6) {
return PJ_FALSE;
}
@@ -451,15 +455,17 @@ static int load_module(void)
CHECK_PJSIP_MODULE_LOADED();
/*
- * We only need one transport type defined. Firefox and Chrome
- * do not support anything other than secure websockets anymore.
+ * We only need one transport type name (ws) defined. Firefox
+ * and Chrome do not support anything other than secure websockets
+ * anymore.
*
* Also we really cannot have two transports with the same name
- * because it would be ambiguous. Outgoing requests may try to
- * find the transport by name and pjproject only finds the first
- * one registered.
+ * and address family because it would be ambiguous. Outgoing
+ * requests may try to find the transport by name and pjproject
+ * only finds the first one registered.
*/
pjsip_transport_register_type(PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE, "ws", 5060, &transport_type_wss);
+ pjsip_transport_register_type(PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE | PJSIP_TRANSPORT_IPV6, "ws", 5060, &transport_type_wss_ipv6);
if (ast_sip_register_service(&websocket_module) != PJ_SUCCESS) {
return AST_MODULE_LOAD_DECLINE;
diff --git a/third-party/pjproject/Makefile b/third-party/pjproject/Makefile
index bfd1c27fc..99c22fa8b 100644
--- a/third-party/pjproject/Makefile
+++ b/third-party/pjproject/Makefile
@@ -135,7 +135,7 @@ source/pjlib/include/pj/%.h: patches/%.h
$(ECHO_PREFIX) Applying custom include file $<
$(CMD_PREFIX) cp -f $< source/pjlib/include/pj/
-.rebuild_needed: $(wildcard ../../makeopts) $(wildcard ../../menuselect.makeopts)
+.rebuild_needed: $(wildcard ../../.lastclean)
$(ECHO_PREFIX) Rebuilding
$(CMD_PREFIX) $(MAKE) clean $(REALLY_QUIET)
diff --git a/third-party/pjproject/patches/0014-Add-pjsip-transport-register-type-ipv6.patch b/third-party/pjproject/patches/0014-Add-pjsip-transport-register-type-ipv6.patch
new file mode 100644
index 000000000..796473a3c
--- /dev/null
+++ b/third-party/pjproject/patches/0014-Add-pjsip-transport-register-type-ipv6.patch
@@ -0,0 +1,62 @@
+From daeb0956524606b597704a90b54d81340e10b3e4 Mon Sep 17 00:00:00 2001
+From: Joshua Colp <jcolp@digium.com>
+Date: Tue, 7 Mar 2017 12:32:49 +0000
+Subject: [PATCH] Add support for registering IPv6 transport type.
+
+This change allows an IPv6 transport type to be registered
+and used. The IPv4 transport is found (if available) and the
+IPv4 flag added to its type to match how the finding of
+IPv6 transport types works.
+---
+ pjsip/src/pjsip/sip_transport.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c
+index 7df6138..ce72814 100644
+--- a/pjsip/src/pjsip/sip_transport.c
++++ b/pjsip/src/pjsip/sip_transport.c
+@@ -236,6 +236,7 @@ PJ_DEF(pj_status_t) pjsip_transport_register_type( unsigned tp_flag,
+ int *p_tp_type)
+ {
+ unsigned i;
++ pjsip_transport_type_e parent = 0;
+
+ PJ_ASSERT_RETURN(tp_flag && tp_name && def_port, PJ_EINVAL);
+ PJ_ASSERT_RETURN(pj_ansi_strlen(tp_name) <
+@@ -243,6 +244,11 @@ PJ_DEF(pj_status_t) pjsip_transport_register_type( unsigned tp_flag,
+ PJ_ENAMETOOLONG);
+
+ for (i=1; i<PJ_ARRAY_SIZE(transport_names); ++i) {
++ if (tp_flag & PJSIP_TRANSPORT_IPV6 &&
++ pj_stricmp2(&transport_names[i].name, tp_name) == 0)
++ {
++ parent = transport_names[i].type;
++ }
+ if (transport_names[i].type == 0)
+ break;
+ }
+@@ -250,14 +256,19 @@ PJ_DEF(pj_status_t) pjsip_transport_register_type( unsigned tp_flag,
+ if (i == PJ_ARRAY_SIZE(transport_names))
+ return PJ_ETOOMANY;
+
+- transport_names[i].type = (pjsip_transport_type_e)i;
++ if (tp_flag & PJSIP_TRANSPORT_IPV6 && parent) {
++ transport_names[i].type = parent | PJSIP_TRANSPORT_IPV6;
++ } else {
++ transport_names[i].type = (pjsip_transport_type_e)i;
++ }
++
+ transport_names[i].port = (pj_uint16_t)def_port;
+ pj_ansi_strcpy(transport_names[i].name_buf, tp_name);
+ transport_names[i].name = pj_str(transport_names[i].name_buf);
+ transport_names[i].flag = tp_flag;
+
+ if (p_tp_type)
+- *p_tp_type = i;
++ *p_tp_type = transport_names[i].type;
+
+ return PJ_SUCCESS;
+ }
+--
+2.7.4
+