Compare commits

...

49 Commits
master ... 17.0

Author SHA1 Message Date
Asterisk Development Team fc13cc2f59 Update for 17.0.1 2019-11-21 16:18:51 -05:00
Asterisk Development Team 95c35e1765 Update CHANGES and UPGRADE.txt for 17.0.1 2019-11-21 16:17:34 -05:00
Benjamin Keith Ford 07001c3033 Merge "manager.c: Prevent the Originate action from running the Originate app" into 17.0 2019-11-21 14:45:31 -06:00
George Joseph a6bdc1268a manager.c: Prevent the Originate action from running the Originate app
If an AMI user without the "system" authorization calls the
Originate AMI command with the Originate application,
the second Originate could run the "System" command.

Action: Originate
Channel: Local/1111
Application: Originate
Data: Local/2222,app,System,touch /tmp/owned

If the "system" authorization isn't set, we now block the
Originate app as well as the System, Exec, etc. apps.

ASTERISK-28580
Reported by: Eliel Sardañons

Change-Id: Ic4c9dedc34c426f03c8c14fce334a71386d8a5fa
(cherry picked from commit 1b9281a5de)
2019-11-21 15:38:30 -05:00
Ben Ford 92499125e8 chan_sip.c: Prevent address change on unauthenticated SIP request.
If the name of a peer is known and a SIP request is sent using that
peer's name, the address of the peer will change even if the request
fails the authentication challenge. This means that an endpoint can
be altered and even rendered unusuable, even if it was in a working
state previously. This can only occur when the nat option is set to the
default, or auto_force_rport.

This change checks the result of authentication first to ensure it is
successful before setting the address and the nat option.

ASTERISK-28589 #close

Change-Id: I581c5ed1da60ca89f590bd70872de2b660de02df
(cherry picked from commit c2279540ba)
2019-11-21 15:37:02 -05:00
Asterisk Development Team 5ffe12b6ef Update for 17.0.0 2019-10-25 09:44:25 -05:00
Joshua Colp b3951ee5b5 res_rtp_asterisk: Remove a log message that slipped in.
This was only supposed to be for testing, so now it can be
removed.

Change-Id: I3dfc2e776e70b3196aeed5688372ea80c0214b59
2019-10-17 05:51:00 -05:00
Asterisk Development Team 6f7ff1297c Update for 17.0.0-rc3 2019-10-16 12:29:13 -05:00
George Joseph 3fb68578a2 Merge "res_pjsip_mwi: potential double unref, and potential unwanted double link" into 17.0 2019-10-14 12:01:06 -05:00
Kevin Harwell 84e8364ce7 pbx: deadlock when outgoing dialed channel hangs up too quickly
Here's the basic scenario that occurred when executing an AMI fast originate
while at the same time something else locks the channels container, and also
wants a lock on the dialed channel:

1. pbx_outgoing_attempt obtains a lock on a dialed channel
2. concurrently another thread obtains a lock on the channels container, and
   subsequently requests a lock on the dialed channel. It waits on #1. For
   instance, "core show channel <dialed channel"
3. the outgoing call does not fail, but ends before the pbx_outgoing_attempt
   function exits
4. pbx_outgoing_attempt function exits, the outgoing structure destructs, and
   attempts to hang up the dialed channel
5. hang up tries to obtain the channels container lock, but can't due to #2.
6. Asterisk is deadlocked.

The solution was to allow the pbx_outgoing_exec function to "steal" ownership
of the dialed channel, and handle hanging it up. The channel now is either hung
up prior to it being potentially locked by the initiating thread, or if locked
the hang up takes place in a different thread, thus alleviating the deadlock.

ASTERISK-28561
patches:
  iliketrains.diff submitted by Joshua Colp (license 5000)

Change-Id: I51b42b92dde8f2215b69bb509e28667ee3a3853a
2019-10-11 09:49:20 -05:00
Kevin Harwell 5214acbd7f res_pjsip_mwi: potential double unref, and potential unwanted double link
When creating an unsolicited MWI aggregate subscription it was possible for
the subscription object to be double unref'ed. This patch removes the explicit
unref as it is not needed since the RAII_VAR will handle it at function end.

Less concerning there was also a bug that could potentially allow the aggregate
subscription object to be added to the unsolicited container twice. This patch
ensures it is added only once.

ASTERISK-28575

Change-Id: I9ccfdb5ea788bc0c3618db183aae235e53c12763
2019-10-10 15:31:10 -05:00
George Joseph 9cc9c0267b pjproject_bundled: Replace earlier reverts with official fixes.
Issues in pjproject 2.9 caused us to revert some of their changes
as a work around.  This introduced another issue where pjproject
wouldn't build with older gcc versions such as that found on
CentOS 6.  This commit replaces the reverts with the official
fixes for the original issues and allows pjproject to be built
on CentOS 6 again.

ASTERISK-28574
Reported-by: Niklas Larsson

Change-Id: I06f8507bea553d1a01b0b8874197d35b9d47ec4c
2019-10-10 07:02:02 -05:00
Asterisk Development Team 708cd4d4d7 Update for 17.0.0-rc2 2019-09-25 12:27:15 -05:00
George Joseph abcb8efdcd Merge "pjproject_bundled: Revert pjproject 2.9 commits causing leaks" into 17.0 2019-09-24 15:37:48 -05:00
George Joseph 410ee33355 pjproject_bundled: Revert pjproject 2.9 commits causing leaks
We've found a connection re-use regression in pjproject 2.9
introduced by commit
"Close #1019: Support for multiple listeners."
https://trac.pjsip.org/repos/changeset/6002
https://trac.pjsip.org/repos/ticket/1019

Normally, multiple SSL requests should reuse the same connection
if one already exists to the remote server.  When a transport
error occurs, the next request should establish a new connection
and any following requests should use that same one.  With this
patch, when a transport error occurs, every new request creates
a new connection so you can wind up with thousands of open tcp
sockets, possibly exhausting file handles, and increasing memory
usage.

Reverting pjproject commit 6002 (and related 6021) restores the
expected behavior.

We also found a memory leak in SSL processing that was introduced by
commit
"Fixed #2204: Add OpenSSL remote certificate chain info"
https://trac.pjsip.org/repos/changeset/6014
https://trac.pjsip.org/repos/ticket/2204

Apparently the remote certificate chain is continually recreated
causing the leak.

Reverting pjproject commit 6014 (and related 6022) restores the
expected behavior.

Both of these issues have been acknowledged by Teluu.

ASTERISK-28521

Change-Id: I8ae7233c3ac4ec29a3b991f738e655dabcaba9f1
2019-09-24 08:16:43 -05:00
Kevin Harwell fb29778ae4 res_sorcery_memory_cache: stale item update leak
When a stale item was being updated the object was being retrieved, but its
reference was not being decremented after the update. This patch makes it so
the object is now appropriately de-referenced.

ASTERISK-28523

Change-Id: I9d8173d3a0416a242f4eba92fa0853279c500ec7
2019-09-23 11:05:47 -05:00
Joshua Colp ce7641c8e8 chan_pjsip: Relock correct channel during "fax" redirect.
When fax detection occurs on an outbound PJSIP channel the
redirect operation will result in a masquerade occurring and
the underlying channel on the session changing. The code
incorrectly relocked the new channel instead of the old
channel when returning. This resulted in the new channel
being locked indefinitely. The code now always acts on the
expected channel.

ASTERISK-28538

Change-Id: I2b2e60d07e74383ae7e90d752c036c4b02d6b3a3
2019-09-17 15:35:59 -05:00
Guido Falsi e23ed0eff0 chan_dahdi: Fix build with clang/llvm
On FreeBSD using the clang/llvm compiler build fails to build due
to the switch statement argument being a non integer type expression.
Switch to an if/else if/else construct to sidestep the issue.

ASTERISK-28536 #close

Change-Id: Idf4a82cc1e94580a2d017fe9e351c226f23e20c8
2019-09-16 10:11:52 -05:00
George Joseph e86fbd0ba7 chan_sip: Update links referenced in deprecation notice
The links in the deprecation notice were the shortened
variety but it makes better sense to show the unshortened
links as they're more descriptive.

I.E.
wiki.asterisk.org/wiki/display/AST/Migrating+from+chan_sip+to+res_pjsip
rather than
wiki.asterisk.org/wiki/x/tAHOAQ

Change-Id: If2da5d5243e2d4a6f193b15691d23e7e5a7c57a9
2019-09-10 07:46:01 -05:00
George Joseph 5a856f640a Merge "AST-2019-005 - translate: Don't assume all frames will have a src." into 17.0 2019-09-05 07:52:40 -05:00
Joshua Colp a60ffe0255 AST-2019-005 - translate: Don't assume all frames will have a src.
This change removes the assumption that a frame will always have
a src set on it. This assumption is incorrect.

Given a scenario where an RTP packet is received with no payload
the resulting audio frame will have no samples. If this frame goes
through a signed linear translation path an interpolated frame can
be created (if generic packet loss concealment is enabled) that has
minimal data on it, including no src. If this frame is given to a
translation path a crash will occur due to the lack of src.

ASTERISK-28499

Change-Id: I024d10dd98207eb8a6b35b59880bcdf1090538f8
2019-09-05 05:45:59 -05:00
Kevin Harwell 2976625d42 AST-2019-004 - res_pjsip_t38.c: Add NULL checks before using session media
After receiving a 200 OK with a declined stream in response to a T.38
initiated re-invite Asterisk would crash when attempting to dereference
a NULL session media object.

This patch checks to make sure the session media object is not NULL before
attempting to use it.

ASTERISK-28495
patches:
  ast-2019-004.patch submitted by Alexei Gradinari (license 5691)

Change-Id: I168f45f4da29cfe739acf87e597baa2aae7aa572
2019-09-05 05:44:34 -05:00
Kevin Harwell c02cbeade8 res_pjsip_mwi: add better handling of solicited vs unsolicited subscriptions
res_pjsip_mwi allows both solicited and unsolicited MWI subscription types.
While both can be set in the configuration for a given endpoint/aor, only
one is allowed. Precedence is given to unsolicited. Meaning if an endpoint/aor
is configured to allow both types then the solicited subscription is rejected
when it comes in. However, there is a configuration option to override that
behavior:

mwi_subscribe_replaces_unsolicited

When set to "yes" then when a solicited subscription comes in instead of
rejecting it Asterisk is suppose to replace the unsolicited one if it exists.
Prior to this patch there was a bug in Asterisk that allowed the solicted one
to be added, but did not remove the unsolicited. As a matter of fact a new
unsolicited subscription got added everytime a SIP register was received.
Over time this eventually could "flood" a phone with SIP notifies.

This patch fixes that behavior to now make it work as expected. If configured
to do so a solicited subscription now properly replaces the unsolicited one.
As well when an unsubscribe is received the unsolicited subscription is
restored. Logic was also put in to handle reloads, and any configuration changes
that might result from that. For instance, if a solicited subscription had
previously replaced an unsolicited one, but after reload it was configured to
not allow that then the solicited one needs to be shutdown, and the unsolicited
one added.

ASTERISK-28488

Change-Id: Iec2ec12d9431097e97ed5f37119963aee41af7b1
2019-08-28 18:22:08 -05:00
Asterisk Development Team eec4ab633e Update for 17.0.0-rc1 2019-08-28 10:58:25 -05:00
Joshua Colp 03ca4a98dc Merge "Fix misname 'res_external_mwi' to 'res_mwi_external' in comments." into 17.0 2019-08-23 08:01:36 -05:00
Alexei Gradinari c961d3d9ad Fix misname 'res_external_mwi' to 'res_mwi_external' in comments.
Change-Id: Ic784be8500e5cb75dcb34bae9f03cfd93b6b34fb
2019-08-22 19:04:56 -05:00
Dan Cropp 64a2eeef89 pjproject: Configurable setting for cnonce to include hyphens or not
NEC SIP Station interface with authenticated registration only supports cnonce
up to 32 characters.  In Linux, PJSIP would generate 36 character cnonce
which included hyphens.  Teluu developed this patch adding a compile time
setting to default to not include the hyphens.  They felt it best to still
generate the UUID and strip the hyphens.
They have indicated it will be part of PJSIP 2.10.

ASTERISK-28509
Reported-by: Dan Cropp

Change-Id: Ibdfcf845d4f8c0a14df09fd983b11f2d72c5f470
2019-08-21 18:44:37 -05:00
George Joseph fe6551f69b res_ari.c: Prefer exact handler match over wildcard
Given the following request path and 2 handler paths...
Request: /channels/externalMedia
Handler: /channels/{channelId}      "wildcard"
Handler: /channels/externalmedia    "non-wildcard"

...if /channels/externalMedia was registered as a handler after
/channels/{channelId} as shown above, the request would automatically
match the wildcard handler and attempt to parse "externalMedia" into
the channelId variable which isn't what was intended.  It'd work
if the non-wildard entry was defined in rest-api/api-docs/channels.json
before the wildcard entry but that makes the json files
order-dependent which isn't a good thing.

To combat this issue, the search loop saves any wildcard match but
continues looking for exact matches at the same level.  If it finds
one, it's used.  If it hasn't found an exact match at the end of
the current level, the wildcard is used.  Regardless, after
searching the current level, the wildcard is cleared so it won't
accidentally match for a different object or a higher level.

BTW, it's currently not possible for more than 1 wildcard entry
to be defined for a level.  For instance, there couldn't be:
Handler: /channels/{channelId}
Handler: /channels/{channelName}
We wouldn't know which one to match.

Change-Id: I574aa3cbe4249c92c30f74b9b40e750e9002f925
2019-08-20 13:19:27 -05:00
Alexei Gradinari 7591e0f3a4 app_voicemail/IMAP: check mailstream not NULL in leave_voicemail
The function leave_voicemail checks if expungeonhangup is set,
but does not check if IMAP stream is closed,
so it could call imap function with NULL stream.
This leads to segfault.

ASTERISK-28505 #close

Change-Id: Ib66c57c1f1ba97774e447b36349198e2626a8d7c
2019-08-15 10:08:30 -05:00
Sean Bright fa7883c492 menuselect: Fix curses build on Gentoo Linux
Because keypad() is exported by libtinfo, it needs to be explicitly
added to the linker options.

ASTERISK-28487 #close

Change-Id: I6c2ad5b95f422c263d078b5c0e84c111807dffc6
2019-08-12 09:55:43 -05:00
George Joseph 6113d21710 Merge "srtp: Fix possible race condition, and add NULL checks" into 17.0 2019-08-09 07:52:00 -05:00
Friendly Automation 9936616290 Merge "cdr / cel: Use event time at event creation instead of processing." into 17.0 2019-08-08 13:27:27 -05:00
Kevin Harwell a92f9f595b srtp: Fix possible race condition, and add NULL checks
Somehow it's possible for the srtp session object to be NULL even though the
Asterisk srtp object itself is valid. When this happened it would cause a
crash down in the srtp code when attempting to protect or unprotect data.

After looking at the code there is at least one spot that makes this situation
possible. If Asterisk fails to unprotect the data, and after several retries
it still can't then the srtp->session gets freed, and set to NULL while still
leaving the Asterisk srtp object around. However, according to the original
issue reporter this does not appear to be their situation since they found
no errors logged stating the above happened (which Asterisk does for that
situation).

An issue was found however, where a possible race condition could occur between
the pjsip incoming negotiation, and the receiving of RTP packets. Both places
could attempt to create/setup srtp for the same rtp instance at the same time.
This potentially could be the cause of the problem as well.

Given the above this patch adds locking around srtp setup for a given rtp, or
rtcp instance. NULL checks for the session have also been added within the
protect and unprotect functions as a precaution. These checks should at least
stop Asterisk from crashing if it gets in this situation again.

This patch also fixes one other issue noticed during investigation. When doing
a replace the old object was freed before creating the replacement. If the new
replacement object failed to create then the rtp/rtcp instance would now point
to freed srtp data which could potentially cause a crash as well when the next
attempt to reference it was made. This is now fixed so the old srtp object is
kept upon replacement failure.

Lastly, more logging has been added to help diagnose future issues.

ASTERISK-28472

Change-Id: I240e11cbb1e9ea8083d59d50db069891228fe5cc
2019-08-08 13:15:53 -05:00
George Joseph b083537d84 CI: Escape backslashes in printenv/sort/tr
Change-Id: I52be64c8f6af2bbe15148a856d1f10cb113e1e94
(cherry picked from commit c6558e09af)
2019-08-08 12:15:37 -05:00
George Joseph c4b6e3c1af CI: Add "throttle" label and "skip_gate" capability
To make throttling by label fully active, the "throttle" option
has to be specified with a specific label.

You can now specify "skip_gate" in the Gerrit comments when you
do a +2 code review to tell Jenkins not to actually run the
gate.  You'd do this if you plan to manually merge the change.

Also updated the "printenv" debug output to better sort multi-line
comments.

Change-Id: I4c0b1085acec4805f2ca207eebac50aad81f27e2
2019-08-08 09:49:17 -05:00
George Joseph d567518086 Merge "app_voicemail: Remove extra menuselect build options" into 17.0 2019-08-08 07:25:54 -05:00
Joshua Colp 37a49cc6d3 cdr / cel: Use event time at event creation instead of processing.
When updating times on CDR or CEL records using the time at which
it is done can result in times being incorrect if the system is
heavily loaded and stasis message processing is delayed.

This change instead makes it so CDR and CEL use the time at which
the stasis messages that drive the systems are created. This allows
them to be backed up while still producing correct records.

ASTERISK-28498

Change-Id: I6829227e67aefa318efe5e183a94d4a1b4e8500a
2019-08-07 06:23:59 -06:00
George Joseph 6d610a6b56 CI: Make node labels job-specific
Originally, the eligible nodes for a job were labelled only by
"swdev-docker".  So basically any node could run any job.  We had
found that allowing a node to run more than 1 gate at a time was
problematic so we limited the nodes to processing 1 job at a time.
With the creation of the Asterisk 17 branches however, we now have
so many active branches that getting checks and gates through in
a timely manner is problematic when a node can run only 1 job
at a time.

Now the nodes are also labelled by the job type they can run.
For instance: "asterisk-check", "asterisk-gate", etc.  With the
"Throttle Concurrent Builds" plugin, we can now allow a node to
run more than 1 job BUT throttle by job type.  For instance:
  Allow 2 jobs but only 1 asterisk-gate at a time.
Now a node can run 2 checks or 1 check and 1 gate or 1 gate but
not 2 gates at a time.

Change-Id: I2032bf6afbcec5c341d9b852214c0c812d3d6db5
2019-08-06 09:52:43 -06:00
Friendly Automation 3fdb788f33 Merge "various modules: json integer overflow" into 17.0 2019-08-06 10:29:52 -05:00
George Joseph 95b490fc2e Merge "main/udptl.c: correctly handle udptl sequence wrap around" into 17.0 2019-08-06 09:47:34 -05:00
Kevin Harwell 66b607db88 various modules: json integer overflow
There were still a few places in the code that could overflow when "packing"
a json object with a value outside the base type integer's range. For instance:

unsigned int value = INT_MAX + 1
ast_json_pack("{s: i}", value);

would result in a negative number being "packed". In those situations this patch
alters those values to a ast_json_int_t, which widens the value up to a long or
long long.

ASTERISK-28480

Change-Id: Ied530780d83e6f1772adba0e28d8938ef30c49a1
2019-08-06 07:44:18 -06:00
Sean Bright 40e3bdc50c app_voicemail: Remove extra menuselect build options
You now select voicemail backends like normal dialplan applications, so
there is no longer a need for their own menuselect category.

