Compare commits

...

8 Commits
18.6 ... 18.0.1

Author SHA1 Message Date
Asterisk Development Team
3c299d2aa0 Update for 18.0.1 2020-11-05 16:25:45 -05:00
Ben Ford
7d33320cbe AST-2020-002 - res_pjsip: Stop sending INVITEs after challenge limit.
If Asterisk sends out an INVITE and receives a challenge with a
different nonce value each time, it will continuously send out INVITEs,
even if the call is hung up. The endpoint must be configured for
outbound authentication for this to occur. A limit has been set on
outbound INVITEs so that, once reached, Asterisk will stop sending
INVITEs and the transaction will terminate.

ASTERISK-29013

Change-Id: I2d001ca745b00ca8aa12030f2240cd72363b46f7
2020-11-05 15:23:50 -06:00
Kevin Harwell
eed50a17e5 AST-2020-001 - res_pjsip: Return dialog locked and referenced
pjproject returns the dialog locked and with a reference. However,
in Asterisk the method that handles this decrements the reference
and removes the lock prior to returning. This makes it possible,
under some circumstances, for another thread to free said dialog
before the thread that created it attempts to use it again. Of
course when the thread that created it tries to use a freed dialog
a crash can occur.

This patch makes it so Asterisk now returns the newly created
dialog both locked, and with an added reference. This allows the
caller to de-reference, and unlock the dialog when it is safe to
do so.

In the case of a new SIP Invite the lock, and reference are now
held for the entirety of the new invite handling process.
Otherwise it's possible for the dialog, or its dependent objects,
like the transaction, to disappear. For example if there is a TCP
transport error.

ASTERISK-29057 #close

Change-Id: I5ef645a47829596f402cf383dc02c629c618969e
(cherry picked from commit 6baa4b53be)
2020-11-05 15:34:40 -05:00
Asterisk Development Team
2c1bba3cbe Update for 18.0.0 2020-10-19 13:31:06 -05:00
Andrew Siplas
79d749d2b5 logger.conf.sample: add missing comment mark
Add missing comment mark from stock configuration.

ASTERISK-29123 #close

Change-Id: I4f94eb4544166bca8af4c17fd11edee3c6980620
2020-10-16 07:09:28 -05:00
Asterisk Development Team
6fd94258f8 Update for 18.0.0-rc2 2020-10-13 11:24:42 -05:00
Joshua C. Colp
5cc4a391b3 res_pjsip: Adjust outgoing offer call pref.
This changes the outgoing offer call preference
default option to match the behavior of previous
versions of Asterisk.

The additional advanced codec negotiation options
have also been removed from the sample configuration
and marked as reserved for future functionality in
XML documentation.

The codec preference options have also been fixed to
enforce local codec configuration.

ASTERISK-29109

Change-Id: Iad19347bd5f3d89900c15ecddfebf5e20950a1c2
2020-10-13 09:43:03 -05:00
Asterisk Development Team
704cb88799 Update for 18.0.0-rc1 2020-09-09 10:43:27 -05:00
21 changed files with 95465 additions and 107 deletions

1
.lastclean Normal file
View File

@@ -0,0 +1 @@
40

1
.version Normal file
View File

@@ -0,0 +1 @@
18.0.1

92196
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><title>Release Summary - asterisk-18.0.1</title><h1 align="center"><a name="top">Release Summary</a></h1><h3 align="center">asterisk-18.0.1</h3><h3 align="center">Date: 2020-11-05</h3><h3 align="center">&lt;asteriskteam@digium.com&gt;</h3><hr><h2 align="center">Table of Contents</h2><ol>
<li><a href="#summary">Summary</a></li>
<li><a href="#contributors">Contributors</a></li>
<li><a href="#closed_issues">Closed Issues</a></li>
<li><a href="#diffstat">Diffstat</a></li>
</ol><hr><a name="summary"><h2 align="center">Summary</h2></a><center><a href="#top">[Back to Top]</a></center><p>This release has been made to address one or more security vulnerabilities that have been identified. A security advisory document has been published for each vulnerability that includes additional information. Users of versions of Asterisk that are affected are strongly encouraged to review the advisories and determine what action they should take to protect their systems from these issues.</p><p>Security Advisories:</p><ul>
<li><a href="http://downloads.asterisk.org/pub/security/AST-2020-001,AST-2020-002.html">AST-2020-001,AST-2020-002</a></li>
</ul><p>The data in this summary reflects changes that have been made since the previous release, asterisk-18.0.0.</p><hr><a name="contributors"><h2 align="center">Contributors</h2></a><center><a href="#top">[Back to Top]</a></center><p>This table lists the people who have submitted code, those that have tested patches, as well as those that reported issues on the issue tracker that were resolved in this release. For coders, the number is how many of their patches (of any size) were committed into this release. For testers, the number is the number of times their name was listed as assisting with testing a patch. Finally, for reporters, the number is the number of issues that they reported that were affected by commits that went into this release.</p><table width="100%" border="0">
<tr><th width="33%">Coders</th><th width="33%">Testers</th><th width="33%">Reporters</th></tr>
<tr valign="top"><td width="33%">1 Kevin Harwell <kharwell@sangoma.com><br/>1 Ben Ford <bford@digium.com><br/></td><td width="33%"><td width="33%">1 Sandro Gauci <sandro@enablesecurity.com><br/>1 Sebastian Damm <damm@sipgate.de><br/></td></tr>
</table><hr><a name="closed_issues"><h2 align="center">Closed Issues</h2></a><center><a href="#top">[Back to Top]</a></center><p>This is a list of all issues from the issue tracker that were closed by changes that went into this release.</p><h3>Security</h3><h4>Category: pjproject/pjsip</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-29057">ASTERISK-29057</a>: pjsip: Crash on call rejection during high load<br/>Reported by: Sandro Gauci<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=eed50a17e57817ba7e85bdce253852466639adb0">[eed50a17e5]</a> Kevin Harwell -- AST-2020-001 - res_pjsip: Return dialog locked and referenced</li>
</ul><br><h3>Bug</h3><h4>Category: Resources/res_pjsip</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-29013">ASTERISK-29013</a>: res_pjsip: Asterisk doesn't stop sending invites (with auth) on 407 replies<br/>Reported by: Sebastian Damm<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=7d33320cbe14d15b7ce45c3293f122c48c9a2fda">[7d33320cbe]</a> Ben Ford -- AST-2020-002 - res_pjsip: Stop sending INVITEs after challenge limit.</li>
</ul><br><h4>Category: Resources/res_pjsip_authenticator_digest</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-29013">ASTERISK-29013</a>: res_pjsip: Asterisk doesn't stop sending invites (with auth) on 407 replies<br/>Reported by: Sebastian Damm<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=7d33320cbe14d15b7ce45c3293f122c48c9a2fda">[7d33320cbe]</a> Ben Ford -- AST-2020-002 - res_pjsip: Stop sending INVITEs after challenge limit.</li>
</ul><br><hr><a name="diffstat"><h2 align="center">Diffstat Results</h2></a><center><a href="#top">[Back to Top]</a></center><p>This is a summary of the changes to the source code that went into this release that was generated using the diffstat utility.</p><pre>include/asterisk/res_pjsip.h | 46 ++++++++++++
include/asterisk/res_pjsip_session.h | 2
res/res_pjsip.c | 52 +++++++++++---
res/res_pjsip_pubsub.c | 10 ++
res/res_pjsip_session.c | 128 ++++++++++++++++++++++++++++++++---
5 files changed, 219 insertions(+), 19 deletions(-)</pre><br></html>

