Change rawdata buffer from char to unsigned char to prevent
sign-extension of TLV length bytes >= 0x80. On signed-char
platforms (all Asterisk builds due to -fsigned-char in
configure.ac), these values become negative when assigned to
int, bypass the `if (res > 32)` bounds check, and reach
memcpy as size_t producing a ~18 EB read that immediately
crashes with SIGSEGV.
Affects DAHDI analog (FXO) channels only. Not reachable
via SIP, PRI/BRI, or DTMF-based Caller ID.
Fixes: #1839
When the res_cdrel_custom modules is reloaded and the config has not been changed asterisk should not free the old config. Otherwise the connection to the database will be closed and no new connection will be opened.
Resolves: #1852
Several issues are resolved:
* Internally, floats were used for timestamp values but this could result
in wrapping so they've been changed to doubles.
* Historically, the default CEL eventtime format is `<seconds>.<microseconds>`
with `<microseconds>` always being 6 digits. This should have continued to be
the case but res_cdrel_custom wasn't checking the `dateformat` setting in
cel.conf and was defaulting to `%F %T`. res_cdrel_custom now gets the default
date format from cel.conf, which will be whatever the `dateformat` parameter
is set to or `<seconds>.<microseconds>` if not set.
* The timeval field formatter for both CDR and CEL wasn't handling custom
strftime format strings correctly. This is now fixed so you should be able
to specifiy custom strftime format strings for the CEL `eventtime` and CDR
`start`, `answer` and `end` fields. For example: `eventtime(%FT%T%z)`.
Resolves: #1844Resolves: #1845
ast_channel_datastore_find() and ast_channel_datastore_add() must only be
called while the channel is locked (see channel.h). raise_exception() and the
EXCEPTION dialplan function read path accessed the exception datastore without
holding ast_channel_lock, which could corrupt the per-channel datastore list
under concurrency and lead to crashes during teardown (e.g. double free in
ast_datastore_free).
Resolves: #1831
The PR #1522 introduced the header read loop for audiosocket packets
which does not handle partial header reads correctly. This commit
adds the missing buffer offsets.
manager.c: Fix CLI event display
- `manager show events`: fix event names being truncated at 20 characters, widen column to 28 to accommodate the longest registered event name
- `manager show events`: skip duplicate entries caused by multiple modules registering the same event name, list is already sorted so adjacent name comparison is sufficient
Redirects initiated by 302 response codes weren't handled correctly
when setting the hangup cause code and tech cause code on the responding
channel. They're now set to 23 (REDIRECTED_TO_NEW_DESTINATION) and
302 (Moved permanently). Other non-2XX response codes also had issues.
A new API ast_channel_dialed_causes_iterator() was added to retrieve
the hangup cause codes for a channel.
chan_pjsip_session_end() in chan_pjsip has been refactored to set the
correct cause codes on a channel based on the cause codes added by
chan_pjsip_incoming_response_update_cause(). Copious amounts of
debugging and comments were also added.
Resolves: #1819
Currently, endpoints created via the PJSIP Config Wizard do not update
their ACL rules if the underlying Named ACL (in acl.conf) changes.
This occurs because the wizard relies on file timestamp and content
caching of pjsip_wizard.conf, which remains unchanged during an external
ACL update. As a result, endpoints retain stale ACL rules even after
a reload.
This patch updates res_pjsip_config_wizard to subscribe to the
ast_named_acl_change_type Stasis event. A local generation counter is
incremented whenever an ACL change event is received.
During a reload, the wizard compares the current local generation against
the generation stored in the wizard object. If a change is detected:
1. The file cache optimization (CONFIG_FLAG_FILEUNCHANGED) is bypassed.
2. Wizard objects utilizing 'acl' or 'contact_acl' are forced to update,
ensuring they pick up the new IP rules.
Signed-off-by: Michal Hajek michal.hajek@daktela.comFixes: #1641
If a channel in Stasis/ARI is hung up by the channel driver, the RTPAUDIOQOS
variables are set before the channel leaves Stasis and are therefore
available to the ARI app via ChannelVarset events. If the channel is hung up
by ARI however, the channel leaves Stasis before the RTPAUDIOQOS variables
are set so the app may not get the ChannelVarset events.
We now set the RTPAUDIOQOS variables when ast_softhangup() is called as well
as when the channel driver hangs up a channel. Since ARI hangups call
ast_softhangup(), the variables will be set before the channel leaves Stasis
and the app should get the ChannelVarset events.
ast_rtp_instance_set_stats_vars(), which actually sets the variables, now
checks to see if the variables are already set before attempting to set them.
This prevents double messages from being generated.
Resolves: #1816
Description:
When Asterisk is running without a timing module, attempting to process DTMF
triggers a segmentation fault. This occurs because the system
attempts to access a null timing file descriptor when setting up the
DTMF emulation timer.
This fix ensures that the system checks for a valid timing source before
attempting to start the DTMF emulation timer. If no timing module is
present, it logs a warning and skips the emulation instead of crashing
the process.
Changes:
- Modified main/channel.c to add a safety check within the __ast_read function.
- Implemented a graceful return path when no timing source is available
- Added a LOG_WARNING to inform the administrator that DTMF emulation
was skipped due to missing timing modules.
Testing:
- Disabled all timing_ modules in modules.conf and confirmed with
'timing test'.
- Reproduced the crash by modifying the dialplan with:
exten => 707,1,NoOp(Starting DTMF - No Timing Mode)
same => n,Answer()
same => n,Background(demo-congrats)
same => n,WaitExten(10)
same => n,Hangup()
And calling 707 followed by 1
- Verified that with the fix applied, the system logs "No timing module
loaded; skipping DTMF timer" and continues dialplan
execution without crashing.
- Confirmed stability during concurrent media sessions and DTMF input.
Fixes: #566
If a pjsip transport (A) fails to load, its temporary state gets left behind
causing the next transport to load (B) to pick up some of its parameters,
including its name. This can cause B to have the correct name (B) in its
transport object but the wrong name (A) in its internal state object. When a
transport state is searched for later on, transport state B is returned but a
retrieval of the actual transport object will fail because B's transport
state id is actually "A" and transport "A" doesn't exist because it failed
to load.
remove_temporary_state() is now being called in all error paths in
config_transport.c functions that call find_or_create_temporary_state().
A bit of extra debugging was also added to res_pjsip_nat.c.
Resolves: #1814
According to RFC 3428 (Section 5), a Contact header is not required in a
MESSAGE request unless the sender wants to establish a session. This
patch ensures that the Contact header is removed from out-of-dialog
MESSAGE requests within res_pjsip_messaging.c.
Fixes: #1356
Add uri prefix based acl support to the built in http server.
This allows an acl to be added per uri prefix (ie '/metrics'
or '/ws') to restrict access.
Add user based acl support for ARI. This adds new acl options
to the user section of ari.conf to restrict access on a per
user basis.
resolves: #1799
UserNote: A new section, type=restriction has been added to http.conf
to allow an uri prefix based acl to be configured. See
http.conf.sample for examples and more information.
The user section of ari.conf can now contain an acl configuration
to restrict users access. See ari.conf.sample for examples and more
information
When TURN is configured in rtp.conf, pjproject re-injects TURN packets
via 127.0.0.1 (the loopback address). The DTLS packet handler checks the
source address against the ICE active candidate list before the loopback
address substitution runs, causing the packet to be silently dropped as
the source 127.0.0.1 is not in the candidate list.
Fix by performing the loopback address substitution before the ICE
candidate source check in the DTLS path, mirroring the logic already
present in the non-DTLS RTP path.
Fixes: #1795
UserNote: WebRTC calls using TURN configured in rtp.conf (turnaddr,
turnusername, turnpassword) will now correctly complete DTLS/SRTP
negotiation. Previously all DTLS packets were silently dropped due to
the loopback re-injection address not being in the ICE active candidate
list.
Extend the existing DTMF/MF tone detection support by adding support
for R2 tones, another variant of MF (R1) signaling. Both forward
and backward signaling are supported.
Resolves: #1804
Include the channel name in warnings during wait_for_answer to make
them more useful and allow problematic channels to be easily identified.
Resolves: #1802
For application, function, manager, managerEvent, managerEventInstance
and info XML documentation nodes, the make_xml_documentation script will
add a "module" attribute if not already present. For XML in separate
"*_doc.xml" files, the script figures out the correct module name. For
documentation in the "main" directory, the module name is set to "builtin".
The CLI handlers for "core show application", "core show function",
"manager show command" and "manager show event", have been updated to
show the following after the Synopsis...
```
[Provided By]
<modulename>
```
For modules that provide additional "info" elements (like the technologies
do for Dial), the providing module has also been added.
```
Technology: WebSocket Provided by: chan_websocket
WebSocket Dial Strings:
...
```
UserNote: The CLI help for applications, functions, manager commands and
manager events now shows the module that provides its functionality.
The AudioSocket encapsulation for externalMedia requires a UUID to be
provided in the `data` parameter of the ARI call. If not provided, we
should return a 400 Bad Request instead of a 500 Internal Server
Error.
Pointed out by AVT in the community forum[1].
1: https://community.asterisk.org/t/externalmedia-audiosocket-on-asterisk-22/112149
There is a LOT of work in this commit but the TL;DR is that it takes
CEL processing from using 38% of the CPU instructions used by a call,
which is more than that used by the call processing itself, down to less
than 10% of the instructions.
So here's the deal... cdr_custom, cdr_sqlite3_custom, cel_custom
and cel_sqlite3_custom all shared one ugly trait...they all used
ast_str_substitute_variables() or pbx_substitute_variables_helper()
to resolve the dialplan functions used in their config files. Not only
are they both extraordinarily expensive, they both require a dummy
channel to be allocated and destroyed for each record written. For CDRs,
that's not too bad because we only write one CDR per call. For CELs however,
it's a disaster.
As far as source code goes, the modules basically all did the same thing.
Unfortunately, they did it badly. The config files simply contained long
opaque strings which were intepreted by ast_str_substitute_variables() or
pbx_substitute_variables_helper(), the very functions that ate all the
instructions. This meant introducing a new "advanced" config format much
like the advanced manager event filtering added to manager.conf in 2024.
Fortunately however, if the legacy config was recognizable, we were able to
parse it as an advanced config and gain the benefit. If not, then it
goes the legacy, and very expensive, route.
Given the commonality among the modules, instead of making the same
improvements to 4 modules then trying to maintain them over time, a single
module "res_cdrel_custom" was created that contains all of the common code.
A few bonuses became possible in the process...
* The cdr_custom and cel_custom modules now support JSON formatted output.
* The cdr_sqlite_custom and cel_sqlite3_custom modules no longer have
to share an Sqlite3 database.
Summary of changes:
A new module "res/res_cdrel_custom.c" has been created and the existing
cdr_custom, cdr_sqlite3_custom, cel_custom and cel_sqlite3_custom modules
are now just stubs that call the code in res_cdrel_custom.
res_cdrel_custom contains:
* A common configuration facility.
* Getters for both CDR and CEL fields that share the same abstraction.
* Formatters for all data types found in the ast_cdr and ast_event
structures that share the same abstraction.
* Common writers for the text file and database backends that, you guessed it,
share the same abstraction.
The result is that while there is certainly a net increase in the number of
lines in the code base, most of it is in the configuration handling at
load-time. The run-time instruction path length is now significanty shorter.
```
Scenario Instructions Latency
=====================================================
CEL pre changes 38.49% 37.51%
CEL Advanced 9.68% 6.06%
CEL Legacy (auto-conv to adv) 9.95% 6.13%
CEL Sqlite3 pre changes 39.41% 39.90%
CEL Sqlite3 Advanced 25.68% 24.24%
CEL Sqlite3 Legacy (auto conv) 25.88% 24.53%
CDR pre changes 4.79% 2.95%
CDR Advanced 0.79% 0.47%
CDR Legacy (auto conv to adv) 0.86% 0.51%
CDR Sqlite3 pre changes 4.47% 2.89%
CEL Sqlite3 Advanced 2.16% 1.29%
CEL Sqlite3 Legacy (auto conv) 2.19% 1.30%
```
Notes:
* We only write one CDR per call but every little bit helps.
* Sqlite3 still takes a fair amount of resources but the new config
makes a decent improvement.
* Legacy configs that we can't auto convert will still take the
"pre changes" path.
If you're interested in more implementation details, see the comments
at the top of the res_cdrel_custom.c file.
One minor fix to CEL is also included...Although TenantID was added to the
ast_event structure, it was always rendered as an empty string. It's now
properly rendered.
UserNote: Significant performance improvements have been made to the
cdr_custom, cdr_sqlite3_custom, cel_custom and cel_sqlite3_custom modules.
See the new sample config files for those modules to see how to benefit
from them.
The original chan_websocket implementation attempted to improve the
call quality experience by generating silence frames to send to the core
when no media was being read from the websocket and padding frames with
silence when short frames were read from the websocket. Both of these
required switching the formats on the channel to slin for short periods
of time then switching them back to whatever format the websocket channel
was configured for. Unfortunately, the format switching caused issues
when transcoding was required and the transcode_via_sln option was enabled
in asterisk.conf (which it is by default). The switch would cause the
transcoding path to be incorrectly set resulting in malformed RTP packets
being sent back out to the caller on the other end which the caller heard
as loud noise.
After looking through the code and performing multiple listening tests,
the best solution to this problem was to just remove the code that was
attempting to generate the silence. There was no decrease in call quality
whatsoever and the code is a bit simpler. None of the other channel drivers
nor res_rtp_asterisk generate silence frames or pad short frames which
backed up decision.
Resolves: #1785
Currently, WebSockets both accept and send media without the option to
disable one or the other. This commit adds the ability to set the media
direction for a WebSocket, making it unidirectional or bidirectional
(the default). Direction is done from the point of view of the
application, NOT Asterisk. The allowed values are 'both', 'in', and
'out'. If media direction is 'both' (the default), Asterisk accepts and
sends media to the application. If it is 'in', Asterisk will drop any
media received from the application. If it is 'out', Asterisk will not
write any media frames to the application.
UserNote: WebSocket now supports media direction, allowing for
unidirectional media. This is done from the perspective of the
application and can be set via channel origination, external media, or
commands sent from the application. Check out
https://docs.asterisk.org/Configuration/Channel-Drivers/WebSocket/ for
more.
"SyntaxWarning: invalid escape sequence '\s'" occurs when using the pjsip
migration script because '\' is an escape character in Python. Instead,
use a raw string for the regex.
`ast_cli_unregister_multiple()` expects internal data members to be heap
allocated which happens during a successful call to
`ast_cli_register_multiple()`. CLI handlers defined traditionally - those whose
handler responds to the CLI_INIT message - take care of this automatically. But
when we statically provide a `command` or `usage` member, we _must_ initialize
them with `ast_cli_register_multiple()` before attempting to destroy them.
Resolves: #1651
According to RFC 8866 (Section 5.2), the Session Name (s=) field and
the username part of origin (o=) are both mandatory and cannot be
empty. If a session has no name, or no username part of origin, the
RFC recommends using a single dash (-) as a placeholder.
This fix ensures that if the session name or the username part of
origin length is zero , it defaults to -.
Fixes: #1524
This hook may not be necessary when we do a retransmit, but when there are two
INVITEs, one *initial* and one with auth digest, the second INVITE contains wrong (unmodified) media address
due to the commented line below.
The NAT hook needs to run due to filters potentially reverting previously modified packets.
Fixes: #449
Fix discarded-qualifiers errors to compile successfully with gcc 15.2.1.
Associated changes have also been made to libss7; however, for compatibility
we cast const char* values to char*. In the future, these casts could be
removed.
Resolves: #1786
chan_iax2 has several code paths where a frame's data length
is calculated by subtraction. On some paths, there is a check
for negative length. One of these paths is missing this check,
and on this path, it is possible for the result to be negative,
leading to a crash as a result of memory operations using the
bogus length.
Add a check to capture this off-nominal case. This will log
the appropriate warnings as in other cases and prevent a crash.
Also update the log messages to be clearer.
Resolves: #1707
GCC 15.2.1 pays attention to the discarding of the const
qualifier when strchr, strrchr, memchr, or memrchr are now
used. This change fixes numerous errors with this throughout
the tree. The fixes can be broken down into the following:
1. The return value should be considered const.
2. The value passed to strchr or strrchr can be cast as it is
expected and allowed to be modified.
3. The pointer passed to strchr or strrchr is not meant to be
modified and so the contents must be duplicated.
4. It was declared const and never should have been.
This change adds an API call to allow direct access to the latest
snapshot of an ast_endpoint. This is then used by chan_pjsip when
calculating device state, eliminating the need to access the cache
which would incur a container find and access.
This adds a 'prio' setting to ensure that call priority is respected across multiple queues.
Using 'yes' could cause high-priority callers to be skipped if a caller
in another queue had a longer wait time, regardless of priority.
Resolves: #1637
UserNote: The 'force_longest_waiting_caller' option now supports a 'prio' setting.
When set to 'prio', calls are offered by priority first, then by wait time.
Resolves: #1612
UserNote: Bundled pjproject has been upgraded to 2.16. For more
information on what all is included in this change, check out the
pjproject Github page: https://github.com/pjsip/pjproject/releases
Adds a new PJSIP_INHERITABLE_HEADER dialplan function to add
inheritable headers from the inbound channel to an outbound
bridged channel. This works similarly to the existing
PJSIP_HEADER function, but will set the header on the bridged
outbound channel's INVITE upon Dial.
Inheritable headers can be updated or removed from the inbound
channel as well as from a pre-dial handler
Resolves: #1670
UserNote: A new PJSIP_HEADER option has been added that allows
inheriting pjsip headers from the inbound to the outbound bridged
channel.
Example- same => n,Set(PJSIP_INHERITABLE_HEADER(add,X-custom-1)=alpha)
will add X-custom-1: alpha to the outbound pjsip channel INVITE
upon Dial.
app_queue: Set Dial-compatible timing variables
Extends Queue() to set Dial-compatible timing variables (ANSWEREDTIME, DIALEDTIME) and introduces a precise QUEUEWAIT metric calculated at agent connect time, with proper initialization to prevent stale or misleading values.
stasis.c: Fix deadlock in stasis_topic_pool_get_topic during module load.
Deadlock occurs when res_manager_devicestate loads concurrently with
device state operations due to lock ordering violation:
Thread 1: Holds pool lock → needs topic lock (in stasis_forward_all)
Thread 2: Holds topic lock → needs pool lock (in stasis_topic_pool_get_topic)
Fix: Release pool lock before calling stasis_topic_create() and
stasis_forward_all(). Re-acquire only for insertion with race check.
Preserves borrowed reference semantics while breaking the deadlock cycle.
Fixes: #1611
QUEUE_RAISE_PENALTY=rN was not respected during member selection. calc_metric() raised penalties below QUEUE_MIN_PENALTY, allowing excluded members to be selected.
This change makes calc_metric() honor raise_respect_min, keeping behavior consistent with queue empty checks and expected rN semantics
UserNote: Fixes an issue where QUEUE_RAISE_PENALTY=rN could raise a member’s penalty below QUEUE_MIN_PENALTY during member selection. This could allow members intended to be excluded to be selected. The queue now consistently respects the minimum penalty when raising penalties, aligning member selection behavior with queue empty checks and documented rN semantics.
This prevents a situation where a call joining at 1st position to a queue with calls
leads to a state where no callers are considered the longest waiting,
causing queues to stop offering calls.
Resolves: #1691