Reported by snuff-work in #asterisk-dev

Change-Id: Idfa4c9c8349726074318a9e6b68d24c374521005
2019-08-06 07:22:39 -06:00
Joshua Colp 02826c20f5 res_pjsip: Fix multiple of the same contact in "pjsip show contacts".
The code for gathering contacts could result in the same contact
being retrieved and added to the list multiple times. The container
which stores the contacts to display will now only allow a contact
to be added to it once instead of multiple times.

ASTERISK-28228

Change-Id: I805185cfcec03340f57d2b9e6cc43c49401812df
2019-08-01 06:40:36 -06:00
George Joseph a59fae9a4b Merge "loader.c: Fix possible SEGV when a module fails to register" into 17.0 2019-07-31 08:56:40 -05:00
Torrey Searle 6af55244a7 main/udptl.c: correctly handle udptl sequence wrap around
incorrect handling of UDPTL squence number wrap arounds causes
loss of packets every time the wrap around occurs

ASTERISK-28483 #close

Change-Id: I33caeb2bf13c574a1ebb81714b58907091d64234
2019-07-30 06:49:22 -06:00
Asterisk Development Team 8b3fd0f564 Update CHANGES and UPGRADE.txt for 17.0.0 2019-07-29 11:47:50 -05:00
George Joseph 7b3a612d69 doc: Add "master-only" flag back to the CHANGES and UPGRADE files
In order to run the documentation scripts the flags needs to be
added back to the staging files.

Change-Id: Ia10a153c50c970cfa1e85815208dfaddb3f2ccd4
2019-07-29 11:47:37 -05:00
George Joseph 2938679ff2 loader.c: Fix possible SEGV when a module fails to register
When a module fails to register itself (usually a coding error
in the module), dlerror() can return NULL.  We weren't checking
for that in load_dlopen() before trying to strdup the error message
so a SEGV was thrown.  dlerror() is now surrounded with an S_OR
so we don't SEGV.

Change-Id: Ie0fb9316f08a321434f3f85aecf3c7d2ede8b956
2019-07-29 07:39:28 -06:00
George Joseph 80d8dce6af Prepare Asterisk 17 Branch
Change-Id: Idb79a69646d2511e7bf1573b9b0322cc22ea54e8
2019-07-26 12:06:57 -06:00
81 changed files with 90680 additions and 480 deletions

View File

@ -1,5 +1,5 @@
[gerrit]
defaultbranch=master
defaultbranch=17
#
# Intentional padding to ensure it is possible to point a commit
# to an alternative gerrit server/repository without breaking

1
.lastclean Normal file
View File

@ -0,0 +1 @@
40

1
.version Normal file
View File

@ -0,0 +1 @@
17.0.1

131
CHANGES
View File

@ -12,6 +12,137 @@
===
==============================================================================
------------------------------------------------------------------------------
--- New functionality introduced in Asterisk 17.0.0 --------------------------
------------------------------------------------------------------------------
Bridging
------------------
* The bridging core no longer uses the stasis cache for bridge
snapshots. The latest bridge snapshot is now stored on the
ast_bridge structure itself.
The following APIs are no longer available since the stasis cache
is no longer used:
ast_bridge_topic_cached()
ast_bridge_topic_all_cached()
A topic pool is now used for individual bridge topics.
The ast_bridge_cache() function was removed since there's no
longer a separate container of snapshots.
A new function "ast_bridges()" was created to retrieve the
container of all bridges. Users formerly calling
ast_bridge_cache() can use the new function to iterate over
bridges and retrieve the latest snapshot directly from the
bridge.
The ast_bridge_snapshot_get_latest() function was renamed to
ast_bridge_get_snapshot_by_uniqueid().
A new function "ast_bridge_get_snapshot()" was created to retrieve
the bridge snapshot directly from the bridge structure.
The ast_bridge_topic_all() function now returns a normal topic
not a cached one so you can't use stasis cache functions on it
either.
The ast_bridge_snapshot_type() stasis message now has the
ast_bridge_snapshot_update structure as it's data. It contains
the last snapshot and the new one.
Channels
------------------
* The core no longer uses the stasis cache for channels snapshots.
The following APIs are no longer available:
ast_channel_topic_cached()
ast_channel_topic_all_cached()
The ast_channel_cache_all() and ast_channel_cache_by_name() functions
now returns an ao2_container of ast_channel_snapshots rather than a
container of stasis_messages therefore you can't call stasis_cache
functions on it.
The ast_channel_topic_all() function now returns a normal topic,
not a cached one so you can't use stasis cache functions on it either.
The ast_channel_snapshot_type() stasis message now has the
ast_channel_snapshot_update structure as it's data.
ast_channel_snapshot_get_latest() still returns the latest snapshot.
chan_sip
------------------
* The chan_sip module is now deprecated, users should migrate to the
replacement module chan_pjsip. See guides at the Asterisk Wiki:
https://wiki.asterisk.org/wiki/x/tAHOAQ
https://wiki.asterisk.org/wiki/x/hYCLAQ
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 16.0.0 to Asterisk 17.0.0 ------------
------------------------------------------------------------------------------
AttendedTransfer
------------------
* A new application, this will queue up attended transfer to the given extension.
BlindTransfer
------------------
* A new application, this will redirect all channels currently
bridged to the caller channel to the specified destination.
ConfBridge
------------------
* Add "average_all", "highest_all", and "lowest_all" values for
the remb_behavior option. These values operate on a bridge
level instead of a per-source level. This means that a single
REMB value is calculated and sent to every sender, instead of
a REMB value that is unique for the specific sender..
Dial
------------------
* Add RINGTIME and RINGTIME_MS variables containing respectively seconds and
milliseconds between creation of the dialing channel and receiving the first
RINGING signal
Add PROGRESSTIME and PROGRESSTIME_MS variables analogous to the above with respect to
the PROGRESS signal. Shorter of these two times should be equivalent to
the PDD (Post Dial Delay) value
Add DIALEDTIME_MS and ANSWEREDTIME_MS variables to get millisecond resolution
versions of DIALEDTIME and ANSWEREDTIME
RTP/ICE
------------------
* You can now indicate that you'd like an ice_host_candidate's local address
to be published as well as the mapped address. See the sample rtp.conf
for more information.
ReadExten
------------------
* Add 'p' option to stop reading extension if user presses '#' key.
pbx_dundi
------------------
* The DUNDi PBX module now supports IPv4/IPv6 dual binding.
res_pjsip
------------------
* Added a new PJSIP global setting called norefersub.
Default is true to keep support working as before.
res_pjsip_refer configures PJSIP norefersub capability accordingly.
Checks the PJSIP global setting value.
If it is true (default) it adds the norefersub capability to PJSIP.
If it is false (disabled) it does not add the norefersub capability
to PJSIP.
This is useful for Cisco switches that do not follow RFC4488.
res_rtp_asterisk
------------------
* DTLS packets will now be fragmented according to the MTU as set in rtp.conf. This
allows larger certificates to be used for the DTLS negotiation. By default this value
is 1200.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 16.2.0 to Asterisk 16.3.0 ----------
------------------------------------------------------------------------------

86200
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,128 @@
===
===========================================================
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 17.0.0 to Asterisk 17.0.1 ------------
------------------------------------------------------------------------------
AMI
------------------
* The AMI Originate action, which optionally takes a dialplan application as
an argument, no longer accepts "Originate" as the application due to
security concerns.
------------------------------------------------------------------------------
--- New functionality introduced in Asterisk 17.0.0 --------------------------
------------------------------------------------------------------------------
Applications
------------------
* The JabberStatus application, deprecated in Asterisk 12, has been removed.
Bridging
------------------
* The bridging core no longer uses the stasis cache for bridge
snapshots. The latest bridge snapshot is now stored on the
ast_bridge structure itself.
The following APIs are no longer available since the stasis cache
is no longer used:
ast_bridge_topic_cached()
ast_bridge_topic_all_cached()
A topic pool is now used for individual bridge topics.
The ast_bridge_cache() function was removed since there's no
longer a separate container of snapshots.
A new function "ast_bridges()" was created to retrieve the
container of all bridges. Users formerly calling
ast_bridge_cache() can use the new function to iterate over
bridges and retrieve the latest snapshot directly from the
bridge.
The ast_bridge_snapshot_get_latest() function was renamed to
ast_bridge_get_snapshot_by_uniqueid().
A new function "ast_bridge_get_snapshot()" was created to retrieve
the bridge snapshot directly from the bridge structure.
The ast_bridge_topic_all() function now returns a normal topic
not a cached one so you can't use stasis cache functions on it
either.
The ast_bridge_snapshot_type() stasis message now has the
ast_bridge_snapshot_update structure as it's data. It contains
the last snapshot and the new one.
Build
------------------
* Asterisk headers are no longer installed and uninstalled automatically when
performing a "make install" or a "make uninstall". To install/uninstall the
headers, use "make install-headers" and "make uninstall-headers". The headers
also continue to be uninstalled when performing a "make uninstall-all".
Channels
------------------
* The core no longer uses the stasis cache for channels snapshots.
The following APIs are no longer available:
ast_channel_topic_cached()
ast_channel_topic_all_cached()
The ast_channel_cache_all() and ast_channel_cache_by_name() functions
now returns an ao2_container of ast_channel_snapshots rather than a
container of stasis_messages therefore you can't call stasis_cache
functions on it.
The ast_channel_topic_all() function now returns a normal topic,
not a cached one so you can't use stasis cache functions on it either.
The ast_channel_snapshot_type() stasis message now has the
ast_channel_snapshot_update structure as it's data.
ast_channel_snapshot_get_latest() still returns the latest snapshot.
chan_sip
------------------
* The chan_sip module is now deprecated, users should migrate to the
replacement module chan_pjsip. See guides at the Asterisk Wiki:
https://wiki.asterisk.org/wiki/x/tAHOAQ
https://wiki.asterisk.org/wiki/x/hYCLAQ
func_callerid
------------------
* The CALLERPRES() dialplan function, deprecated in Asterisk 1.8, has been
removed.
res_parking
------------------
* The PARKINGSLOT channel variable, deprecated in Asterisk 12 in favor of the
PARKING_SPACE channel variable, will no longer be set.
res_xmpp
------------------
* The JabberStatus application, deprecated in Asterisk 12, has been removed.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 16.0.0 to Asterisk 17.0.0 ------------
------------------------------------------------------------------------------
Core
------------------
* res_pjsip_pubsub is now required so call transfer progress can be monitored
and reported in the channel variable TRANSFERSTATUS.
app_voicemail.c
------------------
* The "Voicemail Build Options" section of menuselect has been removed along with
the FILE_STORAGE, ODBC_STORAGE and IMAP_STORAGE menuselect options. All 3 variants
of the voicemail app can now be built at the same by enabling app_voicemail,
app_voicemail_imap, and app_voicemail_odbc under the "Applications" section.
By default, only app_voicemail is enabled. Also, the modules.conf sample has
been updated to "noload" app_voicemail_imap and app_voicemail_odbc should they
all be built. Packagers must update their build scripts appropriately.
chan_pjsip
------------------
* res_pjsip_pubsub is now required so call transfer progress can be monitored
and reported in the channel variable TRANSFERSTATUS.
New in 16.0.0:
app_fax:

View File