107
asterisk-18.0.1-summary.txt Normal file
View File

@@ -0,0 +1,107 @@
Release Summary
asterisk-18.0.1
Date: 2020-11-05
<asteriskteam@digium.com>
----------------------------------------------------------------------
Table of Contents
1. Summary
2. Contributors
3. Closed Issues
4. Diffstat
----------------------------------------------------------------------
Summary
[Back to Top]
This release has been made to address one or more security vulnerabilities
that have been identified. A security advisory document has been published
for each vulnerability that includes additional information. Users of
versions of Asterisk that are affected are strongly encouraged to review
the advisories and determine what action they should take to protect their
systems from these issues.
Security Advisories:
* AST-2020-001,AST-2020-002
The data in this summary reflects changes that have been made since the
previous release, asterisk-18.0.0.
----------------------------------------------------------------------
Contributors
[Back to Top]
This table lists the people who have submitted code, those that have
tested patches, as well as those that reported issues on the issue tracker
that were resolved in this release. For coders, the number is how many of
their patches (of any size) were committed into this release. For testers,
the number is the number of times their name was listed as assisting with
testing a patch. Finally, for reporters, the number is the number of
issues that they reported that were affected by commits that went into
this release.
Coders Testers Reporters
1 Kevin Harwell 1 Sandro Gauci
1 Ben Ford 1 Sebastian Damm
----------------------------------------------------------------------
Closed Issues
[Back to Top]
This is a list of all issues from the issue tracker that were closed by
changes that went into this release.
Security
Category: pjproject/pjsip
ASTERISK-29057: pjsip: Crash on call rejection during high load
Reported by: Sandro Gauci
* [eed50a17e5] Kevin Harwell -- AST-2020-001 - res_pjsip: Return dialog
locked and referenced
Bug
Category: Resources/res_pjsip
ASTERISK-29013: res_pjsip: Asterisk doesn't stop sending invites (with
auth) on 407 replies
Reported by: Sebastian Damm
* [7d33320cbe] Ben Ford -- AST-2020-002 - res_pjsip: Stop sending
INVITEs after challenge limit.
Category: Resources/res_pjsip_authenticator_digest
ASTERISK-29013: res_pjsip: Asterisk doesn't stop sending invites (with
auth) on 407 replies
Reported by: Sebastian Damm
* [7d33320cbe] Ben Ford -- AST-2020-002 - res_pjsip: Stop sending
INVITEs after challenge limit.
----------------------------------------------------------------------
Diffstat Results
[Back to Top]
This is a summary of the changes to the source code that went into this
release that was generated using the diffstat utility.
include/asterisk/res_pjsip.h | 46 ++++++++++++
include/asterisk/res_pjsip_session.h | 2
res/res_pjsip.c | 52 +++++++++++---
res/res_pjsip_pubsub.c | 10 ++
res/res_pjsip_session.c | 128 ++++++++++++++++++++++++++++++++---
5 files changed, 219 insertions(+), 19 deletions(-)

View File

@@ -112,7 +112,7 @@
; - [plain] - The plain formatter, this outputs log messages using a
; human readable format with the addition of function name
; and line number. No color escape codes are ever printed
nor are verbose messages treated specially.
; nor are verbose messages treated specially.
; - [json] - Log the output in JSON. Note that JSON formatted log entries,
; if specified for a logger type of 'console', will be formatted
; per the 'default' formatter for log messages of type VERBOSE.

View File

