summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES6
-rw-r--r--channels/chan_sip.c5
-rw-r--r--configs/samples/pjsip.conf.sample2
-rw-r--r--configs/samples/sip.conf.sample11
-rw-r--r--contrib/ast-db-manage/config/versions/4e2493ef32e6_add_contact_user_to_endpoint.py22
-rwxr-xr-xcontrib/scripts/sip_to_pjsip/sip_to_pjsip.py155
-rw-r--r--include/asterisk/ari.h3
-rw-r--r--include/asterisk/http.h1
-rw-r--r--include/asterisk/res_pjsip.h2
-rw-r--r--main/http.c2
-rw-r--r--res/res_ari.c16
-rw-r--r--res/res_ari_applications.c6
-rw-r--r--res/res_ari_asterisk.c26
-rw-r--r--res/res_ari_bridges.c16
-rw-r--r--res/res_ari_channels.c38
-rw-r--r--res/res_ari_device_states.c4
-rw-r--r--res/res_ari_endpoints.c10
-rw-r--r--res/res_ari_events.c6
-rw-r--r--res/res_ari_mailboxes.c4
-rw-r--r--res/res_ari_playbacks.c6
-rw-r--r--res/res_ari_recordings.c20
-rw-r--r--res/res_ari_sounds.c4
-rw-r--r--res/res_format_attr_g729.c76
-rw-r--r--res/res_odbc.c1
-rw-r--r--res/res_odbc_transaction.c2
-rw-r--r--res/res_pjsip.c26
-rw-r--r--res/res_pjsip/pjsip_configuration.c31
-rw-r--r--res/res_pjsip_session.c30
-rw-r--r--rest-api-templates/api.wiki.mustache4
-rw-r--r--rest-api-templates/swagger_model.py4
-rw-r--r--tests/test_ari.c8
-rw-r--r--third-party/pjproject/patches/0003-r5403-pjsip_IPV6_V6ONLY.patch13
32 files changed, 406 insertions, 154 deletions
diff --git a/CHANGES b/CHANGES
index 7f3b0ad7c..1cfa7eb7c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -42,6 +42,11 @@ chan_pjsip
dialplan function PJSIP_MEDIA_OFFER, this allows the formats on a PJSIP
channel to be re-negotiated and updated after session set up.
+res_pjsip
+------------------
+ * A new endpoint configuration parameter 'contact_user' has been added which
+ when set will override the default user set on Contact headers in outgoing
+ requests.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 13 to Asterisk 14 --------------------
@@ -407,7 +412,6 @@ cdr_csv
* Added a new configuration option, "newcdrcolumns", which enables use of the
post-1.8 CDR columns 'peeraccount', 'linkedid', and 'sequence'.
-
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 13.10.0 to Asterisk 13.11.0 ----------
------------------------------------------------------------------------------
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index f57d4670b..6250731bd 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -12982,10 +12982,7 @@ static void add_codec_to_sdp(const struct sip_pvt *p,
framing = ast_format_cap_get_format_framing(p->caps, format);
- if (ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
- /* Indicate that we don't support VAD (G.729 annex B) */
- ast_str_append(a_buf, 0, "a=fmtp:%d annexb=no\r\n", rtp_code);
- } else if (ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
+ if (ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
/* Indicate that we don't support VAD (G.723.1 annex A) */
ast_str_append(a_buf, 0, "a=fmtp:%d annexa=no\r\n", rtp_code);
} else if (ast_format_cmp(format, ast_format_g719) == AST_FORMAT_CMP_EQUAL) {
diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample
index eac054904..0d1c03909 100644
--- a/configs/samples/pjsip.conf.sample
+++ b/configs/samples/pjsip.conf.sample
@@ -762,6 +762,8 @@
;rtp_timeout_hold= ; Hang up channel if RTP is not received for the specified
; number of seconds when the channel is on hold (default:
; "0" or not enabled)
+;contact_user= ; On outgoing requests, force the user portion of the Contact
+ ; header to this value (default: "")
;==========================AUTH SECTION OPTIONS=========================
;[auth]
diff --git a/configs/samples/sip.conf.sample b/configs/samples/sip.conf.sample
index a7b74df69..da176b4d6 100644
--- a/configs/samples/sip.conf.sample
+++ b/configs/samples/sip.conf.sample
@@ -611,7 +611,16 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
;
;tlsclientmethod=tlsv1 ; values include tlsv1, sslv3, sslv2.
; Specify protocol for outbound client connections.
- ; If left unspecified, the default is sslv2.
+ ; If left unspecified, the default is the general-
+ ; purpose version-flexible SSL/TLS method (sslv23).
+ ; With that, the actual protocol version used will
+ ; be negotiated to the highest version mutually
+ ; supported by Asterisk and the remote server, i.e.
+ ; TLSv1.2. The supported protocols are listed at
+ ; http://www.openssl.org/docs/ssl/SSL_CTX_new.html
+ ; SSLv2 and SSLv3 are disabled within Asterisk.
+ ; Your distribution might have changed that list
+ ; further.
;
;--------------------------- SIP timers ----------------------------------------------------
; These timers are used primarily in INVITE transactions.
diff --git a/contrib/ast-db-manage/config/versions/4e2493ef32e6_add_contact_user_to_endpoint.py b/contrib/ast-db-manage/config/versions/4e2493ef32e6_add_contact_user_to_endpoint.py
new file mode 100644
index 000000000..f91cff04e
--- /dev/null
+++ b/contrib/ast-db-manage/config/versions/4e2493ef32e6_add_contact_user_to_endpoint.py
@@ -0,0 +1,22 @@
+"""Add contact_user to endpoint
+
+Revision ID: 4e2493ef32e6
+Revises: 3772f8f828da
+Create Date: 2016-08-16 14:19:58.918466
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '4e2493ef32e6'
+down_revision = '3772f8f828da'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade():
+ op.add_column('ps_endpoints', sa.Column('contact_user', sa.String(80)))
+
+
+def downgrade():
+ op.drop_column('ps_endpoints', 'contact_user')
diff --git a/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py b/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py
index 890921673..ee01edfa2 100755
--- a/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py
+++ b/contrib/scripts/sip_to_pjsip/sip_to_pjsip.py
@@ -54,10 +54,11 @@ def set_value(key=None, val=None, section=None, pjsip=None,
def merge_value(key=None, val=None, section=None, pjsip=None,
- nmapped=None, type='endpoint', section_to=None):
+ nmapped=None, type='endpoint', section_to=None,
+ key_to=None):
"""Merge values from the given section with those from the default."""
def _merge_value(k, v, s, r, n):
- merge_value(key if key else k, v, s, r, n, type, section_to)
+ merge_value(key if key else k, v, s, r, n, type, section_to, key_to)
# if no value or section return the merge_value
# function with the enclosed key and type
@@ -71,7 +72,8 @@ def merge_value(key=None, val=None, section=None, pjsip=None,
sect = sip.default(section)[0]
# for each merged value add it to pjsip.conf
for i in sect.get_merged(key):
- set_value(key, i, section_to if section_to else section,
+ set_value(key_to if key_to else key, i,
+ section_to if section_to else section,
pjsip, nmapped, type)
@@ -133,11 +135,14 @@ def set_timers(key, val, section, pjsip, nmapped):
found in sip.conf.
"""
# pjsip.conf values can be yes/no, required, always
+ # 'required' is a new feature of chan_pjsip, which rejects
+ # all SIP clients not supporting Session Timers
+ # 'Accept' is the default value of chan_sip and maps to 'yes'
+ # chan_sip ignores the case, for example 'session-timers=Refuse'
+ val = val.lower()
if val == 'originate':
set_value('timers', 'always', section, pjsip, nmapped)
- elif val == 'accept':
- set_value('timers', 'required', section, pjsip, nmapped)
- elif val == 'never':
+ elif val == 'refuse':
set_value('timers', 'no', section, pjsip, nmapped)
else:
set_value('timers', 'yes', section, pjsip, nmapped)
@@ -383,8 +388,6 @@ peer_map = [
['session-timers', set_timers], # timers
['session-minse', set_value('timers_min_se')],
['session-expires', set_value('timers_sess_expires')],
- ['externip', set_value('external_media_address')],
- ['externhost', set_value('external_media_address')],
# identify_by ?
['directmedia', set_direct_media], # direct_media
# direct_media_method
@@ -396,7 +399,7 @@ peer_map = [
['trustpid', set_value('trust_id_inbound')],
['sendrpid', from_sendrpid], # send_pai, send_rpid
['send_diversion', set_value],
- ['encrpytion', set_media_encryption],
+ ['encryption', set_media_encryption],
['avpf', set_value('use_avpf')],
['recordonfeature', set_record_on_feature], # automixon
['recordofffeature', set_record_off_feature], # automixon
@@ -440,6 +443,9 @@ peer_map = [
['host', from_host], # contact, max_contacts
['qualifyfreq', set_value('qualify_frequency', type='aor')],
+ ['maxexpiry', set_value('maximum_expiration', type='aor')],
+ ['minexpiry', set_value('minimum_expiration', type='aor')],
+ ['defaultexpiry', set_value('default_expiration', type='aor')],
############################# maps to auth#####################################
# type = auth
@@ -454,9 +460,9 @@ peer_map = [
['permit', merge_value(type='acl', section_to='acl')],
['deny', merge_value(type='acl', section_to='acl')],
['acl', merge_value(type='acl', section_to='acl')],
- ['contactpermit', merge_value('contact_permit', type='acl', section_to='acl')],
- ['contactdeny', merge_value('contact_deny', type='acl', section_to='acl')],
- ['contactacl', merge_value('contact_acl', type='acl', section_to='acl')],
+ ['contactpermit', merge_value(type='acl', section_to='acl', key_to='contact_permit')],
+ ['contactdeny', merge_value(type='acl', section_to='acl', key_to='contact_deny')],
+ ['contactacl', merge_value(type='acl', section_to='acl', key_to='contact_acl')],
########################### maps to transport #################################
# type = transport
@@ -464,6 +470,7 @@ peer_map = [
# bind
# async_operations
# ca_list_file
+# ca_list_path
# cert_file
# privkey_file
# password
@@ -499,21 +506,6 @@ peer_map = [
]
-def add_localnet(section, pjsip, nmapped):
- """
- Adds localnet values from sip.conf's general section to a transport in
- pjsip.conf. Ideally, we would have just created a template with the
- localnet sections, but because this is a script, it's not hard to add
- the same thing on to every transport.
- """
- try:
- merge_value('local_net', sip.get('general', 'localnet')[0], 'general',
- pjsip, nmapped, 'transport', section)
- except LookupError:
- # No localnet options configured. No biggie!
- pass
-
-
def set_transport_common(section, pjsip, nmapped):
"""
sip.conf has several global settings that in pjsip.conf apply to individual
@@ -527,21 +519,21 @@ def set_transport_common(section, pjsip, nmapped):
"""
try:
- merge_value('local_net', sip.get('general', 'localnet')[0], 'general',
- pjsip, nmapped, 'transport', section)
+ merge_value('localnet', sip.get('general', 'localnet')[0], 'general',
+ pjsip, nmapped, 'transport', section, "local_net")
except LookupError:
# No localnet options configured. Move on.
pass
try:
- set_value('tos', sip.get('general', 'sip_tos')[0], 'general', pjsip,
- nmapped, 'transport', section)
+ set_value('tos', sip.get('general', 'tos_sip')[0], section, pjsip,
+ nmapped, 'transport')
except LookupError:
pass
try:
- set_value('cos', sip.get('general', 'sip_cos')[0], 'general', pjsip,
- nmapped, 'transport', section)
+ set_value('cos', sip.get('general', 'cos_sip')[0], section, pjsip,
+ nmapped, 'transport')
except LookupError:
pass
@@ -598,6 +590,8 @@ def create_udp(sip, pjsip, nmapped):
extern_addr = sip.multi_get('general', ['externaddr', 'externip',
'externhost'])[0]
host, port = split_hostport(extern_addr)
+ set_value('external_media_address', host, 'transport-udp', pjsip,
+ nmapped, 'transport')
set_value('external_signaling_address', host, 'transport-udp', pjsip,
nmapped, 'transport')
if port:
@@ -645,6 +639,8 @@ def create_tcp(sip, pjsip, nmapped):
tcpport = sip.get('general', 'externtcpport')[0]
except:
tcpport = port
+ set_value('external_media_address', host, 'transport-tcp', pjsip,
+ nmapped, 'transport')
set_value('external_signaling_address', host, 'transport-tcp', pjsip,
nmapped, 'transport')
if tcpport:
@@ -697,6 +693,12 @@ def set_tls_bindaddr(val, pjsip, nmapped):
set_value('bind', bind, 'transport-tls', pjsip, nmapped, 'transport')
+def set_tls_cert_file(val, pjsip, nmapped):
+ """Sets cert_file based on sip.conf tlscertfile"""
+ set_value('cert_file', val, 'transport-tls', pjsip, nmapped,
+ 'transport')
+
+
def set_tls_private_key(val, pjsip, nmapped):
"""Sets privkey_file based on sip.conf tlsprivatekey or sslprivatekey"""
set_value('priv_key_file', val, 'transport-tls', pjsip, nmapped,
@@ -714,6 +716,12 @@ def set_tls_cafile(val, pjsip, nmapped):
'transport')
+def set_tls_capath(val, pjsip, nmapped):
+ """Sets ca_list_path based on sip.conf tlscapath"""
+ set_value('ca_list_path', val, 'transport-tls', pjsip, nmapped,
+ 'transport')
+
+
def set_tls_verifyclient(val, pjsip, nmapped):
"""Sets verify_client based on sip.conf tlsverifyclient"""
set_value('verify_client', val, 'transport-tls', pjsip, nmapped,
@@ -731,11 +739,6 @@ def set_tls_verifyserver(val, pjsip, nmapped):
'transport')
-def set_tls_method(val, pjsip, nmapped):
- """Sets method based on sip.conf tlsclientmethod or sslclientmethod"""
- set_value('method', val, 'transport-tls', pjsip, nmapped, 'transport')
-
-
def create_tls(sip, pjsip, nmapped):
"""
Creates a 'transport-tls' section in pjsip.conf based on the following
@@ -755,12 +758,13 @@ def create_tls(sip, pjsip, nmapped):
tls_map = [
(['tlsbindaddr', 'sslbindaddr'], set_tls_bindaddr),
+ (['tlscertfile', 'sslcert', 'tlscert'], set_tls_cert_file),
(['tlsprivatekey', 'sslprivatekey'], set_tls_private_key),
(['tlscipher', 'sslcipher'], set_tls_cipher),
(['tlscafile'], set_tls_cafile),
+ (['tlscapath', 'tlscadir'], set_tls_capath),
(['tlsverifyclient'], set_tls_verifyclient),
- (['tlsdontverifyserver'], set_tls_verifyserver),
- (['tlsclientmethod', 'sslclientmethod'], set_tls_method)
+ (['tlsdontverifyserver'], set_tls_verifyserver)
]
try:
@@ -780,6 +784,23 @@ def create_tls(sip, pjsip, nmapped):
except LookupError:
pass
+ try:
+ method = sip.multi_get('general', ['tlsclientmethod', 'sslclientmethod'])[0]
+ print 'In chan_sip, you specified the TLS version. With chan_sip, this was just for outbound client connections. In chan_pjsip, this value is for client and server. Instead, consider not to specify \'tlsclientmethod\' for chan_sip and \'method = sslv23\' for chan_pjsip.'
+ except LookupError:
+ """
+ OpenSSL emerged during the 90s. SSLv2 and SSLv3 were the only
+ existing methods at that time. The OpenSSL project continued. And as
+ of today (OpenSSL 1.0.2) this does not start SSLv2 and SSLv3 anymore
+ but TLSv1.0 and v1.2. Or stated differently: This method should
+ have been called 'method = secure' or 'method = automatic' back in
+ the 90s. The PJProject did not realize this and uses 'tlsv1' as
+ default when unspecified, which disables TLSv1.2. chan_sip used
+ 'sslv23' as default when unspecified, which gives TLSv1.0 and v1.2.
+ """
+ method = 'sslv23'
+ set_value('method', method, 'transport-tls', pjsip, nmapped, 'transport')
+
set_transport_common('transport-tls', pjsip, nmapped)
try:
extern_addr = sip.multi_get('general', ['externaddr', 'externip',
@@ -789,6 +810,8 @@ def create_tls(sip, pjsip, nmapped):
tlsport = sip.get('general', 'externtlsport')[0]
except:
tlsport = port
+ set_value('external_media_address', host, 'transport-tls', pjsip,
+ nmapped, 'transport')
set_value('external_signaling_address', host, 'transport-tls', pjsip,
nmapped, 'transport')
if tlsport:
@@ -907,6 +930,17 @@ class Registration:
the right of the user, then finish by using rpartition calls to remove
everything to the left of the user.
"""
+ self.peer = ''
+ self.protocol = 'udp'
+ protocols = ['udp', 'tcp', 'tls']
+ for protocol in protocols:
+ position = user_part.find(protocol + '://')
+ if -1 < position:
+ post_transport = user_part[position + 6:]
+ self.peer, sep, self.protocol = user_part[:position + 3].rpartition('?')
+ user_part = post_transport
+ break
+
colons = user_part.count(':')
if (colons == 3):
# :domainport:secret:authuser
@@ -927,11 +961,7 @@ class Registration:
# Invalid setting
raise
- pre_domain, sep, self.domain = pre_auth.partition('@')
- self.peer, sep, post_peer = pre_domain.rpartition('?')
- transport, sep, self.user = post_peer.rpartition('://')
-
- self.protocol = transport if transport else 'udp'
+ self.user, sep, self.domain = pre_auth.partition('@')
def write(self, pjsip, nmapped):
"""
@@ -981,9 +1011,8 @@ class Registration:
if hasattr(self, 'secret') and self.secret:
set_value('password', self.secret, auth_section, pjsip, nmapped,
'auth')
- if hasattr(self, 'authuser'):
- set_value('username', self.authuser or self.user, auth_section,
- pjsip, nmapped, 'auth')
+ set_value('username', self.authuser if hasattr(self, 'authuser')
+ else self.user, auth_section, pjsip, nmapped, 'auth')
set_value('outbound_auth', auth_section, section, pjsip, nmapped,
'registration')
@@ -1080,6 +1109,35 @@ def find_non_mapped(sections, nmapped):
pass
+def map_system(sip, pjsip, nmapped):
+ section = 'system' # Just a label; you as user can change that
+ type = 'system' # Not a label, therefore not the same as section
+
+ try:
+ user_agent = sip.get('general', 'useragent')[0]
+ set_value('user_agent', user_agent, 'global', pjsip, nmapped, 'global')
+ except LookupError:
+ pass
+
+ try:
+ timer_t1 = sip.get('general', 'timert1')[0]
+ set_value('timer_t1', timer_t1, section, pjsip, nmapped, type)
+ except LookupError:
+ pass
+
+ try:
+ timer_b = sip.get('general', 'timerb')[0]
+ set_value('timer_b', timer_b, section, pjsip, nmapped, type)
+ except LookupError:
+ pass
+
+ try:
+ compact_headers = sip.get('general', 'compactheaders')[0]
+ set_value('compact_headers', compact_headers, section, pjsip, nmapped, type)
+ except LookupError:
+ pass
+
+
def convert(sip, filename, non_mappings, include):
"""
Entry point for configuration file conversion. This
@@ -1092,6 +1150,7 @@ def convert(sip, filename, non_mappings, include):
nmapped = non_mapped(non_mappings[filename])
if not include:
# Don't duplicate transport and registration configs
+ map_system(sip, pjsip, nmapped)
map_transports(sip, pjsip, nmapped)
map_registrations(sip, pjsip, nmapped)
map_auth(sip, pjsip, nmapped)
diff --git a/include/asterisk/ari.h b/include/asterisk/ari.h
index 79b9516eb..4019e94e3 100644
--- a/include/asterisk/ari.h
+++ b/include/asterisk/ari.h
@@ -146,10 +146,11 @@ void ast_ari_invoke(struct ast_tcptls_session_instance *ser,
* for unit testing.
*
* \param uri Requested URI, relative to the docs path.
+ * \param prefix prefix that prefixes all http requests
* \param headers HTTP headers.
* \param[out] response RESTful HTTP response.
*/
-void ast_ari_get_docs(const char *uri, struct ast_variable *headers, struct ast_ari_response *response);
+void ast_ari_get_docs(const char *uri, const char *prefix, struct ast_variable *headers, struct ast_ari_response *response);
/*! \brief Abstraction for reading/writing JSON to a WebSocket */
struct ast_ari_websocket_session;
diff --git a/include/asterisk/http.h b/include/asterisk/http.h
index bb8973dce..d5f54cc65 100644
--- a/include/asterisk/http.h
+++ b/include/asterisk/http.h
@@ -101,6 +101,7 @@ struct ast_http_uri {
AST_LIST_ENTRY(ast_http_uri) entry;
const char *description;
const char *uri;
+ const char *prefix;
ast_http_callback callback;
unsigned int has_subtree:1;
/*! Structure is malloc'd */
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index cd6b33db4..4cede4391 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -755,6 +755,8 @@ struct ast_sip_endpoint {
struct ast_acl_list *contact_acl;
/*! The number of seconds into call to disable fax detection. (0 = disabled) */
unsigned int faxdetect_timeout;
+ /*! Override the user on the outgoing Contact header with this value. */
+ char *contact_user;
};
/*!
diff --git a/main/http.c b/main/http.c
index bc23e6e56..da564da20 100644
--- a/main/http.c
+++ b/main/http.c
@@ -671,6 +671,8 @@ int ast_http_uri_link(struct ast_http_uri *urih)
AST_RWLIST_WRLOCK(&uris);
+ urih->prefix = prefix;
+
if ( AST_RWLIST_EMPTY(&uris) || strlen(AST_RWLIST_FIRST(&uris)->uri) <= len ) {
AST_RWLIST_INSERT_HEAD(&uris, urih, entry);
AST_RWLIST_UNLOCK(&uris);
diff --git a/res/res_ari.c b/res/res_ari.c
index 0cc1ee7b0..eb15a88b8 100644
--- a/res/res_ari.c
+++ b/res/res_ari.c
@@ -579,7 +579,7 @@ void ast_ari_invoke(struct ast_tcptls_session_instance *ser,
}
}
-void ast_ari_get_docs(const char *uri, struct ast_variable *headers,
+void ast_ari_get_docs(const char *uri, const char *prefix, struct ast_variable *headers,
struct ast_ari_response *response)
{
RAII_VAR(struct ast_str *, absolute_path_builder, NULL, ast_free);
@@ -685,9 +685,15 @@ void ast_ari_get_docs(const char *uri, struct ast_variable *headers,
}
}
if (host != NULL) {
- ast_json_object_set(
- obj, "basePath",
- ast_json_stringf("http://%s/ari", host->value));
+ if (prefix != NULL && strlen(prefix) > 0) {
+ ast_json_object_set(
+ obj, "basePath",
+ ast_json_stringf("http://%s%s/ari", host->value,prefix));
+ } else {
+ ast_json_object_set(
+ obj, "basePath",
+ ast_json_stringf("http://%s/ari", host->value));
+ }
} else {
/* Without the host, we don't have the basePath */
ast_json_object_del(obj, "basePath");
@@ -969,7 +975,7 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser,
ast_ari_response_error(&response, 405, "Method Not Allowed", "Unsupported method");
} else {
/* Skip the api-docs prefix */
- ast_ari_get_docs(strchr(uri, '/') + 1, headers, &response);
+ ast_ari_get_docs(strchr(uri, '/') + 1, urih->prefix, headers, &response);
}
} else {
/* Other RESTful resources */
diff --git a/res/res_ari_applications.c b/res/res_ari_applications.c
index f25fd070f..7ce9722fd 100644
--- a/res/res_ari_applications.c
+++ b/res/res_ari_applications.c
@@ -496,7 +496,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/applications.{format} */
+/*! \brief REST handler for /api-docs/applications.json */
static struct stasis_rest_handlers applications_applicationName_subscription = {
.path_segment = "subscription",
.callbacks = {
@@ -506,7 +506,7 @@ static struct stasis_rest_handlers applications_applicationName_subscription = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/applications.{format} */
+/*! \brief REST handler for /api-docs/applications.json */
static struct stasis_rest_handlers applications_applicationName = {
.path_segment = "applicationName",
.is_wildcard = 1,
@@ -516,7 +516,7 @@ static struct stasis_rest_handlers applications_applicationName = {
.num_children = 1,
.children = { &applications_applicationName_subscription, }
};
-/*! \brief REST handler for /api-docs/applications.{format} */
+/*! \brief REST handler for /api-docs/applications.json */
static struct stasis_rest_handlers applications = {
.path_segment = "applications",
.callbacks = {
diff --git a/res/res_ari_asterisk.c b/res/res_ari_asterisk.c
index a9f82eb4a..71f72eea1 100644
--- a/res/res_ari_asterisk.c
+++ b/res/res_ari_asterisk.c
@@ -1178,7 +1178,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_config_dynamic_configClass_objectType_id = {
.path_segment = "id",
.is_wildcard = 1,
@@ -1190,7 +1190,7 @@ static struct stasis_rest_handlers asterisk_config_dynamic_configClass_objectTyp
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_config_dynamic_configClass_objectType = {
.path_segment = "objectType",
.is_wildcard = 1,
@@ -1199,7 +1199,7 @@ static struct stasis_rest_handlers asterisk_config_dynamic_configClass_objectTyp
.num_children = 1,
.children = { &asterisk_config_dynamic_configClass_objectType_id, }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_config_dynamic_configClass = {
.path_segment = "configClass",
.is_wildcard = 1,
@@ -1208,7 +1208,7 @@ static struct stasis_rest_handlers asterisk_config_dynamic_configClass = {
.num_children = 1,
.children = { &asterisk_config_dynamic_configClass_objectType, }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_config_dynamic = {
.path_segment = "dynamic",
.callbacks = {
@@ -1216,7 +1216,7 @@ static struct stasis_rest_handlers asterisk_config_dynamic = {
.num_children = 1,
.children = { &asterisk_config_dynamic_configClass, }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_config = {
.path_segment = "config",
.callbacks = {
@@ -1224,7 +1224,7 @@ static struct stasis_rest_handlers asterisk_config = {
.num_children = 1,
.children = { &asterisk_config_dynamic, }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_info = {
.path_segment = "info",
.callbacks = {
@@ -1233,7 +1233,7 @@ static struct stasis_rest_handlers asterisk_info = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_modules_moduleName = {
.path_segment = "moduleName",
.is_wildcard = 1,
@@ -1246,7 +1246,7 @@ static struct stasis_rest_handlers asterisk_modules_moduleName = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_modules = {
.path_segment = "modules",
.callbacks = {
@@ -1255,7 +1255,7 @@ static struct stasis_rest_handlers asterisk_modules = {
.num_children = 1,
.children = { &asterisk_modules_moduleName, }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_logging_logChannelName_rotate = {
.path_segment = "rotate",
.callbacks = {
@@ -1264,7 +1264,7 @@ static struct stasis_rest_handlers asterisk_logging_logChannelName_rotate = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_logging_logChannelName = {
.path_segment = "logChannelName",
.is_wildcard = 1,
@@ -1275,7 +1275,7 @@ static struct stasis_rest_handlers asterisk_logging_logChannelName = {
.num_children = 1,
.children = { &asterisk_logging_logChannelName_rotate, }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_logging = {
.path_segment = "logging",
.callbacks = {
@@ -1284,7 +1284,7 @@ static struct stasis_rest_handlers asterisk_logging = {
.num_children = 1,
.children = { &asterisk_logging_logChannelName, }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk_variable = {
.path_segment = "variable",
.callbacks = {
@@ -1294,7 +1294,7 @@ static struct stasis_rest_handlers asterisk_variable = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/asterisk.{format} */
+/*! \brief REST handler for /api-docs/asterisk.json */
static struct stasis_rest_handlers asterisk = {
.path_segment = "asterisk",
.callbacks = {
diff --git a/res/res_ari_bridges.c b/res/res_ari_bridges.c
index 119687999..a60b7010a 100644
--- a/res/res_ari_bridges.c
+++ b/res/res_ari_bridges.c
@@ -1452,7 +1452,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/bridges.{format} */
+/*! \brief REST handler for /api-docs/bridges.json */
static struct stasis_rest_handlers bridges_bridgeId_addChannel = {
.path_segment = "addChannel",
.callbacks = {
@@ -1461,7 +1461,7 @@ static struct stasis_rest_handlers bridges_bridgeId_addChannel = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/bridges.{format} */
+/*! \brief REST handler for /api-docs/bridges.json */
static struct stasis_rest_handlers bridges_bridgeId_removeChannel = {
.path_segment = "removeChannel",
.callbacks = {
@@ -1470,7 +1470,7 @@ static struct stasis_rest_handlers bridges_bridgeId_removeChannel = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/bridges.{format} */
+/*! \brief REST handler for /api-docs/bridges.json */
static struct stasis_rest_handlers bridges_bridgeId_moh = {
.path_segment = "moh",
.callbacks = {
@@ -1480,7 +1480,7 @@ static struct stasis_rest_handlers bridges_bridgeId_moh = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/bridges.{format} */
+/*! \brief REST handler for /api-docs/bridges.json */
static struct stasis_rest_handlers bridges_bridgeId_play_playbackId = {
.path_segment = "playbackId",
.is_wildcard = 1,
@@ -1490,7 +1490,7 @@ static struct stasis_rest_handlers bridges_bridgeId_play_playbackId = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/bridges.{format} */
+/*! \brief REST handler for /api-docs/bridges.json */
static struct stasis_rest_handlers bridges_bridgeId_play = {
.path_segment = "play",
.callbacks = {
@@ -1499,7 +1499,7 @@ static struct stasis_rest_handlers bridges_bridgeId_play = {
.num_children = 1,
.children = { &bridges_bridgeId_play_playbackId, }
};
-/*! \brief REST handler for /api-docs/bridges.{format} */
+/*! \brief REST handler for /api-docs/bridges.json */
static struct stasis_rest_handlers bridges_bridgeId_record = {
.path_segment = "record",
.callbacks = {
@@ -1508,7 +1508,7 @@ static struct stasis_rest_handlers bridges_bridgeId_record = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/bridges.{format} */
+/*! \brief REST handler for /api-docs/bridges.json */
static struct stasis_rest_handlers bridges_bridgeId = {
.path_segment = "bridgeId",
.is_wildcard = 1,
@@ -1520,7 +1520,7 @@ static struct stasis_rest_handlers bridges_bridgeId = {
.num_children = 5,
.children = { &bridges_bridgeId_addChannel,&bridges_bridgeId_removeChannel,&bridges_bridgeId_moh,&bridges_bridgeId_play,&bridges_bridgeId_record, }
};
-/*! \brief REST handler for /api-docs/bridges.{format} */
+/*! \brief REST handler for /api-docs/bridges.json */
static struct stasis_rest_handlers bridges = {
.path_segment = "bridges",
.callbacks = {
diff --git a/res/res_ari_channels.c b/res/res_ari_channels.c
index 0952d4901..25da17d4d 100644
--- a/res/res_ari_channels.c
+++ b/res/res_ari_channels.c
@@ -2954,7 +2954,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_create = {
.path_segment = "create",
.callbacks = {
@@ -2963,7 +2963,7 @@ static struct stasis_rest_handlers channels_create = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_continue = {
.path_segment = "continue",
.callbacks = {
@@ -2972,7 +2972,7 @@ static struct stasis_rest_handlers channels_channelId_continue = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_redirect = {
.path_segment = "redirect",
.callbacks = {
@@ -2981,7 +2981,7 @@ static struct stasis_rest_handlers channels_channelId_redirect = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_answer = {
.path_segment = "answer",
.callbacks = {
@@ -2990,7 +2990,7 @@ static struct stasis_rest_handlers channels_channelId_answer = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_ring = {
.path_segment = "ring",
.callbacks = {
@@ -3000,7 +3000,7 @@ static struct stasis_rest_handlers channels_channelId_ring = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_dtmf = {
.path_segment = "dtmf",
.callbacks = {
@@ -3009,7 +3009,7 @@ static struct stasis_rest_handlers channels_channelId_dtmf = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_mute = {
.path_segment = "mute",
.callbacks = {
@@ -3019,7 +3019,7 @@ static struct stasis_rest_handlers channels_channelId_mute = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_hold = {
.path_segment = "hold",
.callbacks = {
@@ -3029,7 +3029,7 @@ static struct stasis_rest_handlers channels_channelId_hold = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_moh = {
.path_segment = "moh",
.callbacks = {
@@ -3039,7 +3039,7 @@ static struct stasis_rest_handlers channels_channelId_moh = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_silence = {
.path_segment = "silence",
.callbacks = {
@@ -3049,7 +3049,7 @@ static struct stasis_rest_handlers channels_channelId_silence = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_play_playbackId = {
.path_segment = "playbackId",
.is_wildcard = 1,
@@ -3059,7 +3059,7 @@ static struct stasis_rest_handlers channels_channelId_play_playbackId = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_play = {
.path_segment = "play",
.callbacks = {
@@ -3068,7 +3068,7 @@ static struct stasis_rest_handlers channels_channelId_play = {
.num_children = 1,
.children = { &channels_channelId_play_playbackId, }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_record = {
.path_segment = "record",
.callbacks = {
@@ -3077,7 +3077,7 @@ static struct stasis_rest_handlers channels_channelId_record = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_variable = {
.path_segment = "variable",
.callbacks = {
@@ -3087,7 +3087,7 @@ static struct stasis_rest_handlers channels_channelId_variable = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_snoop_snoopId = {
.path_segment = "snoopId",
.is_wildcard = 1,
@@ -3097,7 +3097,7 @@ static struct stasis_rest_handlers channels_channelId_snoop_snoopId = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_snoop = {
.path_segment = "snoop",
.callbacks = {
@@ -3106,7 +3106,7 @@ static struct stasis_rest_handlers channels_channelId_snoop = {
.num_children = 1,
.children = { &channels_channelId_snoop_snoopId, }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId_dial = {
.path_segment = "dial",
.callbacks = {
@@ -3115,7 +3115,7 @@ static struct stasis_rest_handlers channels_channelId_dial = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels_channelId = {
.path_segment = "channelId",
.is_wildcard = 1,
@@ -3127,7 +3127,7 @@ static struct stasis_rest_handlers channels_channelId = {
.num_children = 14,
.children = { &channels_channelId_continue,&channels_channelId_redirect,&channels_channelId_answer,&channels_channelId_ring,&channels_channelId_dtmf,&channels_channelId_mute,&channels_channelId_hold,&channels_channelId_moh,&channels_channelId_silence,&channels_channelId_play,&channels_channelId_record,&channels_channelId_variable,&channels_channelId_snoop,&channels_channelId_dial, }
};
-/*! \brief REST handler for /api-docs/channels.{format} */
+/*! \brief REST handler for /api-docs/channels.json */
static struct stasis_rest_handlers channels = {
.path_segment = "channels",
.callbacks = {
diff --git a/res/res_ari_device_states.c b/res/res_ari_device_states.c
index f6d578194..c3876af8b 100644
--- a/res/res_ari_device_states.c
+++ b/res/res_ari_device_states.c
@@ -320,7 +320,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/deviceStates.{format} */
+/*! \brief REST handler for /api-docs/deviceStates.json */
static struct stasis_rest_handlers deviceStates_deviceName = {
.path_segment = "deviceName",
.is_wildcard = 1,
@@ -332,7 +332,7 @@ static struct stasis_rest_handlers deviceStates_deviceName = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/deviceStates.{format} */
+/*! \brief REST handler for /api-docs/deviceStates.json */
static struct stasis_rest_handlers deviceStates = {
.path_segment = "deviceStates",
.callbacks = {
diff --git a/res/res_ari_endpoints.c b/res/res_ari_endpoints.c
index af50a0949..fd385313c 100644
--- a/res/res_ari_endpoints.c
+++ b/res/res_ari_endpoints.c
@@ -434,7 +434,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/endpoints.{format} */
+/*! \brief REST handler for /api-docs/endpoints.json */
static struct stasis_rest_handlers endpoints_sendMessage = {
.path_segment = "sendMessage",
.callbacks = {
@@ -443,7 +443,7 @@ static struct stasis_rest_handlers endpoints_sendMessage = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/endpoints.{format} */
+/*! \brief REST handler for /api-docs/endpoints.json */
static struct stasis_rest_handlers endpoints_tech_resource_sendMessage = {
.path_segment = "sendMessage",
.callbacks = {
@@ -452,7 +452,7 @@ static struct stasis_rest_handlers endpoints_tech_resource_sendMessage = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/endpoints.{format} */
+/*! \brief REST handler for /api-docs/endpoints.json */
static struct stasis_rest_handlers endpoints_tech_resource = {
.path_segment = "resource",
.is_wildcard = 1,
@@ -462,7 +462,7 @@ static struct stasis_rest_handlers endpoints_tech_resource = {
.num_children = 1,
.children = { &endpoints_tech_resource_sendMessage, }
};
-/*! \brief REST handler for /api-docs/endpoints.{format} */
+/*! \brief REST handler for /api-docs/endpoints.json */
static struct stasis_rest_handlers endpoints_tech = {
.path_segment = "tech",
.is_wildcard = 1,
@@ -472,7 +472,7 @@ static struct stasis_rest_handlers endpoints_tech = {
.num_children = 1,
.children = { &endpoints_tech_resource, }
};
-/*! \brief REST handler for /api-docs/endpoints.{format} */
+/*! \brief REST handler for /api-docs/endpoints.json */
static struct stasis_rest_handlers endpoints = {
.path_segment = "endpoints",
.callbacks = {
diff --git a/res/res_ari_events.c b/res/res_ari_events.c
index e4fda0a54..40a18b8fb 100644
--- a/res/res_ari_events.c
+++ b/res/res_ari_events.c
@@ -408,7 +408,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/events.{format} */
+/*! \brief REST handler for /api-docs/events.json */
static struct stasis_rest_handlers events_user_eventName = {
.path_segment = "eventName",
.is_wildcard = 1,
@@ -418,7 +418,7 @@ static struct stasis_rest_handlers events_user_eventName = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/events.{format} */
+/*! \brief REST handler for /api-docs/events.json */
static struct stasis_rest_handlers events_user = {
.path_segment = "user",
.callbacks = {
@@ -426,7 +426,7 @@ static struct stasis_rest_handlers events_user = {
.num_children = 1,
.children = { &events_user_eventName, }
};
-/*! \brief REST handler for /api-docs/events.{format} */
+/*! \brief REST handler for /api-docs/events.json */
static struct stasis_rest_handlers events = {
.path_segment = "events",
.callbacks = {
diff --git a/res/res_ari_mailboxes.c b/res/res_ari_mailboxes.c
index 4f3c73120..5b0532309 100644
--- a/res/res_ari_mailboxes.c
+++ b/res/res_ari_mailboxes.c
@@ -326,7 +326,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/mailboxes.{format} */
+/*! \brief REST handler for /api-docs/mailboxes.json */
static struct stasis_rest_handlers mailboxes_mailboxName = {
.path_segment = "mailboxName",
.is_wildcard = 1,
@@ -338,7 +338,7 @@ static struct stasis_rest_handlers mailboxes_mailboxName = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/mailboxes.{format} */
+/*! \brief REST handler for /api-docs/mailboxes.json */
static struct stasis_rest_handlers mailboxes = {
.path_segment = "mailboxes",
.callbacks = {
diff --git a/res/res_ari_playbacks.c b/res/res_ari_playbacks.c
index d01802145..b4dfd1c1c 100644
--- a/res/res_ari_playbacks.c
+++ b/res/res_ari_playbacks.c
@@ -270,7 +270,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/playbacks.{format} */
+/*! \brief REST handler for /api-docs/playbacks.json */
static struct stasis_rest_handlers playbacks_playbackId_control = {
.path_segment = "control",
.callbacks = {
@@ -279,7 +279,7 @@ static struct stasis_rest_handlers playbacks_playbackId_control = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/playbacks.{format} */
+/*! \brief REST handler for /api-docs/playbacks.json */
static struct stasis_rest_handlers playbacks_playbackId = {
.path_segment = "playbackId",
.is_wildcard = 1,
@@ -290,7 +290,7 @@ static struct stasis_rest_handlers playbacks_playbackId = {
.num_children = 1,
.children = { &playbacks_playbackId_control, }
};
-/*! \brief REST handler for /api-docs/playbacks.{format} */
+/*! \brief REST handler for /api-docs/playbacks.json */
static struct stasis_rest_handlers playbacks = {
.path_segment = "playbacks",
.callbacks = {
diff --git a/res/res_ari_recordings.c b/res/res_ari_recordings.c
index a21943520..aee3d3d2a 100644
--- a/res/res_ari_recordings.c
+++ b/res/res_ari_recordings.c
@@ -797,7 +797,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings_stored_recordingName_file = {
.path_segment = "file",
.callbacks = {
@@ -806,7 +806,7 @@ static struct stasis_rest_handlers recordings_stored_recordingName_file = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings_stored_recordingName_copy = {
.path_segment = "copy",
.callbacks = {
@@ -815,7 +815,7 @@ static struct stasis_rest_handlers recordings_stored_recordingName_copy = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings_stored_recordingName = {
.path_segment = "recordingName",
.is_wildcard = 1,
@@ -826,7 +826,7 @@ static struct stasis_rest_handlers recordings_stored_recordingName = {
.num_children = 2,
.children = { &recordings_stored_recordingName_file,&recordings_stored_recordingName_copy, }
};
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings_stored = {
.path_segment = "stored",
.callbacks = {
@@ -835,7 +835,7 @@ static struct stasis_rest_handlers recordings_stored = {
.num_children = 1,
.children = { &recordings_stored_recordingName, }
};
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings_live_recordingName_stop = {
.path_segment = "stop",
.callbacks = {
@@ -844,7 +844,7 @@ static struct stasis_rest_handlers recordings_live_recordingName_stop = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings_live_recordingName_pause = {
.path_segment = "pause",
.callbacks = {
@@ -854,7 +854,7 @@ static struct stasis_rest_handlers recordings_live_recordingName_pause = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings_live_recordingName_mute = {
.path_segment = "mute",
.callbacks = {
@@ -864,7 +864,7 @@ static struct stasis_rest_handlers recordings_live_recordingName_mute = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings_live_recordingName = {
.path_segment = "recordingName",
.is_wildcard = 1,
@@ -875,7 +875,7 @@ static struct stasis_rest_handlers recordings_live_recordingName = {
.num_children = 3,
.children = { &recordings_live_recordingName_stop,&recordings_live_recordingName_pause,&recordings_live_recordingName_mute, }
};
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings_live = {
.path_segment = "live",
.callbacks = {
@@ -883,7 +883,7 @@ static struct stasis_rest_handlers recordings_live = {
.num_children = 1,
.children = { &recordings_live_recordingName, }
};
-/*! \brief REST handler for /api-docs/recordings.{format} */
+/*! \brief REST handler for /api-docs/recordings.json */
static struct stasis_rest_handlers recordings = {
.path_segment = "recordings",
.callbacks = {
diff --git a/res/res_ari_sounds.c b/res/res_ari_sounds.c
index 8bb217153..f5a1d41ab 100644
--- a/res/res_ari_sounds.c
+++ b/res/res_ari_sounds.c
@@ -208,7 +208,7 @@ fin: __attribute__((unused))
return;
}
-/*! \brief REST handler for /api-docs/sounds.{format} */
+/*! \brief REST handler for /api-docs/sounds.json */
static struct stasis_rest_handlers sounds_soundId = {
.path_segment = "soundId",
.is_wildcard = 1,
@@ -218,7 +218,7 @@ static struct stasis_rest_handlers sounds_soundId = {
.num_children = 0,
.children = { }
};
-/*! \brief REST handler for /api-docs/sounds.{format} */
+/*! \brief REST handler for /api-docs/sounds.json */
static struct stasis_rest_handlers sounds = {
.path_segment = "sounds",
.callbacks = {
diff --git a/res/res_format_attr_g729.c b/res/res_format_attr_g729.c
new file mode 100644
index 000000000..5ba4920d9
--- /dev/null
+++ b/res/res_format_attr_g729.c
@@ -0,0 +1,76 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2016, Digium, Inc.
+ *
+ * Jason Parker <jparker@sangoma.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_REGISTER_FILE()
+
+#include "asterisk/module.h"
+#include "asterisk/format.h"
+
+/* Destroy is a required callback and must exist */
+static void g729_destroy(struct ast_format *format)
+{
+}
+
+/* Clone is a required callback and must exist */
+static int g729_clone(const struct ast_format *src, struct ast_format *dst)
+{
+ return 0;
+}
+
+static void g729_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
+{
+ /*
+ * According to the rfc the joint annexb format parameter should be set to 'yes'
+ * or 'no' based on the answerer (rfc7261 - 3.3). However, Asterisk being a B2BUA
+ * makes things tricky. So for now Asterisk will set annexb=no.
+ */
+ ast_str_append(str, 0, "a=fmtp:%u annexb=no\r\n", payload);
+}
+
+static struct ast_format_interface g729_interface = {
+ .format_destroy = g729_destroy,
+ .format_clone = g729_clone,
+ .format_generate_sdp_fmtp = g729_generate_sdp_fmtp,
+};
+
+static int load_module(void)
+{
+ if (ast_format_interface_register("g729", &g729_interface)) {
+ return AST_MODULE_LOAD_DECLINE;
+ }
+
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+static int unload_module(void)
+{
+ return 0;
+}
+
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "G.729 Format Attribute Module",
+ .support_level = AST_MODULE_SUPPORT_CORE,
+ .load = load_module,
+ .unload = unload_module,
+ .load_pri = AST_MODPRI_CHANNEL_DEPEND,
+);
diff --git a/res/res_odbc.c b/res/res_odbc.c
index 62faf98b2..f89b59e51 100644
--- a/res/res_odbc.c
+++ b/res/res_odbc.c
@@ -41,6 +41,7 @@
/*** MODULEINFO
<depend>generic_odbc</depend>
+ <depend>res_odbc_transaction</depend>
<depend>ltdl</depend>
<support_level>core</support_level>
***/
diff --git a/res/res_odbc_transaction.c b/res/res_odbc_transaction.c
index de78600f3..dd6ee30e5 100644
--- a/res/res_odbc_transaction.c
+++ b/res/res_odbc_transaction.c
@@ -26,7 +26,7 @@
#include "asterisk/module.h"
/*** MODULEINFO
- <depend>res_odbc</depend>
+ <depend>generic_odbc</depend>
<support_level>core</support_level>
***/
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 8a9a19db8..34edc8ca5 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -916,6 +916,12 @@
then the <replaceable>context</replaceable> setting is used.
</para></description>
</configOption>
+ <configOption name="contact_user" default="">
+ <synopsis>Force the user on the outgoing Contact header to this value.</synopsis>
+ <description><para>
+ On outbound requests, force the user portion of the Contact header to this value.
+ </para></description>
+ </configOption>
</configObject>
<configObject name="auth">
<synopsis>Authentication type</synopsis>
@@ -2865,8 +2871,16 @@ pjsip_dialog *ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint,
/* Update the dialog with the new local URI, we do it afterwards so we can use the dialog pool for construction */
pj_strdup_with_null(dlg->pool, &dlg->local.info_str, &local_uri);
dlg->local.info->uri = pjsip_parse_uri(dlg->pool, dlg->local.info_str.ptr, dlg->local.info_str.slen, 0);
+
dlg->local.contact = pjsip_parse_hdr(dlg->pool, &HCONTACT, local_uri.ptr, local_uri.slen, NULL);
+ if (!ast_strlen_zero(endpoint->contact_user)) {
+ pjsip_sip_uri *sip_uri;
+
+ sip_uri = pjsip_uri_get_uri(dlg->local.contact->uri);
+ pj_strdup2(dlg->pool, &sip_uri->user, endpoint->contact_user);
+ }
+
/* If a request user has been specified and we are permitted to change it, do so */
if (!ast_strlen_zero(request_user)) {
pjsip_sip_uri *sip_uri;
@@ -3168,6 +3182,18 @@ static int create_out_of_dialog_request(const pjsip_method *method, struct ast_s
return -1;
}
+ if (endpoint && !ast_strlen_zero(endpoint->contact_user)){
+ pjsip_contact_hdr *contact_hdr;
+ pjsip_sip_uri *contact_uri;
+ static const pj_str_t HCONTACT = { "Contact", 7 };
+
+ contact_hdr = pjsip_msg_find_hdr_by_name((*tdata)->msg, &HCONTACT, NULL);
+ if (contact_hdr) {
+ contact_uri = pjsip_uri_get_uri(contact_hdr->uri);
+ pj_strdup2(pool, &contact_uri->user, endpoint->contact_user);
+ }
+ }
+
/* Add the user=phone parameter if applicable */
ast_sip_add_usereqphone(endpoint, (*tdata)->pool, (*tdata)->msg->line.req.uri);
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 9871b4186..23aa522ce 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -963,7 +963,9 @@ static int dtls_handler(const struct aco_option *opt,
{
struct ast_sip_endpoint *endpoint = obj;
char *name = ast_strdupa(var->name);
- char *front, *back, *buf = name;
+ char *front = NULL;
+ char *back = NULL;
+ char *buf = name;
/* strip out underscores in the name */
front = strtok_r(buf, "_", &back);
@@ -1208,6 +1210,31 @@ static int voicemail_extension_to_str(const void *obj, const intptr_t *args, cha
return 0;
}
+static int contact_user_handler(const struct aco_option *opt,
+ struct ast_variable *var, void *obj)
+{
+ struct ast_sip_endpoint *endpoint = obj;
+
+ endpoint->contact_user = ast_strdup(var->value);
+ if (!endpoint->contact_user) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int contact_user_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_endpoint *endpoint = obj;
+
+ *buf = ast_strdup(endpoint->contact_user);
+ if (!(*buf)) {
+ return -1;
+ }
+
+ return 0;
+}
+
static void *sip_nat_hook_alloc(const char *name)
{
return ast_sorcery_generic_alloc(sizeof(struct ast_sip_nat_hook), NULL);
@@ -1905,6 +1932,7 @@ int ast_res_pjsip_initialize_configuration(void)
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_permit", "", endpoint_acl_handler, NULL, NULL, 0, 0);
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_acl", "", endpoint_acl_handler, contact_acl_to_str, NULL, 0, 0);
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "subscribe_context", "", OPT_CHAR_ARRAY_T, 0, CHARFLDSET(struct ast_sip_endpoint, subscription.context));
+ ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "contact_user", "", contact_user_handler, contact_user_to_str, NULL, 0, 0);
if (ast_sip_initialize_sorcery_transport()) {
ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n");
@@ -2036,6 +2064,7 @@ static void endpoint_destructor(void* obj)
ao2_cleanup(endpoint->persistent);
ast_variables_destroy(endpoint->channel_vars);
AST_VECTOR_FREE(&endpoint->ident_method_order);
+ ast_free(endpoint->contact_user);
}
static int init_subscription_configuration(struct ast_sip_endpoint_subscription_configuration *subscription)
diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 488492f4f..315393fdb 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -2773,22 +2773,21 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
}
break;
case PJSIP_EVENT_TRANSPORT_ERROR:
- /*
- * Clear the module data now to block session_inv_on_state_changed()
- * from calling session_end() if it hasn't already done so.
- */
- inv->mod_data[id] = NULL;
+ if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {
+ /*
+ * Clear the module data now to block session_inv_on_state_changed()
+ * from calling session_end() if it hasn't already done so.
+ */
+ inv->mod_data[id] = NULL;
- if (inv->state != PJSIP_INV_STATE_DISCONNECTED) {
- session_end(session);
+ /*
+ * Pass the session ref held by session->inv_session to
+ * session_end_completion().
+ */
+ session_end_completion(session);
+ return;
}
-
- /*
- * Pass the session ref held by session->inv_session to
- * session_end_completion().
- */
- session_end_completion(session);
- return;
+ break;
case PJSIP_EVENT_TIMER:
/*
* The timer event is run by the pjsip monitor thread and not
@@ -2808,7 +2807,8 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
* Pass the session ref held by session->inv_session to
* session_end_completion().
*/
- if (ast_sip_push_task(session->serializer, session_end_completion, session)) {
+ if (session
+ && ast_sip_push_task(session->serializer, session_end_completion, session)) {
/* Do it anyway even though this is not the right thread. */
session_end_completion(session);
}
diff --git a/rest-api-templates/api.wiki.mustache b/rest-api-templates/api.wiki.mustache
index 0a54a64a7..ad12bb695 100644
--- a/rest-api-templates/api.wiki.mustache
+++ b/rest-api-templates/api.wiki.mustache
@@ -1,7 +1,8 @@
{{#api_declaration}}
h1. {{name_title}}
-|| Method || Path || Return Model || Summary ||
+|| Method || Path<br>h5. Parameters are case-sensitive || Return Model || Summary ||
+
{{#apis}}
{{#operations}}
| {{http_method}} | [{{wiki_path}}|#{{nickname}}] | {{#response_class}}{{#is_primitive}}{{name}}{{/is_primitive}}{{^is_primitive}}[{{wiki_name}}|{{wiki_prefix}} REST Data Models#{{singular_name}}]{{/is_primitive}}{{/response_class}} | {{summary}} |
@@ -17,6 +18,7 @@ h2. {{nickname}}: {{http_method}} {{wiki_path}}
{{#has_path_parameters}}
h3. Path parameters
+Parameters are case-sensitive.
{{#path_parameters}}
* {{name}}: _{{data_type}}_ - {{{wiki_description}}}
{{#default_value}}
diff --git a/rest-api-templates/swagger_model.py b/rest-api-templates/swagger_model.py
index c76cb7f28..c71352a01 100644
--- a/rest-api-templates/swagger_model.py
+++ b/rest-api-templates/swagger_model.py
@@ -691,7 +691,7 @@ class ResourceApi(Stringify):
def load(self, api_json, processor, context):
context = context.next_stack(api_json, 'path')
validate_required_fields(api_json, self.required_fields, context)
- self.path = api_json['path']
+ self.path = api_json['path'].replace('{format}', 'json')
self.description = api_json['description']
if not self.path or self.path[0] != '/':
@@ -700,7 +700,7 @@ class ResourceApi(Stringify):
return self
def load_api_declaration(self, base_dir, processor):
- self.file = (base_dir + self.path).replace('{format}', 'json')
+ self.file = (base_dir + self.path)
self.api_declaration = ApiDeclaration().load_file(self.file, processor)
processor.process_resource_api(self, [self.file])
diff --git a/tests/test_ari.c b/tests/test_ari.c
index efec810e1..da889ec45 100644
--- a/tests/test_ari.c
+++ b/tests/test_ari.c
@@ -218,7 +218,7 @@ AST_TEST_DEFINE(get_docs)
response = response_alloc();
headers = ast_variable_new("Host", "stasis.asterisk.org", __FILE__);
- ast_ari_get_docs("resources.json", headers, response);
+ ast_ari_get_docs("resources.json", "", headers, response);
ast_test_validate(test, 200 == response->response_code);
/* basePath should be relative to the Host header */
@@ -248,7 +248,7 @@ AST_TEST_DEFINE(get_docs_nohost)
}
response = response_alloc();
- ast_ari_get_docs("resources.json", headers, response);
+ ast_ari_get_docs("resources.json", "", headers, response);
ast_test_validate(test, 200 == response->response_code);
/* basePath should be relative to the Host header */
@@ -275,7 +275,7 @@ AST_TEST_DEFINE(get_docs_notfound)
}
response = response_alloc();
- ast_ari_get_docs("i-am-not-a-resource.json", headers, response);
+ ast_ari_get_docs("i-am-not-a-resource.json", "", headers, response);
ast_test_validate(test, 404 == response->response_code);
return AST_TEST_PASS;
@@ -298,7 +298,7 @@ AST_TEST_DEFINE(get_docs_hackerz)
}
response = response_alloc();
- ast_ari_get_docs("../../../../sbin/asterisk", headers, response);
+ ast_ari_get_docs("../../../../sbin/asterisk", "", headers, response);
ast_test_validate(test, 404 == response->response_code);
return AST_TEST_PASS;
diff --git a/third-party/pjproject/patches/0003-r5403-pjsip_IPV6_V6ONLY.patch b/third-party/pjproject/patches/0003-r5403-pjsip_IPV6_V6ONLY.patch
new file mode 100644
index 000000000..b324b53f4
--- /dev/null
+++ b/third-party/pjproject/patches/0003-r5403-pjsip_IPV6_V6ONLY.patch
@@ -0,0 +1,13 @@
+--- a/pjlib/src/pj/sock_bsd.c
++++ b/pjlib/src/pj/sock_bsd.c
+@@ -539,6 +539,10 @@
+ pj_sock_setsockopt(*sock, pj_SOL_SOCKET(), pj_SO_NOSIGPIPE(),
+ &val, sizeof(val));
+ }
++ if (af != PJ_AF_INET) { /* Linux Kernel 2.4.21; June 2003 */
++ pj_sock_setsockopt(*sock, PJ_SOL_IPV6, IPV6_V6ONLY,
++ &val, sizeof(val));
++ }
+ #if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \
+ PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0
+ if (type == pj_SOCK_DGRAM()) {