@ -1457,9 +1457,9 @@ static void send_agent_logoff(struct ast_channel *chan, const char *agent, long
ast_assert(agent != NULL);
blob = ast_json_pack("{s: s, s: i}",
blob = ast_json_pack("{s: s, s: I}",
"agent", agent,
"logintime", logintime);
"logintime", (ast_json_int_t)logintime);
if (!blob) {
return;
}

View File

@ -5898,12 +5898,12 @@ static void send_agent_complete(const char *queuename, struct ast_channel_snapsh
break;
}
blob = ast_json_pack("{s: s, s: s, s: s, s: i, s: i, s: s}",
blob = ast_json_pack("{s: s, s: s, s: s, s: I, s: I, s: s}",
"Queue", queuename,
"Interface", member->interface,
"MemberName", member->membername,
"HoldTime", (long)(callstart - holdstart),
"TalkTime", (long)(time(NULL) - callstart),
"HoldTime", (ast_json_int_t)(callstart - holdstart),
"TalkTime", (ast_json_int_t)(time(NULL) - callstart),
"Reason", reason ?: "");
queue_publish_multi_channel_snapshot_blob(ast_queue_topic(queuename), caller, peer,
@ -7174,12 +7174,12 @@ static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_a
ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "CONNECT", "%ld|%s|%ld", (long) (time(NULL) - qe->start), ast_channel_uniqueid(peer),
(long)(orig - to > 0 ? (orig - to) / 1000 : 0));
blob = ast_json_pack("{s: s, s: s, s: s, s: i, s: i}",
blob = ast_json_pack("{s: s, s: s, s: s, s: I, s: I}",
"Queue", queuename,
"Interface", member->interface,
"MemberName", member->membername,
"HoldTime", (long) (time(NULL) - qe->start),
"RingTime", (long)(orig - to > 0 ? (orig - to) / 1000 : 0));
"HoldTime", (ast_json_int_t)(time(NULL) - qe->start),
"RingTime", (ast_json_int_t)(orig - to > 0 ? (orig - to) / 1000 : 0));
queue_publish_multi_channel_blob(qe->chan, peer, queue_agent_connect_type(), blob);
ast_copy_string(oldcontext, ast_channel_context(qe->chan), sizeof(oldcontext));

View File

@ -46,39 +46,6 @@
* \verbinclude voicemail.conf.sample
*/
/*** MODULEINFO
<defaultenabled>yes</defaultenabled>
<use type="module">res_adsi</use>
<use type="module">res_smdi</use>
<support_level>core</support_level>
***/
/*** MAKEOPTS
<category name="MENUSELECT_OPTS_app_voicemail" displayname="Voicemail Build Options" positive_output="yes" touch_on_change="apps/app_voicemail.c apps/app_directory.c">
<member name="FILE_STORAGE" displayname="Storage of Voicemail using filesystem">
<conflict>ODBC_STORAGE</conflict>
<conflict>IMAP_STORAGE</conflict>
<defaultenabled>yes</defaultenabled>
<support_level>core</support_level>
</member>
<member name="ODBC_STORAGE" displayname="Storage of Voicemail using ODBC">
<depend>generic_odbc</depend>
<conflict>IMAP_STORAGE</conflict>
<conflict>FILE_STORAGE</conflict>
<defaultenabled>no</defaultenabled>
<support_level>core</support_level>
</member>
<member name="IMAP_STORAGE" displayname="Storage of Voicemail using IMAP4">
<depend>imap_tk</depend>
<conflict>ODBC_STORAGE</conflict>
<conflict>FILE_STORAGE</conflict>
<use type="external">openssl</use>
<defaultenabled>no</defaultenabled>
<support_level>core</support_level>
</member>
</category>
***/
#include "asterisk.h"
#ifdef IMAP_STORAGE
@ -7212,7 +7179,7 @@ leave_vm_out:
#ifdef IMAP_STORAGE
/* expunge message - use UID Expunge if supported on IMAP server*/
ast_debug(3, "*** Checking if we can expunge, expungeonhangup set to %d\n", expungeonhangup);
if (expungeonhangup == 1) {
if (expungeonhangup == 1 && vms->mailstream != NULL) {
ast_mutex_lock(&vms->lock);
#ifdef HAVE_IMAP_TK2006
if (LEVELUIDPLUS (vms->mailstream)) {

View File

@ -0,0 +1,19 @@
<!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-17.0.1</title><h1 align="center"><a name="top">Release Summary</a></h1><h3 align="center">asterisk-17.0.1</h3><h3 align="center">Date: 2019-11-21</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="#commits">Other Changes</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-2019-006,AST-2019-007.html">AST-2019-006,AST-2019-007</a></li>
</ul><p>The data in this summary reflects changes that have been made since the previous release, asterisk-17.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 Asterisk Development Team <asteriskteam@digium.com><br/>1 George Joseph <gjoseph@digium.com><br/>1 Ben Ford <bford@digium.com><br/></td><td width="33%"><td width="33%">1 Eliel Sardañons <eliels@gmail.com><br/>1 Andrey V. T. <avt1203@gmail.com><br/>1 Eliel Sardañons<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: Channels/chan_sip/General</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28589">ASTERISK-28589</a>: chan_sip: Depending on configuration an INVITE can alter Addr of a peer<br/>Reported by: Andrey V. T.<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=92499125e8f4b88707b2606186d8cfa2be587918">[92499125e8]</a> Ben Ford -- chan_sip.c: Prevent address change on unauthenticated SIP request.</li>
</ul><br><h4>Category: Core/ManagerInterface</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28580">ASTERISK-28580</a>: Bypass SYSTEM write permission in manager action allows system commands execution<br/>Reported by: Eliel Sardañons<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=a6bdc1268ac5a28d5e39da28ceb508cdfa641068">[a6bdc1268a]</a> George Joseph -- manager.c: Prevent the Originate action from running the Originate app</li>
</ul><br><hr><a name="commits"><h2 align="center">Commits Not Associated with an Issue</h2></a><center><a href="#top">[Back to Top]</a></center><p>This is a list of all changes that went into this release that did not reference a JIRA issue.</p><table width="100%" border="1">
<tr><th>Revision</th><th>Author</th><th>Summary</th></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=95c35e17650b911b311e7038caf9e24162167197">95c35e1765</a></td><td>Asterisk Development Team</td><td>Update CHANGES and UPGRADE.txt for 17.0.1</td></tr>
</table><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>0 files changed</pre><br></html>

111
asterisk-17.0.1-summary.txt Normal file
View File

@ -0,0 +1,111 @@
Release Summary
asterisk-17.0.1
Date: 2019-11-21
<asteriskteam@digium.com>
----------------------------------------------------------------------
Table of Contents
1. Summary
2. Contributors
3. Closed Issues
4. Other Changes
5. 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-2019-006,AST-2019-007
The data in this summary reflects changes that have been made since the
previous release, asterisk-17.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 Asterisk Development Team 1 Eliel Sardañons
1 George Joseph 1 Andrey V. T.
1 Ben Ford 1 Eliel Sardañons
----------------------------------------------------------------------
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: Channels/chan_sip/General
ASTERISK-28589: chan_sip: Depending on configuration an INVITE can alter
Addr of a peer
Reported by: Andrey V. T.
* [92499125e8] Ben Ford -- chan_sip.c: Prevent address change on
unauthenticated SIP request.
Category: Core/ManagerInterface
ASTERISK-28580: Bypass SYSTEM write permission in manager action allows
system commands execution
Reported by: Eliel Sardañons
* [a6bdc1268a] George Joseph -- manager.c: Prevent the Originate action
from running the Originate app
----------------------------------------------------------------------
Commits Not Associated with an Issue
[Back to Top]
This is a list of all changes that went into this release that did not
reference a JIRA issue.
+------------------------------------------------------------------------+
| Revision | Author | Summary |
|------------+---------------------------+-------------------------------|
| 95c35e1765 | Asterisk Development Team | Update CHANGES and |
| | | UPGRADE.txt for 17.0.1 |
+------------------------------------------------------------------------+
----------------------------------------------------------------------
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.
0 files changed

View File

@ -15158,10 +15158,12 @@ static void mfcr2_show_links_of(struct ast_cli_args *a, struct r2links *list_hea
int channo;
int prev_channo;
x++;
switch (mfcr2->r2master) {
case 0L: thread_status = "zero"; break;
case AST_PTHREADT_NULL: thread_status = "none"; break;
default: thread_status = "created"; break;
if (mfcr2->r2master == 0L) {
thread_status = "zero";
} else if (mfcr2->r2master == AST_PTHREADT_NULL) {
thread_status = "none";
} else {
thread_status = "created";
}
snprintf(index, sizeof(index), "%d", mfcr2->index);
snprintf(live_chans_str, sizeof(live_chans_str), "%d", mfcr2->live_chans);

View File

@ -11111,18 +11111,18 @@ static int socket_process_helper(struct iax2_thread *thread)
if (iaxs[fr->callno]->pingtime <= peer->maxms) {
ast_log(LOG_NOTICE, "Peer '%s' is now REACHABLE! Time: %u\n", peer->name, iaxs[fr->callno]->pingtime);
ast_endpoint_set_state(peer->endpoint, AST_ENDPOINT_ONLINE);
blob = ast_json_pack("{s: s, s: i}",
blob = ast_json_pack("{s: s, s: I}",
"peer_status", "Reachable",
"time", iaxs[fr->callno]->pingtime);
"time", (ast_json_int_t)iaxs[fr->callno]->pingtime);
ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "IAX2/%s", peer->name); /* Activate notification */
}
} else if ((peer->historicms > 0) && (peer->historicms <= peer->maxms)) {
if (iaxs[fr->callno]->pingtime > peer->maxms) {
ast_log(LOG_NOTICE, "Peer '%s' is now TOO LAGGED (%u ms)!\n", peer->name, iaxs[fr->callno]->pingtime);
ast_endpoint_set_state(peer->endpoint, AST_ENDPOINT_ONLINE);
blob = ast_json_pack("{s: s, s: i}",
blob = ast_json_pack("{s: s, s: I}",
"peer_status", "Lagged",
"time", iaxs[fr->callno]->pingtime);
"time", (ast_json_int_t)iaxs[fr->callno]->pingtime);
ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "IAX2/%s", peer->name); /* Activate notification */
}
}

View File

@ -749,7 +749,8 @@ static int chan_pjsip_answer(struct ast_channel *ast)
}
/*! \brief Internal helper function called when CNG tone is detected */
static struct ast_frame *chan_pjsip_cng_tone_detected(struct ast_sip_session *session, struct ast_frame *f)
static struct ast_frame *chan_pjsip_cng_tone_detected(struct ast_channel *ast, struct ast_sip_session *session,
struct ast_frame *f)
{
const char *target_context;
int exists;
@ -765,11 +766,11 @@ static struct ast_frame *chan_pjsip_cng_tone_detected(struct ast_sip_session *se
}
/* If already executing in the fax extension don't do anything */
if (!strcmp(ast_channel_exten(session->channel), "fax")) {
if (!strcmp(ast_channel_exten(ast), "fax")) {
return f;
}
target_context = S_OR(ast_channel_macrocontext(session->channel), ast_channel_context(session->channel));
target_context = S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast));
/*
* We need to unlock the channel here because ast_exists_extension has the
@ -778,25 +779,30 @@ static struct ast_frame *chan_pjsip_cng_tone_detected(struct ast_sip_session *se
*
* ast_async_goto() has its own restriction on not holding the channel lock.
*/
ast_channel_unlock(session->channel);
ast_channel_unlock(ast);
ast_frfree(f);
f = &ast_null_frame;
exists = ast_exists_extension(session->channel, target_context, "fax", 1,
S_COR(ast_channel_caller(session->channel)->id.number.valid,
ast_channel_caller(session->channel)->id.number.str, NULL));
exists = ast_exists_extension(ast, target_context, "fax", 1,
S_COR(ast_channel_caller(ast)->id.number.valid,
ast_channel_caller(ast)->id.number.str, NULL));
if (exists) {
ast_verb(2, "Redirecting '%s' to fax extension due to CNG detection\n",
ast_channel_name(session->channel));
pbx_builtin_setvar_helper(session->channel, "FAXEXTEN", ast_channel_exten(session->channel));
if (ast_async_goto(session->channel, target_context, "fax", 1)) {
ast_channel_name(ast));
pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
if (ast_async_goto(ast, target_context, "fax", 1)) {
ast_log(LOG_ERROR, "Failed to async goto '%s' into fax extension in '%s'\n",
ast_channel_name(session->channel), target_context);
ast_channel_name(ast), target_context);
}
} else {
ast_log(LOG_NOTICE, "FAX CNG detected on '%s' but no fax extension in '%s'\n",
ast_channel_name(session->channel), target_context);
ast_channel_name(ast), target_context);
}
ast_channel_lock(session->channel);
/* It's possible for a masquerade to have occurred when doing the ast_async_goto resulting in
* the channel on the session having changed. Since we need to return with the original channel
* locked we lock the channel that was passed in and not session->channel.
*/
ast_channel_lock(ast);
return f;
}
@ -895,7 +901,11 @@ static struct ast_frame *chan_pjsip_read_stream(struct ast_channel *ast)
if (f->subclass.integer == 'f') {
ast_debug(3, "Channel driver fax CNG detected on %s\n",
ast_channel_name(ast));
f = chan_pjsip_cng_tone_detected(session, f);
f = chan_pjsip_cng_tone_detected(ast, session, f);
/* When chan_pjsip_cng_tone_detected returns it is possible for the
* channel pointed to by ast and by session->channel to differ due to a
* masquerade. It's best not to touch things after this.
*/
} else {
ast_debug(3, "* Detected inband DTMF '%c' on '%s'\n", f->subclass.integer,
ast_channel_name(ast));

View File

@ -19245,18 +19245,6 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
bogus_peer = NULL;
}
/* build_peer, called through sip_find_peer, is not able to check the
* sip_pvt->natdetected flag in order to determine if the peer is behind
* NAT or not when SIP_PAGE3_NAT_AUTO_RPORT or SIP_PAGE3_NAT_AUTO_COMEDIA
* are set on the peer. So we check for that here and set the peer's
* address accordingly.
*/
set_peer_nat(p, peer);
if (p->natdetected && ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
ast_sockaddr_copy(&peer->addr, &p->recv);
}
if (!ast_apply_acl(peer->acl, addr, "SIP Peer ACL: ")) {
ast_debug(2, "Found peer '%s' for '%s', but fails host access\n", peer->name, of);
sip_unref_peer(peer, "sip_unref_peer: check_peer_ok: from sip_find_peer call, early return of AUTH_ACL_FAILED");
@ -19325,6 +19313,21 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
ast_string_field_set(p, peermd5secret, NULL);
}
if (!(res = check_auth(p, req, peer->name, p->peersecret, p->peermd5secret, sipmethod, uri2, reliable))) {
/* build_peer, called through sip_find_peer, is not able to check the
* sip_pvt->natdetected flag in order to determine if the peer is behind
* NAT or not when SIP_PAGE3_NAT_AUTO_RPORT or SIP_PAGE3_NAT_AUTO_COMEDIA
* are set on the peer. So we check for that here and set the peer's
* address accordingly. The address should ONLY be set once we are sure
* authentication was a success. If, for example, an INVITE was sent that
* matched the peer name but failed the authentication check, the address
* would be updated, which is bad.
*/
set_peer_nat(p, peer);
if (p->natdetected && ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
ast_sockaddr_copy(&peer->addr, &p->recv);
}
/* If we have a call limit, set flag */
if (peer->call_limit)
ast_set_flag(&p->flags[0], SIP_CALL_LIMIT);
@ -19424,6 +19427,7 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
}
}
sip_unref_peer(peer, "check_peer_ok: sip_unref_peer: tossing temp ptr to peer from sip_find_peer");
return res;
}
@ -35349,8 +35353,8 @@ static void deprecation_notice(void)
{
ast_log(LOG_WARNING, "chan_sip has no official maintainer and is deprecated. Migration to\n");
ast_log(LOG_WARNING, "chan_pjsip is recommended. See guides at the Asterisk Wiki:\n");
ast_log(LOG_WARNING, "https://wiki.asterisk.org/wiki/x/tAHOAQ\n");
ast_log(LOG_WARNING, "https://wiki.asterisk.org/wiki/x/hYCLAQ\n");
ast_log(LOG_WARNING, "https://wiki.asterisk.org/wiki/display/AST/Migrating+from+chan_sip+to+res_pjsip\n");
ast_log(LOG_WARNING, "https://wiki.asterisk.org/wiki/display/AST/Configuring+res_pjsip\n");
}
/*! \brief Event callback which indicates we're fully booted */

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

@ -1,3 +0,0 @@
Subject: AttendedTransfer
A new application, this will queue up attended transfer to the given extension.

View File

@ -1,4 +0,0 @@
Subject: BlindTransfer
A new application, this will redirect all channels currently
bridged to the caller channel to the specified destination.

View File

@ -1,7 +0,0 @@
Subject: ConfBridge
Add "average_all", "highest_all", and "lowest_all" values for
the remb_behavior option. These values operate on a bridge
level instead of a per-source level. This means that a single
REMB value is calculated and sent to every sender, instead of
a REMB value that is unique for the specific sender..

View File

@ -1,12 +0,0 @@
Subject: Dial
Add RINGTIME and RINGTIME_MS variables containing respectively seconds and
milliseconds between creation of the dialing channel and receiving the first
RINGING signal
Add PROGRESSTIME and PROGRESSTIME_MS variables analogous to the above with respect to
the PROGRESS signal. Shorter of these two times should be equivalent to
the PDD (Post Dial Delay) value
Add DIALEDTIME_MS and ANSWEREDTIME_MS variables to get millisecond resolution
versions of DIALEDTIME and ANSWEREDTIME

View File

@ -1,3 +0,0 @@
Subject: ReadExten
Add 'p' option to stop reading extension if user presses '#' key.

View File

@ -1,36 +0,0 @@
Subject: Bridging
Master-Only: true
The bridging core no longer uses the stasis cache for bridge
snapshots. The latest bridge snapshot is now stored on the
ast_bridge structure itself.
The following APIs are no longer available since the stasis cache
is no longer used:
ast_bridge_topic_cached()
ast_bridge_topic_all_cached()
A topic pool is now used for individual bridge topics.
The ast_bridge_cache() function was removed since there's no
longer a separate container of snapshots.
A new function "ast_bridges()" was created to retrieve the
container of all bridges. Users formerly calling
ast_bridge_cache() can use the new function to iterate over
bridges and retrieve the latest snapshot directly from the
bridge.
The ast_bridge_snapshot_get_latest() function was renamed to
ast_bridge_get_snapshot_by_uniqueid().
A new function "ast_bridge_get_snapshot()" was created to retrieve
the bridge snapshot directly from the bridge structure.
The ast_bridge_topic_all() function now returns a normal topic
not a cached one so you can't use stasis cache functions on it
either.
The ast_bridge_snapshot_type() stasis message now has the
ast_bridge_snapshot_update structure as it's data. It contains
the last snapshot and the new one.

View File

@ -1,7 +0,0 @@
Subject: chan_sip
Master-Only: true
The chan_sip module is now deprecated, users should migrate to the
replacement module chan_pjsip. See guides at the Asterisk Wiki:
https://wiki.asterisk.org/wiki/x/tAHOAQ
https://wiki.asterisk.org/wiki/x/hYCLAQ

View File

@ -1,16 +0,0 @@
Subject: Channels
Master-Only: true
The core no longer uses the stasis cache for channels snapshots.
The following APIs are no longer available:
ast_channel_topic_cached()
ast_channel_topic_all_cached()
The ast_channel_cache_all() and ast_channel_cache_by_name() functions
now returns an ao2_container of ast_channel_snapshots rather than a
container of stasis_messages therefore you can't call stasis_cache
functions on it.
The ast_channel_topic_all() function now returns a normal topic,
not a cached one so you can't use stasis cache functions on it either.
The ast_channel_snapshot_type() stasis message now has the
ast_channel_snapshot_update structure as it's data.
ast_channel_snapshot_get_latest() still returns the latest snapshot.

View File

@ -1,3 +0,0 @@
Subject: pbx_dundi
The DUNDi PBX module now supports IPv4/IPv6 dual binding.

View File

@ -1,13 +0,0 @@
Subject: res_pjsip
Added a new PJSIP global setting called norefersub.
Default is true to keep support working as before.
res_pjsip_refer configures PJSIP norefersub capability accordingly.
Checks the PJSIP global setting value.
If it is true (default) it adds the norefersub capability to PJSIP.
If it is false (disabled) it does not add the norefersub capability
to PJSIP.
This is useful for Cisco switches that do not follow RFC4488.

View File

@ -1,5 +0,0 @@
Subject: res_rtp_asterisk
DTLS packets will now be fragmented according to the MTU as set in rtp.conf. This
allows larger certificates to be used for the DTLS negotiation. By default this value
is 1200.

View File

@ -1,5 +0,0 @@
Subject: RTP/ICE
You can now indicate that you'd like an ice_host_candidate's local address
to be published as well as the mapped address. See the sample rtp.conf
for more information.

View File

@ -1,9 +0,0 @@
Subject: app_voicemail.c
The "Voicemail Build Options" section of menuselect has been removed along with
the FILE_STORAGE, ODBC_STORAGE and IMAP_STORAGE menuselect options. All 3 variants
of the voicemail app can now be built at the same by enabling app_voicemail,
app_voicemail_imap, and app_voicemail_odbc under the "Applications" section.
By default, only app_voicemail is enabled. Also, the modules.conf sample has
been updated to "noload" app_voicemail_imap and app_voicemail_odbc should they
all be built. Packagers must update their build scripts appropriately.

View File

@ -1,4 +0,0 @@
Subject: Applications
Master-Only: true
The JabberStatus application, deprecated in Asterisk 12, has been removed.

View File

@ -1,36 +0,0 @@
Subject: Bridging
Master-Only: true
The bridging core no longer uses the stasis cache for bridge
snapshots. The latest bridge snapshot is now stored on the
ast_bridge structure itself.
The following APIs are no longer available since the stasis cache
is no longer used:
ast_bridge_topic_cached()
ast_bridge_topic_all_cached()
A topic pool is now used for individual bridge topics.
The ast_bridge_cache() function was removed since there's no
longer a separate container of snapshots.
A new function "ast_bridges()" was created to retrieve the
container of all bridges. Users formerly calling
ast_bridge_cache() can use the new function to iterate over
bridges and retrieve the latest snapshot directly from the
bridge.
The ast_bridge_snapshot_get_latest() function was renamed to
ast_bridge_get_snapshot_by_uniqueid().
A new function "ast_bridge_get_snapshot()" was created to retrieve
the bridge snapshot directly from the bridge structure.
The ast_bridge_topic_all() function now returns a normal topic
not a cached one so you can't use stasis cache functions on it
either.
The ast_bridge_snapshot_type() stasis message now has the
ast_bridge_snapshot_update structure as it's data. It contains
the last snapshot and the new one.

View File

@ -1,5 +0,0 @@
Subject: chan_pjsip
Subject: Core
res_pjsip_pubsub is now required so call transfer progress can be monitored
and reported in the channel variable TRANSFERSTATUS.

View File

@ -1,7 +0,0 @@
Subject: chan_sip
Master-Only: true
The chan_sip module is now deprecated, users should migrate to the
replacement module chan_pjsip. See guides at the Asterisk Wiki:
https://wiki.asterisk.org/wiki/x/tAHOAQ
https://wiki.asterisk.org/wiki/x/hYCLAQ

View File

@ -1,16 +0,0 @@
Subject: Channels
Master-Only: true
The core no longer uses the stasis cache for channels snapshots.
The following APIs are no longer available:
ast_channel_topic_cached()
ast_channel_topic_all_cached()
The ast_channel_cache_all() and ast_channel_cache_by_name() functions
now returns an ao2_container of ast_channel_snapshots rather than a
container of stasis_messages therefore you can't call stasis_cache
functions on it.
The ast_channel_topic_all() function now returns a normal topic,
not a cached one so you can't use stasis cache functions on it either.
The ast_channel_snapshot_type() stasis message now has the
ast_channel_snapshot_update structure as it's data.
ast_channel_snapshot_get_latest() still returns the latest snapshot.

View File

@ -1,5 +0,0 @@
Subject: func_callerid
Master-Only: true
The CALLERPRES() dialplan function, deprecated in Asterisk 1.8, has been
removed.

View File

@ -1,7 +0,0 @@
Subject: Build
Master-Only: true
Asterisk headers are no longer installed and uninstalled automatically when
performing a "make install" or a "make uninstall". To install/uninstall the
headers, use "make install-headers" and "make uninstall-headers". The headers
also continue to be uninstalled when performing a "make uninstall-all".

View File

@ -1,5 +0,0 @@
Subject: res_parking
Master-Only: true
The PARKINGSLOT channel variable, deprecated in Asterisk 12 in favor of the
PARKING_SPACE channel variable, will no longer be set.

View File

@ -1,4 +0,0 @@
Subject: res_xmpp
Master-Only: true
The JabberStatus application, deprecated in Asterisk 12, has been removed.

View File