@@ -828,69 +828,17 @@
; local - Include all codecs in the local list that
; are also in the remote list preserving the local
; order.
; local_merge - Include all codecs in BOTH lists
; preserving the local list order. Codes in the
; remote list not in the local list will be placed
; at the end of the joint list.
; local_merge - Include all codecs in the local list
; preserving the local order.
; local_first - Include only the first codec in the
; local list.
; remote - Include all codecs in the remote list that
; are also in the local list preserving remote list
; order. (default)
; remote_merge - Include all codecs in BOTH lists
; preserving the remote list order. Codes in the
; local list not in the remote list will be placed
; at the end of the joint list.
; remote_first - Include only the first codec in
; the remote list.
;codec_prefs_incoming_offer=; This is a string that describes how the codecs
; specified on an incoming SDP offer (pending) are
; reconciled with the codecs specified on an endpoint
; (configured) before being sent to the Asterisk core.
; The string actually specifies 4 name:value pair
; parameters separated by commas. Whitespace is
; ignored and they may be specified in any order.
; prefer: <pending | configured>,
; operation: <intersect | only_preferred
; | only_nonpreferred>,
; keep: <first | all>,
; transcode: <allow | prevent>
;codec_prefs_outgoing_offer=; This is a string that describes how the codecs
; specified in the topology that comes from the
; Asterisk core (pending) are reconciled with the
; codecs specified on an endpoint (configured)
; when sending an SDP offer.
; The string actually specifies 4 name:value pair
; parameters separated by commas. Whitespace is
; ignored and they may be specified in any order.
; prefer: <pending | configured>,
; operation: <intersect | union
; | only_preferred | only_nonpreferred>,
; keep: <first | all>,
; transcode: <allow | prevent>
;codec_prefs_incoming_answer=; This is a string that describes how the codecs
; specified in an incoming SDP answer (pending)
; are reconciled with the codecs specified on an
; endpoint (configured) when receiving an SDP
; answer.
; The string actually specifies 4 name:value pair
; parameters separated by commas. Whitespace is
; ignored and they may be specified in any order.
; prefer: <pending | configured>,
; operation: <intersect | union
; | only_preferred | only_nonpreferred>,
; keep: <first | all>
;codec_prefs_outgoing_answer=; This is a string that describes how the codecs
; that come from the core (pending) are reconciled
; with the codecs specified on an endpoint
; (configured) when sending an SDP answer.
; The string actually specifies 4 name:value pair
; parameters separated by commas. Whitespace is
; ignored and they may be specified in any order.
; prefer: <pending | configured>,
; operation: <intersect | union
; | only_preferred | only_nonpreferred>,
; keep: <first | all>
; order.
; remote_merge - Include all codecs in the local list
; preserving the remote list order. (default)
; remote_first - Include only the first codec in the
; remote list that is also in the local list.
;preferred_codec_only=no ; Respond to a SIP invite with the single most
; preferred codec rather than advertising all joint
; codec capabilities. This limits the other side's

View File

@@ -0,0 +1,41 @@
CREATE TABLE alembic_version (
version_num VARCHAR(32) NOT NULL,
CONSTRAINT alembic_version_pkc PRIMARY KEY (version_num)
);
-- Running upgrade -> 210693f3123d
CREATE TABLE cdr (
accountcode VARCHAR(20),
src VARCHAR(80),
dst VARCHAR(80),
dcontext VARCHAR(80),
clid VARCHAR(80),
channel VARCHAR(80),
dstchannel VARCHAR(80),
lastapp VARCHAR(80),
lastdata VARCHAR(80),
start DATETIME,
answer DATETIME,
end DATETIME,
duration INTEGER,
billsec INTEGER,
disposition VARCHAR(45),
amaflags VARCHAR(45),
userfield VARCHAR(256),
uniqueid VARCHAR(150),
linkedid VARCHAR(150),
peeraccount VARCHAR(20),
sequence INTEGER
);
INSERT INTO alembic_version (version_num) VALUES ('210693f3123d');
-- Running upgrade 210693f3123d -> 54cde9847798
ALTER TABLE cdr MODIFY accountcode VARCHAR(80) NULL;
ALTER TABLE cdr MODIFY peeraccount VARCHAR(80) NULL;
UPDATE alembic_version SET version_num='54cde9847798' WHERE alembic_version.version_num = '210693f3123d';

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
CREATE TABLE alembic_version (
version_num VARCHAR(32) NOT NULL,
CONSTRAINT alembic_version_pkc PRIMARY KEY (version_num)
);
-- Running upgrade -> a2e9769475e
CREATE TABLE voicemail_messages (
dir VARCHAR(255) NOT NULL,
msgnum INTEGER NOT NULL,
context VARCHAR(80),
macrocontext VARCHAR(80),
callerid VARCHAR(80),
origtime INTEGER,
duration INTEGER,
recording BLOB,
flag VARCHAR(30),
category VARCHAR(30),
mailboxuser VARCHAR(30),
mailboxcontext VARCHAR(30),
msg_id VARCHAR(40)
);
ALTER TABLE voicemail_messages ADD CONSTRAINT voicemail_messages_dir_msgnum PRIMARY KEY (dir, msgnum);
CREATE INDEX voicemail_messages_dir ON voicemail_messages (dir);
INSERT INTO alembic_version (version_num) VALUES ('a2e9769475e');
-- Running upgrade a2e9769475e -> 39428242f7f5
ALTER TABLE voicemail_messages MODIFY recording BLOB(4294967295) NULL;
UPDATE alembic_version SET version_num='39428242f7f5' WHERE alembic_version.version_num = 'a2e9769475e';

View File

