Fixes two related instance, group lock inversion deadlocks.
When writing the RTP stream via rtp_sendto, the RTP instance was only unlocked
before being passed to pj project when the instance was un-bundled (ie video
was not bundled onto the audio stream's ICE transport.)
The first change unlocks the instance whether bundled or unbundled to avoid the
deadlock, then re-checks the bundled status upon return to know wether or not the
transport should be used.
For the second change, when an incoming RTCP NACK record was recieved, the parent
(transport) and child (instance) locks were both held before the call to rtp_sendto,
which is only able to release the child lock. Now in the un-bundled case the parent
and child will be unlocked and re-locked in the correct order via a new helper
function before and after the call to send_to.
Fixes: #1946
When placing outbound calls each call would get its own
taskprocessor for things related to the call. In practice this
is overkill as few things actually occur. Inbound calls on
the other hand already use one of the fixed number of
distributor taskprocessors. This also occurred for OPTIONS
requests with each AOR having its own taskprocessor.
This change moves both to using a distributor taskprocessor
instead.
When an attended transfer is controlled by ARI using
PJSIP_TRANSFER_HANDLING()=ari-only, and a REFER request is received with
a Refer-Sub: false header to suppress the automatic progress
subscription, a segfault occurs in
res_pjsip_refer:refer_incoming_ari_request().
However, even if the segfault were prevented, there's another issue...
Suppressing the subscription and NOTIFYs to the referer also prevents
the ARI app from getting any progress events for the transfer which it's
controlling.
So...
* The segfault has been fixed.
* Suppressing the subscription no longer suppress the ARI events from being
sent to the controlling ARI app.
* A good amount of tracing has also been added.
Resolves: #2021
The 'none' value can be used to disable DSP processing for DTMF
on PJSIP channels and is sometimes necessary for this reason,
and already exists in the code, but is not documented. Add it to
the documentation enum.
Resolves: #2026
When an inbound REGISTER is matched to an endpoint using an
identification method such as IP, header, or request URI, the endpoint can
be identified and authenticated successfully while registrar AOR
resolution still fails.
find_registrar_aor() only resolved AOR names for username and
auth_username identify methods. A header-only endpoint therefore left
aor_name unset and failed registration with "AOR '' not found" even when
the REGISTER To URI matched one of the endpoint's configured AORs.
Resolve the REGISTER AOR from the To URI for endpoint identification
methods that do not directly provide an AOR name, while still
constraining the match to the already-identified endpoint's configured AOR
list.
Fixes: #1398
Two error paths in res_http_websocket could leak an ast_websocket session by
failing to drop a reference after the session had been allocated.
The first occurs when session ID generation fails. While this is largely
theoretical, as it would require an out-of-memory condition, the session
reference should still be released correctly.
The second occurs when the ast_websocket_pre_callback session_attempted callback
returns an error. This path is reachable through ari_websockets, which
implements this callback and can legitimately fail under certain conditions.
Fixes: #2020
Bundled pjproject uses ./third-party/pjproject/patches/config_site.h to set
many pjproject build options like PJ_IOQUEUE_MAX_HANDLES, PJSIP_MAX_URL_SIZE,
etc. Editing that file however, causes the git tree to become dirty which
is inconvenient. So...
* Updated the Asterisk configure scripts to pass the PJPROJECT_CFLAGS variable
down to the pjproject configure scripts. See the UserNote below for details.
* Updated ./third-party/pjproject/patches/config_site.h to allow the following
options to be overridden:
PJ_MAX_HOSTNAME, PJSIP_MAX_URL_SIZE, PJ_IOQUEUE_MAX_HANDLES.
Other options in config_site.h are not overridable because they can have a
bad effect on the overall operation of pjproject. This may be revisited in
the future. Options not already set in config_site.h can still be set.
* Fixed an issue where if the Linux `epoll` facility is used (which it is by
default) the default PJ_IOQUEUE_MAX_HANDLES and PJSIP_MAX_TRANSPORTS were
being left at 1024 instead of being icnreased to 5000.
* The `pjproject show buildopts` CLI command previously only showed options from
the top level `PJ` pjproject layer but now also shows many from the `PJSIP`
layer. Many of these, such as PJSIP_MAX_TRANSPORTS, can be set using
PJPROJECT_CFLAGS provided they're not already unconditionally set in
config_site.h.
* The `pjsip dump endpt` CLI command previously required that the pjproject
log level be already set to at least 3 or no output would be produced. The
command now does that automatically then sets it back to whatever it was.
This isn't strictly related to this PR but was just nagging me.
UserNote: Bundled pjproject: It's now possible to override some of the pjproject
build options contained in ./third-party/pjproject/patches/config_site.h by
adding PJPROJECT_CFLAGS to your Asterisk ./configure command line. For example:
`./configure ... PJPROJECT_CFLAGS='-DPJ_OPT1=8192 -DPJ_OPT2=512'`
Any option in config_site.h that's wrapped in a `#ifndef` block can be overridden
and many of the `PJSIP` options displayed by `pjproject show buildopts` can be
set. WARNING: Adjusting these options without understanding their effect can
cripple your Asterisk instances. You shouldn't adjust them unless you need
to solve a specific issue.
Resolves: #2011
When a confirmed session is being terminated while an outgoing in-dialog
INVITE transaction is still outstanding, the BYE is delayed until the
outstanding transaction terminates.
If that INVITE has already received a provisional response and the final
response is malformed and rejected before transaction processing, the
transaction can remain outstanding and the delayed BYE can keep the
session, media state, RTP instance, and PJPROJECT pools referenced after
the channels are gone.
When a BYE is delayed behind an outstanding UAC INVITE, set a PJPROJECT
transaction timeout on that INVITE so the delayed cleanup path has a
bounded wait. If PJPROJECT terminates the dialog as a result of the
timeout, discard the delayed BYE instead of sending a duplicate BYE.
Fixes: #1965
The REST over WebSocket path now properly prevents non-GET methods from
being executed on inbound WebSockets.
* The query parameters from the original incoming GET request that caused the
upgrade to WebSocket are now passed to all REST requests that come from the
client. This ensures that if the client authenticated with a read-only
userid using the "api_key" query_string parameter, REST requests coming
in over the WebSocket will only be able to execute GETs on resources.
The HTTP headers were already passed to the REST requests so if the
client had authenticated via an "Authorization" it was properly handled.
* New tests have been added to test_ari.c to check that read-only users
are properly denied access to resources using non-GET methods. Several
memory leaks were also squashed.
Resolves: #GHSA-wcvv-g26m-wx5c
The filter_on_tx_message() function was using pj_strassign() to save the pointer
of the pjproject transport local address to a local pj_str_t variable. That
variable was ultimately used to set the Contact header's uri->host and the SDP
connection attribute's address again using pj_strassign. pj_strassign() doesn't
copy the actual value of the pj_str_t however, it just copies the pointer so
if a connection-oriented transport is disconnected before the 200 OK with the
SDP is sent, those pointers will be invalid which can cause use-after-free
issues. To prevent this, filter_on_tx_message() now uses pj_strdup with the
tdata->pool as the backing store to save the local IP address to the local
variable. pj_strassign() can then be used safely later on since the tdata
will be available for the life of the transaction.
Resolves: #GHSA-g8q2-p36q-94f6
DeveloperNote: ARI applications can no longer call "dangerous" dialplan
functions like DB(), FILE(), SHELL(), CURL(), STAT(), etc. without
enabling "live_dangerously" in asterisk.conf.
Resolves: #GHSA-vrfp-mg3q-3959
* Add check to red_t140_to_red() to ensure that the new primary payload
can't cause the rtp_red->len array items to wrap or cause an overrun of
the rtp_red->t140red_data buffer.
* Add check to rtp_red_buffer() to ensure that a T.140 frame to be sent
can't cause rtp_red->len array items to wrap or cause an overrun of
the rtp_red->buf_data buffer.
Resolves: #GHSA-vfhr-r9x9-c687
Resolves: #GHSA-j2mm-57pq-jh94
Add constraint checks to prevent unauthenticated users from crashing Asterisk
instance by sending a crafted inbound SIP NOTIFY request with "Content-Type:
application/simple-message-summary".
Resolves: #GHSA-8jw3-ccr9-xrmf
The snprintf size parameter in xmpp_action_hook() is computed from
the attacker-controlled namespace prefix length and is not bounded
by the 256-byte stack buffer size. When a remote XMPP peer sends a
stanza with a child element whose namespace prefix exceeds 249
characters, snprintf writes past the buffer boundary.
Use sizeof(attr) as the snprintf size limit and %.*s precision to
extract only the prefix portion of the element name, preserving
the original truncation behavior for valid inputs.
Resolves: #GHSA-mxgm-8c6f-5p8f
The parse_simple_message_summary() function uses sscanf with an
unbounded %s format specifier to parse the Message-Account field
from incoming SIP NOTIFY bodies into a fixed-size 512-byte stack
buffer (PJSIP_MAX_URL_SIZE). A single unauthenticated SIP NOTIFY
with a Message-Account value exceeding 512 bytes overflows the
buffer, corrupting adjacent stack data and permanently disabling
the PJSIP transport layer without crashing the process.
Add a width specifier (%511s) to limit the sscanf write to
PJSIP_MAX_URL_SIZE - 1 bytes plus the NUL terminator, matching
the destination buffer size.
Resolves: #GHSA-589g-qgf8-m6mx
The LDAP realtime driver constructs search filters by directly
concatenating user-supplied values without RFC 4515 escaping.
When LDAP is used as a realtime backend for endpoint
identification, characters with special meaning in LDAP filters
(*, (, ), \) can be injected via the SIP From header username.
Add ldap_filter_escape_value() that escapes RFC 4515 special
characters to their \HH hex representation, and apply it to
non-LIKE query values. The LIKE query path preserves the existing
wildcard conversion behavior with a note for maintainers.
Resolves: #GHSA-r6c2-hwc2-j4mp
The websocket client proxy and server handshakes use ast_iostream_gets which
are blocking calls. If the outgoing connection succeeds at the TCP or TLS
layer but the proxy (if configured) or the websocket server fails to respond
to the CONNECT or GET requests, the process can hang indefinitely and escalate
to a deadlock. To address this, the handshakes are now guarded with calls to
ast_iostream_set_timeout_sequence() with the timeout set to the client's
(connection_timeout * 2) milliseconds.
In order to use ast_iostream_set_timeout_sequence(), the iostream has to be
set to non-blocking with ast_iostream_nonblock() but there was no way to
reset the stream back to blocking mode so a new API ast_iostream_blocking()
was added for it.
Tracing was also enabled in the websocket_client_handshake function for
future troubleshooting.
Resolves: #1979
Adds a new transport option 'external_signaling_hostname' which allows
a hostname or FQDN to be used in SIP Contact and Via headers instead of
the automatically determined IP address. This is useful when a remote
SIP endpoint requires a fully qualified domain name in these headers.
The option is mutually exclusive with 'external_signaling_address' and
an error is raised at transport load time if both are set simultaneously.
Resolves: #1749
UserNote: A new pjsip.conf transport option 'external_signaling_hostname'
has been added. When set, this value will be used in SIP Contact and Via
headers instead of the automatically determined IP address. This option
is mutually exclusive with 'external_signaling_address'.
See the notes below for high-level descriptions of the new features.
* Proxies
Outbound/forward HTTP proxies are now supported and configurable in
websocket_client.conf. You can specify a host:port plus optional proxy_username
and proxy_password. Because WebSockets aren't consistently supported among
proxies (specifically passing through UPGRADEs), the CONNECT method is always
used to establish a TCP tunnel through the proxy. This is required if a TLS
session is to be established with the WebSocket server anyway. It's important
to understand that that negotiation with the proxy is ALWAYS unsecured. Once
the proxy establishes the tunnel, the TLS session will be negotiated directly
with the remote WebSocket server via the tunnel.
* Keepalives
Both TCP-level and WebSocket PING/PONG keepalives can be configured and are
available with either the curl or tcptls client implementations. The TCP
keepalives are handled entirely by the operating system and require no
resources from Asterisk but by their very nature, they can't traverse proxies.
WebSocket PING/PONGs are implemented in the Asterisk websocket code and require
a scheduler thread to keep track of them so they're a bit more complicated but
they do traverse proxies. Which one is used is completely up to the admin.
You could use both.
* Other Changes
A few changes were needed to res/ari/ari_websockets and
res/res_aeap/transport_websocket to add explicit calls to ast_websocket_close.
They had been assuming that the websocket session destructor would close the
websocket when it unreffed it but the keepalive process now holds a reference
so the destructor wouldn't actually run without the call to ast_websocket_close
to stop the keepalives.
A few new methods were added to tcptls.c to allow switching an existing
connection from unsecured to TLS. These were required because the initial
connection and handshake with a proxy is always unsecured but then needs
to be switched to TLS if required for the remote WebSocket server.
There was a bug in sorcery.h where the ast_sorcery_register_uint macro
was referencing _stringify (which doesn't exist) instead of _sorcery_stringify.
Resolves: #1881Resolves: #1933
UserNote: Forward/outbound proxies can now be specified for outbound websockets.
See the websocket_client.conf.sample file for configuration information.
UserNote: TCP-level or WebSocket PING/PONG keepalives can now be enabled on
outbound websockets. They can help detect network failures even when a
persistent connection is idle. See the websocket_client.conf.sample
file for configuration information.
DeveloperNote: The addition of the proxy and keepalive configuration parameters
pushed the websocket client parameter count over 32. This necessitated changing
the size of the ast_ws_client_fields enum from a 32 bit bitfield to a 64-bit
bitfield with a corresponding change to the ast_websocket_client structure.
chan_local no longer exists since Local channels are built into the
core (core_local), but there are still comments which reference it,
including in the configs. Update these to avoid confusion.
Resolves: #1849
Under certain timing/load conditions, res_ari_model may not load until after
res_ari on startup or it might unload before res_ari on shutdown. This can
cause a segfault when DEVMODE is enabled and there are persistent outbound
websocket connections because DEVMODE forces validation of outgoing events
against the models. To prevent this, res_ari_model has been added as an
"optional_module" to res_ari's NODULE_INFO. This will enforce load/unload
order but not make res_ari dependent on res_ari_model. However, if
Asterisk is configured with --enable-dev-mode, res_ari will fail to
load if res_ari_model isn't available.
Resolves: #1970
Adds the ability to attach multiple states to both Channels and Bridges in the form
of variables that are included in all events on the associated object.
First, this adds an optional boolean field to channel variables 'report_events'
that causes the variable to automatically be included in all events on that channel.
To allow this, variables can now be either name value pairs (the current format):
`<variable_name>: '<value_string>'`
- or -
`<variable_name>: {value: '<value_string>', report_events: [true|false]}`
If the old format is used or 'report_events' is not included, it will default to
false and retain current behavior.
Second, this extends both reported and unreported variables to Bridges so they too
may have stateful information.
Resolves: #1910
UserNote: Bridge variables now can be set and retrieved via the following paths:
`/bridges/{bridgeId}/variable`
`/bridges/{bridgeId}/variables`
Both Bridge and Channel variables can now be set with an optional 'report_events'
boolean flag that will cause those variables to be included on all events on that
object. The 'report_events' flag will default to False if not set to maintain
backwards capability.
To allow this, variables can now be either name value pairs (the current format):
`<variable_name>: '<value_string>'`
- or -
`<variable_name>: {value: '<value_string>', report_events: [true|false]}`
Two new paths exist for ARI to get and set multiple channel variables at
the same time. This is done via GET and POST like the single get and set
variable equivalents. Leading and trailing whitespace will be stripped
from the variable names for both paths. When setting variables, the
values will be read as-is, whitespace included. GET takes in a single
string with comma-separated values, while POST takes in a dictionary of
key value pairs. The code follows the same paths as when setting
multiple variables when originating a channel via ARI.
UserNote: Added new ARI paths for getting and setting multiple channel
variables at a time. For GET, this takes in a single string of
comma-separated variable names, while POST takes in a dictionary of key
value pairs. The behavior is the same as passing in variables when
originating a channel.
libical 4.0 removed the icaltime_add() function in favor of icaltime_adjust(). Additionally, the callback signature for icalcomponent_foreach_recurrence() was updated to use a const pointer for the icaltime_span argument.
This commit adds conditional compilation using ICAL_MAJOR_VERSION to support both libical 3.X and the new 4.X API, ensuring backward compatibility.
Fixes: #1957
The reference identifier (what the client provides - in this case a
hostname) must start with a domain label, not a `.`.
The current implementation will match `.seanbright.com` against
`*.seanbright.com` which is incorrect.
If the channel is locked when calling ast_set_variables and any of the
variables contained dialplan functions, there's a possiblilty of a deadlock.
To prevent this, either the explicit locks were removed or the call to
ast_set_variables moved out of the lock scope. A warning to not hold
channel locks is also added to the documentation for ast_set_variables.
Resolves: #1936
The original trigger for setting the RTP stats in ast_softhangup() came from
an ARI issue where stats weren't being set in time to be reported on STASIS_END
events. The thought was that setting them in a common place like ast_softhangup()
would ensure the stats were set in possibly other scenarios. Unfortunately,
setting the RTP stats variables in ast_softhangup() broke ABI as it required
that no channel locks be held which was not the case earlier.
Given that the original issue was ARI, we can move setting the stats to
ast_ari_channels_hangup() in resource_channels just before it calls
ast_softhangup(). This might not catch all cases of the stats not being set,
but it won't break ABI or deadlock either.
Resolves: #1928
If a hostname is specified for stunaddr in rtp.conf, periodic DNS resolution
is enabled based on the TTL returned in the DNS results. If the TTL returned
is 0, it means that the next time the IP address is needed, it must be
looked up again. I.E. Don't cache. Historically (and incorrectly) however,
res_rtp_asterisk stopped the periodic resolution and never re-resolved the
hostname again.
Besides what's mentioned in the user notes...
* Additional debugging was added in various STUN/DNS functions.
* The `rtp show settings` CLI command shows more detailed STUN info.
* Some debugging was added to dns_core.c and dns_recurring.c.
UserNote: A new `stunaddr_reresolve_ttl_0` parameter has been added to rtp.conf
that allows control over what happens when a STUN server hostname lookup
returns a TTL of 0. The values can be set as follows:
- 'no': This is the historical (and current default) behavior of not doing
any further lookups and continuing to use the last successful result until
Asterisk is restarted or rtp.conf is reloaded.
- 'yes': Use the last cached result for the current call but trigger
re-resolution in the background for the benefit of future calls.
If the result of the background lookup is a ttl > 0, periodic resolution
will be restarted otherwise the next call will use the new cached value
and will trigger a background lookup again.
UserNote: A new CLI command `rtp resolve stun hostname` has been added
that will force a resolution of the STUN hostname and (re)start periodic
resolution if the result has a TTL > 0.
Resolves: #1858
Rather than merely showing
dtls_verify : Yes/No
in pjsip show endpoint xxx it will now be shown what exactly is being
checked, ie, one of:
dtls_verify : No
dtls_verify : Fingerprint
dtls_verify : Certificate
dtls_verify : Yes
Where Yes implies both Fingerprint and Certificate.
Signed-off-by: Jaco Kroon <jaco@uls.co.za>
When a message is sent via ARI, the ARI endpoint only provides a To
field which is also used as destination field. This means that the To
field might not necessarily contain a SIP URI but might instead specify
an Asterisk endpoint (in MessageDestinationInfo format). This led to
many warnings even though the message was sent correctly.
The fix is to only call `ast_sip_update_to_uri` if the To field starts
with the sip: or sips: scheme.
Resolves: #1357
crypto_utils uses ast_asprintf to allocate the search string when checking the
certificate subject, but was not using ast_free to free it. This caused a crash
when Asterisk was built with malloc_debug
Resolves: #1921
Modified the bridge playback teardown so the worker thread removes only the
playback control, while the after-bridge callback removes the playback
wrapper once the announcer has actually left the bridge.
This avoids a stale window where a new playback request could create a
replacement announcer before the old announcer had fully exited the holding
bridge.
Also replaced the flexible trailing bridge_id storage in the shared worker
thread data with an optional bridge_id pointer, since recording paths use the
same structure without a bridge id.
Fixes: #1861
Add rtp_port_start and rtp_port_end options to PJSIP endpoint
configuration, allowing each endpoint to use a dedicated RTP port
range instead of the global rtp.conf setting.
This is useful for scenarios where different endpoints need isolated
port ranges, such as firewall rules per trunk, multi-tenant systems,
or network QoS policies tied to port ranges.
The implementation adds ast_rtp_instance_new_with_port_range() to the
RTP engine API, which sets the port range on the instance before the
engine allocates the transport. The default RTP engine
(res_rtp_asterisk) checks for per-instance overrides in
rtp_allocate_transport() and falls back to the global range when
none is set.
Both options must be set together, with values >= 1024 and
rtp_port_end > rtp_port_start. Setting both to 0 (the default)
preserves existing behavior.
Resolves: https://github.com/asterisk/asterisk-feature-requests/issues/71
UserNote: PJSIP endpoints now support rtp_port_start and
rtp_port_end options to configure a dedicated RTP port range per
endpoint, overriding the global rtp.conf setting.
UpgradeNote: An alembic database migration has been added to add
the rtp_port_start and rtp_port_end columns to the ps_endpoints
table. Run "alembic upgrade head" to apply the schema change.
DeveloperNote: New public API: ast_rtp_instance_new_with_port_range()
creates an RTP instance with a per-instance port range.
ast_rtp_instance_get_port_start() and ast_rtp_instance_get_port_end()
allow RTP engines to query the override. Third-party RTP engines can
use these getters to support per-instance port ranges.
1. session_cleanup() now saves the websocket type before unlinking the
session from the session registry. This prevents a FRACK when cleaning
up per-call websockets when MALLOC_DEBUG is used.
2. session_shutdown_cb() and outbound_sessions_load() now call
pthread_cancel() to cancel the session handler thread to prevent the
thread from continually trying to connect to a server after the
connection config has been removed by a reload. This required the
thread to use pthread_cleanup_push() to clean up its reference to the
session instead of RAII because RAII destructors don't get run when
pthread_cancel() is used.
Resolves: #1894
cdrel_custom: fix SQLite compatibility for versions < 3.20.0
Replace sqlite3_prepare_v3 + SQLITE_PREPARE_PERSISTENT with a version-guarded fallback to sqlite3_prepare_v2 for older SQLite builds.
Resolves: #1885
Adds two optional modules:
res_stasis_broadcast.so: Infrastructure for broadcasting a single incoming
channel to multiple ARI applications with atomic first-claim-wins semantics.
app_stasis_broadcast.so: Provides the StasisBroadcast() dialplan application
which invokes the broadcast infrastructure.
Both modules are self-contained; if neither is loaded there is zero runtime
impact. Loading them does not alter existing Stasis or ARI behavior unless
explicitly used.
Key Features (only active when modules are loaded):
Fisher-Yates shuffled broadcast dispatch for fair claim races
Atomic claim operations using mutex + condition variable signaling
Configurable broadcast timeouts
Safe regex application filtering with validation to mitigate ReDoS risk
Thread-safe channel variable snapshotting (channel locked during reads)
Late-claim safety: broadcast context kept alive until after the Stasis
session ends so concurrent claimants always receive 409 Conflict rather
than 404 Not Found
Memory safety via RAII_VAR, ast_json_ref/unref, and ao2 reference counting
Components Added:
res/res_stasis_broadcast.c: Core broadcast + claim logic
apps/app_stasis_broadcast.c: StasisBroadcast() dialplan application
include/asterisk/stasis_app_broadcast.h: Public API header
res/ari/resource_events.c: Integrates POST /ari/events/claim endpoint
rest-api/api-docs/events.json: New CallBroadcast and CallClaimed events
Implementation Notes:
Broadcast contexts reside in an ao2 hash container keyed by channel id. Each
context holds atomic claim state, winner application name, timeout metadata,
and a condition variable for waiters. Broadcast contexts are kept alive until
after stasis_app_exec() returns so that concurrent claimants racing against
the timeout always receive 409 Conflict. Broadcast dispatch calls
stasis_app_send() directly for each matching application in shuffled order.
Regex filters are validated with bounded length, group depth, quantified
group count, and alternation limits to reduce pathological backtracking.
Timeout calculation uses timespec arithmetic with overflow-safe millisecond
remainder handling. Event JSON follows existing Stasis/ARI conventions;
references are managed correctly to avoid leaks or double frees.
Optional Nature / Impact:
No changes to existing APIs, events, or applications when absent.
Clean fallback: systems ignoring the modules behave identically to prior
versions.
Development was assisted by Claude (Anthropic). All generated code has been
reviewed, tested, and is understood by the author.
UserNote: New optional modules res_stasis_broadcast.so and
app_stasis_broadcast.so enable broadcasting an incoming channel to multiple
ARI applications. The first application to successfully claim (via
POST /ari/events/claim) wins channel control. StasisBroadcast() dialplan
application initiates broadcasts. CallBroadcast and CallClaimed events notify
applications. When modules are not loaded, behavior is unchanged.
DeveloperNote: New public APIs in stasis_app_broadcast.h:
stasis_app_broadcast_channel(), stasis_app_claim_channel(),
stasis_app_broadcast_winner(), and stasis_app_broadcast_wait(). New ARI event
types (CallBroadcast, CallClaimed) added to events.json. All code is isolated;
no existing ABI modified.
This commit implements the handling of non-voice or DTMF frames like the
chan_websocket handling added in #1588. Rather than treating unsupported
frames as fatal errors, silently ignore CNG frames and log a warning for
other unsupported types.
The rtp_ioqueue_thread_destroy() function was destroying the the ioqueue
thread and releasing its pool but not destroying the ioqueue itself. This
was causing the ioqueue's epoll file descriptor to leak.
Resolves: #1867
Introduces res_pjsip_maintenance, a loadable module that allows
operators to place individual PJSIP endpoints into maintenance mode
at runtime without unregistering or disabling them.
While an endpoint is in maintenance mode:
* New inbound INVITE and SUBSCRIBE dialogs are rejected with
503 Service Unavailable and a Retry-After: 300 header.
* In-progress dialogs (re-INVITE, UPDATE, BYE, etc.) are
unaffected and complete normally.
* Outbound originations via Dial() or ARI originate are refused
before any SIP session is created.
State is held in-memory only and is cleared on module unload
or Asterisk restart.
This module was developed with AI assistance (Claude). All code
has been reviewed and tested by the author, who takes full
responsibility for the submission.
CLI interface:
pjsip set maintenance <on|off> <endpoint|all>
pjsip show maintenance [endpoint]
AMI interface:
Action: PJSIPSetMaintenance
Endpoint: <name>|all
State: on|off
Action: PJSIPShowMaintenance
Endpoint: <name> (optional; omit to list all)
Emits PJSIPMaintenanceStatus events per result, followed by
PJSIPMaintenanceStatusComplete. State changes also emit an
unsolicited PJSIPMaintenanceStatus event.
To support outbound blocking, a new session_create callback is
added to ast_sip_session_supplement. Supplements that set this
callback are invoked at the start of ast_sip_session_create_outgoing()
in res_pjsip_session, before any dialog or invite session resources
are allocated. res_pjsip_maintenance registers itself as a session
supplement and uses this callback to gate outbound session creation
on a per-endpoint basis.
MODULEINFO:
<depend>pjproject</depend>
<depend>res_pjsip</depend>
<depend>res_pjsip_session</depend>
UserNote: New module res_pjsip_maintenance adds runtime maintenance
mode for PJSIP endpoints. Use "pjsip set maintenance <on|off>
<endpoint|all>" to enable or disable, and "pjsip show maintenance"
to list affected endpoints. AMI actions PJSIPSetMaintenance and
PJSIPShowMaintenance provide programmatic access. No configuration
file changes required.
DeveloperNote: ast_sip_session_supplement gains a new optional
callback - int (*session_create)(struct ast_sip_endpoint *endpoint,
const char *destination). It is called from the global supplement
list (not per-session) at the start of ast_sip_session_create_outgoing()
via ast_sip_session_check_supplement_create(). Returning non-zero
blocks the outgoing session. Modules that need to gate outbound
SIP session creation should register a supplement with this callback
set rather than hooking into chan_pjsip directly.
The PJSIP outbound registration API has undocumented behavior when reconfiguring
the outbound registration if the expires value being set is the same as what was
previously set.
In this case PJSIP will remove the Expires header entirely from subsequent
outbound REGISTER requests. To eliminate this as an issue we now check the current
expires value against the configured expires value and only apply it if it differs.
This ensures that outbound REGISTER requests always contain an Expires header.
Resolves: #1859
When res_pjsip is reloaded directly, it does the sorcery reload in a pjsip
servant thread as it's supposed to. res_pjsip_config_wizard however
was not which was leading to occasional deadlocks. It now does the reload
in a servant thread just like res_pjsip.
Resolves: #1855
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
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.
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 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