@ -203,7 +203,7 @@ static int talk_detect_audiohook_cb(struct ast_audiohook *audiohook, struct ast_
int64_t diff_ms = ast_tvdiff_ms(ast_tvnow(), td_params->talking_start);
diff_ms -= td_params->dsp_silence_threshold;
blob = ast_json_pack("{s: i}", "duration", diff_ms);
blob = ast_json_pack("{s: I}", "duration", (ast_json_int_t)diff_ms);
if (!blob) {
return 1;
}

View File

@ -263,6 +263,28 @@ struct ast_event *ast_cel_create_event(struct ast_channel_snapshot *snapshot,
enum ast_cel_event_type event_type, const char *userdefevname,
struct ast_json *extra, const char *peer_str);
/*!
* \brief Allocate and populate a CEL event structure
*
* \param snapshot An ast_channel_snapshot of the primary channel associated
* with this channel event.
* \param event_type The type of call event being reported.
* \param event_time The time at which the event occurred.
* \param userdefevname Custom name for the call event. (optional)
* \param extra An event-specific opaque JSON blob to be rendered and placed
* in the "CEL_EXTRA" information element of the call event. (optional)
* \param peer_str A list of comma-separated peer channel names. (optional)
*
* \since 13.29.0
* \since 16.6.0
*
* \retval The created ast_event structure
* \retval NULL on failure
*/
struct ast_event *ast_cel_create_event_with_time(struct ast_channel_snapshot *snapshot,
enum ast_cel_event_type event_type, const struct timeval *event_time,
const char *userdefevname, struct ast_json *extra, const char *peer_str);
/*!
* \brief CEL backend callback
*/

View File

@ -54,7 +54,7 @@
- \ref manager.c Main manager code file
*/
#define AMI_VERSION "5.0.0"
#define AMI_VERSION "6.0.0"
#define DEFAULT_MANAGER_PORT 5038 /* Default port for Asterisk management via TCP */
#define DEFAULT_MANAGER_TLS_PORT 5039 /* Default port for Asterisk management via TCP */

View File

@ -1738,13 +1738,13 @@ static struct ast_json *s_to_json(const struct ast_aoc_decoded *decoded)
decoded->aoc_s_entries[i].rate.duration.amount,
decoded->aoc_s_entries[i].rate.duration.multiplier);
time = ast_json_pack("{s:i, s:i}",
"Length", decoded->aoc_s_entries[i].rate.duration.time,
time = ast_json_pack("{s:I, s:i}",
"Length", (ast_json_int_t)decoded->aoc_s_entries[i].rate.duration.time,
"Scale", decoded->aoc_s_entries[i].rate.duration.time_scale);
if (decoded->aoc_s_entries[i].rate.duration.granularity_time) {
granularity = ast_json_pack("{s:i, s:i}",
"Length", decoded->aoc_s_entries[i].rate.duration.granularity_time,
granularity = ast_json_pack("{s:I, s:i}",
"Length", (ast_json_int_t)decoded->aoc_s_entries[i].rate.duration.granularity_time,
"Scale", decoded->aoc_s_entries[i].rate.duration.granularity_time_scale);
}

View File

@ -1076,9 +1076,9 @@ static void cc_publish_offertimerstart(int core_id, const char *caller, unsigned
{
struct ast_json *extras;
extras = ast_json_pack("{s: s, s: i}",
extras = ast_json_pack("{s: s, s: I}",
"caller", caller,
"expires", expires);
"expires", (ast_json_int_t)expires);
cc_publish(ast_cc_offertimerstart_type(), core_id, extras);
ast_json_unref(extras);

View File

@ -718,6 +718,7 @@ struct cdr_object {
struct timeval start; /*!< When this CDR was created */
struct timeval answer; /*!< Either when the channel was answered, or when the path between channels was established */
struct timeval end; /*!< When this CDR was finalized */
struct timeval lastevent; /*!< The time at which the last event was created regarding this CDR */
unsigned int sequence; /*!< A monotonically increasing number for each CDR */
struct ast_flags flags; /*!< Flags on the CDR */
AST_DECLARE_STRING_FIELDS(
@ -1035,7 +1036,7 @@ static void cdr_object_dtor(void *obj)
* This implicitly sets the state of the newly created CDR to the Single state
* (\ref single_state_fn_table)
*/
static struct cdr_object *cdr_object_alloc(struct ast_channel_snapshot *chan)
static struct cdr_object *cdr_object_alloc(struct ast_channel_snapshot *chan, const struct timeval *event_time)
{
struct cdr_object *cdr;
@ -1055,6 +1056,7 @@ static struct cdr_object *cdr_object_alloc(struct ast_channel_snapshot *chan)
ast_string_field_set(cdr, linkedid, chan->peer->linkedid);
cdr->disposition = AST_CDR_NULL;
cdr->sequence = ast_atomic_fetchadd_int(&global_cdr_sequence, +1);
cdr->lastevent = *event_time;
cdr->party_a.snapshot = chan;
ao2_t_ref(cdr->party_a.snapshot, +1, "bump snapshot during CDR creation");
@ -1070,14 +1072,14 @@ static struct cdr_object *cdr_object_alloc(struct ast_channel_snapshot *chan)
* \brief Create a new \ref cdr_object and append it to an existing chain
* \param cdr The \ref cdr_object to append to
*/
static struct cdr_object *cdr_object_create_and_append(struct cdr_object *cdr)
static struct cdr_object *cdr_object_create_and_append(struct cdr_object *cdr, const struct timeval *event_time)
{
struct cdr_object *new_cdr;
struct cdr_object *it_cdr;
struct cdr_object *cdr_last;
cdr_last = cdr->last;
new_cdr = cdr_object_alloc(cdr_last->party_a.snapshot);
new_cdr = cdr_object_alloc(cdr_last->party_a.snapshot, event_time);
if (!new_cdr) {
return NULL;
}
@ -1440,7 +1442,7 @@ static void cdr_object_finalize(struct cdr_object *cdr)
if (!ast_tvzero(cdr->end)) {
return;
}
cdr->end = ast_tvnow();
cdr->end = cdr->lastevent;
if (cdr->disposition == AST_CDR_NULL) {
if (!ast_tvzero(cdr->answer)) {
@ -1490,7 +1492,7 @@ static void cdr_object_check_party_a_hangup(struct cdr_object *cdr)
static void cdr_object_check_party_a_answer(struct cdr_object *cdr)
{
if (cdr->party_a.snapshot->state == AST_STATE_UP && ast_tvzero(cdr->answer)) {
cdr->answer = ast_tvnow();
cdr->answer = cdr->lastevent;
/* tv_usec is suseconds_t, which could be int or long */
CDR_DEBUG("%p - Set answered time to %ld.%06ld\n", cdr,
(long)cdr->answer.tv_sec,
@ -1634,7 +1636,7 @@ static int base_process_parked_channel(struct cdr_object *cdr, struct ast_parked
static void single_state_init_function(struct cdr_object *cdr)
{
cdr->start = ast_tvnow();
cdr->start = cdr->lastevent;
cdr_object_check_party_a_answer(cdr);
}
@ -2149,6 +2151,7 @@ static void handle_dial_message(void *data, struct stasis_subscription *sub, str
ao2_lock(cdr);
for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
it_cdr->lastevent = *stasis_message_timestamp(message);
if (ast_strlen_zero(dial_status)) {
if (!it_cdr->fn_table->process_dial_begin) {
continue;
@ -2179,7 +2182,7 @@ static void handle_dial_message(void *data, struct stasis_subscription *sub, str
if (res && ast_strlen_zero(dial_status)) {
struct cdr_object *new_cdr;
new_cdr = cdr_object_create_and_append(cdr);
new_cdr = cdr_object_create_and_append(cdr, stasis_message_timestamp(message));
if (new_cdr) {
new_cdr->fn_table->process_dial_begin(new_cdr, caller, peer);
}
@ -2281,7 +2284,7 @@ static void handle_channel_snapshot_update_message(void *data, struct stasis_sub
}
if (update->new_snapshot && !update->old_snapshot) {
cdr = cdr_object_alloc(update->new_snapshot);
cdr = cdr_object_alloc(update->new_snapshot, stasis_message_timestamp(message));
if (!cdr) {
return;
}
@ -2300,6 +2303,7 @@ static void handle_channel_snapshot_update_message(void *data, struct stasis_sub
ao2_lock(cdr);
for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
it_cdr->lastevent = *stasis_message_timestamp(message);
if (!it_cdr->fn_table->process_party_a) {
continue;
}
@ -2309,7 +2313,7 @@ static void handle_channel_snapshot_update_message(void *data, struct stasis_sub
/* We're not hung up and we have a new snapshot - we need a new CDR */
struct cdr_object *new_cdr;
new_cdr = cdr_object_create_and_append(cdr);
new_cdr = cdr_object_create_and_append(cdr, stasis_message_timestamp(message));
if (new_cdr) {
new_cdr->fn_table->process_party_a(new_cdr, update->new_snapshot);
}
@ -2321,6 +2325,7 @@ static void handle_channel_snapshot_update_message(void *data, struct stasis_sub
ao2_lock(cdr);
CDR_DEBUG("%p - Beginning finalize/dispatch for %s\n", cdr, update->old_snapshot->base->name);
for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
it_cdr->lastevent = *stasis_message_timestamp(message);
cdr_object_finalize(it_cdr);
}
cdr_object_dispatch(cdr);
@ -2429,6 +2434,7 @@ static void handle_bridge_leave_message(void *data, struct stasis_subscription *
/* Party A */
ao2_lock(cdr);
for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
it_cdr->lastevent = *stasis_message_timestamp(message);
if (!it_cdr->fn_table->process_bridge_leave) {
continue;
}
@ -2463,7 +2469,7 @@ static void bridge_candidate_add_to_cdr(struct cdr_object *cdr,
{
struct cdr_object *new_cdr;
new_cdr = cdr_object_create_and_append(cdr);
new_cdr = cdr_object_create_and_append(cdr, &cdr->lastevent);
if (!new_cdr) {
return;
}
@ -2574,7 +2580,8 @@ static void handle_bridge_pairings(struct cdr_object *cdr, struct ast_bridge_sna
*/
static void handle_parking_bridge_enter_message(struct cdr_object *cdr,
struct ast_bridge_snapshot *bridge,
struct ast_channel_snapshot *channel)
struct ast_channel_snapshot *channel,
const struct timeval *event_time)
{
int res = 1;
struct cdr_object *it_cdr;
@ -2583,6 +2590,8 @@ static void handle_parking_bridge_enter_message(struct cdr_object *cdr,
ao2_lock(cdr);
for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
it_cdr->lastevent = *event_time;
if (it_cdr->fn_table->process_parking_bridge_enter) {
res &= it_cdr->fn_table->process_parking_bridge_enter(it_cdr, bridge, channel);
}
@ -2595,7 +2604,7 @@ static void handle_parking_bridge_enter_message(struct cdr_object *cdr,
if (res) {
/* No one handled it - we need a new one! */
new_cdr = cdr_object_create_and_append(cdr);
new_cdr = cdr_object_create_and_append(cdr, event_time);
if (new_cdr) {
/* Let the single state transition us to Parked */
cdr_object_transition_state(new_cdr, &single_state_fn_table);
@ -2612,7 +2621,8 @@ static void handle_parking_bridge_enter_message(struct cdr_object *cdr,
*/
static void handle_standard_bridge_enter_message(struct cdr_object *cdr,
struct ast_bridge_snapshot *bridge,
struct ast_channel_snapshot *channel)
struct ast_channel_snapshot *channel,
const struct timeval *event_time)
{
enum process_bridge_enter_results result;
struct cdr_object *it_cdr;
@ -2623,6 +2633,8 @@ static void handle_standard_bridge_enter_message(struct cdr_object *cdr,
try_again:
for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
it_cdr->lastevent = *event_time;
if (it_cdr->fn_table->process_party_a) {
CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,
channel->base->name);
@ -2669,7 +2681,7 @@ try_again:
handle_bridge_pairings(handled_cdr, bridge);
} else {
/* Nothing handled it - we need a new one! */
new_cdr = cdr_object_create_and_append(cdr);
new_cdr = cdr_object_create_and_append(cdr, event_time);
if (new_cdr) {
/* This is guaranteed to succeed: the new CDR is created in the single state
* and will be able to handle the bridge enter message
@ -2717,9 +2729,9 @@ static void handle_bridge_enter_message(void *data, struct stasis_subscription *
}
if (!strcmp(bridge->subclass, "parking")) {
handle_parking_bridge_enter_message(cdr, bridge, channel);
handle_parking_bridge_enter_message(cdr, bridge, channel, stasis_message_timestamp(message));
} else {
handle_standard_bridge_enter_message(cdr, bridge, channel);
handle_standard_bridge_enter_message(cdr, bridge, channel, stasis_message_timestamp(message));
}
ao2_cleanup(cdr);
}
@ -2769,6 +2781,7 @@ static void handle_parked_call_message(void *data, struct stasis_subscription *s
ao2_lock(cdr);
for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
it_cdr->lastevent = *stasis_message_timestamp(message);
if (it_cdr->fn_table->process_parked_channel) {
unhandled &= it_cdr->fn_table->process_parked_channel(it_cdr, payload);
}
@ -2778,7 +2791,7 @@ static void handle_parked_call_message(void *data, struct stasis_subscription *s
/* Nothing handled the messgae - we need a new one! */
struct cdr_object *new_cdr;
new_cdr = cdr_object_create_and_append(cdr);
new_cdr = cdr_object_create_and_append(cdr, stasis_message_timestamp(message));
if (new_cdr) {
/* As the new CDR is created in the single state, it is guaranteed
* to have a function for the parked call message and will handle
@ -3607,6 +3620,7 @@ int ast_cdr_reset(const char *channel_name, int keep_variables)
memset(&it_cdr->end, 0, sizeof(it_cdr->end));
memset(&it_cdr->answer, 0, sizeof(it_cdr->answer));
it_cdr->start = ast_tvnow();
it_cdr->lastevent = it_cdr->start;
cdr_object_check_party_a_answer(it_cdr);
}
ao2_unlock(cdr);
@ -3628,6 +3642,7 @@ int ast_cdr_fork(const char *channel_name, struct ast_flags *options)
{
SCOPED_AO2LOCK(lock, cdr);
struct timeval now = ast_tvnow();
cdr_obj = cdr->last;
if (cdr_obj->fn_table == &finalized_state_fn_table) {
@ -3641,7 +3656,7 @@ int ast_cdr_fork(const char *channel_name, struct ast_flags *options)
* copied over automatically as part of the append
*/
ast_debug(1, "Forking CDR for channel %s\n", cdr->party_a.snapshot->base->name);
new_cdr = cdr_object_create_and_append(cdr);
new_cdr = cdr_object_create_and_append(cdr, &now);
if (!new_cdr) {
return -1;
}
@ -3671,6 +3686,7 @@ int ast_cdr_fork(const char *channel_name, struct ast_flags *options)
}
new_cdr->start = cdr_obj->start;
new_cdr->answer = cdr_obj->answer;
new_cdr->lastevent = ast_tvnow();
/* Modify the times based on the flags passed in */
if (ast_test_flag(options, AST_CDR_FLAG_SET_ANSWER)

View File

@ -519,14 +519,23 @@ struct ast_event *ast_cel_create_event(struct ast_channel_snapshot *snapshot,
struct ast_json *extra, const char *peer)
{
struct timeval eventtime = ast_tvnow();
return ast_cel_create_event_with_time(snapshot, event_type, &eventtime,
userdefevname, extra, peer);
}
struct ast_event *ast_cel_create_event_with_time(struct ast_channel_snapshot *snapshot,
enum ast_cel_event_type event_type, const struct timeval *event_time,
const char *userdefevname, struct ast_json *extra, const char *peer)
{
RAII_VAR(char *, extra_txt, NULL, ast_json_free);
if (extra) {
extra_txt = ast_json_dump_string(extra);
}
return ast_event_new(AST_EVENT_CEL,
AST_EVENT_IE_CEL_EVENT_TYPE, AST_EVENT_IE_PLTYPE_UINT, event_type,
AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_sec,
AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_usec,
AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_PLTYPE_UINT, event_time->tv_sec,
AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_PLTYPE_UINT, event_time->tv_usec,
AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_STR, S_OR(userdefevname, ""),
AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->caller->name,
AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_PLTYPE_STR, snapshot->caller->number,
@ -558,8 +567,9 @@ static int cel_backend_send_cb(void *obj, void *arg, int flags)
}
static int cel_report_event(struct ast_channel_snapshot *snapshot,
enum ast_cel_event_type event_type, const char *userdefevname,
struct ast_json *extra, const char *peer_str)
enum ast_cel_event_type event_type, const struct timeval *event_time,
const char *userdefevname, struct ast_json *extra,
const char *peer_str)
{
struct ast_event *ev;
RAII_VAR(struct cel_config *, cfg, ao2_global_obj_ref(cel_configs), ao2_cleanup);
@ -587,7 +597,7 @@ static int cel_report_event(struct ast_channel_snapshot *snapshot,
return 0;
}
ev = ast_cel_create_event(snapshot, event_type, userdefevname, extra, peer_str);
ev = ast_cel_create_event_with_time(snapshot, event_type, event_time, userdefevname, extra, peer_str);
if (!ev) {
return -1;
}
@ -601,7 +611,7 @@ static int cel_report_event(struct ast_channel_snapshot *snapshot,
/* called whenever a channel is destroyed or a linkedid is changed to
* potentially emit a CEL_LINKEDID_END event */
static void check_retire_linkedid(struct ast_channel_snapshot *snapshot)
static void check_retire_linkedid(struct ast_channel_snapshot *snapshot, const struct timeval *event_time)
{
RAII_VAR(struct ao2_container *, linkedids, ao2_global_obj_ref(cel_linkedids), ao2_cleanup);
struct cel_linkedid *lid;
@ -632,7 +642,7 @@ static void check_retire_linkedid(struct ast_channel_snapshot *snapshot)
ao2_unlink(linkedids, lid);
ao2_unlock(linkedids);
cel_report_event(snapshot, AST_CEL_LINKEDID_END, NULL, NULL, NULL);
cel_report_event(snapshot, AST_CEL_LINKEDID_END, event_time, NULL, NULL, NULL);
} else {
ao2_unlock(linkedids);
}
@ -852,7 +862,8 @@ int ast_cel_fill_record(const struct ast_event *e, struct ast_cel_event_record *
/*! \brief Typedef for callbacks that get called on channel snapshot updates */
typedef void (*cel_channel_snapshot_monitor)(
struct ast_channel_snapshot *old_snapshot,
struct ast_channel_snapshot *new_snapshot);
struct ast_channel_snapshot *new_snapshot,
const struct timeval *event_time);
static struct cel_dialstatus *get_dialstatus(const char *uniqueid)
{
@ -884,12 +895,13 @@ static const char *get_blob_variable(struct ast_multi_channel_blob *blob, const
/*! \brief Handle channel state changes */
static void cel_channel_state_change(
struct ast_channel_snapshot *old_snapshot,
struct ast_channel_snapshot *new_snapshot)
struct ast_channel_snapshot *new_snapshot,
const struct timeval *event_time)
{
int is_hungup, was_hungup;
if (!old_snapshot) {
cel_report_event(new_snapshot, AST_CEL_CHANNEL_START, NULL, NULL, NULL);
cel_report_event(new_snapshot, AST_CEL_CHANNEL_START, event_time, NULL, NULL, NULL);
return;
}
@ -904,26 +916,27 @@ static void cel_channel_state_change(
"hangupcause", new_snapshot->hangup->cause,
"hangupsource", new_snapshot->hangup->source,
"dialstatus", dialstatus ? dialstatus->dialstatus : "");
cel_report_event(new_snapshot, AST_CEL_HANGUP, NULL, extra, NULL);
cel_report_event(new_snapshot, AST_CEL_HANGUP, event_time, NULL, extra, NULL);
ast_json_unref(extra);
ao2_cleanup(dialstatus);
cel_report_event(new_snapshot, AST_CEL_CHANNEL_END, NULL, NULL, NULL);
cel_report_event(new_snapshot, AST_CEL_CHANNEL_END, event_time, NULL, NULL, NULL);
if (ast_cel_track_event(AST_CEL_LINKEDID_END)) {
check_retire_linkedid(new_snapshot);
check_retire_linkedid(new_snapshot, event_time);
}
return;
}
if (old_snapshot->state != new_snapshot->state && new_snapshot->state == AST_STATE_UP) {
cel_report_event(new_snapshot, AST_CEL_ANSWER, NULL, NULL, NULL);
cel_report_event(new_snapshot, AST_CEL_ANSWER, event_time, NULL, NULL, NULL);
return;
}
}
static void cel_channel_linkedid_change(
struct ast_channel_snapshot *old_snapshot,
struct ast_channel_snapshot *new_snapshot)
struct ast_channel_snapshot *new_snapshot,
const struct timeval *event_time)
{
if (!old_snapshot) {
return;
@ -935,13 +948,14 @@ static void cel_channel_linkedid_change(
if (ast_cel_track_event(AST_CEL_LINKEDID_END)
&& strcmp(old_snapshot->peer->linkedid, new_snapshot->peer->linkedid)) {
cel_linkedid_ref(new_snapshot->peer->linkedid);
check_retire_linkedid(old_snapshot);
check_retire_linkedid(old_snapshot, event_time);
}
}
static void cel_channel_app_change(
struct ast_channel_snapshot *old_snapshot,
struct ast_channel_snapshot *new_snapshot)
struct ast_channel_snapshot *new_snapshot,
const struct timeval *event_time)
{
if (old_snapshot && !strcmp(old_snapshot->dialplan->appl, new_snapshot->dialplan->appl)) {
return;
@ -949,12 +963,12 @@ static void cel_channel_app_change(
/* old snapshot has an application, end it */
if (old_snapshot && !ast_strlen_zero(old_snapshot->dialplan->appl)) {
cel_report_event(old_snapshot, AST_CEL_APP_END, NULL, NULL, NULL);
cel_report_event(old_snapshot, AST_CEL_APP_END, event_time, NULL, NULL, NULL);
}
/* new snapshot has an application, start it */
if (!ast_strlen_zero(new_snapshot->dialplan->appl)) {
cel_report_event(new_snapshot, AST_CEL_APP_START, NULL, NULL, NULL);
cel_report_event(new_snapshot, AST_CEL_APP_START, event_time, NULL, NULL, NULL);
}
}
@ -988,7 +1002,7 @@ static void cel_snapshot_update_cb(void *data, struct stasis_subscription *sub,
}
for (i = 0; i < ARRAY_LEN(cel_channel_monitors); ++i) {
cel_channel_monitors[i](update->old_snapshot, update->new_snapshot);
cel_channel_monitors[i](update->old_snapshot, update->new_snapshot, stasis_message_timestamp(message));
}
}
@ -1056,7 +1070,8 @@ static void cel_bridge_enter_cb(
return;
}
cel_report_event(chan_snapshot, AST_CEL_BRIDGE_ENTER, NULL, extra, ast_str_buffer(peer_str));
cel_report_event(chan_snapshot, AST_CEL_BRIDGE_ENTER, stasis_message_timestamp(message),
NULL, extra, ast_str_buffer(peer_str));
}
static void cel_bridge_leave_cb(
@ -1085,7 +1100,8 @@ static void cel_bridge_leave_cb(
return;
}
cel_report_event(chan_snapshot, AST_CEL_BRIDGE_EXIT, NULL, extra, ast_str_buffer(peer_str));
cel_report_event(chan_snapshot, AST_CEL_BRIDGE_EXIT, stasis_message_timestamp(message),
NULL, extra, ast_str_buffer(peer_str));
}
static void cel_parking_cb(
@ -1102,7 +1118,8 @@ static void cel_parking_cb(
"parker_dial_string", parked_payload->parker_dial_string,
"parking_lot", parked_payload->parkinglot);
if (extra) {
cel_report_event(parked_payload->parkee, AST_CEL_PARK_START, NULL, extra, NULL);
cel_report_event(parked_payload->parkee, AST_CEL_PARK_START, stasis_message_timestamp(message),
NULL, extra, NULL);
}
return;
case PARKED_CALL_TIMEOUT:
@ -1131,7 +1148,8 @@ static void cel_parking_cb(
}
if (extra) {
cel_report_event(parked_payload->parkee, AST_CEL_PARK_END, NULL, extra, NULL);
cel_report_event(parked_payload->parkee, AST_CEL_PARK_END, stasis_message_timestamp(message),
NULL, extra, NULL);
}
}
@ -1224,7 +1242,8 @@ static void cel_dial_cb(void *data, struct stasis_subscription *sub,
extra = ast_json_pack("{s: s}", "forward", get_blob_variable(blob, "forward"));
if (extra) {
cel_report_event(snapshot, AST_CEL_FORWARD, NULL, extra, NULL);
cel_report_event(snapshot, AST_CEL_FORWARD, stasis_message_timestamp(message),
NULL, extra, NULL);
ast_json_unref(extra);
}
}
@ -1247,7 +1266,8 @@ static void cel_generic_cb(
{
const char *event = ast_json_string_get(ast_json_object_get(event_details, "event"));
struct ast_json *extra = ast_json_object_get(event_details, "extra");
cel_report_event(obj->snapshot, event_type, event, extra, NULL);
cel_report_event(obj->snapshot, event_type, stasis_message_timestamp(message),
event, extra, NULL);
break;
}
default:
@ -1276,7 +1296,8 @@ static void cel_blind_transfer_cb(
"transferee_channel_name", transfer_msg->transferee ? transfer_msg->transferee->base->name : "N/A",
"transferee_channel_uniqueid", transfer_msg->transferee ? transfer_msg->transferee->base->uniqueid : "N/A");
if (extra) {
cel_report_event(chan_snapshot, AST_CEL_BLINDTRANSFER, NULL, extra, NULL);
cel_report_event(chan_snapshot, AST_CEL_BLINDTRANSFER, stasis_message_timestamp(message),
NULL, extra, NULL);
ast_json_unref(extra);
}
}
@ -1339,7 +1360,8 @@ static void cel_attended_transfer_cb(
}
break;
}
cel_report_event(channel1, AST_CEL_ATTENDEDTRANSFER, NULL, extra, NULL);
cel_report_event(channel1, AST_CEL_ATTENDEDTRANSFER, stasis_message_timestamp(message),
NULL, extra, NULL);
ast_json_unref(extra);
}
@ -1363,7 +1385,7 @@ static void cel_pickup_cb(
return;
}
cel_report_event(target, AST_CEL_PICKUP, NULL, extra, NULL);
cel_report_event(target, AST_CEL_PICKUP, stasis_message_timestamp(message), NULL, extra, NULL);
ast_json_unref(extra);
}
@ -1387,7 +1409,7 @@ static void cel_local_cb(
return;
}
cel_report_event(localone, AST_CEL_LOCAL_OPTIMIZE, NULL, extra, NULL);
cel_report_event(localone, AST_CEL_LOCAL_OPTIMIZE, stasis_message_timestamp(message), NULL, extra, NULL);
ast_json_unref(extra);
}

View File

@ -3328,10 +3328,10 @@ static void send_dtmf_end_event(struct ast_channel *chan,
RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
char digit_str[] = { digit, '\0' };
blob = ast_json_pack("{ s: s, s: s, s: i }",
blob = ast_json_pack("{ s: s, s: s, s: I }",
"digit", digit_str,
"direction", dtmf_direction_to_string(direction),
"duration_ms", duration_ms);
"duration_ms", (ast_json_int_t)duration_ms);
if (!blob) {
return;
}

View File

@ -394,8 +394,8 @@ static void local_optimization_started_cb(struct ast_unreal_pvt *base, struct as
return;
}
json_object = ast_json_pack("{s: i, s: i}",
"dest", dest, "id", id);
json_object = ast_json_pack("{s: i, s: I}",
"dest", dest, "id", (ast_json_int_t)id);
if (!json_object) {
return;
@ -436,7 +436,7 @@ static void local_optimization_finished_cb(struct ast_unreal_pvt *base, int succ
return;
}
json_object = ast_json_pack("{s: i, s: i}", "success", success, "id", id);
json_object = ast_json_pack("{s: i, s: I}", "success", success, "id", (ast_json_int_t)id);
if (!json_object) {
return;

View File

@ -1087,7 +1087,7 @@ static struct ast_module *load_dlopen(const char *resource_in, const char *so_ex
if (resource_being_loaded) {
struct ast_str *list;
int c = 0;
const char *dlerror_msg = ast_strdupa(dlerror());
const char *dlerror_msg = ast_strdupa(S_OR(dlerror(), ""));
resource_being_loaded = NULL;
if (mod->lib) {

View File

@ -5698,6 +5698,7 @@ static int action_originate(struct mansession *s, const struct message *m)
EAGI(/bin/rm,-rf /) */
strcasestr(app, "mixmonitor") || /* MixMonitor(blah,,rm -rf) */
strcasestr(app, "externalivr") || /* ExternalIVR(rm -rf) */
strcasestr(app, "originate") || /* Originate(Local/1234,app,System,rm -rf) */
(strstr(appdata, "SHELL") && (bad_appdata = 1)) || /* NoOp(${SHELL(rm -rf /)}) */
(strstr(appdata, "EVAL") && (bad_appdata = 1)) /* NoOp(${EVAL(${some_var_containing_SHELL})}) */
)) {

View File

@ -7599,6 +7599,7 @@ static void *pbx_outgoing_exec(void *data)
{
RAII_VAR(struct pbx_outgoing *, outgoing, data, ao2_cleanup);
enum ast_dial_result res;
struct ast_channel *chan;
res = ast_dial_run(outgoing->dial, NULL, 0);
@ -7619,36 +7620,37 @@ static void *pbx_outgoing_exec(void *data)
return NULL;
}
/* We steal the channel so we get ownership of when it is hung up */
chan = ast_dial_answered_steal(outgoing->dial);
if (!ast_strlen_zero(outgoing->app)) {
struct ast_app *app = pbx_findapp(outgoing->app);
if (app) {
ast_verb(4, "Launching %s(%s) on %s\n", outgoing->app, S_OR(outgoing->appdata, ""),
ast_channel_name(ast_dial_answered(outgoing->dial)));
pbx_exec(ast_dial_answered(outgoing->dial), app, outgoing->appdata);
ast_channel_name(chan));
pbx_exec(chan, app, outgoing->appdata);
} else {
ast_log(LOG_WARNING, "No such application '%s'\n", outgoing->app);
}
} else {
struct ast_channel *answered = ast_dial_answered(outgoing->dial);
ast_hangup(chan);
} else {
if (!ast_strlen_zero(outgoing->context)) {
ast_channel_context_set(answered, outgoing->context);
ast_channel_context_set(chan, outgoing->context);
}
if (!ast_strlen_zero(outgoing->exten)) {
ast_channel_exten_set(answered, outgoing->exten);
ast_channel_exten_set(chan, outgoing->exten);
}
if (outgoing->priority > 0) {
ast_channel_priority_set(answered, outgoing->priority);
ast_channel_priority_set(chan, outgoing->priority);
}
if (ast_pbx_run(answered)) {
ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(answered));
} else {
/* PBX will have taken care of hanging up, so we steal the answered channel so dial doesn't do it */
ast_dial_answered_steal(outgoing->dial);
if (ast_pbx_run(chan)) {
ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(chan));
ast_hangup(chan);
}
}

View File

@ -2742,6 +2742,7 @@ int ast_rtp_instance_add_srtp_policy(struct ast_rtp_instance *instance, struct a
return -1;
}
ao2_lock(instance);
srtp = rtcp ? &instance->rtcp_srtp : &instance->srtp;
@ -2754,6 +2755,8 @@ int ast_rtp_instance_add_srtp_policy(struct ast_rtp_instance *instance, struct a
res = res_srtp->add_stream(*srtp, local_policy);
}
ao2_unlock(instance);
return res;
}
@ -3394,14 +3397,14 @@ static struct ast_json *rtcp_report_to_json(struct stasis_message *msg,
char str_lsr[32];
snprintf(str_lsr, sizeof(str_lsr), "%u", payload->report->report_block[i]->lsr);
json_report_block = ast_json_pack("{s: I, s: i, s: i, s: i, s: i, s: s, s: i}",
json_report_block = ast_json_pack("{s: I, s: I, s: I, s: I, s: I, s: s, s: I}",
"source_ssrc", (ast_json_int_t)payload->report->report_block[i]->source_ssrc,
"fraction_lost", payload->report->report_block[i]->lost_count.fraction,
"packets_lost", payload->report->report_block[i]->lost_count.packets,
"highest_seq_no", payload->report->report_block[i]->highest_seq_no,
"ia_jitter", payload->report->report_block[i]->ia_jitter,
"fraction_lost", (ast_json_int_t)payload->report->report_block[i]->lost_count.fraction,
"packets_lost", (ast_json_int_t)payload->report->report_block[i]->lost_count.packets,
"highest_seq_no", (ast_json_int_t)payload->report->report_block[i]->highest_seq_no,
"ia_jitter", (ast_json_int_t)payload->report->report_block[i]->ia_jitter,
"lsr", str_lsr,
"dlsr", payload->report->report_block[i]->dlsr);
"dlsr", (ast_json_int_t)payload->report->report_block[i]->dlsr);
if (!json_report_block
|| ast_json_array_append(json_rtcp_report_blocks, json_report_block)) {
ast_json_unref(json_rtcp_report_blocks);
@ -3415,21 +3418,21 @@ static struct ast_json *rtcp_report_to_json(struct stasis_message *msg,
snprintf(sec, sizeof(sec), "%lu", (unsigned long)payload->report->sender_information.ntp_timestamp.tv_sec);
snprintf(usec, sizeof(usec), "%lu", (unsigned long)payload->report->sender_information.ntp_timestamp.tv_usec);
json_rtcp_sender_info = ast_json_pack("{s: s, s: s, s: i, s: i, s: i}",
json_rtcp_sender_info = ast_json_pack("{s: s, s: s, s: I, s: I, s: I}",
"ntp_timestamp_sec", sec,
"ntp_timestamp_usec", usec,
"rtp_timestamp", payload->report->sender_information.rtp_timestamp,
"packets", payload->report->sender_information.packet_count,
"octets", payload->report->sender_information.octet_count);
"rtp_timestamp", (ast_json_int_t)payload->report->sender_information.rtp_timestamp,
"packets", (ast_json_int_t)payload->report->sender_information.packet_count,
"octets", (ast_json_int_t)payload->report->sender_information.octet_count);
if (!json_rtcp_sender_info) {
ast_json_unref(json_rtcp_report_blocks);
return NULL;
}
}
json_rtcp_report = ast_json_pack("{s: I, s: i, s: i, s: o, s: o}",
json_rtcp_report = ast_json_pack("{s: I, s: I, s: i, s: o, s: o}",
"ssrc", (ast_json_int_t)payload->report->ssrc,
"type", payload->report->type,
"type", (ast_json_int_t)payload->report->type,
"report_count", payload->report->reception_report_count,
"sender_information", json_rtcp_sender_info ?: ast_json_null(),
"report_blocks", json_rtcp_report_blocks);

View File

@ -1408,11 +1408,11 @@ static struct ast_json *dtmf_end_to_json(
return NULL;
}
return ast_json_pack("{s: s, s: o, s: s, s: i, s: o}",
return ast_json_pack("{s: s, s: o, s: s, s: I, s: o}",
"type", "ChannelDtmfReceived",
"timestamp", ast_json_timeval(*tv, NULL),
"digit", digit,
"duration_ms", duration_ms,
"duration_ms", (ast_json_int_t)duration_ms,
"channel", json_channel);
}

View File

@ -403,7 +403,7 @@ static int framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
if (f->samples == 0) {
/* Do not log empty audio frame */
if (strcasecmp(f->src, "ast_prod")) {
if (!f->src || strcasecmp(f->src, "ast_prod")) {
ast_log(LOG_WARNING, "no samples for %s\n", pvt->t->name);
}
}

View File

@ -405,6 +405,24 @@ static int udptl_rx_packet(struct ast_udptl *s, uint8_t *buf, unsigned int len)
seq_no = (buf[0] << 8) | buf[1];
ptr += 2;
/* UDPTL sequence numbers are 16 bit so after 0xFFFF comes
0 which breaks all packet recovery logic. To fix this
if we see that next expected packet (rx_seq_no) is close
to or beyond the wrap around limit & the received packet
is still near zero, then we 'unwrap' the received seqno
so it has the value it would have had. After a 16
packet grace period (there shouldn't be more than
that many recovery packets) we wrap the expected
sequence number around and things can return back
to normal */
if (seq_no < 0x000F && s->rx_seq_no > 0xFFF0) {
/* received seq_no has wrapped adjust it */
seq_no += 0x10000;
} else {
/* otherwise make sure expected rx_seq_no is properly wrapped */
s->rx_seq_no &= 0xFFFF;
}
/* Break out the primary packet */
if ((stat1 = decode_open_type(buf, len, &ptr, &ifp, &ifp_len)) != 0)
return -1;

View File

@ -38,8 +38,8 @@ endif
ifdef NCURSES_LIB
C_OBJS += menuselect_curses.o
C_LIBS +=$(NCURSES_LIB)
C_INCLUDE += $(NCURSES_INCLUDE)
C_LIBS += $(NCURSES_LIB) $(TINFO_LIB)
C_INCLUDE += $(NCURSES_INCLUDE) $(TINFO_INCLUDE)
ALL_TGTS += cmenuselect
CFLAGS += -DHAVE_NCURSES
ifeq ($(HAVE_NCURSES_SUBDIR),yes)
@ -48,8 +48,8 @@ ifdef NCURSES_LIB
else
ifdef CURSES_LIB
C_OBJS += menuselect_curses.o
C_LIBS +=$(CURSES_LIB)
C_INCLUDE += $(CURSES_INCLUDE)
C_LIBS += $(CURSES_LIB) $(TINFO_LIB)
C_INCLUDE += $(CURSES_INCLUDE) $(TINFO_INCLUDE)
ALL_TGTS += cmenuselect
endif
endif

View File

@ -79,6 +79,9 @@
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the terminfo library. */
#undef HAVE_TINFO
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H

334
menuselect/configure vendored
View File

@ -635,6 +635,10 @@ PKG_CONFIG
CONFIG_LIBXML2
SED
HAVE_NCURSES_SUBDIR
PBX_TINFO
TINFO_DIR
TINFO_INCLUDE
TINFO_LIB
PBX_LIBXML2
LIBXML2_DIR
LIBXML2_INCLUDE
@ -720,6 +724,7 @@ with_newt
with_curses
with_ncurses
with_libxml2
with_libtinfo
'
ac_precious_vars='build_alias
host_alias
@ -1366,6 +1371,7 @@ Optional Packages:
--with-curses=PATH use curses files in PATH
--with-ncurses=PATH use ncurses files in PATH
--with-libxml2=PATH use LibXML2 files in PATH
--with-libtinfo=PATH use terminfo files in PATH
Some influential environment variables:
CC C compiler command
@ -3928,6 +3934,38 @@ fi
TINFO_DESCRIP="terminfo"
TINFO_OPTION="libtinfo"
PBX_TINFO=0
# Check whether --with-libtinfo was given.
if test "${with_libtinfo+set}" = set; then :
withval=$with_libtinfo;
case ${withval} in
n|no)
USE_TINFO=no
# -1 is a magic value used by menuselect to know that the package
# was disabled, other than 'not found'
PBX_TINFO=-1
;;
y|ye|yes)
ac_mandatory_list="${ac_mandatory_list} TINFO"
;;
*)
TINFO_DIR="${withval}"
ac_mandatory_list="${ac_mandatory_list} TINFO"
;;
esac
fi
if test "x${PBX_NEWT}" != "x1" -a "${USE_NEWT}" != "no"; then
pbxlibdir=""
@ -4320,6 +4358,302 @@ fi
fi
fi
if test "${PBX_NCURSES}" = 1; then
if test "${HAVE_NCURSES_SUBDIR}" = "yes"; then
if test "x${PBX_TINFO}" != "x1" -a "${USE_TINFO}" != "no"; then
pbxlibdir=""
# if --with-TINFO=DIR has been specified, use it.
if test "x${TINFO_DIR}" != "x"; then
if test -d ${TINFO_DIR}/lib; then
pbxlibdir="-L${TINFO_DIR}/lib"
else
pbxlibdir="-L${TINFO_DIR}"
fi
fi
ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
CFLAGS="${CFLAGS} "
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for keypad in -ltinfo" >&5
$as_echo_n "checking for keypad in -ltinfo... " >&6; }
if ${ac_cv_lib_tinfo_keypad+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ltinfo ${pbxlibdir} $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char keypad ();
int
main ()
{
return keypad ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_tinfo_keypad=yes
else
ac_cv_lib_tinfo_keypad=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tinfo_keypad" >&5
$as_echo "$ac_cv_lib_tinfo_keypad" >&6; }
if test "x$ac_cv_lib_tinfo_keypad" = xyes; then :
AST_TINFO_FOUND=yes
else
AST_TINFO_FOUND=no
fi
CFLAGS="${ast_ext_lib_check_save_CFLAGS}"
# now check for the header.
if test "${AST_TINFO_FOUND}" = "yes"; then
TINFO_LIB="${pbxlibdir} -ltinfo "
# if --with-TINFO=DIR has been specified, use it.
if test "x${TINFO_DIR}" != "x"; then
TINFO_INCLUDE="-I${TINFO_DIR}/include"
fi
TINFO_INCLUDE="${TINFO_INCLUDE} "
# check for the header
ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}"
CPPFLAGS="${CPPFLAGS} ${TINFO_INCLUDE}"
ac_fn_c_check_header_mongrel "$LINENO" "ncurses/ncurses.h" "ac_cv_header_ncurses_ncurses_h" "$ac_includes_default"
if test "x$ac_cv_header_ncurses_ncurses_h" = xyes; then :
TINFO_HEADER_FOUND=1
else
TINFO_HEADER_FOUND=0
fi
CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}"
if test "x${TINFO_HEADER_FOUND}" = "x0" ; then
TINFO_LIB=""
TINFO_INCLUDE=""
else
PBX_TINFO=1
cat >>confdefs.h <<_ACEOF
#define HAVE_TINFO 1
_ACEOF
fi
fi
fi
else
if test "x${PBX_TINFO}" != "x1" -a "${USE_TINFO}" != "no"; then
pbxlibdir=""
# if --with-TINFO=DIR has been specified, use it.
if test "x${TINFO_DIR}" != "x"; then
if test -d ${TINFO_DIR}/lib; then
pbxlibdir="-L${TINFO_DIR}/lib"
else
pbxlibdir="-L${TINFO_DIR}"
fi
fi
ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
CFLAGS="${CFLAGS} "
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for keypad in -ltinfo" >&5
$as_echo_n "checking for keypad in -ltinfo... " >&6; }
if ${ac_cv_lib_tinfo_keypad+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ltinfo ${pbxlibdir} $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char keypad ();
int
main ()
{
return keypad ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_tinfo_keypad=yes
else
ac_cv_lib_tinfo_keypad=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tinfo_keypad" >&5
$as_echo "$ac_cv_lib_tinfo_keypad" >&6; }
if test "x$ac_cv_lib_tinfo_keypad" = xyes; then :
AST_TINFO_FOUND=yes
else
AST_TINFO_FOUND=no
fi
CFLAGS="${ast_ext_lib_check_save_CFLAGS}"
# now check for the header.
if test "${AST_TINFO_FOUND}" = "yes"; then
TINFO_LIB="${pbxlibdir} -ltinfo "
# if --with-TINFO=DIR has been specified, use it.
if test "x${TINFO_DIR}" != "x"; then
TINFO_INCLUDE="-I${TINFO_DIR}/include"
fi
TINFO_INCLUDE="${TINFO_INCLUDE} "
# check for the header
ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}"
CPPFLAGS="${CPPFLAGS} ${TINFO_INCLUDE}"
ac_fn_c_check_header_mongrel "$LINENO" "ncurses.h" "ac_cv_header_ncurses_h" "$ac_includes_default"
if test "x$ac_cv_header_ncurses_h" = xyes; then :
TINFO_HEADER_FOUND=1
else
TINFO_HEADER_FOUND=0
fi
CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}"
if test "x${TINFO_HEADER_FOUND}" = "x0" ; then
TINFO_LIB=""
TINFO_INCLUDE=""
else
PBX_TINFO=1
cat >>confdefs.h <<_ACEOF
#define HAVE_TINFO 1
_ACEOF
fi
fi
fi
fi
else
if test "x${PBX_TINFO}" != "x1" -a "${USE_TINFO}" != "no"; then
pbxlibdir=""
# if --with-TINFO=DIR has been specified, use it.
if test "x${TINFO_DIR}" != "x"; then
if test -d ${TINFO_DIR}/lib; then
pbxlibdir="-L${TINFO_DIR}/lib"
else
pbxlibdir="-L${TINFO_DIR}"
fi
fi
ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
CFLAGS="${CFLAGS} "
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for keypad in -ltinfo" >&5
$as_echo_n "checking for keypad in -ltinfo... " >&6; }
if ${ac_cv_lib_tinfo_keypad+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-ltinfo ${pbxlibdir} $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char keypad ();
int
main ()
{
return keypad ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_tinfo_keypad=yes
else
ac_cv_lib_tinfo_keypad=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tinfo_keypad" >&5
$as_echo "$ac_cv_lib_tinfo_keypad" >&6; }
if test "x$ac_cv_lib_tinfo_keypad" = xyes; then :
AST_TINFO_FOUND=yes
else
AST_TINFO_FOUND=no
fi
CFLAGS="${ast_ext_lib_check_save_CFLAGS}"
# now check for the header.
if test "${AST_TINFO_FOUND}" = "yes"; then
TINFO_LIB="${pbxlibdir} -ltinfo "
# if --with-TINFO=DIR has been specified, use it.
if test "x${TINFO_DIR}" != "x"; then
TINFO_INCLUDE="-I${TINFO_DIR}/include"
fi
TINFO_INCLUDE="${TINFO_INCLUDE} "
# check for the header
ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}"
CPPFLAGS="${CPPFLAGS} ${TINFO_INCLUDE}"
ac_fn_c_check_header_mongrel "$LINENO" "curses.h" "ac_cv_header_curses_h" "$ac_includes_default"
if test "x$ac_cv_header_curses_h" = xyes; then :
TINFO_HEADER_FOUND=1
else
TINFO_HEADER_FOUND=0
fi
CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}"
if test "x${TINFO_HEADER_FOUND}" = "x0" ; then
TINFO_LIB=""
TINFO_INCLUDE=""
else
PBX_TINFO=1
cat >>confdefs.h <<_ACEOF
#define HAVE_TINFO 1
_ACEOF
fi
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
$as_echo_n "checking for a sed that does not truncate output... " >&6; }
if ${ac_cv_path_SED+:} false; then :

View File

@ -65,6 +65,7 @@ AST_EXT_LIB_SETUP([NEWT], [newt], [newt])
AST_EXT_LIB_SETUP([CURSES], [curses], [curses])
AST_EXT_LIB_SETUP([NCURSES], [ncurses], [ncurses])
AST_EXT_LIB_SETUP([LIBXML2], [LibXML2], [libxml2])
AST_EXT_LIB_SETUP([TINFO], [terminfo], [libtinfo])
AST_EXT_LIB_CHECK([NEWT], [newt], [newtBell], [newt.h])
AST_EXT_LIB_CHECK([NCURSES], [ncurses], [initscr], [ncurses.h])
@ -78,6 +79,17 @@ if test "${PBX_NCURSES}" != 1; then
fi
fi
AC_SUBST(HAVE_NCURSES_SUBDIR)
if test "${PBX_NCURSES}" = 1; then
if test "${HAVE_NCURSES_SUBDIR}" = "yes"; then
AST_EXT_LIB_CHECK([TINFO], [tinfo], [keypad], [ncurses/ncurses.h])
else
AST_EXT_LIB_CHECK([TINFO], [tinfo], [keypad], [ncurses.h])
fi
else
AST_EXT_LIB_CHECK([TINFO], [tinfo], [keypad], [curses.h])
fi
AST_EXT_TOOL_CHECK([LIBXML2], [xml2-config], , ,
[#include <libxml/tree.h>
#include <libxml/parser.h>],

View File

@ -19,6 +19,9 @@ NCURSES_INCLUDE=@NCURSES_INCLUDE@
NCURSES_LIB=@NCURSES_LIB@
HAVE_NCURSES_SUBDIR=@HAVE_NCURSES_SUBDIR@
TINFO_INCLUDE=@TINFO_INCLUDE@
TINFO_LIB=@TINFO_LIB@
NEWT_INCLUDE=@NEWT_INCLUDE@
NEWT_LIB=@NEWT_LIB@

View File

@ -495,6 +495,7 @@ void ast_ari_invoke(struct ast_tcptls_session_instance *ser,
{
RAII_VAR(struct stasis_rest_handlers *, root, NULL, ao2_cleanup);
struct stasis_rest_handlers *handler;
struct stasis_rest_handlers *wildcard_handler = NULL;
RAII_VAR(struct ast_variable *, path_vars, NULL, ast_variables_destroy);
char *path = ast_strdupa(uri);
char *path_segment;
@ -503,37 +504,49 @@ void ast_ari_invoke(struct ast_tcptls_session_instance *ser,
root = handler = get_root_handler();
ast_assert(root != NULL);
ast_debug(3, "Finding handler for %s\n", path);
while ((path_segment = strsep(&path, "/")) && (strlen(path_segment) > 0)) {
struct stasis_rest_handlers *found_handler = NULL;
int i;
ast_uri_decode(path_segment, ast_uri_http_legacy);
ast_debug(3, "Finding handler for %s\n", path_segment);
ast_debug(3, " Finding handler for %s\n", path_segment);
for (i = 0; found_handler == NULL && i < handler->num_children; ++i) {
struct stasis_rest_handlers *child = handler->children[i];
ast_debug(3, " Checking %s\n", child->path_segment);
if (child->is_wildcard) {
/* Record the path variable */
struct ast_variable *path_var = ast_variable_new(child->path_segment, path_segment, __FILE__);
path_var->next = path_vars;
path_vars = path_var;
found_handler = child;
wildcard_handler = child;
ast_debug(3, " Checking %s %s: Matched wildcard.\n", handler->path_segment, child->path_segment);
} else if (strcmp(child->path_segment, path_segment) == 0) {
found_handler = child;
ast_debug(3, " Checking %s %s: Explicit match with %s\n", handler->path_segment, child->path_segment, path_segment);
} else {
ast_debug(3, " Checking %s %s: Didn't match %s\n", handler->path_segment, child->path_segment, path_segment);
}
}
if (!found_handler && wildcard_handler) {
ast_debug(3, " No explicit handler found for %s. Using wildcard %s.\n",
path_segment, wildcard_handler->path_segment);
found_handler = wildcard_handler;
wildcard_handler = NULL;
}
if (found_handler == NULL) {
/* resource not found */
ast_debug(3, " Handler not found\n");
ast_debug(3, " Handler not found for %s\n", path_segment);
ast_ari_response_error(
response, 404, "Not Found",
"Resource not found");
return;
} else {
ast_debug(3, " Got it!\n");
handler = found_handler;
}
}

View File

@ -371,7 +371,7 @@
changes happen for any of the specified mailboxes. More than one mailbox can be
specified with a comma-delimited string. app_voicemail mailboxes must be specified
as mailbox@context; for example: mailboxes=6001@default. For mailboxes provided by
external sources, such as through the res_external_mwi module, you must specify
external sources, such as through the res_mwi_external module, you must specify
strings supported by the external system.
</para><para>
For endpoints that SUBSCRIBE for MWI, use the <literal>mailboxes</literal> option in your AOR
@ -1546,7 +1546,7 @@
More than one mailbox can be specified with a comma-delimited string.
app_voicemail mailboxes must be specified as mailbox@context;
for example: mailboxes=6001@default. For mailboxes provided by external sources,
such as through the res_external_mwi module, you must specify strings supported by
such as through the res_mwi_external module, you must specify strings supported by
the external system.
</para><para>
For endpoints that cannot SUBSCRIBE for MWI, you can set the <literal>mailboxes</literal> option in your

View File

@ -1035,7 +1035,11 @@ static struct ao2_container *cli_contact_get_container(const char *regex)
return NULL;
}
contacts_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
/* Retrieving all the contacts may result in finding the same contact multiple
* times. So that they don't get displayed multiple times we only allow a
* single one to be placed into the container.
*/
contacts_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT,
cli_contact_sort, cli_contact_compare);
if (!contacts_container) {
return NULL;

View File

@ -42,6 +42,7 @@
struct mwi_subscription;
static struct ao2_container *unsolicited_mwi;
static struct ao2_container *solicited_mwi;
static char *default_voicemail_extension;
@ -119,6 +120,8 @@ struct mwi_subscription {
char *aors;
/*! Is the MWI solicited (i.e. Initiated with an external SUBSCRIBE) ? */
unsigned int is_solicited;
/*! True if this subscription is to be terminated */
unsigned int terminate;
/*! Identifier for the subscription.
* The identifier is the same as the corresponding endpoint's stasis ID.
* Used as a hash key
@ -665,7 +668,7 @@ static void send_mwi_notify(struct mwi_subscription *sub)
ao2_cleanup(aor);
ao2_cleanup(endpoint);
ast_sip_subscription_notify(sub->sip_sub, &data, 0);
ast_sip_subscription_notify(sub->sip_sub, &data, sub->terminate);
return;
}
@ -676,18 +679,22 @@ static void send_mwi_notify(struct mwi_subscription *sub)
static int unsubscribe_stasis(void *obj, void *arg, int flags)
{
struct mwi_stasis_subscription *mwi_stasis = obj;
if (mwi_stasis->mwi_subscriber) {
ast_debug(3, "Removing stasis subscription to mailbox %s\n", mwi_stasis->mailbox);
mwi_stasis->mwi_subscriber = ast_mwi_unsubscribe_and_join(mwi_stasis->mwi_subscriber);
}
return CMP_MATCH;
}
static int create_unsolicited_mwi_subscriptions(struct ast_sip_endpoint *endpoint,
int recreate, int send_now);
static void mwi_subscription_shutdown(struct ast_sip_subscription *sub)
{
struct mwi_subscription *mwi_sub;
struct ast_datastore *mwi_datastore;
struct ast_sip_endpoint *endpoint = NULL;
mwi_datastore = ast_sip_subscription_get_datastore(sub, MWI_DATASTORE);
if (!mwi_datastore) {
@ -695,10 +702,25 @@ static void mwi_subscription_shutdown(struct ast_sip_subscription *sub)
}
mwi_sub = mwi_datastore->data;
ao2_callback(mwi_sub->stasis_subs, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, unsubscribe_stasis, NULL);
ast_sip_subscription_remove_datastore(sub, MWI_DATASTORE);
endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", mwi_sub->id);
ao2_ref(mwi_datastore, -1);
ao2_unlink(solicited_mwi, mwi_sub);
/*
* When a solicited subscription is removed it's possible an unsolicited one
* needs to be [re-]created. Attempt to establish unsolicited MWI.
*/
if (unsolicited_mwi && endpoint) {
ao2_lock(unsolicited_mwi);
create_unsolicited_mwi_subscriptions(endpoint, 1, 1);
ao2_unlock(unsolicited_mwi);
}
ao2_cleanup(endpoint);
}
static void mwi_ds_destroy(void *data)
@ -734,43 +756,165 @@ static int add_mwi_datastore(struct mwi_subscription *sub)
}
/*!
* \brief Determines if an endpoint is receiving unsolicited MWI for a particular mailbox.
* \internal
* \brief Determine if an MWI subscription already exists for the given endpoint/mailbox
*
* \param endpoint The endpoint to check
* \param mailbox The candidate mailbox
* \retval 0 The endpoint does not receive unsolicited MWI for this mailbox
* \retval 1 The endpoint receives unsolicited MWI for this mailbox
* Search the given container, and attempt to find out if the given endpoint has a
* current subscription within. If so pass back the associated mwi_subscription and
* mwi_stasis_subscription objects.
*
* \note If a subscription is located then the caller is responsible for removing the
* references to the passed back mwi_subscription and mwi_stasis_subscription objects.
*
* \note Must be called with the given container already locked.
*
* \param container The ao2_container to search
* \param endpoint The endpoint to find
* \param mailbox The mailbox potentially subscribed
* \param mwi_sub [out] May contain the located mwi_subscription
* \param mwi_stasis [out] May contain the located mwi_stasis_subscription
*
* \retval 1 if a subscription was located, 0 otherwise
*/
static int endpoint_receives_unsolicited_mwi_for_mailbox(struct ast_sip_endpoint *endpoint,
const char *mailbox)
static int has_mwi_subscription(struct ao2_container *container,
struct ast_sip_endpoint *endpoint, const char *mailbox,
struct mwi_subscription **mwi_sub, struct mwi_stasis_subscription **mwi_stasis)
{
struct ao2_iterator *mwi_subs;
struct mwi_subscription *mwi_sub;
const char *endpoint_id = ast_sorcery_object_get_id(endpoint);
int ret = 0;
mwi_subs = ao2_find(unsolicited_mwi, endpoint_id, OBJ_SEARCH_KEY | OBJ_MULTIPLE);
*mwi_sub = NULL;
*mwi_stasis = NULL;
mwi_subs = ao2_find(container, ast_sorcery_object_get_id(endpoint),
OBJ_SEARCH_KEY | OBJ_MULTIPLE | OBJ_NOLOCK);
if (!mwi_subs) {
return 0;
}
for (; (mwi_sub = ao2_iterator_next(mwi_subs)) && !ret; ao2_cleanup(mwi_sub)) {
struct mwi_stasis_subscription *mwi_stasis;
mwi_stasis = ao2_find(mwi_sub->stasis_subs, mailbox, OBJ_SEARCH_KEY);
if (mwi_stasis) {
if (endpoint->subscription.mwi.subscribe_replaces_unsolicited) {
unsubscribe_stasis(mwi_stasis, NULL, 0);
ao2_unlink(mwi_sub->stasis_subs, mwi_stasis);
} else {
ret = 1;
}
ao2_cleanup(mwi_stasis);
while ((*mwi_sub = ao2_iterator_next(mwi_subs))) {
*mwi_stasis = ao2_find((*mwi_sub)->stasis_subs, mailbox, OBJ_SEARCH_KEY);
if (*mwi_stasis) {
/* If found then caller is responsible for unrefs of passed back objects */
break;
}
ao2_ref(*mwi_sub, -1);
}
ao2_iterator_destroy(mwi_subs);
return ret;
return *mwi_stasis ? 1 : 0;
}
/*!
* \internal
* \brief Allow and/or replace the unsolicited subscription
*
* Checks to see if solicited subscription is allowed. If allowed, and an
* unsolicited one exists then prepare for replacement by removing the
* current unsolicited subscription.
*
* \param endpoint The endpoint
* \param mailbox The mailbox
*
* \retval 1 if a solicited subscription is allowed for the endpoint/mailbox
* 0 otherwise
*/
static int allow_and_or_replace_unsolicited(struct ast_sip_endpoint *endpoint, const char *mailbox)
{
struct mwi_subscription *mwi_sub;
struct mwi_stasis_subscription *mwi_stasis;
if (!has_mwi_subscription(unsolicited_mwi, endpoint, mailbox, &mwi_sub, &mwi_stasis)) {
/* If no unsolicited subscription then allow the solicited one */
return 1;
}
if (!endpoint->subscription.mwi.subscribe_replaces_unsolicited) {
/* Has unsolicited subscription and can't replace, so disallow */
ao2_ref(mwi_stasis, -1);
ao2_ref(mwi_sub, -1);
return 0;
}
/*
* The unsolicited subscription exists, and it is allowed to be replaced.
* So, first remove the unsolicited stasis subscription, and if aggregation
* is not enabled then also remove the mwi_subscription object as well.
*/
ast_debug(1, "Unsolicited subscription being replaced by solicited for "
"endpoint '%s' mailbox '%s'\n", ast_sorcery_object_get_id(endpoint), mailbox);
unsubscribe_stasis(mwi_stasis, NULL, 0);
ao2_unlink(mwi_sub->stasis_subs, mwi_stasis);
if (!endpoint->subscription.mwi.aggregate) {
ao2_unlink(unsolicited_mwi, mwi_sub);
}
ao2_ref(mwi_stasis, -1);
ao2_ref(mwi_sub, -1);
/* This solicited subscription is replacing an unsolicited one, so allow */
return 1;
}
static int send_notify(void *obj, void *arg, int flags);
/*!
* \internal
* \brief Determine if an unsolicited MWI subscription is allowed
*
* \param endpoint The endpoint
* \param mailbox The mailbox
*
* \retval 1 if an unsolicited subscription is allowed for the endpoint/mailbox
* 0 otherwise
*/
static int is_unsolicited_allowed(struct ast_sip_endpoint *endpoint, const char *mailbox)
{
struct mwi_subscription *mwi_sub;
struct mwi_stasis_subscription *mwi_stasis;
if (ast_strlen_zero(mailbox)) {
return 0;
}
/*
* First check if an unsolicited subscription exists. If it does then we don't
* want to add another one.
*/
if (has_mwi_subscription(unsolicited_mwi, endpoint, mailbox, &mwi_sub, &mwi_stasis)) {
ao2_ref(mwi_stasis, -1);
ao2_ref(mwi_sub, -1);
return 0;
}
/*
* If there is no unsolicited subscription, next check to see if a solicited
* subscription exists for the endpoint/mailbox. If not, then allow.
*/
if (!has_mwi_subscription(solicited_mwi, endpoint, mailbox, &mwi_sub, &mwi_stasis)) {
return 1;
}
/*
* If however, a solicited subscription does exist then we'll need to see if that
* subscription is allowed to replace the unsolicited one. If is allowed to replace
* then disallow the unsolicited one.
*/
if (endpoint->subscription.mwi.subscribe_replaces_unsolicited) {
ao2_ref(mwi_stasis, -1);
ao2_ref(mwi_sub, -1);
return 0;
}
/* Otherwise, shutdown the solicited subscription and allow the unsolicited */
mwi_sub->terminate = 1;
send_notify(mwi_sub, NULL, 0);
ao2_ref(mwi_stasis, -1);
ao2_ref(mwi_sub, -1);
return 1;
}
/*!
@ -796,19 +940,23 @@ static int mwi_validate_for_aor(void *obj, void *arg, int flags)
return 0;
}
/* A reload could be taking place so lock while checking if allowed */
ao2_lock(unsolicited_mwi);
mailboxes = ast_strdupa(aor->mailboxes);
while ((mailbox = ast_strip(strsep(&mailboxes, ",")))) {
if (ast_strlen_zero(mailbox)) {
continue;
}
if (endpoint_receives_unsolicited_mwi_for_mailbox(endpoint, mailbox)) {
if (!allow_and_or_replace_unsolicited(endpoint, mailbox)) {
ast_debug(1, "Endpoint '%s' already configured for unsolicited MWI for mailbox '%s'. "
"Denying MWI subscription to %s\n", ast_sorcery_object_get_id(endpoint), mailbox,
ast_sorcery_object_get_id(aor));
ao2_unlock(unsolicited_mwi);
return -1;
}
}
ao2_unlock(unsolicited_mwi);
return 0;
}
@ -954,6 +1102,7 @@ static int mwi_subscription_established(struct ast_sip_subscription *sip_sub)
ast_sip_subscription_remove_datastore(sip_sub, MWI_DATASTORE);
}
ao2_link(solicited_mwi, sub);
ao2_cleanup(sub);
ao2_cleanup(endpoint);
return 0;
@ -1090,12 +1239,25 @@ static void mwi_stasis_cb(void *userdata, struct stasis_subscription *sub,
}
}
/*! \note Called with the unsolicited_mwi container lock held. */
static int create_mwi_subscriptions_for_endpoint(void *obj, void *arg, int flags)
/*!
* \internal
* \brief Create unsolicited MWI subscriptions for an endpoint
*
* \note Call with the unsolicited_mwi container lock held.
*
* \param endpoint An endpoint object
* \param recreate Whether or not unsolicited subscriptions are potentially being recreated
* \param send_now Whether or not to send a notify once the subscription is created
*
* \retval 0
*/
static int create_unsolicited_mwi_subscriptions(struct ast_sip_endpoint *endpoint,
int recreate, int send_now)
{
RAII_VAR(struct mwi_subscription *, aggregate_sub, NULL, ao2_cleanup);
struct ast_sip_endpoint *endpoint = obj;
char *mailboxes, *mailbox;
char *mailboxes;
char *mailbox;
int sub_added = 0;
if (ast_strlen_zero(endpoint->subscription.mwi.mailboxes)) {
return 0;
@ -1104,45 +1266,90 @@ static int create_mwi_subscriptions_for_endpoint(void *obj, void *arg, int flags
if (endpoint->subscription.mwi.aggregate) {
const char *endpoint_id = ast_sorcery_object_get_id(endpoint);
/* Check if subscription exists */
/* Check if aggregate subscription exists */
aggregate_sub = ao2_find(unsolicited_mwi, endpoint_id, OBJ_SEARCH_KEY | OBJ_NOLOCK);
if (aggregate_sub) {
/*
* If enabled there should only ever exist a single aggregate subscription object
* for an endpoint. So if it exists just return unless subscriptions are potentially
* being added back in. If that's the case then continue.
*/
if (aggregate_sub && !recreate) {
return 0;
}
aggregate_sub = mwi_subscription_alloc(endpoint, 0, NULL);
if (!aggregate_sub) {
return 0;
aggregate_sub = mwi_subscription_alloc(endpoint, 0, NULL);
if (!aggregate_sub) {
return 0; /* No MWI aggregation for you */
}
/*
* Just in case we somehow get in the position of recreating with no previous
* aggregate object, set recreate to false here in order to allow the new
* object to be linked into the container below
*/
recreate = 0;
}
}
/* Lock solicited so we don't potentially add to both containers */
ao2_lock(solicited_mwi);
mailboxes = ast_strdupa(endpoint->subscription.mwi.mailboxes);
while ((mailbox = ast_strip(strsep(&mailboxes, ",")))) {
struct mwi_subscription *sub;
struct mwi_stasis_subscription *mwi_stasis_sub;
/* check if subscription exists */
if (ast_strlen_zero(mailbox) ||
(!aggregate_sub && endpoint_receives_unsolicited_mwi_for_mailbox(endpoint, mailbox))) {
if (!is_unsolicited_allowed(endpoint, mailbox)) {
continue;
}
sub = aggregate_sub ?: mwi_subscription_alloc(endpoint, 0, NULL);
if (!sub) {
continue;
}
mwi_stasis_sub = mwi_stasis_subscription_alloc(mailbox, sub);
if (mwi_stasis_sub) {
ao2_link(sub->stasis_subs, mwi_stasis_sub);
ao2_ref(mwi_stasis_sub, -1);
}
if (!aggregate_sub && sub) {
if (!aggregate_sub) {
ao2_link_flags(unsolicited_mwi, sub, OBJ_NOLOCK);
if (send_now) {
send_notify(sub, NULL, 0);
}
ao2_ref(sub, -1);
}
if (aggregate_sub && !sub_added) {
/* If aggregation track if at least one subscription has been added */
sub_added = 1;
}
}
if (aggregate_sub) {
ao2_link_flags(unsolicited_mwi, aggregate_sub, OBJ_NOLOCK);
if (ao2_container_count(aggregate_sub->stasis_subs)) {
/* Only link if we're dealing with a new aggregate object */
if (!recreate) {
ao2_link_flags(unsolicited_mwi, aggregate_sub, OBJ_NOLOCK);
}
if (send_now && sub_added) {
send_notify(aggregate_sub, NULL, 0);
}
}
}
ao2_unlock(solicited_mwi);
return 0;
}
static int create_mwi_subscriptions_for_endpoint(void *obj, void *arg, int flags)
{
return create_unsolicited_mwi_subscriptions(obj, 0, 0);
}
static int unsubscribe(void *obj, void *arg, int flags)
{
struct mwi_subscription *mwi_sub = obj;
@ -1347,11 +1554,20 @@ static int load_module(void)
ast_log(AST_LOG_WARNING, "Failed to create MWI serializer pool. The default SIP pool will be used for MWI\n");
}
solicited_mwi = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, MWI_BUCKETS,
mwi_sub_hash, NULL, mwi_sub_cmp);
if (!solicited_mwi) {
mwi_serializer_pool_shutdown();
ast_sip_unregister_subscription_handler(&mwi_handler);
return AST_MODULE_LOAD_DECLINE;
}
unsolicited_mwi = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_MUTEX, 0, MWI_BUCKETS,
mwi_sub_hash, NULL, mwi_sub_cmp);
if (!unsolicited_mwi) {
mwi_serializer_pool_shutdown();
ast_sip_unregister_subscription_handler(&mwi_handler);
ao2_ref(solicited_mwi, -1);
return AST_MODULE_LOAD_DECLINE;
}
@ -1384,6 +1600,8 @@ static int unload_module(void)
ao2_ref(unsolicited_mwi, -1);
unsolicited_mwi = NULL;
ao2_cleanup(solicited_mwi);
mwi_serializer_pool_shutdown();
ast_sip_unregister_subscription_handler(&mwi_handler);

View File

@ -1006,7 +1006,7 @@ static int setup_sdes_srtp(struct ast_sip_session_media *session_media,
return 0;
}
ast_debug(1, "Ignoring crypto offer with unsupported parameters: %s\n", crypto_str);
ast_log(LOG_WARNING, "Ignoring crypto offer with unsupported parameters: %s\n", crypto_str);
}
/* no usable crypto attributes found */

View File

@ -203,7 +203,6 @@ static int t38_automatic_reject(void *obj)
{
RAII_VAR(struct ast_sip_session *, session, obj, ao2_cleanup);
RAII_VAR(struct ast_datastore *, datastore, ast_sip_session_get_datastore(session, "t38"), ao2_cleanup);
struct ast_sip_session_media *session_media;
if (!datastore) {
return 0;
@ -212,8 +211,7 @@ static int t38_automatic_reject(void *obj)
ast_debug(2, "Automatically rejecting T.38 request on channel '%s'\n",
session->channel ? ast_channel_name(session->channel) : "<gone>");
session_media = session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
t38_change_state(session, session_media, datastore->data, T38_REJECTED);
t38_change_state(session, NULL, datastore->data, T38_REJECTED);
ast_sip_session_resume_reinvite(session);
return 0;
@ -322,28 +320,37 @@ static int t38_reinvite_response_cb(struct ast_sip_session *session, pjsip_rx_da
int index;
session_media = session->active_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
t38_change_state(session, session_media, state, T38_ENABLED);
if (!session_media) {
ast_log(LOG_WARNING, "Received %d response to T.38 re-invite on '%s' but no active session media\n",
status.code, session->channel ? ast_channel_name(session->channel) : "unknown channel");
} else {
t38_change_state(session, session_media, state, T38_ENABLED);
/* Stop all the streams in the stored away active state, they'll go back to being active once
* we reinvite back.
*/
for (index = 0; index < AST_VECTOR_SIZE(&state->media_state->sessions); ++index) {
struct ast_sip_session_media *session_media = AST_VECTOR_GET(&state->media_state->sessions, index);
/* Stop all the streams in the stored away active state, they'll go back to being active once
* we reinvite back.
*/
for (index = 0; index < AST_VECTOR_SIZE(&state->media_state->sessions); ++index) {
struct ast_sip_session_media *session_media = AST_VECTOR_GET(&state->media_state->sessions, index);
if (session_media && session_media->handler && session_media->handler->stream_stop) {
session_media->handler->stream_stop(session_media);
if (session_media && session_media->handler && session_media->handler->stream_stop) {
session_media->handler->stream_stop(session_media);
}
}
return 0;
}
} else {
session_media = session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
t38_change_state(session, session_media, state, T38_REJECTED);
/* Abort this attempt at switching to T.38 by resetting the pending state and freeing our stored away active state */
ast_sip_session_media_state_free(state->media_state);
state->media_state = NULL;
ast_sip_session_media_state_reset(session->pending_media_state);
}
/* If no session_media then response contained a declined stream, so disable */
t38_change_state(session, NULL, state, session_media ? T38_REJECTED : T38_DISABLED);
/* Abort this attempt at switching to T.38 by resetting the pending state and freeing our stored away active state */
ast_sip_session_media_state_free(state->media_state);
state->media_state = NULL;
ast_sip_session_media_state_reset(session->pending_media_state);
return 0;
}
@ -426,12 +433,10 @@ static int t38_interpret_parameters(void *obj)
/* Negotiation can not take place without a valid max_ifp value. */
if (!parameters->max_ifp) {
if (data->session->t38state == T38_PEER_REINVITE) {
session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
t38_change_state(data->session, session_media, state, T38_REJECTED);
t38_change_state(data->session, NULL, state, T38_REJECTED);
ast_sip_session_resume_reinvite(data->session);
} else if (data->session->t38state == T38_ENABLED) {
session_media = data->session->active_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
t38_change_state(data->session, session_media, state, T38_DISABLED);
t38_change_state(data->session, NULL, state, T38_DISABLED);
ast_sip_session_refresh(data->session, NULL, NULL, NULL,
AST_SIP_SESSION_REFRESH_METHOD_INVITE, 1, state->media_state);
state->media_state = NULL;
@ -454,6 +459,11 @@ static int t38_interpret_parameters(void *obj)
state->our_parms.version = MIN(state->our_parms.version, state->their_parms.version);
state->our_parms.rate_management = state->their_parms.rate_management;
session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
if (!session_media) {
ast_log(LOG_ERROR, "Failed to negotiate parameters for reinvite on channel '%s' (No pending session media).\n",
data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
break;
}
ast_udptl_set_local_max_ifp(session_media->udptl, state->our_parms.max_ifp);
t38_change_state(data->session, session_media, state, T38_ENABLED);
ast_sip_session_resume_reinvite(data->session);
@ -468,8 +478,13 @@ static int t38_interpret_parameters(void *obj)
}
state->our_parms = *parameters;
session_media = media_state->default_session[AST_MEDIA_TYPE_IMAGE];
if (!session_media) {
ast_log(LOG_ERROR, "Failed to negotiate parameters on channel '%s' (No default session media).\n",
data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
break;
}
ast_udptl_set_local_max_ifp(session_media->udptl, state->our_parms.max_ifp);
t38_change_state(data->session, session_media, state, T38_LOCAL_REINVITE);
t38_change_state(data->session, NULL, state, T38_LOCAL_REINVITE);
ast_sip_session_refresh(data->session, NULL, t38_reinvite_sdp_cb, t38_reinvite_response_cb,
AST_SIP_SESSION_REFRESH_METHOD_INVITE, 1, media_state);
}
@ -478,12 +493,10 @@ static int t38_interpret_parameters(void *obj)
case AST_T38_REFUSED:
case AST_T38_REQUEST_TERMINATE: /* Shutdown T38 */
if (data->session->t38state == T38_PEER_REINVITE) {
session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
t38_change_state(data->session, session_media, state, T38_REJECTED);
t38_change_state(data->session, NULL, state, T38_REJECTED);
ast_sip_session_resume_reinvite(data->session);
} else if (data->session->t38state == T38_ENABLED) {
session_media = data->session->active_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
t38_change_state(data->session, session_media, state, T38_DISABLED);
t38_change_state(data->session, NULL, state, T38_DISABLED);
ast_sip_session_refresh(data->session, NULL, NULL, NULL, AST_SIP_SESSION_REFRESH_METHOD_INVITE, 1, state->media_state);
state->media_state = NULL;
}
@ -493,6 +506,11 @@ static int t38_interpret_parameters(void *obj)
if (data->session->t38state == T38_PEER_REINVITE) {
session_media = data->session->pending_media_state->default_session[AST_MEDIA_TYPE_IMAGE];
if (!session_media) {
ast_log(LOG_ERROR, "Failed to request parameters for reinvite on channel '%s' (No pending session media).\n",
data->session->channel ? ast_channel_name(data->session->channel) : "unknown channel");
break;
}
parameters.max_ifp = ast_udptl_get_far_max_ifp(session_media->udptl);
parameters.request_response = AST_T38_REQUEST_NEGOTIATE;
ast_queue_control_data(data->session->channel, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
@ -788,7 +806,7 @@ static int negotiate_incoming_sdp_stream(struct ast_sip_session *session,
if ((session->t38state == T38_REJECTED) || (session->t38state == T38_DISABLED)) {
ast_debug(3, "Declining; T.38 state is rejected or declined\n");
t38_change_state(session, session_media, state, T38_DISABLED);
t38_change_state(session, NULL, state, T38_DISABLED);
return 0;
}

View File

@ -6713,7 +6713,6 @@ static void rtp_instance_parse_transport_wide_cc(struct ast_rtp_instance *instan
if (transport_rtp->transport_wide_cc.schedid < 0 && transport_rtp->rtcp) {
ast_debug(1, "Starting RTCP transport-cc feedback transmission on RTP instance '%p'\n", transport);
ao2_ref(transport, +1);
ast_log(LOG_NOTICE, "Starting feedback\n");
transport_rtp->transport_wide_cc.schedid = ast_sched_add(rtp->sched, 1000,
rtp_transport_wide_cc_feedback_produce, transport);
if (transport_rtp->transport_wide_cc.schedid < 0) {

View File

@ -1006,6 +1006,7 @@ static int stale_item_update(const void *data)
ast_sorcery_object_get_id(task_data->object));
sorcery_memory_cache_create(task_data->sorcery, task_data->cache,
object);
ao2_ref(object, -1);
}
ast_test_suite_event_notify("SORCERY_MEMORY_CACHE_REFRESHED", "Cache: %s\r\nType: %s\r\nName: %s\r\n",

View File

@ -373,6 +373,12 @@ static int ast_srtp_unprotect(struct ast_srtp *srtp, void *buf, int *len, int rt
tryagain:
if (!srtp->session) {
ast_log(LOG_ERROR, "SRTP unprotect %s - missing session\n", rtcp ? "rtcp" : "rtp");
errno = EINVAL;
return -1;
}
for (i = 0; i < 2; i++) {
res = rtcp ? srtp_unprotect_rtcp(srtp->session, buf, len) : srtp_unprotect(srtp->session, buf, len);
if (res != err_status_no_ctx) {
@ -481,6 +487,12 @@ static int ast_srtp_protect(struct ast_srtp *srtp, void **buf, int *len, int rtc
int res;
unsigned char *localbuf;
if (!srtp->session) {
ast_log(LOG_ERROR, "SRTP protect %s - missing session\n", rtcp ? "rtcp" : "rtp");
errno = EINVAL;
return -1;
}
if ((*len + SRTP_MAX_TRAILER_LEN) > sizeof(srtp->buf)) {
return -1;
}
@ -501,6 +513,7 @@ static int ast_srtp_protect(struct ast_srtp *srtp, void **buf, int *len, int rtc
static int ast_srtp_create(struct ast_srtp **srtp, struct ast_rtp_instance *rtp, struct ast_srtp_policy *policy)
{
struct ast_srtp *temp;
int status;
if (!(temp = res_srtp_new())) {
return -1;
@ -508,10 +521,13 @@ static int ast_srtp_create(struct ast_srtp **srtp, struct ast_rtp_instance *rtp,
ast_module_ref(ast_module_info->self);
/* Any failures after this point can use ast_srtp_destroy to destroy the instance */
if (srtp_create(&temp->session, &policy->sp) != err_status_ok) {
status = srtp_create(&temp->session, &policy->sp);
if (status != err_status_ok) {
/* Session either wasn't created or was created and dealloced. */
temp->session = NULL;
ast_srtp_destroy(temp);
ast_log(LOG_ERROR, "Failed to create srtp session on rtp instance (%p) - %s\n",
rtp, srtp_errstr(status));
return -1;
}
@ -525,10 +541,19 @@ static int ast_srtp_create(struct ast_srtp **srtp, struct ast_rtp_instance *rtp,
static int ast_srtp_replace(struct ast_srtp **srtp, struct ast_rtp_instance *rtp, struct ast_srtp_policy *policy)
{
if ((*srtp) != NULL) {
ast_srtp_destroy(*srtp);
struct ast_srtp *old = *srtp;
int res = ast_srtp_create(srtp, rtp, policy);
if (!res && old) {
ast_srtp_destroy(old);
}
return ast_srtp_create(srtp, rtp, policy);
if (res) {
ast_log(LOG_ERROR, "Failed to replace srtp (%p) on rtp instance (%p) "
"- keeping old\n", *srtp, rtp);
}
return res;
}
static void ast_srtp_destroy(struct ast_srtp *srtp)

View File

@ -2,7 +2,7 @@
"_copyright": "Copyright (C) 2012 - 2013, Digium, Inc.",
"_author": "David M. Lee, II <dlee@digium.com>",
"_svn_revision": "$Revision$",
"apiVersion": "4.0.0",
"apiVersion": "5.0.0",
"swaggerVersion": "1.1",
"basePath": "http://localhost:8088/ari",
"apis": [

View File

@ -20,6 +20,8 @@ if (env.TIMEOUT_GATES) {
pipeline {
options {
ansiColor('gnome-terminal')
throttle(['asterisk-gate'])
timestamps()
timeout(time: timeoutTime, unit: timeoutUnits)
}
@ -57,19 +59,20 @@ pipeline {
agent {
/* All of the stages need to be performed on a docker host */
label "swdev-docker"
label "asterisk-gate"
}
stages {
stage ("->") {
/*
* Jenkins will try to automatically rebuild this job when
* the jenkinsfile changes but since this job is dependent on
* Gerrit, we really don't want to do anything in that case.
*/
when {
/*
* Jenkins will try to automatically rebuild this job when
* the jenkinsfile changes but since this job is dependent on
* Gerrit, we really don't want to do anything in that case.
*/
not { environment name: 'GERRIT_CHANGE_NUMBER', value: '' }
not { environment name: 'GERRIT_EVENT_ACCOUNT_NAME', value: 'Jenkins2' }
/* If "skip_gate" is in the comments, don't run the job */
not { expression { env.GERRIT_EVENT_COMMENT_TEXT ==~ /.*skip_gate.*/ } }
}
steps {
/* Here's where we switch to scripted pipeline */
@ -97,7 +100,7 @@ pipeline {
withCredentials([usernamePassword(credentialsId: "${JENKINS_GERRIT_CREDS}",
passwordVariable: 'GERRIT_USER_PW', usernameVariable: 'GERRIT_USER_NAME')]) {
sh "printenv | sort"
sh "printenv -0 | sort -z | tr '\\0' '\\n'"
checkout scm: [$class: 'GitSCM',
branches: [[name: env.GERRIT_BRANCH ]],

View File

@ -20,6 +20,8 @@ if (env.TIMEOUT_DAILIES) {
pipeline {
options {
ansiColor('gnome-terminal')
throttle(['asterisk-daily'])
timestamps()
timeout(time: timeoutTime, unit: timeoutUnits)
}
@ -29,7 +31,7 @@ pipeline {
agent {
/* All of the stages need to be performed on a docker host */
label "swdev-docker"
label "asterisk-daily"
}
stages {
@ -41,7 +43,7 @@ pipeline {
stage ("Checkout") {
sh "sudo chown -R jenkins:users ."
sh "printenv | sort"
sh "printenv -0 | sort -z | tr '\\0' '\\n'"
sh "sudo tests/CI/setupJenkinsEnvironment.sh"
}

View File

@ -20,6 +20,8 @@ if (env.TIMEOUT_REF_DEBUG) {
pipeline {
options {
ansiColor('gnome-terminal')
throttle(['asterisk-ref-debug'])
timestamps()
timeout(time: timeoutTime, unit: timeoutUnits)
}
@ -29,7 +31,7 @@ pipeline {
agent {
/* All of the stages need to be performed on a docker host */
label "swdev-docker"
label "asterisk-ref-debug"
}
stages {
@ -41,7 +43,7 @@ pipeline {
stage ("Checkout") {
sh "sudo chown -R jenkins:users ."
sh "printenv | sort"
sh "printenv -0 | sort -z | tr '\\0' '\\n'"
sh "sudo tests/CI/setupJenkinsEnvironment.sh"
}

View File

@ -20,6 +20,8 @@ if (env.TIMEOUT_UNITTESTS) {
pipeline {
options {
ansiColor('gnome-terminal')
throttle(['asterisk-check'])
timestamps()
timeout(time: timeoutTime, unit: timeoutUnits)
}
@ -59,7 +61,7 @@ pipeline {
}
agent {
/* All of the stages need to be performed on a docker host */
label "swdev-docker"
label "asterisk-check"
}
stages {
@ -98,7 +100,7 @@ pipeline {
withCredentials([usernamePassword(credentialsId: "${JENKINS_GERRIT_CREDS}",
passwordVariable: 'GERRIT_USER_PW', usernameVariable: 'GERRIT_USER_NAME')]) {
sh "printenv | sort"
sh "printenv -0 | sort -z | tr '\\0' '\\n'"
checkout scm: [$class: 'GitSCM',
branches: [[name: env.GERRIT_BRANCH ]],

View File

@ -0,0 +1,53 @@
Index: pjsip/include/pjsip/sip_config.h
===================================================================
--- a/pjsip/include/pjsip/sip_config.h (revision 6050)
+++ b/pjsip/include/pjsip/sip_config.h (working copy)
@@ -1190,6 +1190,20 @@
# define PJSIP_AUTH_CACHED_POOL_MAX_SIZE (20 * 1024)
#endif
+
+/**
+ * Specify whether the cnonce used for SIP authentication contain digits only.
+ * The "cnonce" value is setup using GUID generator, i.e:
+ * pj_create_unique_string(), and the GUID string may contain hyphen character
+ * ("-"). Some SIP servers do not like this GUID format, so this option will
+ * strip any hyphens from the GUID string.
+ *
+ * Default is 1 (cnonce will only contain digit characters).
+ */
+#ifndef PJSIP_AUTH_CNONCE_USE_DIGITS_ONLY
+# define PJSIP_AUTH_CNONCE_USE_DIGITS_ONLY 1
+#endif
+
/*****************************************************************************
* SIP Event framework and presence settings.
*/
Index: pjsip/src/pjsip/sip_auth_client.c
===================================================================
--- a/pjsip/src/pjsip/sip_auth_client.c (revision 6050)
+++ b/pjsip/src/pjsip/sip_auth_client.c (working copy)
@@ -396,7 +396,23 @@
/* Create cnonce */
pj_create_unique_string( cached_auth->pool, &cached_auth->cnonce );
+#if defined(PJSIP_AUTH_CNONCE_USE_DIGITS_ONLY) && \
+ PJSIP_AUTH_CNONCE_USE_DIGITS_ONLY!=0
+ if (pj_strchr(&cached_auth->cnonce, '-')) {
+ /* remove hyphen character. */
+ int w, r, len = pj_strlen(&cached_auth->cnonce);
+ char *s = cached_auth->cnonce.ptr;
+ w = r = 0;
+ for (; r < len; r++) {
+ if (s[r] != '-')
+ s[w++] = s[r];
+ }
+ s[w] = '\0';
+ cached_auth->cnonce.slen = w;
+ }
+#endif
+
/* Initialize nonce-count */
cached_auth->nc = 1;

View File

@ -0,0 +1,105 @@
From 489281f29fc7b97143cf79154f22e5007adaba39 Mon Sep 17 00:00:00 2001
From: George Joseph <gjoseph@digium.com>
Date: Wed, 9 Oct 2019 07:49:44 -0600
Subject: [PATCH 30/31] ssl regression fix
---
pjlib/src/pj/ssl_sock_gtls.c | 6 ++++--
pjlib/src/pj/ssl_sock_imp_common.c | 4 ++++
pjlib/src/pj/ssl_sock_imp_common.h | 3 +++
pjlib/src/pj/ssl_sock_ossl.c | 9 +++++----
4 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/pjlib/src/pj/ssl_sock_gtls.c b/pjlib/src/pj/ssl_sock_gtls.c
index 311b7b757..484770ae4 100644
--- a/pjlib/src/pj/ssl_sock_gtls.c
+++ b/pjlib/src/pj/ssl_sock_gtls.c
@@ -1050,7 +1050,8 @@ static void ssl_update_certs_info(pj_ssl_sock_t *ssock)
goto us_out;
tls_cert_get_info(ssock->pool, &ssock->local_cert_info, cert);
- tls_cert_get_chain_raw(ssock->pool, &ssock->local_cert_info, us, 1);
+ pj_pool_reset(ssock->info_pool);
+ tls_cert_get_chain_raw(ssock->info_pool, &ssock->local_cert_info, us, 1);
us_out:
tls_last_error = ret;
@@ -1077,7 +1078,8 @@ us_out:
goto peer_out;
tls_cert_get_info(ssock->pool, &ssock->remote_cert_info, cert);
- tls_cert_get_chain_raw(ssock->pool, &ssock->remote_cert_info, certs,
+ pj_pool_reset(ssock->info_pool);
+ tls_cert_get_chain_raw(ssock->info_pool, &ssock->remote_cert_info, certs,
certslen);
peer_out:
diff --git a/pjlib/src/pj/ssl_sock_imp_common.c b/pjlib/src/pj/ssl_sock_imp_common.c
index e6273d832..51a62a2fb 100644
--- a/pjlib/src/pj/ssl_sock_imp_common.c
+++ b/pjlib/src/pj/ssl_sock_imp_common.c
@@ -616,6 +616,7 @@ static void ssl_on_destroy(void *arg)
}
/* Secure release pool, i.e: all memory blocks will be zeroed first */
+ pj_pool_secure_release(&ssock->info_pool);
pj_pool_secure_release(&ssock->pool);
}
@@ -1262,15 +1263,18 @@ PJ_DEF(pj_status_t) pj_ssl_sock_create (pj_pool_t *pool,
{
pj_ssl_sock_t *ssock;
pj_status_t status;
+ pj_pool_t *info_pool;
PJ_ASSERT_RETURN(pool && param && p_ssock, PJ_EINVAL);
PJ_ASSERT_RETURN(param->sock_type == pj_SOCK_STREAM(), PJ_ENOTSUP);
+ info_pool = pj_pool_create(pool->factory, "ssl_chain%p", 512, 512, NULL);
pool = pj_pool_create(pool->factory, "ssl%p", 512, 512, NULL);
/* Create secure socket */
ssock = ssl_alloc(pool);
ssock->pool = pool;
+ ssock->info_pool = info_pool;
ssock->sock = PJ_INVALID_SOCKET;
ssock->ssl_state = SSL_STATE_NULL;
ssock->circ_buf_input.owner = ssock;
diff --git a/pjlib/src/pj/ssl_sock_imp_common.h b/pjlib/src/pj/ssl_sock_imp_common.h
index 09f259ef7..eb45f14e0 100644
--- a/pjlib/src/pj/ssl_sock_imp_common.h
+++ b/pjlib/src/pj/ssl_sock_imp_common.h
@@ -96,6 +96,9 @@ typedef struct circ_buf_t {
struct pj_ssl_sock_t
{
pj_pool_t *pool;
+ pj_pool_t *info_pool; /* this is for certificate chain
+ * information allocation. Don't use for
+ * other purposes. */
pj_ssl_sock_t *parent;
pj_ssl_sock_param param;
pj_ssl_sock_param newsock_param;
diff --git a/pjlib/src/pj/ssl_sock_ossl.c b/pjlib/src/pj/ssl_sock_ossl.c
index b4ac5c15f..2545b7c37 100644
--- a/pjlib/src/pj/ssl_sock_ossl.c
+++ b/pjlib/src/pj/ssl_sock_ossl.c
@@ -1637,11 +1637,12 @@ static void ssl_update_certs_info(pj_ssl_sock_t *ssock)
chain = SSL_get_peer_cert_chain(ossock->ossl_ssl);
if (chain) {
- ssl_update_remote_cert_chain_info(ssock->pool,
- &ssock->remote_cert_info,
- chain, PJ_TRUE);
+ pj_pool_reset(ssock->info_pool);
+ ssl_update_remote_cert_chain_info(ssock->info_pool,
+ &ssock->remote_cert_info,
+ chain, PJ_TRUE);
} else {
- ssock->remote_cert_info.raw_chain.cnt = 0;
+ ssock->remote_cert_info.raw_chain.cnt = 0;
}
}
--
2.21.0

View File

@ -0,0 +1,187 @@
From 9c6108ca392d5e0392e7fb5d2ffde85e3c44ce55 Mon Sep 17 00:00:00 2001
From: George Joseph <gjoseph@digium.com>
Date: Wed, 9 Oct 2019 07:50:32 -0600
Subject: [PATCH 31/31] transport regression fix
---
pjsip/src/pjsip/sip_transport.c | 73 +++++++++++++++++++++++++++------
1 file changed, 61 insertions(+), 12 deletions(-)
diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c
index 65ac823d4..da6b70e50 100644
--- a/pjsip/src/pjsip/sip_transport.c
+++ b/pjsip/src/pjsip/sip_transport.c
@@ -50,6 +50,24 @@ static const char *addr_string(const pj_sockaddr_t *addr)
str, sizeof(str));
return str;
}
+static const char* print_tpsel_info(const pjsip_tpselector *sel)
+{
+ static char tpsel_info_buf[80];
+ if (!sel) return "(null)";
+ if (sel->type==PJSIP_TPSELECTOR_LISTENER)
+ pj_ansi_snprintf(tpsel_info_buf, sizeof(tpsel_info_buf),
+ "listener[%s], reuse=%d", sel->u.listener->obj_name,
+ !sel->disable_connection_reuse);
+ else if (sel->type==PJSIP_TPSELECTOR_TRANSPORT)
+ pj_ansi_snprintf(tpsel_info_buf, sizeof(tpsel_info_buf),
+ "transport[%s], reuse=%d", sel->u.transport->info,
+ !sel->disable_connection_reuse);
+ else
+ pj_ansi_snprintf(tpsel_info_buf, sizeof(tpsel_info_buf),
+ "unknown[%p], reuse=%d", sel->u.ptr,
+ !sel->disable_connection_reuse);
+ return tpsel_info_buf;
+}
#else
# define TRACE_(x)
#endif
@@ -1210,10 +1228,14 @@ PJ_DEF(pj_status_t) pjsip_transport_register( pjsip_tpmgr *mgr,
* new transport to the list.
*/
pj_list_push_back(tp_ref, tp_add);
+ TRACE_((THIS_FILE, "Remote address already registered, "
+ "appended the transport to the list"));
} else {
/* Transport list not found, add it to the hash table. */
pj_hash_set_np(mgr->table, &tp->key, key_len, hval, tp_add->tp_buf,
tp_add);
+ TRACE_((THIS_FILE, "Remote address not registered, "
+ "added the transport to the hash"));
}
/* Add ref transport group lock, if any */
@@ -1283,6 +1305,13 @@ static pj_status_t destroy_transport( pjsip_tpmgr *mgr,
/* The transport list has multiple entry. */
pj_hash_set_np(mgr->table, &tp_next->tp->key, key_len,
hval, tp_next->tp_buf, tp_next);
+ TRACE_((THIS_FILE, "Hash entry updated after "
+ "transport %d being destroyed",
+ tp->obj_name));
+ } else {
+ TRACE_((THIS_FILE, "Hash entry deleted after "
+ "transport %d being destroyed",
+ tp->obj_name));
}
}
@@ -1294,6 +1323,14 @@ static pj_status_t destroy_transport( pjsip_tpmgr *mgr,
}
tp_iter = tp_iter->next;
} while (tp_iter != tp_ref);
+
+ if (tp_iter->tp != tp) {
+ PJ_LOG(3, (THIS_FILE, "Warning: transport %s being destroyed is "
+ "not registered", tp->obj_name));
+ }
+ } else {
+ PJ_LOG(3, (THIS_FILE, "Warning: transport %s being destroyed is "
+ "not found in the hash table", tp->obj_name));
}
pj_lock_release(mgr->lock);
@@ -2159,6 +2196,7 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport(pjsip_tpmgr *mgr,
NULL, tp);
}
+
/*
* pjsip_tpmgr_acquire_transport2()
*
@@ -2176,8 +2214,9 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
pjsip_tpfactory *factory;
pj_status_t status;
- TRACE_((THIS_FILE,"Acquiring transport type=%s, remote=%s:%d",
+ TRACE_((THIS_FILE,"Acquiring transport type=%s, sel=%s remote=%s:%d",
pjsip_transport_get_type_name(type),
+ print_tpsel_info(sel),
addr_string(remote),
pj_sockaddr_get_port(remote)));
@@ -2194,6 +2233,7 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
/* See if the transport is (not) suitable */
if (seltp->key.type != type) {
pj_lock_release(mgr->lock);
+ TRACE_((THIS_FILE, "Transport type in tpsel not matched"));
return PJSIP_ETPNOTSUITABLE;
}
@@ -2234,6 +2274,7 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
{
if (sel->u.listener->type != type) {
pj_lock_release(mgr->lock);
+ TRACE_((THIS_FILE, "Listener type in tpsel not matched"));
return PJSIP_ETPNOTSUITABLE;
}
}
@@ -2249,21 +2290,25 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
tp_entry = (transport *)pj_hash_get(mgr->table, &key, key_len,
NULL);
if (tp_entry) {
- if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER) {
- transport *tp_iter = tp_entry;
- do {
+ transport *tp_iter = tp_entry;
+ do {
+ /* Don't use transport being shutdown */
+ if (!tp_iter->tp->is_shutdown) {
if (sel && sel->type == PJSIP_TPSELECTOR_LISTENER &&
- sel->u.listener &&
- tp_iter->tp->factory == sel->u.listener)
+ sel->u.listener)
{
+ /* Match listener if selector is set */
+ if (tp_iter->tp->factory == sel->u.listener) {
+ tp_ref = tp_iter->tp;
+ break;
+ }
+ } else {
tp_ref = tp_iter->tp;
break;
}
- tp_iter = tp_iter->next;
- } while (tp_iter != tp_entry);
- } else {
- tp_ref = tp_entry->tp;
- }
+ }
+ tp_iter = tp_iter->next;
+ } while (tp_iter != tp_entry);
}
}
@@ -2276,7 +2321,7 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
/* Ignore address for loop transports. */
if (type == PJSIP_TRANSPORT_LOOP ||
- type == PJSIP_TRANSPORT_LOOP_DGRAM)
+ type == PJSIP_TRANSPORT_LOOP_DGRAM)
{
pj_sockaddr *addr = &key.rem_addr;
@@ -2315,6 +2360,7 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
* 'duplicate' of the existing transport (same type & remote addr,
* but different factory).
*/
+ TRACE_((THIS_FILE, "Transport found but from different listener"));
}
if (tp_ref!=NULL && !tp_ref->is_shutdown) {
@@ -2347,10 +2393,13 @@ PJ_DEF(pj_status_t) pjsip_tpmgr_acquire_transport2(pjsip_tpmgr *mgr,
*/
/* Verify that the listener type matches the destination type */
+ /* Already checked above. */
+ /*
if (sel->u.listener->type != type) {
pj_lock_release(mgr->lock);
return PJSIP_ETPNOTSUITABLE;
}
+ */
/* We'll use this listener to create transport */
factory = sel->u.listener;
--
2.21.0