@@ -0,0 +1,45 @@
BEGIN;
CREATE TABLE alembic_version (
version_num VARCHAR(32) NOT NULL,
CONSTRAINT alembic_version_pkc PRIMARY KEY (version_num)
);
-- Running upgrade -> 210693f3123d
CREATE TABLE cdr (
accountcode VARCHAR(20),
src VARCHAR(80),
dst VARCHAR(80),
dcontext VARCHAR(80),
clid VARCHAR(80),
channel VARCHAR(80),
dstchannel VARCHAR(80),
lastapp VARCHAR(80),
lastdata VARCHAR(80),
start TIMESTAMP WITHOUT TIME ZONE,
answer TIMESTAMP WITHOUT TIME ZONE,
"end" TIMESTAMP WITHOUT TIME ZONE,
duration INTEGER,
billsec INTEGER,
disposition VARCHAR(45),
amaflags VARCHAR(45),
userfield VARCHAR(256),
uniqueid VARCHAR(150),
linkedid VARCHAR(150),
peeraccount VARCHAR(20),
sequence INTEGER
);
INSERT INTO alembic_version (version_num) VALUES ('210693f3123d');
-- Running upgrade 210693f3123d -> 54cde9847798
ALTER TABLE cdr ALTER COLUMN accountcode TYPE VARCHAR(80);
ALTER TABLE cdr ALTER COLUMN peeraccount TYPE VARCHAR(80);
UPDATE alembic_version SET version_num='54cde9847798' WHERE alembic_version.version_num = '210693f3123d';
COMMIT;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
BEGIN;
CREATE TABLE alembic_version (
version_num VARCHAR(32) NOT NULL,
CONSTRAINT alembic_version_pkc PRIMARY KEY (version_num)
);
-- Running upgrade -> a2e9769475e
CREATE TABLE voicemail_messages (
dir VARCHAR(255) NOT NULL,
msgnum INTEGER NOT NULL,
context VARCHAR(80),
macrocontext VARCHAR(80),
callerid VARCHAR(80),
origtime INTEGER,
duration INTEGER,
recording BYTEA,
flag VARCHAR(30),
category VARCHAR(30),
mailboxuser VARCHAR(30),
mailboxcontext VARCHAR(30),
msg_id VARCHAR(40)
);
ALTER TABLE voicemail_messages ADD CONSTRAINT voicemail_messages_dir_msgnum PRIMARY KEY (dir, msgnum);
CREATE INDEX voicemail_messages_dir ON voicemail_messages (dir);
INSERT INTO alembic_version (version_num) VALUES ('a2e9769475e');
-- Running upgrade a2e9769475e -> 39428242f7f5
ALTER TABLE voicemail_messages ALTER COLUMN recording TYPE BYTEA;
UPDATE alembic_version SET version_num='39428242f7f5' WHERE alembic_version.version_num = 'a2e9769475e';
COMMIT;

View File

@@ -78,6 +78,9 @@ struct pjsip_tpselector;
AST_VECTOR(ast_sip_service_route_vector, char *);
/*! Maximum number of challenges before assuming that we are in a loop */
#define MAX_RX_CHALLENGES 10
/*!
* \brief Structure for SIP transport information
*/
@@ -1998,12 +2001,55 @@ pjsip_dialog *ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint,
/*!
* \brief General purpose method for creating a UAS dialog with an endpoint
*
* \deprecated This function is unsafe (due to the returned object not being locked nor
* having its reference incremented) and should no longer be used. Instead
* use ast_sip_create_dialog_uas_locked so a properly locked and referenced
* object is returned.
*
* \param endpoint A pointer to the endpoint
* \param rdata The request that is starting the dialog
* \param[out] status On failure, the reason for failure in creating the dialog
*/
pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status);
/*!
* \brief General purpose method for creating a UAS dialog with an endpoint
*
* This function creates and returns a locked, and referenced counted pjsip
* dialog object. The caller is thus responsible for freeing the allocated
* memory, decrementing the reference, and releasing the lock when done with
* the returned object.
*
* \note The safest way to unlock the object, and decrement its reference is by
* calling pjsip_dlg_dec_lock. Alternatively, pjsip_dlg_dec_session can be
* used to decrement the reference only.
*
* The dialog is returned locked and with a reference in order to ensure that the
* dialog object, and any of its associated objects (e.g. transaction) are not
* untimely destroyed. For instance, that could happen when a transport error
* occurs.
*
* As long as the caller maintains a reference to the dialog there should be no
* worry that it might unknowningly be destroyed. However, once the caller unlocks
* the dialog there is a danger that some of the dialog's internal objects could
* be lost and/or compromised. For example, when the aforementioned transport error
* occurs the dialog's associated transaction gets destroyed (see pjsip_dlg_on_tsx_state
* in sip_dialog.c, and mod_inv_on_tsx_state in sip_inv.c).
*
* In this case and before using the dialog again the caller should re-lock the
* dialog, check to make sure the dialog is still established, and the transaction
* still exists and has not been destroyed.
*
* \param endpoint A pointer to the endpoint
* \param rdata The request that is starting the dialog
* \param[out] status On failure, the reason for failure in creating the dialog
*
* \retval A locked, and reference counted pjsip_dialog object.
* \retval NULL on failure
*/
pjsip_dialog *ast_sip_create_dialog_uas_locked(const struct ast_sip_endpoint *endpoint,
pjsip_rx_data *rdata, pj_status_t *status);
/*!
* \brief General purpose method for creating an rdata structure using specific information
* \since 13.15.0

View File

@@ -233,6 +233,8 @@ struct ast_sip_session {
AST_VECTOR(, struct ast_rtp_instance_stats *) media_stats;
/*! The direction of the call respective to Asterisk */
enum ast_sip_session_call_direction call_direction;
/*! Number of challenges received during outgoing requests to determine if we are in a loop */
unsigned int authentication_challenge_count:4;
};
typedef int (*ast_sip_session_request_creation_cb)(struct ast_sip_session *session, pjsip_tx_data *tdata);

View File

@@ -111,6 +111,7 @@
on an endpoint (configured) before being sent to the Asterisk core.
The string actually specifies 4 <literal>name:value</literal> pair parameters
separated by commas. Whitespace is ignored and they may be specified in any order.
Note that this option is reserved for future functionality.
</para>
<para>
@@ -171,6 +172,7 @@
endpoint (configured) when sending an SDP offer.
The string actually specifies 4 <literal>name:value</literal> pair parameters
separated by commas. Whitespace is ignored and they may be specified in any order.
Note that this option is reserved for future functionality.
</para>
<para>
@@ -232,6 +234,8 @@
when receiving an SDP answer.
The string actually specifies 4 <literal>name:value</literal> pair parameters
separated by commas. Whitespace is ignored and they may be specified in any order.
Note that this option is reserved for future functionality.
</para>
<para>
Parameters:
@@ -288,6 +292,8 @@
when sending an SDP answer.
The string actually specifies 4 <literal>name:value</literal> pair parameters
separated by commas. Whitespace is ignored and they may be specified in any order.
Note that this option is reserved for future functionality.
</para>
<para>
Parameters:
@@ -1210,7 +1216,7 @@
</enumlist>
</description>
</configOption>
<configOption name="outgoing_call_offer_pref" default="local">
<configOption name="outgoing_call_offer_pref" default="remote_merge">
<synopsis>Preferences for selecting codecs for an outgoing call.</synopsis>
<description>
<para>Based on this setting, a joint list of preferred codecs between
@@ -1223,24 +1229,20 @@
preserving the local order.
</para></enum>
<enum name="local_merge"><para>
Include all codecs in BOTH lists preserving the local order.
Remote codecs not in the local list will be placed at the end
of the joint list.
Include all codecs in the local list preserving the local order.
</para></enum>
<enum name="local_first"><para>
Include only the first codec in the local list.
</para></enum>
<enum name="remote"><para>
Include all codecs in the remote list that are also in the local list
preserving the remote order. (default)
preserving the remote order.
</para></enum>
<enum name="remote_merge"><para>
Include all codecs in BOTH lists preserving the remote order.
Local codecs not in the remote list will be placed at the end
of the joint list.
Include all codecs in the local list preserving the remote order. (default)
</para></enum>
<enum name="remote_first"><para>
Include only the first codec in the remote list.
Include only the first codec in the remote list that is also in the local list.
</para></enum>
</enumlist>
</description>
@@ -4050,7 +4052,11 @@ static int uas_use_sips_contact(pjsip_rx_data *rdata)
return 0;
}
pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status)
typedef pj_status_t (*create_dlg_uac)(pjsip_user_agent *ua, pjsip_rx_data *rdata,
const pj_str_t *contact, pjsip_dialog **p_dlg);
static pjsip_dialog *create_dialog_uas(const struct ast_sip_endpoint *endpoint,
pjsip_rx_data *rdata, pj_status_t *status, create_dlg_uac create_fun)
{
pjsip_dialog *dlg;
pj_str_t contact;
@@ -4085,11 +4091,7 @@ pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint,
(type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? ";transport=" : "",
(type != PJSIP_TRANSPORT_UDP && type != PJSIP_TRANSPORT_UDP6) ? pjsip_transport_get_type_name(type) : "");
#ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
*status = pjsip_dlg_create_uas_and_inc_lock(pjsip_ua_instance(), rdata, &contact, &dlg);
#else
*status = pjsip_dlg_create_uas(pjsip_ua_instance(), rdata, &contact, &dlg);
#endif
*status = create_fun(pjsip_ua_instance(), rdata, &contact, &dlg);
if (*status != PJ_SUCCESS) {
char err[PJ_ERR_MSG_SIZE];
@@ -4106,13 +4108,47 @@ pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint,
ast_sip_tpselector_unref(&selector);
#ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
pjsip_dlg_dec_lock(dlg);
#endif
return dlg;
}
pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status)
{
#ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
pjsip_dialog *dlg;
dlg = create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
if (dlg) {
pjsip_dlg_dec_lock(dlg);
}
return dlg;
#else
return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas);
#endif
}
pjsip_dialog *ast_sip_create_dialog_uas_locked(const struct ast_sip_endpoint *endpoint,
pjsip_rx_data *rdata, pj_status_t *status)
{
#ifdef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
return create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas_and_inc_lock);
#else
/*
* This is put here in order to be compatible with older versions of pjproject.
* Best we can do in this case is immediately lock after getting the dialog.
* However, that does leave a "gap" between creating and locking.
*/
pjsip_dialog *dlg;
dlg = create_dialog_uas(endpoint, rdata, status, pjsip_dlg_create_uas);
if (dlg) {
pjsip_dlg_inc_lock(dlg);
}
return dlg;
#endif
}
int ast_sip_create_rdata_with_contact(pjsip_rx_data *rdata, char *packet, const char *src_name, int src_port,
char *transport_type, const char *local_name, int local_port, const char *contact)
{
@@ -4409,8 +4445,6 @@ static pj_bool_t does_method_match(const pj_str_t *message_method, const char *s
return pj_stristr(&method, message_method) ? PJ_TRUE : PJ_FALSE;
}
/*! Maximum number of challenges before assuming that we are in a loop */
#define MAX_RX_CHALLENGES 10
#define TIMER_INACTIVE 0
#define TIMEOUT_TIMER2 5

View File

@@ -2137,7 +2137,7 @@ int ast_res_pjsip_initialize_configuration(void)
ast_sorcery_object_field_register(sip_sorcery, "endpoint", "ignore_183_without_sdp", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_endpoint, ignore_183_without_sdp));
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "incoming_call_offer_pref", "local",
call_offer_pref_handler, incoming_call_offer_pref_to_str, NULL, 0, 0);
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "outgoing_call_offer_pref", "remote",
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "outgoing_call_offer_pref", "remote_merge",
call_offer_pref_handler, outgoing_call_offer_pref_to_str, NULL, 0, 0);
ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "codec_prefs_incoming_offer",
"prefer: pending, operation: intersect, keep: all, transcode: allow",

View File

@@ -1477,7 +1477,7 @@ static struct sip_subscription_tree *create_subscription_tree(const struct ast_s
}
sub_tree->role = AST_SIP_NOTIFIER;
dlg = ast_sip_create_dialog_uas(endpoint, rdata, dlg_status);
dlg = ast_sip_create_dialog_uas_locked(endpoint, rdata, dlg_status);
if (!dlg) {
if (*dlg_status != PJ_EEXISTS) {
ast_log(LOG_WARNING, "Unable to create dialog for SIP subscription\n");
@@ -1498,8 +1498,16 @@ static struct sip_subscription_tree *create_subscription_tree(const struct ast_s
}
pjsip_evsub_create_uas(dlg, &pubsub_cb, rdata, 0, &sub_tree->evsub);
subscription_setup_dialog(sub_tree, dlg);
/*
* The evsub and subscription setup both add dialog refs, so the dialog ref that
* was added when the dialog was created (see ast_sip_create_dialog_uas_lock) can
* now be removed. The lock should no longer be needed so can be removed too.
*/
pjsip_dlg_dec_lock(dlg);
#ifdef HAVE_PJSIP_EVSUB_GRP_LOCK
pjsip_evsub_add_ref(sub_tree->evsub);
#endif

View File

@@ -2246,7 +2246,6 @@ static pjsip_module session_reinvite_module = {
.on_rx_request = session_reinvite_on_rx_request,
};
void ast_sip_session_send_request_with_cb(struct ast_sip_session *session, pjsip_tx_data *tdata,
ast_sip_session_response_cb on_response)
{
@@ -2499,6 +2498,9 @@ struct ast_sip_session *ast_sip_session_alloc(struct ast_sip_endpoint *endpoint,
return NULL;
}
/* Track the number of challenges received on outbound requests */
session->authentication_challenge_count = 0;
/* Fire seesion begin handlers */
handle_session_begin(session);
@@ -2668,6 +2670,11 @@ static pj_bool_t outbound_invite_auth(pjsip_rx_data *rdata)
session = inv->mod_data[session_module.id];
if (++session->authentication_challenge_count > MAX_RX_CHALLENGES) {
ast_debug(3, "%s: Initial INVITE reached maximum number of auth attempts.\n", ast_sip_session_get_name(session));
return PJ_FALSE;
}
if (ast_sip_create_request_with_auth(&session->endpoint->outbound_auths, rdata,
tsx->last_tx, &tdata)) {
return PJ_FALSE;
@@ -3118,6 +3125,75 @@ static enum sip_get_destination_result get_destination(struct ast_sip_session *s
return SIP_GET_DEST_EXTEN_NOT_FOUND;
}
/*
* /internal
* /brief Process initial answer for an incoming invite
*
* This function should only be called during the setup, and handling of a
* new incoming invite. Most, if not all of the time, this will be called
* when an error occurs and we need to respond as such.
*
* When a SIP session termination code is given for the answer it's assumed
* this call then will be the final bit of processing before ending session
* setup. As such, we've been holding a lock, and a reference on the invite
* session's dialog. So before returning this function removes that reference,
* and unlocks the dialog.
*
* \param inv_session The session on which to answer
* \param rdata The original request
* \param answer_code The answer's numeric code
* \param terminate_code The termination code if the answer fails
* \param notify Whether or not to call on_state_changed
*
* \retval 0 if invite successfully answered, -1 if an error occurred
*/
static int new_invite_initial_answer(pjsip_inv_session *inv_session, pjsip_rx_data *rdata,
int answer_code, int terminate_code, pj_bool_t notify)
{
pjsip_tx_data *tdata = NULL;
int res = 0;
if (inv_session->state != PJSIP_INV_STATE_DISCONNECTED) {
if (pjsip_inv_initial_answer(
inv_session, rdata, answer_code, NULL, NULL, &tdata) != PJ_SUCCESS) {
pjsip_inv_terminate(inv_session, terminate_code ? terminate_code : answer_code, notify);
res = -1;
} else {
pjsip_inv_send_msg(inv_session, tdata);
}
}
if (answer_code >= 300) {
/*
* A session is ending. The dialog has a reference that needs to be
* removed and holds a lock that needs to be unlocked before returning.
*/
pjsip_dlg_dec_lock(inv_session->dlg);
}
return res;
}
/*
* /internal
* /brief Create and initialize a pjsip invite session
* pjsip_inv_session adds, and maintains a reference to the dialog upon a successful
* invite session creation until the session is destroyed. However, we'll wait to
* remove the reference that was added for the dialog when it gets created since we're
* not ready to unlock the dialog in this function.
*
* So, if this function successfully returns that means it returns with its newly
* created, and associated dialog locked and with two references (i.e. dialog's
* reference count should be 2).
*
* \param endpoint A pointer to the endpoint
* \param rdata The request that is starting the dialog
*
* \retval A pjsip invite session object
* \retval NULL on error
*/
static pjsip_inv_session *pre_session_setup(pjsip_rx_data *rdata, const struct ast_sip_endpoint *endpoint)
{
pjsip_tx_data *tdata;
@@ -3136,15 +3212,28 @@ static pjsip_inv_session *pre_session_setup(pjsip_rx_data *rdata, const struct a
}
return NULL;
}
dlg = ast_sip_create_dialog_uas(endpoint, rdata, &dlg_status);
dlg = ast_sip_create_dialog_uas_locked(endpoint, rdata, &dlg_status);
if (!dlg) {
if (dlg_status != PJ_EEXISTS) {
pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
}
return NULL;
}
/*
* The returned dialog holds a lock and has a reference added. Any paths where the
* dialog invite session is not returned must unlock the dialog and remove its reference.
*/
if (pjsip_inv_create_uas(dlg, rdata, NULL, options, &inv_session) != PJ_SUCCESS) {
pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
/*
* The acquired dialog holds a lock, and a reference. Since the dialog is not
* going to be returned here it must first be unlocked and de-referenced. This
* must be done prior to calling dialog termination.
*/
pjsip_dlg_dec_lock(dlg);
pjsip_dlg_terminate(dlg);
return NULL;
}
@@ -3153,12 +3242,13 @@ static pjsip_inv_session *pre_session_setup(pjsip_rx_data *rdata, const struct a
inv_session->sdp_neg_flags = PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE;
#endif
if (pjsip_dlg_add_usage(dlg, &session_module, NULL) != PJ_SUCCESS) {
if (pjsip_inv_initial_answer(inv_session, rdata, 500, NULL, NULL, &tdata) != PJ_SUCCESS) {
pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
}
pjsip_inv_send_msg(inv_session, tdata);
/* Dialog's lock and a reference are removed in new_invite_initial_answer */
new_invite_initial_answer(inv_session, rdata, 500, 500, PJ_FALSE);
/* Remove 2nd reference added at inv_session creation */
pjsip_dlg_dec_session(inv_session->dlg, &session_module);
return NULL;
}
return inv_session;
}
@@ -3366,7 +3456,6 @@ static void handle_new_invite_request(pjsip_rx_data *rdata)
{
RAII_VAR(struct ast_sip_endpoint *, endpoint,
ast_pjsip_rdata_get_endpoint(rdata), ao2_cleanup);
pjsip_tx_data *tdata = NULL;
pjsip_inv_session *inv_session = NULL;
struct ast_sip_session *session;
struct new_invite invite;
@@ -3382,15 +3471,37 @@ static void handle_new_invite_request(pjsip_rx_data *rdata)
SCOPE_EXIT_RTN("Failure in pre session setup\n");
}
/*
* Upon a successful pre_session_setup the associated dialog is returned locked
* and with an added reference. Well actually two references. One added when the
* dialog itself was created, and another added when the pjsip invite session was
* created and the dialog was added to it.
*
* In order to ensure the dialog's, and any of its internal attributes, lifetimes
* we'll hold the lock and maintain the reference throughout the entire new invite
* handling process. See ast_sip_create_dialog_uas_locked for more details but,
* basically we do this to make sure a transport failure does not destroy the dialog
* and/or transaction out from underneath us between pjsip calls. Alternatively, we
* could probably release the lock if we needed to, but then we'd have to re-lock and
* check the dialog and transaction prior to every pjsip call.
*
* That means any off nominal/failure paths in this function must remove the associated
* dialog reference added at dialog creation, and remove the lock. As well the
* referenced pjsip invite session must be "cleaned up", which should also then
* remove its reference to the dialog at that time.
*
* Nominally we'll unlock the dialog, and release the reference when all new invite
* process handling has successfully completed.
*/
#ifdef HAVE_PJSIP_INV_SESSION_REF
if (pjsip_inv_add_ref(inv_session) != PJ_SUCCESS) {
ast_log(LOG_ERROR, "Can't increase the session reference counter\n");
if (inv_session->state != PJSIP_INV_STATE_DISCONNECTED) {
if (pjsip_inv_initial_answer(inv_session, rdata, 500, NULL, NULL, &tdata) == PJ_SUCCESS) {
pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
} else {
pjsip_inv_send_msg(inv_session, tdata);
}
/* Dialog's lock and a reference are removed in new_invite_initial_answer */
if (!new_invite_initial_answer(inv_session, rdata, 500, 500, PJ_FALSE)) {
/* Terminate the session if it wasn't done in the answer */
pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
}
SCOPE_EXIT_RTN("Couldn't add invite session reference\n");
}
@@ -3398,10 +3509,10 @@ static void handle_new_invite_request(pjsip_rx_data *rdata)
session = ast_sip_session_alloc(endpoint, NULL, inv_session, rdata);
if (!session) {
if (pjsip_inv_initial_answer(inv_session, rdata, 500, NULL, NULL, &tdata) == PJ_SUCCESS) {
/* Dialog's lock and reference are removed in new_invite_initial_answer */
if (!new_invite_initial_answer(inv_session, rdata, 500, 500, PJ_FALSE)) {
/* Terminate the session if it wasn't done in the answer */
pjsip_inv_terminate(inv_session, 500, PJ_FALSE);
} else {
pjsip_inv_send_msg(inv_session, tdata);
}
#ifdef HAVE_PJSIP_INV_SESSION_REF
pjsip_inv_dec_ref(inv_session);
@@ -3421,6 +3532,17 @@ static void handle_new_invite_request(pjsip_rx_data *rdata)
invite.rdata = rdata;
new_invite(&invite);
/*
* The dialog lock and reference added at dialog creation time must be
* maintained throughout the new invite process. Since we're pretty much
* done at this point with things it's safe to go ahead and remove the lock
* and the reference here. See ast_sip_create_dialog_uas_locked for more info.
*
* Note, any future functionality added that does work using the dialog must
* be done before this.
*/
pjsip_dlg_dec_lock(inv_session->dlg);
SCOPE_EXIT("Request: %s Session: %s\n", req_uri, ast_sip_session_get_name(session));
ao2_ref(session, -1);
}
@@ -4066,6 +4188,7 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
ast_debug(1, "reINVITE received final response code %d\n",
tsx->status_code);
if ((tsx->status_code == 401 || tsx->status_code == 407)
&& ++session->authentication_challenge_count < MAX_RX_CHALLENGES
&& !ast_sip_create_request_with_auth(
&session->endpoint->outbound_auths,
e->body.tsx_state.src.rdata, tsx->last_tx, &tdata)) {
@@ -4160,6 +4283,7 @@ static void session_inv_on_tsx_state_changed(pjsip_inv_session *inv, pjsip_trans
(int) pj_strlen(&tsx->method.name), pj_strbuf(&tsx->method.name),
tsx->status_code);
if ((tsx->status_code == 401 || tsx->status_code == 407)
&& ++session->authentication_challenge_count < MAX_RX_CHALLENGES
&& !ast_sip_create_request_with_auth(
&session->endpoint->outbound_auths,
e->body.tsx_state.src.rdata, tsx->last_tx, &tdata)) {

View File

@@ -68,34 +68,43 @@ struct ast_format_cap *ast_sip_create_joint_call_cap(const struct ast_format_cap
{
struct ast_format_cap *joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
struct ast_format_cap *local_filtered = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
struct ast_format_cap *remote_filtered = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!joint || !local_filtered) {
if (!joint || !local_filtered || !remote_filtered) {
ast_log(LOG_ERROR, "Failed to allocate %s call offer capabilities\n",
ast_codec_media_type2str(media_type));
ao2_cleanup(joint);
ao2_cleanup(local_filtered);
ao2_cleanup(remote_filtered);
return NULL;
}
ast_format_cap_append_from_cap(local_filtered, local, media_type);
/* Remote should always be a subset of local, as local is what defines the underlying
* permitted formats.
*/
ast_format_cap_get_compatible(remote, local_filtered, remote_filtered);
if (ast_sip_call_codec_pref_test(codec_pref, LOCAL)) {
if (ast_sip_call_codec_pref_test(codec_pref, INTERSECT)) {
ast_format_cap_get_compatible(local_filtered, remote, joint); /* Get common, prefer local */
ast_format_cap_get_compatible(local_filtered, remote_filtered, joint); /* Get common, prefer local */
} else {
ast_format_cap_append_from_cap(joint, local_filtered, media_type); /* Add local */
ast_format_cap_append_from_cap(joint, remote, media_type); /* Then remote */
ast_format_cap_append_from_cap(joint, remote_filtered, media_type); /* Then remote */
}
} else {
if (ast_sip_call_codec_pref_test(codec_pref, INTERSECT)) {
ast_format_cap_get_compatible(remote, local_filtered, joint); /* Get common, prefer remote */
joint = remote_filtered; /* Get common, prefer remote - as was done when filtering initially */
remote_filtered = NULL;
} else {
ast_format_cap_append_from_cap(joint, remote, media_type); /* Add remote */
ast_format_cap_append_from_cap(joint, remote_filtered, media_type); /* Add remote */
ast_format_cap_append_from_cap(joint, local_filtered, media_type); /* Then local */
}
}
ao2_ref(local_filtered, -1);
ao2_cleanup(remote_filtered);
if (ast_format_cap_empty(joint)) {
return joint;

View File

@@ -147,11 +147,11 @@ AST_TEST_DEFINE(low_level)
ast_test_status_update(test, "Testing outgoing expected pass\n");
RUN_CREATE_JOINT("ulaw,alaw,g722", "g722,g729,alaw", "local", 1, "alaw,g722", AST_TEST_PASS);
RUN_CREATE_JOINT("ulaw,alaw,g722", "g722,g729,alaw", "local_first", 1, "alaw", AST_TEST_PASS);
RUN_CREATE_JOINT("ulaw,alaw,g722", "g722,g729,alaw", "local_merge", 1, "ulaw,alaw,g722,g729", AST_TEST_PASS);
RUN_CREATE_JOINT("ulaw,alaw,g722", "g722,g729,alaw", "local_merge", 1, "ulaw,alaw,g722", AST_TEST_PASS);
RUN_CREATE_JOINT("ulaw,alaw,g722", "g722,g729,alaw", "remote", 1, "g722,alaw", AST_TEST_PASS);
RUN_CREATE_JOINT("ulaw,alaw,g722", "g722,g729,alaw", "remote_first", 1, "g722", AST_TEST_PASS);
RUN_CREATE_JOINT("ulaw,alaw,g722", "g722,g729,alaw", "remote_merge", 1, "g722,g729,alaw,ulaw", AST_TEST_PASS);
RUN_CREATE_JOINT("!all", "g722,g729,alaw", "remote_merge", 1, "g722,g729,alaw", AST_TEST_PASS);
RUN_CREATE_JOINT("ulaw,alaw,g722", "g722,g729,alaw", "remote_merge", 1, "g722,alaw,ulaw", AST_TEST_PASS);
RUN_CREATE_JOINT("!all", "g722,g729,alaw", "remote_merge", 1, "nothing", AST_TEST_PASS);
return rc >= 1 ? AST_TEST_FAIL : AST_TEST_PASS;
}