Compare commits

...

496 Commits
master ... 19.8

Author SHA1 Message Date
Asterisk Development Team e528299031 Update for 19.8.0 2023-01-12 06:44:08 -05:00
Asterisk Development Team b40f0f6fce Update for 19.8.0-rc2 2023-01-05 14:14:42 -05:00
George Joseph 7129752201 res_pjsip_transport_websocket: Add remote port to transport
When Asterisk receives a new websocket conenction, it creates a new
pjsip transport for it and copies connection data into it.  The
transport manager then uses the remote IP address and port on the
transport to create a monitor for each connection.  However, the
remote port wasn't being copied, only the IP address which meant
that the transport manager was creating only 1 monitoring entry for
all websocket connections from the same IP address. Therefore, if
one of those connections failed, it deleted the transport taking
all the the connections from that same IP address with it.

* We now copy the remote port into the created transport and the
  transport manager behaves correctly.

ASTERISK-30369

Change-Id: Ib506d40897ea6286455ac0be4dfbb0ed43b727e1
2023-01-03 06:51:54 -06:00
Asterisk Development Team 1eee96543b Update for 19.8.0-rc1 2022-12-15 07:54:21 -05:00
Asterisk Development Team c4703f070a Update CHANGES and UPGRADE.txt for 19.8.0 2022-12-15 07:39:06 -05:00
Alexandre Fournier c900a7dc39 res_geoloc: fix NULL pointer dereference bug
The `ast_geoloc_datastore_add_eprofile` function does not return 0 on
success, it returns the size of the underlying datastore. This means
that the datastore will be freed and its pointer set to NULL when no
error occured at all.

ASTERISK-30346

Change-Id: Iea9b209bd1244cc57b903b9496cb680c356e4bb9
2022-12-13 10:32:10 -05:00
Ben Ford 1c8f57e298 pjproject: 2.13 security fixes
Backports two security fixes (c4d3498 and 450baca) from pjproject 2.13.

ASTERISK-30338

Change-Id: I86fdc003d5d22cb66e7cc6dc3313a8194f27eb69
2022-12-03 10:26:09 -06:00
George Joseph 69c2459c33 pjsip_transport_events: Fix possible use after free on transport
It was possible for a module that registered for transport monitor
events to pass in a pjsip_transport that had already been freed.
This caused pjsip_transport_events to crash when looking up the
monitor for the transport.  The fix is a two pronged approach.

1. We now increment the reference count on pjsip_transports when we
create monitors for them, then decrement the count when the
transport is going to be destroyed.

2. There are now APIs to register and unregister monitor callbacks
by "transport key" which is a string concatenation of the remote ip
address and port.  This way the module needing to monitor the
transport doesn't have to hold on to the transport object itself to
unregister.  It just has to save the transport_key.

* Added the pjsip_transport reference increment and decrement.

* Changed the internal transport monitor container key from the
  transport->obj_name (which may not be unique anyway) to the
  transport_key.

* Added a helper macro AST_SIP_MAKE_REMOTE_IPADDR_PORT_STR() that
  fills a buffer with the transport_key using a passed-in
  pjsip_transport.

* Added the following functions:
  ast_sip_transport_monitor_register_key
  ast_sip_transport_monitor_register_replace_key
  ast_sip_transport_monitor_unregister_key
  and marked their non-key counterparts as deprecated.

* Updated res_pjsip_pubsub and res_pjsip_outbound_register to use
  the new "key" monitor functions.

NOTE: res_pjsip_registrar also uses the transport monitor
functionality but doesn't have a persistent object other than
contact to store a transport key.  At this time, it continues to
use the non-key monitor functions.

ASTERISK-30244

Change-Id: I1a20baf2a8643c272dcf819871d6c395f148f00b
2022-12-03 10:24:14 -06:00
Mike Bradeen 764ca33473 manager: prevent file access outside of config dir
Add live_dangerously flag to manager and use this flag to
determine if a configuation file outside of AST_CONFIG_DIR
should be read.

ASTERISK-30176

Change-Id: I46b26af4047433b49ae5c8a85cb8cda806a07404
2022-12-03 10:22:29 -06:00
Mike Bradeen 42ecf402a3 ooh323c: not checking for IE minimum length
When decoding q.931 encoded calling/called number
now checking for length being less than minimum required.

ASTERISK-30103

Change-Id: I3dcfce0f35eca258dc450f87c92d4d7af402c2e7
2022-12-01 11:02:53 -06:00
Naveen Albert e553546eff tcptls: Prevent crash when freeing OpenSSL errors.
write_openssl_error_to_log has been erroneously
using ast_free instead of free, which will
cause a crash when MALLOC_DEBUG is enabled since
the memory was not allocated by Asterisk's memory
manager. This changes it to use the actual free
function directly to avoid this.

ASTERISK-30278 #close

Change-Id: Iac8b6468b718075809c45d8ad16b101af21a474d
2022-11-01 06:31:40 -05:00
Mike Bradeen d7dae7b1fc res_pjsip: prevent crash on websocket disconnect
When a websocket (or potentially any stateful connection) is quickly
created then destroyed, it is possible that the qualify thread will
destroy the transaction before the initialzing thread is finished
with it.

Depending on the timing, this can cause an assertion within pjsip.

To prevent this, ast_send_stateful_response will now create the group
lock and add a reference to it before creating the transaction.

While this should resolve the crash, there is still the potential that
the contact will not be cleaned up properly, see:ASTERISK~29286. As a
result, the contact has to 'time out' before it will be removed.

ASTERISK-28689

Change-Id: Id050fded2247a04d8f0fc5b8a2cf3e5482cb8cee
2022-10-31 10:09:24 -05:00
Igor Goncharovsky 09af7e0aca res_pjsip_outbound_registration: Allow to use multiple proxies for registration
Current registration code use pjsip_parse_uri to verify outbound_proxy
that is different from the reading this option for the endpoint. This
made value with multiple proxies invalid for registration pjsip settings.
Removing URI validation helps to use registration through multiple proxies.

ASTERISK-30217 #close

Change-Id: I064558e66f04b9f3260c46181812a01349761357
2022-10-28 11:38:05 -05:00
Naveen Albert 025dbcfd68 tests: Fix compilation errors on 32-bit.
Fix compilation errors caused by using size_t
instead of uintmax_t and non-portable format
specifiers.

ASTERISK-30273 #close

Change-Id: I363e6057ef84d54b88af80d23ad6147eef9216ee
2022-10-27 14:29:40 -05:00
Henning Westerholt a6aebab79b res_pjsip: return all codecs on a re-INVITE without SDP
Currently chan_pjsip on receiving a re-INVITE without SDP will only
return the codecs that are previously negotiated and not offering
all enabled codecs.

This causes interoperability issues with different equipment (e.g.
from Cisco) for some of our customers and probably also in other
scenarios involving 3PCC infrastructure.

According to RFC 3261, section 14.2 we SHOULD return all codecs
on a re-INVITE without SDP

The PR proposes a new parameter to configure this behaviour:
all_codecs_on_empty_reinvite. It includes the code, documentation,
alembic migrations, CHANGES file and example configuration additions.

ASTERISK-30193 #close

Change-Id: I69763708d5039d512f391e296ee8a4d43a1e2148
2022-10-27 11:22:13 -05:00
Naveen Albert 05a7b4132a res_pjsip_logger: Add method-based logging option.
Expands the pjsip logger to support the ability to filter
by SIP message method. This can make certain types of SIP debugging
easier by only logging messages of particular method(s).

ASTERISK-30146 #close

Co-authored-by: Sean Bright <sean@seanbright.com>
Change-Id: I9c8cbb6fc8686ef21190eb42e08bc9a9b147707f
2022-10-27 10:08:12 -05:00
Naveen Albert a0dd8c27b5 res_pjsip_notify: Add option support for AMI.
The PJSIP notify CLI commands allow for using
"options" configured in pjsip_notify.conf.

This allows these same options to be used in
AMI actions as well.

Additionally, as part of this improvement,
some repetitive common code is refactored.

ASTERISK-30263 #close

Change-Id: Ie4496b322b63b61eaf9672183a959ab99a04b6b5
2022-10-27 07:42:01 -05:00
Frederic LE FOLL 83498bec35 Dialing API: Cancel a running async thread, may not cancel all calls
race condition: ast_dial_join() may not cancel outgoing call, if
function is called just after called party answer and before
application execution (bit is_running_app not yet set).

This fix adds ast_softhangup() calls in addition to existing
pthread_kill() when is_running_app is not set.

ASTERISK-30258

Change-Id: Idbdd5c15122159661aa8e996a42d5800083131e4
2022-10-26 11:21:33 -05:00
Naveen Albert 3bae133afa chan_dahdi: Fix unavailable channels returning busy.
This fixes dahdi_request to properly set the cause
code to CONGESTION instead of BUSY if no channels
were actually available.

Currently, the cause is erroneously set to busy
if the channel itself is found, regardless of its
current state. However, if the channel is not available
(e.g. T1 down, card not operable, etc.), then the
channel itself may not be in a functional state,
in which case CHANUNAVAIL is the correct cause to use.

This adds a simple check to ensure that busy tone
is only returned if a channel is encountered that
has an owner, since that is the only possible way
that a channel could actually be busy.

ASTERISK-30274 #close

Change-Id: Iad5870223c081240c925b19df8d6af136953b994
2022-10-26 11:14:50 -05:00
Naveen Albert 8bea5052db res_pjsip_pubsub: Prevent removing subscriptions.
pjproject does not provide any mechanism of removing
event packages, which means that once a subscription
handler is registered, it is effectively permanent.

pjproject will assert if the same event package is
ever registered again, so currently unloading and
loading any Asterisk modules that use subscriptions
will cause a crash that is beyond our control.

For that reason, we now prevent users from being
able to unload these modules, to prevent them
from ever being loaded twice.

ASTERISK-30264 #close

Change-Id: I7fdcb1a5e44d38b7ba10c44259fe98f0ae9bc12c
2022-10-26 09:07:41 -05:00
Naveen Albert 57b1f5a7c3 say: Don't prepend ampersand erroneously.
Some logic in say.c for determining if we need
to also add an ampersand for file seperation was faulty,
as non-successful files would increment the count, causing
a leading ampersand to be added improperly.

This is fixed, and a unit test that captures this regression
is also added.

ASTERISK-30248 #close

Change-Id: I02c1d3a11d82fe4ea8b462070cbd1effb5834d2b
2022-10-26 07:48:10 -05:00
Philip Prindeville 23a4135fe7 res_crypto: handle unsafe private key files
ASTERISK-30213 #close

Change-Id: I4a77143d41615b7c4fc25bb1251c0a9cb87b417a
2022-10-14 10:00:53 -05:00
Mike Bradeen f61dbd566b audiohook: add directional awareness
Add enum to allow setting optional direction. If set to only one
direction, only feed matching-direction frames to the associated
slin factory.

This prevents mangling the transcoder on non-mixed frames when the
READ and WRITE frames would have otherwise required it.  Also
removes the need to mute or discard the un-wanted frames as they
are no longer added in the first place.

res_stasis_snoop is changed to use this addition to set direction
on audiohook based on spy direction.

If no direction is set, the ast_audiohook_init will init this enum
to BOTH which maintains existing functionality.

ASTERISK-30252

Change-Id: If8716bad334562a5d812be4eeb2a92e4f3be28eb
2022-10-11 08:13:03 -05:00
Naveen Albert b397dc3ca3 cdr: Allow bridging and dial state changes to be ignored.
Allows bridging, parking, and dial messages to be globally
ignored for all CDRs such that only a single CDR record
is generated per channel.

This is useful when CDRs should endure for the lifetime of
an entire channel and bridging and dial updates in the
dialplan should not result in multiple CDR records being
created for the call. With the ignore bridging option,
bridging changes have no impact on the channel's CDRs.
With the ignore dial state option, multiple Dials and their
outcomes have no impact on the channel's CDRs. The
last disposition on the channel is preserved in the CDR,
so the actual disposition of the call remains available.

These two options can reduce the amount of "CDR hacks" that
have hitherto been necessary to ensure that CDR was not
"spoiled" by these messages if that was undesired, such as
putting a dummy optimization-disabled local channel between
the caller and the actual call and putting the CDR on the channel
in the middle to ensure that CDR would persist for the entire
call and properly record start, answer, and end times.
Enabling these options is desirable when calls correspond
to the entire lifetime of channels and the CDR should
reflect that.

Current default behavior remains unchanged.

ASTERISK-30091 #close

Change-Id: I393981af42732ec5ac3ff9266444abb453b7c832
2022-10-10 12:07:10 -05:00
Naveen Albert f9297117d9 res_tonedetect: Add ringback support to TONE_DETECT.
Adds support for detecting audible ringback tone
to the TONE_DETECT function using the p option.

ASTERISK-30254 #close

Change-Id: Ie2329ff245248768367d26749c285fbe823f6414
2022-10-10 12:04:39 -05:00
Naveen Albert 11d97dc5ca chan_dahdi: Resolve format truncation warning.
Fixes a format truncation warning in notify_message.

ASTERISK-30256 #close

Change-Id: I983a423c0214641ca4f8c9dfe0b19c47448fdee1
2022-10-10 12:01:01 -05:00
Philip Prindeville 44684fdd51 res_crypto: don't modify fname in try_load_key()
"fname" is passed in as a const char *, but strstr() mangles that
into a char *, and we were attempting to modify the string in place.
This is an unwanted (and undocumented) side-effect.

ASTERISK-30213

Change-Id: Ifa36d352aafeb7f9beec3f746332865c7d21e629
2022-10-10 10:13:26 -05:00
Philip Prindeville 109c2335ef res_crypto: use ast_file_read_dirs() to iterate
ASTERISK-30213

Change-Id: I115f5f8942ffcfb23cd2559a55bac8a2eba081e0
2022-10-10 10:10:48 -05:00
George Joseph 54cafbc67f res_geolocation: Update wiki documentation
Also added a note to the geolocation.conf.sample file
and added a README to the res/res_geolocation/wiki
directory.

Change-Id: I89c3c5db8c0701b33127993622d5e4f904bddfbc
2022-10-10 07:31:34 -05:00
Maximilian Fridrich 6170073800 res_pjsip: Add mediasec capabilities.
This patch adds support for mediasec SIP headers and SDP attributes.
These are defined in RFC 3329, 3GPP TS 24.229 and
draft-dawes-sipcore-mediasec-parameter. The new features are
implemented so that a backbone for RFC 3329 is present to streamline
future work on RFC 3329.

With this patch, Asterisk can communicate with Deutsche Telekom trunks
which require these fields.

ASTERISK-30032

Change-Id: Ia7f5b5ba42db18074fdd5428c4e1838728586be2
2022-09-29 04:10:26 -05:00
Asterisk Development Team 2209afddb9 Update CHANGES and UPGRADE.txt for 19.7.0 2022-09-28 07:41:13 -05:00
George Joseph 95a25fddac manager.h: Bump version to 8.0.2
Change-Id: I99c16241f74a909c792cec3c722a3142a1892197
2022-09-28 05:58:57 -06:00
Holger Hans Peter Freyther 02be2a5f1a res_prometheus: Do not crash on invisible bridges
Avoid crashing by skipping invisible bridges and checking the
snapshot for a null pointer. In effect this is how the bridges
are enumerated in res/ari/resource_bridges.c already.

ASTERISK-30239
ASTERISK-30237

Change-Id: I58ef9f44036feded5966b5fc70ae754f8182883d
2022-09-27 06:16:23 -05:00
Naveen Albert aefb9fc216 db: Fix incorrect DB tree count for AMI.
The DBGetTree AMI action's ListItem previously
always reported 1, regardless of the count. This
is corrected to report the actual count.

ASTERISK-30245 #close
patches:
  gettreecount.diff submitted by Birger Harzenetter (license 5870)

Change-Id: I46d8992710f1b8524426b1255f57d1ef4a4934d4
2022-09-26 17:19:27 -05:00
Naveen Albert 0a0b141278 res_pjsip_geolocation: Change some notices to debugs.
If geolocation is not in use for an endpoint, the NOTICE
log level is currently spammed with messages about this,
even though nothing is wrong and these messages provide
no real value. These log messages are therefore changed
to debugs.

ASTERISK-30241 #close

Change-Id: I656b355d812f67cc0f0fdf09b00b0e1458598bb4
2022-09-26 17:18:00 -05:00
Naveen Albert 9ba789d297 func_logic: Don't emit warning if both IF branches are empty.
The IF function currently emits warnings if both IF branches
are empty. However, there is no actual necessity that either
branch be non-empty as, unlike other conditional applications/
functions, nothing is inherently done with IF, and both
sides could legitimately be empty. The warning is thus turned
into a debug message.

ASTERISK-30243 #close

Change-Id: I5250625dd720f95e1859b5dfb933905d7e7a730e
2022-09-26 12:33:02 -05:00
Naveen Albert 231f99b397 features: Add no answer option to Bridge.
Adds the n "no answer" option to the Bridge application
so that answer supervision can not automatically
be provided when Bridge is executed.

Additionally, a mechanism (dialplan variable)
is added to prevent bridge targets (typically the
target of a masquerade) from answering the channel
when they enter the bridge.

ASTERISK-30223 #close

Change-Id: I76f73fcd8e403bcd18f2abb40c658f537ac1ba6d
2022-09-26 11:44:24 -05:00
Naveen Albert 999b162786 app_bridgewait: Add option to not answer channel.
Adds the n option to not answer the channel when calling
BridgeWait, so the application can be used without
forcing answer supervision.

ASTERISK-30216 #close

Change-Id: I6b85ef300b1f7b5170f8537e2b10889cc2e6605a
2022-09-26 10:39:28 -05:00
Naveen Albert fd5683f74b app_amd: Add option to play audio during AMD.
Adds an option that will play an audio file
to the party while AMD is running on the
channel, so the called party does not just
hear silence.

ASTERISK-30179 #close

Change-Id: I4af306274552b61b3d9f0883c33f698abd4699b6
2022-09-26 09:42:37 -05:00
Philip Prindeville 1d6e7c6843 test: initialize capture structure before freeing
ASTERISK-30232 #close

Change-Id: I2603e2cef8f93f6b0a6ef39f7eac744251bb3902
2022-09-26 08:55:33 -05:00
Naveen Albert 5199a70c07 func_export: Add EXPORT function
Adds the EXPORT function, which allows write
access to variables and functions on other
channels.

ASTERISK-29432 #close

Change-Id: I7492645ae4307553d0f586d78e13a4f586231fdf
2022-09-26 07:52:19 -05:00
Maximilian Fridrich 2efcb5890e res_pjsip: Add 100rel option "peer_supported".
This patch adds a new option to the 100rel parameter for pjsip
endpoints called "peer_supported". When an endpoint with this option
receives an incoming request and the request indicated support for the
100rel extension, then Asterisk will send 1xx responses reliably. If
the request did not indicate 100rel support, Asterisk sends 1xx
responses normally.

ASTERISK-30158

Change-Id: Id6d95ffa8f00dab118e0b386146e99f254f287ad
2022-09-22 12:21:05 -05:00
Jaco Kroon ef20afda63 manager: be more aggressive about purging http sessions.
If we find that n_max (currently hard wired to 1) sessions were purged,
schedule the next purge for 1ms into the future rather than 5000ms (as
per current).  This way we will purge up to 1000 sessions per second
rather than 1 every 5 seconds.

This mitigates a build-up of sessions should http sessions gets
established faster than 1 per 5 seconds.

Change-Id: I9820d39aa080109df44fe98c1325cafae48d54f5
Signed-off-by: Jaco Kroon <jaco@uls.co.za>
2022-09-22 11:26:59 -05:00
Naveen Albert 086b1abf66 func_scramble: Fix null pointer dereference.
Fix segfault due to null pointer dereference
inside the audiohook callback.

ASTERISK-30220 #close

Change-Id: Ideb80f606974366e89d619d908744230b5a5a259
2022-09-22 11:26:00 -05:00
Naveen Albert 0bf6d7af33 func_strings: Add trim functions.
Adds TRIM, LTRIM, and RTRIM, which can be used
for trimming leading and trailing whitespace
from strings.

ASTERISK-30222 #close

Change-Id: I50fb0c40726d044a7a41939fa9026f3da4872554
2022-09-22 05:48:54 -05:00
George Joseph f09b9e6678 res_crypto: Memory issues and uninitialized variable errors
ASTERISK-30235

Change-Id: Ia1e326e7b52cd06fd5e6c9009e3e63193c92f6cd
2022-09-19 05:32:24 -06:00
George Joseph c2a343b8c9 res_geolocation: Fix issues exposed by compiling with -O2
Fixed "may be used uninitialized" errors in geoloc_config.c.

ASTERISK-30234

Change-Id: I1ea336bf7abbc16fa59b75720f0db8f1d960b3d4
2022-09-16 08:42:21 -06:00
Philip Prindeville 70489083b1 res_crypto: don't complain about directories
ASTERISK-30226 #close

Change-Id: I5695fb0c9521f112f754b8362cff2a8f3eff05c5
2022-09-14 23:15:13 -06:00
Asterisk Development Team 6d8d367722 Update CHANGES and UPGRADE.txt for 19.7.0 2022-09-14 09:14:10 -05:00
Mike Bradeen 9227fb4d52 res_pjsip: Add user=phone on From and PAID for usereqphone=yes
Adding user=phone to local-side uri's when user_eq_phone=yes is set for
an endpoint. Previously this would only add the header to the To and R-URI.

ASTERISK-30178

Change-Id: Id3bfb5d225d762e7d2668c023fe09e4541ae8600
2022-09-14 07:20:17 -05:00
George Joseph 7beedd85e1 res_geolocation: Fix segfault when there's an empty element
Fixed a segfault caused by var_list_from_loc_info() encountering
an empty location info element.

Fixed an issue in ast_strsep() where a value with only whitespace
wasn't being preserved.

Fixed an issue in ast_variable_list_from_quoted_string() where
an empty value was considered a failure.

ASTERISK-30215
Reported by: Dan Cropp

Change-Id: Ieca64e061a6d9298f0196c694b60d986ef82613a
2022-09-13 09:51:11 -05:00
sungtae kim bdf8ef8882 res_musiconhold: Add option to not play music on hold on unanswered channels
This change adds an option, answeredonly, that will prevent music on
hold on channels that are not answered.

ASTERISK-30135

Change-Id: I1ab0defa43a29a26ae39f94c623596cf90fddc08
2022-09-13 05:47:35 -05:00
Ben Ford 94731d815a res_pjsip: Add TEL URI support for basic calls.
This change allows TEL URI requests to come through for basic calls. The
allowed requests are INVITE, ACK, BYE, and CANCEL. The From and To
headers will now allow TEL URIs, as well as the request URI.

Support is only for TEL URIs present in traffic from a remote party.
Asterisk does not generate any TEL URIs on its own.

ASTERISK-26894

Change-Id: If5729e6cd583be7acf666373bf9f1b9d653ec29a
2022-09-13 04:51:46 -05:00
Philip Prindeville a5fb810f5f res_crypto: Use EVP API's instead of legacy API's
ASTERISK-30046 #close

Change-Id: I5c738756de75fd27ebad54be144c0ac6193f21b2
2022-09-12 16:19:28 -05:00
Philip Prindeville 63e7832f26 test: Add coverage for res_crypto
We're validating the following functionality:

encrypting a block of data with RSA
decrypting a block of data with RSA
signing a block of data with RSA
verifying a signature with RSA
encrypting a block of data with AES-ECB
encrypting a block of data with AES-ECB

as well as accessing test keys from the keystore.

ASTERISK-30045 #close

Change-Id: I0d10e7b41009c5290a4356c6480e636712d5c96d
2022-09-12 14:57:52 -05:00
Philip Prindeville 6f7280a4ca res_crypto: make keys reloadable on demand for testing
ASTERISK-30045

Change-Id: If59bbb50c1771084bfe2fef307a6077c90d35ce8
2022-09-12 13:09:03 -05:00
Philip Prindeville a11495affd test: Add test coverage for capture child process output
ASTERISK-30037 #close

Change-Id: I0273e85eeeb6b8e46703f24cd74d84f3daf0a69a
2022-09-12 11:23:20 -05:00
Philip Prindeville b89130c184 main/utils: allow checking for command in $PATH
ASTERISK-30037

Change-Id: I4b6f7264c8c737c476c798d2352f3232b263bbdf
2022-09-12 09:49:38 -05:00
Philip Prindeville 55328b1e5c test: Add ability to capture child process output
ASTERISK-30037

Change-Id: Icbf84ce05addb197a458361c35d784e460d8d6c2
2022-09-12 08:15:40 -05:00
Philip Prindeville 81bcceca5a res_crypto: Don't load non-regular files in keys directory
ASTERISK-30046

Change-Id: Ie77e0648f8b0b1c2159fb24662d1989cfd4cc36d
2022-09-12 07:55:38 -05:00
Naveen Albert 62264edde2 func_frame_trace: Remove bogus assertion.
The FRAME_TRACE function currently asserts if it sees
a MASQUERADE_NOTIFY. However, this is a legitimate thing
that can happen so asserting is inappropriate, as there
are no clear negative ramifications of such a thing. This
is adjusted to be like the other frames to print out
the subclass.

ASTERISK-30210 #close

Change-Id: I8ecbdcf17e35f64bdeab42868471f581ad1d1a56
2022-09-11 18:04:49 -05:00
Naveen Albert 1456dc757b lock.c: Add AMI event for deadlocks.
Adds an AMI event to indicate that a deadlock
has likely started, when Asterisk is compiled
with DETECT_DEADLOCKS enabled. This can make
it easier to perform automated deadlock detection
and take appropriate action (such as doing a core
dump). Unlike the deadlock warnings, the AMI event
is emitted only once per deadlock.

ASTERISK-30161 #close

Change-Id: Ifc6ed3e390f8b4cff7f8077a50e4d7a5b54e42fb
2022-09-11 18:01:56 -05:00
Naveen Albert f4ea243e49 app_confbridge: Add end_marked_any option.
Adds the end_marked_any option, which can be used
to kick a user from a conference if any marked user
leaves.

ASTERISK-30211 #close

Change-Id: I9e8da7ccb892e522546c0f2b5476d172e022c2f5
2022-09-11 16:22:16 -05:00
George Joseph e8220afbd8 res_geolocation: Add two new options to GEOLOC_PROFILE
Added an 'a' option to the GEOLOC_PROFILE function to allow
variable lists like location_info_refinement to be appended
to instead of replacing the entire list.

Added an 'r' option to the GEOLOC_PROFILE function to resolve all
variables before a read operation and after a Set operation.

Added a few missing parameters to the ones allowed for writing
with GEOLOC_PROFILE.

Fixed a bug where calling GEOLOC_PROFILE to read a parameter
might actually update the profile object.

Cleaned up XML documentation a bit.

ASTERISK-30190

Change-Id: I75f541db43345509a2e86225bfa4cf8e242e5b6c
2022-09-10 12:53:49 -05:00
George Joseph a9c6f4bd54 res_geolocation: Allow location parameters on the profile object
You can now specify the location object's format, location_info,
method, location_source and confidence parameters directly on
a profile object for simple scenarios where the location
information isn't common with any other profiles.  This is
mutually exclusive with setting location_reference on the
profile.

Updated appdocsxml.dtd to allow xi:include in a configObject
element.  This makes it easier to link to complete configOptions
in another object.  This is used to add the above fields to the
profile object without having to maintain the option descriptions
in two places.

ASTERISK-30185

Change-Id: Ifd5f05be0a76f0a6ad49fa28d17c394027677569
2022-09-10 12:49:56 -05:00
George Joseph 833b9319a4 res_geolocation: Add profile parameter suppress_empty_ca_elements
Added profile parameter "suppress_empty_ca_elements" that
will cause Civic Address elements that are empty to be
suppressed from the outgoing PIDF-LO document.

Fixed a possible SEGV if a sub-parameter value didn't have a
value.

ASTERISK-30177

Change-Id: I924ccc5aa2f45110a3155b22e53dfaf3ef2092dd
2022-09-10 11:08:01 -05:00
George Joseph a8997a6896 res_geolocation: Add built-in profiles
The trigger to perform outgoing geolocation processing is the
presence of a geoloc_outgoing_call_profile on an endpoint. This
is intentional so as to not leak location information to
destinations that shouldn't receive it.   In a totally dynamic
configuration scenario however, there may not be any profiles
defined in geolocation.conf.  This makes it impossible to do
outgoing processing without defining a "dummy" profile in the
config file.

This commit adds 4 built-in profiles:
  "<prefer_config>"
  "<discard_config>"
  "<prefer_incoming>"
  "<discard_incoming>"
The profiles are empty except for having their precedence
set and can be set on an endpoint to allow processing without
entries in geolocation.conf.  "<discard_config>" is actually the
best one to use in this situation.

ASTERISK-30182

Change-Id: I1819ccfa404ce59802a3a07ad1cabed60fb9480a
2022-09-10 11:04:38 -05:00
Joshua C. Colp 273dd16c3c res_pjsip_sdp_rtp: Skip formats without SDP details.
When producing an outgoing SDP we iterate through the configured
formats and produce SDP information. It is possible for some
configured formats to not have SDP information available. If this
is the case we skip over them to allow the SDP to still be
produced.

ASTERISK-29185

Change-Id: I3e37569aa4ca341260e6ca5904dc2f75e46a1749
2022-09-10 11:00:04 -05:00
Naveen Albert 116ec0b9bb cli: Prevent assertions on startup from bad ao2 refs.
If "core show channels" is run before startup has completed, it
is possible for bad ao2 refs to occur because the system is not
yet fully initialized. This will lead to an assertion failing.

To prevent this, initialization of CLI builtins is moved to be
later along in the main load sequence. Core CLI commands are
loaded at the same time, but channel-related commands are loaded
later on.

ASTERISK-29846 #close

Change-Id: If6b3cde802876bd738c1b4cf2683bea6ddc615b6
2022-09-09 20:41:23 -05:00
Joshua C. Colp 03bda8845c pjsip: Add TLS transport reload support for certificate and key.
This change adds support using the pjsip_tls_transport_restart
function for reloading the TLS certificate and key, if the filenames
remain unchanged. This is useful for Let's Encrypt and other
situations. Note that no restart of the transport will occur if
the certificate and key remain unchanged.

ASTERISK-30186

Change-Id: I9bc95a6bf791830a9491ad9fa43c17d4010028d0
2022-09-09 18:40:58 -05:00
Naveen Albert 5f712c0060 res_tonedetect: Fix typos referring to wrong variables.
Fixes two typos that cause fax detection to not work.
One refers to the wrong frame variable, and the other
refers to the subclass.integer instead of the frametype
as it should.

ASTERISK-30192 #close

Change-Id: I7b35fdb7bcf25a29a212eee37c20812c64ab3ef1
2022-09-09 13:31:25 -05:00
Mike Bradeen b6c953dcf7 alembic: add missing ps_endpoints columns
The following required columns were missing,
now added to the ps_endpoints table:

incoming_call_offer_pref
outgoing_call_offer_pref
stir_shaken_profile

ASTERISK-29453

Change-Id: I5cf565edf30195844d6acbc1e1de8c5f0d837568
2022-09-09 11:34:42 -05:00
Sean Bright ddc6d1f796 chan_dahdi.c: Resolve a format-truncation build warning.
With gcc (Ubuntu 11.2.0-19ubuntu1) 11.2.0:

> chan_dahdi.c:4129:18: error: ‘%s’ directive output may be truncated
>   writing up to 255 bytes into a region of size between 242 and 252
>   [-Werror=format-truncation=]

This removes the error-prone sizeof(...) calculations in favor of just
doubling the size of the base buffer.

Change-Id: I2d276785286730d3d5d0a921bcea2e065dbf27c5
2022-09-09 09:39:06 -05:00
Alexei Gradinari 9eadb789d5 res_pjsip_pubsub: Postpone destruction of old subscriptions on RLS update
Set termination state to old subscriptions to prevent queueing and sending
NOTIFY messages on exten/device state changes.

Postpone destruction of old subscriptions until all already queued tasks
that may be using old subscriptions have completed.

ASTERISK-29906

Change-Id: I96582aad3a26515ca73a8460ee6756f56f6ba23b
2022-09-09 08:36:00 -05:00
Sean Bright 217766b706 channel.h: Remove redundant declaration.
The DECLARE_STRINGFIELD_SETTERS_FOR() declares ast_channel_name_set()
for us, so no need to declare it separately.

Change-Id: I4813a884ada475ddc62bca480bceb4a53b3ec59a
2022-09-09 05:59:36 -05:00
Naveen Albert a5d5c3a92c features: Add transfer initiation options.
Adds additional control options over the transfer
feature functionality to give users more control
in how the transfer feature sounds and works.

First, the "transfer" sound that plays when a transfer is
initiated can now be customized by the user in
features.conf, just as with the other transfer sounds.

Secondly, the user can now specify the transfer extension
in advance by using the TRANSFER_EXTEN variable. If
a valid extension is contained in this variable, the call
will automatically be transferred to this destination.
Otherwise, it will fall back to collecting the extension
from the user as is always done now.

ASTERISK-29899 #close

Change-Id: Ibff309caa459a2b958706f2ed0ca393b1ef502e3
2022-09-08 12:44:06 -05:00
Mike Bradeen 1390a247a6 CI: Fixing path issue on venv check
ASTERISK-26826

Change-Id: I07388d16f74452cebc9c981f99044eb6b77df792
2022-08-31 15:56:26 -05:00
Mike Bradeen f22516a4ac CI: use Python3 virtual environment
Requires Python3 testsuite changes

ASTERISK-26826

Change-Id: I92ec7dec751ad455503a584d6e860db88c56d6bc
2022-08-30 11:40:45 -05:00
Naveen Albert 409cc1f36e general: Very minor coding guideline fixes.
Fixes a few coding guideline violations:
* Use of C99 comments
* Opening brace on same line as function prototype

ASTERISK-30163 #close

Change-Id: I07771c4c89facd41ce8d323859f022ddbddf6ca7
2022-08-17 11:05:14 -05:00
Asterisk Development Team c40b0134ce Update CHANGES and UPGRADE.txt for 19.6.0 2022-08-11 10:52:26 -05:00
George Joseph 4846dd5d18 res_geolocation: Address user issues, remove complexity, plug leaks
* Added processing for the 'confidence' element.
* Added documentation to some APIs.
* removed a lot of complex code related to the very-off-nominal
  case of needing to process multiple location info sources.
* Create a new 'ast_geoloc_eprofile_to_pidf' API that just takes
  one eprofile instead of a datastore of multiples.
* Plugged a huge leak in XML processing that arose from
  insufficient documentation by the libxml/libxslt authors.
* Refactored stylesheets to be more efficient.
* Renamed 'profile_action' to 'profile_precedence' to better
  reflect it's purpose.
* Added the config option for 'allow_routing_use' which
  sets the value of the 'Geolocation-Routing' header.
* Removed the GeolocProfileCreate and GeolocProfileDelete
  dialplan apps.
* Changed the GEOLOC_PROFILE dialplan function as follows:
  * Removed the 'profile' argument.
  * Automatically create a profile if it doesn't exist.
  * Delete a profile if 'inheritable' is set to no.
* Fixed various bugs and leaks
* Updated Asterisk WiKi documentation.

ASTERISK-30167

Change-Id: If38c23f26228e96165be161c2f5e849cb8e16fa0
2022-08-10 12:49:36 -05:00
Naveen Albert bb7ffce381 chan_iax2: Add missing options documentation.
Adds missing dial resource option documentation.

ASTERISK-30164 #close

Change-Id: I674e1fc9b1e5d67a20599bd4b418ce294d48fc83
2022-08-10 08:39:55 -05:00
Naveen Albert ba5febd14c app_confbridge: Fix memory leak on updated menu options.
If the CONFBRIDGE function is used to dynamically set
menu options, a memory leak occurs when a menu option
that has been set is overridden, since the menu entry
is not destroyed before being freed. This ensures that
it is.

Additionally, logic that duplicates the destroy function
is removed in lieu of the destroy function itself.

ASTERISK-28422 #close

Change-Id: I71cfb5c24e636984d41086d1333a416dc12ff995
2022-08-08 05:20:06 -05:00
George Joseph df4ba41731 Geolocation: Wiki Documentation
Change-Id: I68ba22db0a69d9e2eabcc2141b48a2395f7f1a23
2022-08-05 10:02:13 -05:00
Naveen Albert d09ccb17ce manager: Remove documentation for nonexistent action.
The manager XML documentation documents a "FilterList"
action, but there is no such action. Therefore, this can
lead to confusion when people try to use a documented
action that does not, in fact, exist. This is removed
as the action never did exist in the past, nor would it
be trivial to add since we only store the regex_t
objects, so the filter list can't actually be provided
without storing that separately. Most likely, the
documentation was originally added (around version 10)
in anticipation of something that never happened.

ASTERISK-29917 #close

Change-Id: I846b16fd6f80a91d4ddc5d8a861b522d7c6f8f97
2022-08-02 09:26:21 -05:00
Naveen Albert eccc4593b0 app_confbridge: Add missing AMI documentation.
Documents the ConfbridgeListRooms AMI response,
which is currently not documented.

ASTERISK-30020 #close

Change-Id: Id6fff7a936244bae7b52686301eb740c1169cdea
2022-08-01 11:06:10 -05:00
Naveen Albert 890cbf4293 general: Improve logging levels of some log messages.
Adjusts some logging levels to be more or less important,
that is more prominent when actual problems occur and less
prominent for less noteworthy things.

ASTERISK-30153 #close

Change-Id: Ifc8f7df427aa018627db462125ae744986d3261b
2022-08-01 11:04:02 -05:00
Naveen Albert 865582f582 cdr.conf: Remove obsolete app_mysql reference.
The CDR sample config still mentions that app_mysql
is available in the addons directory, but this is
incorrect as it was removed as of 19. This removes
that to avoid confusion.

ASTERISK-30160 #close

Change-Id: Ie5293ccb4f2b365896981811b480544e67bb9cd7
2022-08-01 09:57:20 -05:00
Naveen Albert 9be41593f0 general: Remove obsolete SVN references.
There are a handful of files in the tree that
reference an SVN link for the coding guidelines.

This removes these because the links are dead
and the vast majority of source files do not
contain these links, so this is more consistent.

app_skel still maintains an (up to date) link
to the coding guidelines.

ASTERISK-30159 #close

Change-Id: I35bbb20f66982e98099cff3029ede20091ffdac7
2022-08-01 09:11:48 -05:00
Naveen Albert eb316354a9 app_meetme: Add missing AMI documentation.
The MeetmeList and MeetmeListRooms AMI
responses are currently completely undocumented.
This adds documentation for these responses.

ASTERISK-30018 #close

Change-Id: Id93135b7edf01de6f8fba266e2122989dc8996b8
2022-08-01 07:07:13 -05:00
Naveen Albert 419932691b func_srv: Document field parameter.
Adds missing documentation for the field parameter
for the SRVRESULT function.

ASTERISK-30151
Reported by: Chris Young

Change-Id: I4385a2e0892a07e30dea1a8a0588e2c1bea2b1f1
2022-08-01 06:58:48 -05:00
Asterisk Development Team 3814cf5703 Update CHANGES and UPGRADE.txt for 19.6.0 2022-07-28 10:42:21 -05:00
Naveen Albert f6c3c7d8f8 pbx_functions.c: Manually update ast_str strlen.
When ast_func_read2 is used to read a function using
its read function (as opposed to a native ast_str read2
function), the result is copied directly by the function
into the ast_str buffer. As a result, the ast_str length
remains initialized to 0, which is a bug because this is
not the real string length.

This can cascade and have issues elsewhere, such as when
reading substrings of functions that only register read
as opposed to read2 callbacks. In this case, since reading
ast_str_strlen returns 0, the returned substring is empty
as opposed to the actual substring. This has caused
the ast_str family of functions to behave inconsistently
and erroneously, in contrast to the pbx_variables substitution
functions which work correctly.

This fixes this issue by manually updating the ast_str length
when the result is copied directly into the ast_str buffer.

Additionally, an assertion and a unit test that previously
exposed these issues are added, now that the issue is fixed.

ASTERISK-29966 #close

Change-Id: I4e2dba41410f9d4dff61c995d2ca27718248e07f
2022-07-26 10:48:14 -05:00
Sergey V. Lobanov 085b71ccad build: fix bininstall launchd issue on cross-platform build
configure script detects /sbin/launchd, but the result of this
check is not used in Makefile (bininstall). Makefile also detects
/sbin/launchd file to decide if it is required to install
safe_asterisk.

configure script correctly detects cross compile build and sets
PBX_LAUNCHD=0

In case of building asterisk on MacOS host for Linux target using
external toolchain (e.g. OpenWrt toolchain), bininstall does not
install safe_asterisk (due to /sbin/launchd detection in Makefile),
but it is required on target (Linux).

This patch adds HAVE_SBIN_LAUNCHD=@PBX_LAUNCHD@ to makeopts.in to
use the result of /sbin/launchd detection from configure script in
Makefile.
Also this patch uses HAVE_SBIN_LAUNCHD in Makefile (bininstall) to
decide if it is required to install safe_asterisk.

ASTERISK-29905 #close

Change-Id: Iff61217276cd188f43f51ef4cdbffe39d9f07f65
2022-07-24 11:52:20 -05:00
Naveen Albert f7e39e2eca db: Add AMI action to retrieve DB keys at prefix.
Adds the DBGetTree action, which can be used to
retrieve all of the DB keys beginning with a
particular prefix, similar to the capability
provided by the database show CLI command.

ASTERISK-30136 #close

Change-Id: I3be9425e53be71f24303fdd4d2923c14e84337e6
2022-07-20 10:39:09 -05:00
Naveen Albert 3b05eee506 manager: Fix incomplete filtering of AMI events.
The global event filtering code was only in one
possible execution path, so not all events were
being properly filtered out if requested. This moves
that into the universal AMI handling code so all
events are properly handled.

Additionally, the CLI listing of disabled events can
also get truncated, so we now print out everything.

ASTERISK-30137 #close

Change-Id: If8c42edcb2abc5158552da7eba2a8ff6b20e1959
2022-07-18 12:35:30 -05:00
Michael Neuhauser 477f6ec887 res_pjsip: delay contact pruning on Asterisk start
Move the call to ast_sip_location_prune_boot_contacts() *after* the call
to ast_res_pjsip_init_options_handling() so that
res/res_pjsip/pjsip_options.c is informed about the contact deletion and
updates its sip_options_contact_statuses list. This allows for an AMI
event to be sent by res/res_pjsip/pjsip_options.c if the endpoint
registers again from the same remote address and port (i.e., same URI)
as used before the Asterisk restart.

ASTERISK-30109
Reported-by: Michael Neuhauser

Change-Id: I1ba4478019e4931a7085f62708d9b66837e901a8
2022-07-14 09:46:06 -05:00
Sam Banks 35bb9c0970 queues.conf.sample: Correction of typo
ASTERISK-30126 #close

Change-Id: I009c4dcbf9338a13e3baf87b52a5bbe4f9f81a42
2022-07-14 08:17:15 -05:00
Naveen Albert 0bd21cc88f chan_dahdi: Add POLARITY function.
Adds a POLARITY function which can be used to
retrieve the current polarity of an FXS channel
as well as set the polarity of an FXS channel
to idle or reverse at any point during a call.

ASTERISK-30000 #close

Change-Id: If6f50998f723e4484bf68e2473f5cedfeaf9b8f1
2022-07-14 07:19:49 -05:00
Naveen Albert d2746b6e99 chan_dahdi: Fix buggy and missing Caller ID parameters
There are several things wrong with analog Caller ID
handling that are fixed by this commit:

callerid.c's Caller ID generation function contains the
logic to use the presentation to properly send the proper
Caller ID. However, currently, DAHDI does not pass any
presentation information to the Caller ID module, which
means that presentation is completely ignored on all calls.
This means that lines could be getting Caller ID information
they aren't supposed to.

Part of the reason this has been obscured is because the
simple switch logic for handling the built in *67 and *82
is completely wrong. Rather than modifying the presentation
for the call accordingly (which is what it's supposed to do),
it simply blanks out the Caller ID or fills it in. This is
wrong, so wrong that it makes a mockery of the specification.
Additionally, it would leave to the "UNAVAILABLE" disposition
being used for Caller ID generation as opposed to the "PRIVATE"
disposition that it should have been using. This is now fixed
to only update the presentation and not modify the number and
name, so that the simple switch *67/*82 work correctly.

Next, sig_analog currently only copies over the name and number,
nothing else, when it is filling in a duplicated caller id
structure. Thus, we also now copy over the presentation
information so that is available for the Caller ID spill.
Additionally, this meant that "valid" was implicitly 0,
and as such presentation would always fail to "Unavailable".
The validity is therefore also copied over so it can be used
by ast_party_id_presentation.

As part of this fix, new API is added so that all the relevant
Caller ID information can be passed in to the Caller ID generation
functions. Parameters that are also completely missing from the
Caller ID spill have also been added, to enhance the compatibility,
correctness, and completeness of the Asterisk Caller ID implementation.

ASTERISK-29991 #close

Change-Id: Icc44a5e09979916f4c18a440f96e10dc1c76ae15
2022-07-14 07:11:17 -05:00
Mike Bradeen ba51a05a6f Makefile: Avoid git-make user conflict
make_version now silently checks if the required git commands will
fail.  If they do, then return UNKNOWN__git_check_fail to
distinguish this failure from other UNKNOWN__ version failures

Makefile checks for this value on install and exits out with
instructions

ASTERISK-30029

Change-Id: If8f10cac8f509c08981120f17555762342020221
2022-07-13 18:35:41 -05:00
Naveen Albert 6f9d07ecb9 app_confbridge: Always set minimum video update interval.
Currently, if multiple video-enabled ConfBridges are
conferenced together, we immediately get into a scenario
where an infinite sequence of video updates fills up
the taskprocessor queue and causes memory consumption
to climb unabated until Asterisk is killed. This is due
to the core bridging mechanism that provides video updates
(softmix_bridge_write_control in bridge_softmix.c)
continously updating all the channels in the bridge with
video updates.

The logic to do so in the core is that the video updates
should be provided if the video_update_discard property
for the bridge is 0, or if enough time has elapsed since
the last video update. Thus, we already have a safeguard
built in to ensure the scenario described above does not
happen. Currently, however, this safeguard is not being
adequately ensured.

In app_confbridge, the video_update_discard property
defaults to 2000, which is a healthy value that should
completely prevent this issue. However, this value is
only set onto the bridge in the SFU video mode. This
leaves video modes such as follow_talker completely
vulnerable, since video_update_discard will actually
be 0, since the default or set value was never applied.
As a result, the core bridging mechanism will always
try to provide video updates regardless of when the last
one was sent.

To prevent this issue from happening, we now always
set the video_update_discard property on the bridge
with the value from the bridge profile. The app_confbridge
defaults will thus ensure that infinite video updates
no longer happen in any video mode.

ASTERISK-29907 #close

Change-Id: I4accb2536ac62797950468e9930f12ef7dd486b2
2022-07-13 18:01:26 -05:00
Sean Bright fbd84f9e74 pbx.c: Simplify ast_context memory management.
Allocate all of the ast_context's character data in the structure's
flexible array member and eliminate the clunky fake_context. This will
simplify future changes to ast_context.

Change-Id: I98357de75d8ac2b3c4c9f201223632e6901021ea
2022-07-13 17:02:28 -05:00
George Joseph 6163de3295 geoloc_eprofile.c: Fix setting of loc_src in set_loc_src()
line 196:    loc_src = '\0';
should have been
line 196:    *loc_src = '\0';

The issue was caught by the gcc optimizer complaining that
loc_src had a zero length because the pointer itself was being
set to NULL instead of the _contents_ of the pointer being set
to the NULL terminator.

ASTERISK-30138
Reported-by: Sean Bright

Change-Id: Id247be113cc8510f043ca053d5b4f5f3d32acd29
2022-07-13 13:44:09 -05:00
George Joseph 6c2f4d57a3 Geolocation: chan_pjsip Capability Preview
This commit adds res_pjsip_geolocation which gives chan_pjsip
the ability to use the core geolocation capabilities.

This commit message is intentionally short because this isn't
a simple capability.  See the documentation at
https://wiki.asterisk.org/wiki/display/AST/Geolocation
for more information.

THE CAPABILITIES IMPLEMENTED HERE MAY CHANGE BASED ON
USER FEEDBACK!

ASTERISK-30128

Change-Id: Ie2e2bcd87243c2cfabc43eb823d4427c7086f4d9
2022-07-12 13:35:55 -05:00
George Joseph abacf2d1a4 Geolocation: Core Capability Preview
This commit adds res_geolocation which creates the core capabilities
to manipulate Geolocation information on SIP INVITEs.

An upcoming commit will add res_pjsip_geolocation which will
allow the capabilities to be used with the pjsip channel driver.

This commit message is intentionally short because this isn't
a simple capability.  See the documentation at
https://wiki.asterisk.org/wiki/display/AST/Geolocation
for more information.

THE CAPABILITIES IMPLEMENTED HERE MAY CHANGE BASED ON
USER FEEDBACK!

ASTERISK-30127

Change-Id: Ibfde963121b1ecf57fd98ee7060c4f0808416303
2022-07-12 07:51:15 -05:00
Naveen Albert 7448443f21 general: Fix various typos.
ASTERISK-30089 #close

Change-Id: I1f5db911fd05a3a211c522c13e990fa1d0e62275
2022-07-12 07:45:35 -05:00
Kevin Harwell b7599a380d cel_odbc & res_config_odbc: Add support for SQL_DATETIME field type
See also: ASTERISK_30023

ASTERISK-30096 #close
patches:
  inline on issue - submitted by Morvai Szabolcs

Change-Id: I79c0b74862100acd9c8319dca5cc456a654d02eb
2022-07-11 04:13:30 -05:00
Naveen Albert f6cac9d0ab chan_iax2: Allow compiling without OpenSSL.
ASTERISK_30007 accidentally made OpenSSL a
required depdendency. This adds an ifdef so
the relevant code is compiled only if OpenSSL
is available, since it only needs to be executed
if OpenSSL is available anyways.

ASTERISK-30083 #close

Change-Id: Iad05c1a9a8bd2a48e7edf8d234eaa9f80779e34d
2022-07-11 04:11:22 -05:00
Joshua C. Colp 311e3e11e2 websocket / aeap: Handle poll() interruptions better.
A sporadic test failure was happening when executing the AEAP
Websocket transport tests. It was originally thought this was
due to things not getting cleaned up fast enough, but upon further
investigation I determined the underlying cause was poll()
getting interrupted and this not being handled in all places.

This change adds EINTR and EAGAIN handling to the Websocket
client connect code as well as the AEAP Websocket transport code.
If either occur then the code will just go back to waiting
for data.

The originally disabled failure test case has also been
re-enabled.

ASTERISK-30099

Change-Id: I1711a331ecf5d35cd542911dc6aaa9acf1e172ad
2022-07-11 04:10:53 -05:00
Naveen Albert daa81f6359 res_cliexec: Add dialplan exec CLI command.
Adds a CLI command similar to "dialplan eval function" except for
applications: "dialplan exec application", useful for quickly
testing certain application behavior directly from the CLI
without writing any dialplan.

ASTERISK-30062 #close

Change-Id: I42e9fa9b60746c21450d40f99a026d48d2486dde
2022-07-08 09:27:54 -05:00
Trevor Peirce a19fc264b4 features: Update documentation for automon and automixmon
The current documentation is out of date and does not reflect actual
behaviour.  This change makes documentation clearer and accurately
reflect the purpose of relevant channel variables.

ASTERISK-30123

Change-Id: I160d0b01fce862477ad55ac1aa708a730473eb6f
2022-07-08 08:56:10 -05:00
George Joseph 104e53aecd Geolocation: Base Asterisk Prereqs
* Added ast_variable_list_from_quoted_string()
  Parse a quoted string into an ast_variable list.

* Added ast_str_substitute_variables_full2()
  Perform variable/function/expression substitution on an ast_str.

* Added ast_strsep_quoted()
  Like ast_strsep except you can specify a specific quote character.
  Also added unit test.

* Added ast_xml_find_child_element()
  Find a direct child element by name.

* Added ast_xml_doc_dump_memory()
  Dump the specified document to a buffer

* ast_datastore_free() now checks for a NULL datastore
  before attempting to destroy it.

Change-Id: I5dcefed2f5f93a109e8b489e18d80d42e45244ec
2022-07-07 08:24:10 -05:00
Boris P. Korzun a692e79ec6 pbx_lua: Remove compiler warnings
Improved variable definitions (specified correct type) for avoiding
compiler warnings.

ASTERISK-30117 #close

Change-Id: I3b00c1befb658ee9379ddabd9a9132765ca9201a
2022-07-06 16:06:15 -05:00
Jose Lopes 71adb35c00 res_pjsip_header_funcs: Add functions PJSIP_RESPONSE_HEADER and PJSIP_RESPONSE_HEADERS
These new functions allow retrieving information from headers on 200 OK
INVITE response.

ASTERISK-29999

Change-Id: I264a610a9333359297a0825feb29a1bb4f4ad144
2022-07-06 14:45:50 -05:00
Boris P. Korzun cd9b332118 res_prometheus: Optional load res_pjsip_outbound_registration.so
Switched res_pjsip_outbound_registration.so dep to optional. Added
module loaded check before using it.

ASTERISK-30101 #close

Change-Id: Ia34f1684d984e821fbdd4de8911f930337703666
2022-07-05 06:37:12 -05:00
Naveen Albert 2619350741 app_dial: Fix dial status regression.
ASTERISK_28638 caused a regression by incorrectly aborting
early and overwriting the status on certain calls.
This was exhibited by certain technologies such as DAHDI,
where DAHDI returns NULL for the request if a line is busy.
This caused the BUSY condition to be incorrectly treated
as CHANUNAVAIL because the DIALSTATUS was getting incorrectly
overwritten and call handling was aborted early.

This is fixed by instead checking if any valid peers have been
specified, as opposed to checking the list size of successful
requests. This is because the latter could be empty but this
does not indicate any kind of problem. This restores the
previous working behavior.

ASTERISK-29989 #close

Change-Id: I4d4b209b967816b1bc791534593ababa2b99bb88
2022-07-01 10:19:38 -05:00
Naveen Albert d0ee3652be res_calendar_icalendar: Send user agent in request.
Microsoft recently began rejecting all requests for
ICS calendars on Office 365 with 400 errors if
the request doesn't contain a user agent. See:

https://docs.microsoft.com/en-us/answers/questions/883904/34the-remote-server-returned-an-error-400-bad-requ.html

Accordingly, we now send a user agent on requests for
ICS files so that requests to Office 365 will work as
they did before.

ASTERISK-30106

Change-Id: Ie9dcaef12ae8adf37533c684499eb11005fac8f7
2022-07-01 10:09:08 -05:00
Naveen Albert 55fece6198 db: Notify user if deleted DB entry didn't exist.
Currently, if using the CLI to delete a DB entry,
"Database entry removed" is always returned,
regardless of whether or not the entry actually
existed in the first place. This meant that users
were never told if entries did not exist.

The same issue occurs if trying to delete a DB key
using AMI.

To address this, new API is added that is more stringent
in deleting values from AstDB, which will not return
success if the value did not exist in the first place,
and will print out specific error details if available.

ASTERISK-30001 #close

Change-Id: Ic84e3eddcd66c7a6ed7fea91cdfd402568378b18
2022-06-30 19:27:53 -05:00
Naveen Albert 5b730d0bc8 cli: Fix CLI blocking forever on terminating backslash
A corner case exists in CLI parsing where if
a CLI user in a remote console ends with
a backslash and then invokes command completion
(using TAB or ?), then the console will freeze
forever until a SIGQUIT signal is sent to the
process, due to getting blocked forever
reading the command completion. CTRL+C
and other key combinations have no impact on
the CLI session.

This occurs because, in such cases, the CLI
process is waiting for AST_CLI_COMPLETE_EOF
to appear in the buffer from the main process,
but instead the main process is confused by
the funny syntax and thus prints out the CLI help.
As a result, the CLI process is stuck on the
read call, waiting for the completion that
will never come.

This prevents blocking forever by checking
if the data from the main process starts with
"Usage:". If it does, that means that CLI help
was sent instead of the tab complete vector,
and thus the CLI should bail out and not wait
any longer.

ASTERISK-29822 #close

Change-Id: I9810ac59304fec162da701653c9c834f0ec8f670
2022-06-30 18:28:48 -05:00
Naveen Albert 90b403adee app_dial: Propagate outbound hook flashes.
The Dial application currently stops hook flashes
dead in their tracks from propagating through on
outbound calls. This fixes that so they can go
down the wire.

ASTERISK-30115 #close

Change-Id: Id4e78b29a049f35c5b1e7520eaa10d0eb5b7f97c
2022-06-30 17:26:07 -05:00
Naveen Albert 1b93cf97fc say: Abort play loop if caller hangs up.
If the caller has hung up, break out of the play loop so we don't try
to play remaining files and fail to do so.

ASTERISK-30075 #close

Change-Id: I55e85be28ee90b48c0fe4ce20ac136a7dbb49f14
2022-06-30 17:09:57 -05:00
Kevin Harwell b47d3be483 res_pjsip: allow TLS verification of wildcard cert-bearing servers
Rightly the use of wildcards in certificates is disallowed in accordance
with RFC5922. However, RFC2818 does make some allowances with regards to
their use when using subject alt names with DNS name types.

As such this patch creates a new setting for TLS transports called
'allow_wildcard_certs', which when it and 'verify_server' are both enabled
allows DNS name types, as well as the common name that start with '*.'
to match as a wildcard.

For instance: *.example.com
will match for: foo.example.com

Partial matching is not allowed, e.g. f*.example.com, foo.*.com, etc...
And the starting wildcard only matches for a single level.

For instance: *.example.com
will NOT match for: foo.bar.example.com

The new setting is disabled by default.

ASTERISK-30072 #close

Change-Id: If0be3fdab2e09c2a66bb54824fca406ebaac3da4
2022-06-30 16:20:50 -05:00
Naveen Albert e23ed9bf06 pbx: Add helper function to execute applications.
Finding an application and executing it if found is
a common task throughout Asterisk. This adds a helper
function around pbx_exec to do this, to eliminate
redundant code and make it easier for modules to
substitute variables and execute applications by name.

ASTERISK-30061 #close

Change-Id: Ifee4d2825df7545fb515d763d393065675140c84
2022-06-30 15:20:34 -05:00
Stanislav Abramenkov 28d8647d4d pjsip: Upgrade bundled version to pjproject 2.12.1
More information:
https://github.com/pjsip/pjproject/releases/tag/2.12.1

Pull request to third-party
https://github.com/asterisk/third-party/pull/11

ASTERISK-30050

Change-Id: Icb4e86d4b85ef9b975355c91f3ed56a50b51c6bd
2022-06-17 12:42:57 -05:00
Asterisk Development Team df5bc6468f Update CHANGES and UPGRADE.txt for 19.5.0 2022-06-16 13:45:39 -05:00
Naveen Albert 8fe7eb35f2 asterisk.c: Fix incompatibility warnings for remote console.
A previous review fixing ASTERISK_22246 and ASTERISK_26582
got a couple of the options mixed up as to whether or not
they are compatible with the remote console. This fixes
those to the best of my knowledge.

ASTERISK-30097 #close

Change-Id: Id54166991aa79f04fb02699cc499bedda854253b
2022-06-16 10:52:06 -05:00
Kevin Harwell 4367f1ac41 test_aeap_transport: disable part of failing unit test
The 'transport_binary' test sporadically fails, but on a theory that the
problem is caused by a previously executed test, transport_connect_fail,
part of that test has been disabled until a solution is found.

ASTERISK_30099

Change-Id: I48ed74d696aa9b6159f59661f3d535cac4c909e1
2022-06-15 16:40:10 -05:00
Naveen Albert 00b44f1c25 sig_analog: Fix broken three-way conferencing.
Three-way calling for analog lines is currently broken.
If party A is on a call with party B and initiates a
three-way call to party C, the behavior differs depending
on whether the call is conferenced prior to party C
answering. The post-answer case is correct. However,
if A flashes before C answers, then the next flash
disconnects B rather than C, which is incorrect.

This error occurs because the subs are not swapped
in the misbehaving case. This is because the flash
handler only swaps the subs if C has answered already,
which is wrong. To fix this, we swap the subs regardless
of whether C has answered or not when the call is
conferenced. This ensures that C is disconnected
on the next hook flash, rather than B as can happen
currently.

ASTERISK-30043 #close

Change-Id: I96c5bf6c9b7eb2636136b716c677c82c079b6f06
2022-06-15 12:20:11 -05:00
Kevin Harwell 49433ac1c5 ARI version: increase non-breaking number
A recent change, ASTERISK_30027, now exposes a channel driver's unique
id to ARI channel resources so bump the ARI version.

Change-Id: Ic9da84b7b0eca6f3ff5b6a738b2be8362237951e
2022-06-15 11:37:48 -05:00
Naveen Albert efbcab8d65 app_voicemail: Add option to prevent message deletion.
Adds an option to VoiceMailMain that prevents the user
from deleting messages during that application invocation.
This can be useful for public or shared mailboxes, where
some users should be able to listen to messages but not
delete them.

ASTERISK-30063 #close

Change-Id: Icdfb8423ae8d1fce65a056b603eb84a672e80a26
2022-06-09 19:40:51 -05:00
Alexei Gradinari b3671a55f0 res_pjsip_pubsub: delete scheduled notification on RLS update
If there is scheduled notification, we must delete it
to avoid using destroyed subscriptions.

ASTERISK-29906

Change-Id: I1c644e5e15a8fe43eed8e4f9112f113cbf87a40f
2022-06-09 03:48:19 -05:00
Alexei Gradinari a852fe9402 res_pjsip_pubsub: XML sanitized RLS display name
ASTERISK-29891

Change-Id: Ic8c9697e616446e06e6302653eae902aa23372ad
2022-06-09 03:47:10 -05:00
Naveen Albert f88cc626af res_pjsip_outbound_registration: Make max random delay configurable.
Currently, PJSIP will randomly wait up to 10 seconds for each
outbound registration's initial attempt. The reason for this
is to avoid having all outbound registrations attempt to register
simultaneously.

This can create limitations with the test suite where we need to
be able to receive inbound calls potentially within 10 seconds of
starting up. For instance, we might register to another server
and then try to receive a call through the registration, but if
the registration hasn't happened yet, this will fail, and hence
this inconsistent behavior can cause tests to fail. Ultimately,
this requires a smaller random value because there may be no good
reason to wait for up to 10 seconds in these circumstances.

To address this, a new config option is introduced which makes this
maximum delay configurable. This allows, for instance, this to be
set to a very small value in test systems to ensure that registrations
happen immediately without an unnecessary delay, and can be used more
generally to control how "tight" the initial outbound registrations
are.

ASTERISK-29965 #close

Change-Id: Iab989a8e94323e645f3a21cbb6082287c7b2f3fd
2022-06-09 03:46:23 -05:00
Trevor Peirce 6436d82654 res_pjsip: Actually enable session timers when timers=always
When a pjsip endpoint is defined with timers=always, this has been a
functional noop.  This patch correctly sets the feature bitmap to both
enable support for session timers and to enable them even when the
endpoint itself does not request or support timers.

ASTERISK-29603
Reported-By: Ray Crumrine

Change-Id: I8b5eeaa9ec7f50cc6d96dd34c2b4aa9c53fb5440
2022-06-08 22:33:42 -05:00
Naveen Albert 7f892d03a5 xmldocs: Improve examples.
Use example tags instead of regular para tags
where possible.

ASTERISK-30090

Change-Id: Iada8bbfda08f30b118cedf2d040bbb21e4966ec5
2022-06-08 21:37:16 -05:00
Christof Efkemann e92f047e5f app_sayunixtime: Use correct inflection for German time.
In function ast_say_date_with_format_de(), take special
care when the hour is one o'clock. In this case, the
German number "eins" must be inflected to its neutrum form,
"ein". This is achieved by playing "digits/1N" instead of
"digits/1". Fixes both 12- and 24-hour formats.

ASTERISK-30092

Change-Id: Ica9b80125c0b317e378d89c1ea786816e2635510
2022-06-08 20:39:24 -05:00
Naveen Albert d8bbcf4b25 res_parking: Add music on hold override option.
An m option to Park and ParkAndAnnounce now allows
specifying a music on hold class override.

ASTERISK-30087

Change-Id: I03de8d97b100e451b2611b5a621d48750f5d6a9e
2022-06-06 18:58:18 -05:00
Naveen Albert 05a0b08222 res_calendar: Prevent assertion if event ends in past.
res_calendar will trigger an assertion currently
if the ending time is calculated to be in the past.
Unlike the reminder and start times, however, there
is currently no check to catch non-positive times
and set them to 1. As a result, if we get a negative
value by happenstance, this can cause a crash.

To prevent the assertion from begin triggered, we now
use the same logic as the reminder and start events
to catch this issue before it can cause a problem.

ASTERISK-29981 #close

Change-Id: Idfb3204d195f350d2575fb4bc72a54a597d6e93c
2022-06-06 17:44:57 -05:00
Naveen Albert 6e88448e80 chan_iax2: Prevent deadlock due to duplicate autoservice.
If a switch is invoked using chan_iax2, deadlock can result
because the PBX core is autoservicing the channel while chan_iax2
also then attempts to service it while waiting for the result
of the switch. This removes servicing of the channel to prevent
any conflicts.

ASTERISK-30064 #close

Change-Id: Ie92f206d32f9a36924af734ddde652b21106af22
2022-06-06 17:42:11 -05:00
Naveen Albert 61bc3a8aa1 loader: Prevent deadlock using tab completion.
If tab completion using ast_module_helper is attempted
during startup, deadlock will ensue because the CLI
will attempt to lock the module list while it is already
locked by the loader. This causes deadlock because when
the loader tries to acquire the CLI lock, they are blocked
on each other.

Waiting for startup to complete is not feasible because
the CLI lock is acquired while waiting, so deadlock will
ensure regardless of whether or not a lock on the module
list is attempted.

To prevent deadlock, we immediately abort if tab completion
is attempted on the module list before Asterisk is fully
booted.

ASTERISK-30039 #close

Change-Id: Idd468906c512bb196631e366a8f597a0e2e9271d
2022-06-06 16:51:55 -05:00
Naveen Albert b86ce7fbb9 res_parking: Warn if out of bounds parking spot requested.
Emits a warning if the user has requested a parking spot that
is out of bounds for the requested parking lot.

ASTERISK-30086

Change-Id: I1080371e4f63e94724455003753014fbd3f95fbf
2022-06-02 12:19:53 -05:00
Maximilian Fridrich 318d6b02ee chan_pjsip: Only set default audio stream on hold.
When a PJSIP channel is set on hold or off hold, all streams were set
on/off hold. This is not the desired behaviour and caused issues
when there were multiple streams in the topology.

Now, only the default audio stream is set on/off hold when a hold is
indicated.

ASTERISK-30051

Change-Id: I04f1110565fd05fea565f5539b534b54549d4f71
2022-06-02 11:38:13 -05:00
Alexei Gradinari 1576004e07 res_pjsip_dialog_info_body_generator: Set LOCAL target URI as local URI
The change "Add LOCAL/REMOTE tags in dialog-info+xml" set both "local"
Identity Element URI and Target Element URI to the same value -
the channel Caller Number.
For Identity Element it's ok to set as Caller ID.
But Local Target URI should be set as local URI.

In this case the Local Target URI can be used for Directed Call Pickup
by Polycom ip-phones (parameter useLocalTargetUriforLegacyPickup).

Also XML sanitized Display names.

ASTERISK-24601

Change-Id: If130a2f2f3b2339b14dca0ec0ebeea3a87b34343
2022-06-02 09:26:07 -05:00
Shloime Rosenblum d1f32e75d7 res_agi: Evaluate dialplan functions and variables in agi exec if enabled
Agi commnad exec can now evaluate dialplan functions and
variables if variable AGIEXECFULL is set to yes. this can
be useful when executing Playback or Read from agi.

ASTERISK-30058 #close

Change-Id: I669991f540496e7bddd096fec82b52c083036832
2022-05-26 09:34:37 -05:00
Sean Bright 29165bf2e1 ast_pkgconfig.m4: AST_PKG_CONFIG_CHECK() relies on sed.
Make sure that we have a working sed before trying to use it.

ASTERISK-30059 #close

Change-Id: I9abad67a5df11b665d480feec304ab9d6f55cc76
2022-05-22 16:36:36 -05:00
Moritz Fain de838c241b ari: expose channel driver's unique id to ARI channel resource
This change exposes the channel driver's unique id (i.e. the Call-ID
for chan_sip/chan_pjsip based channels) to ARI channel resources
as `protocol_id`.

ASTERISK-30027
Reported by: Moritz Fain
Tested by: Moritz Fain

Change-Id: I7cc6e7a9d29efe74bc27811d788dac20fe559b87
2022-05-19 21:34:59 -05:00
Sean Bright 8db9a02962 loader.c: Use portable printf conversion specifier for int64.
ASTERISK-30060 #close

Change-Id: I88d47a1488be2f39017b8d562f993f081844fcb8
2022-05-19 20:40:54 -05:00
Joshua C. Colp dc1e446ebd res_pjsip_transport_websocket: Also set the remote name.
As part of PJSIP 2.11 a behavior change was done to require
a matching remote hostname on an established transport for
secure transports. Since the Websocket transport is considered
a secure transport this caused the existing connection to not
be found and used.

We now set the remote hostname and the transport can be found.

ASTERISK-30065

Change-Id: Ia1cdef33e1411f927985b4b852c95e163c080e94
2022-05-17 07:20:29 -05:00
Naveen Albert a143c37fc0 res_pjsip_outbound_registration: Show time until expiration
Adjusts the pjsip show registration(s) commands to show
the amount of seconds remaining until a registration
expires.

ASTERISK-29845 #close

Change-Id: Ic4fea15a1a1056c424416def49d1ca8e776c0483
2022-05-13 09:54:43 -05:00
Thomas Guebels d457838b77 res_pjsip_transport_websocket: save the original contact host
This is needed to be able to restore it in REGISTER responses,
otherwise the client won't be able to find the contact it created.

ASTERISK-30042

Change-Id: I0c5823918199acf09246b3b206fbde66773688f6
2022-05-13 09:23:20 -05:00
Naveen Albert 46d395c248 app_confbridge: Add function to retrieve channels.
Adds the CONFBRIDGE_CHANNELS function which can be used
to retrieve a comma-separated list of channels, filtered
by a particular type of participant category. This output
can then be used with functions like UNSHIFT, SHIFT, POP,
etc.

ASTERISK-30036 #close

Change-Id: I1950aff932437476dc1abab6f47fb4ac90520b83
2022-05-11 07:26:01 -05:00
Naveen Albert 2b8086e382 chan_dahdi: Fix broken operator mode clearing.
Currently, the operator services mode in DAHDI is broken and unusable.
The actual operator recall functionality works properly; however,
when the operator hangs up (which is the only way that such a call
is allowed to end), both lines are permanently taken out of service
until "dahdi restart" is run. This prevents this feature from being
used.

Operator mode is one of the few factors that can cause the general
analog event handling in sig_analog not to be used. Several years
back, much of the analog handling was moved from chan_dahdi to
sig_analog. However, this was not done fully or consistently at
the time, and when operator mode is active, sig_analog does not
get used. Generally this is correct, but in the case of hangup
it should be using sig_analog regardless of the operator mode;
otherwise, the lines do not properly clear and they become unusable.

This bug is fixed so the operator can now hang up and properly
release the call. It is treated just like any other hangup. The
operator mode functionality continues to work as it did before.

ASTERISK-29993 #close

Change-Id: Ib2e3ddb40d9c71e8801e0b4bb0a12e2b52f51d24
2022-05-09 09:39:23 -05:00
George Joseph 910d9caf86 GCC12: Fixes for 18+. state_id_by_topic comparing wrong value
GCC 12 caught an issue in state_id_by_topic where we were
checking a pointer for NULL instead of the contents of
the pointer for '\0'.

ASTERISK-30044

Change-Id: Ia0b04d4fff45c92acb7f07132a33622fa341148e
2022-05-09 07:55:17 -05:00
George Joseph 3c96566655 GCC12: Fixes for 16+
Most issues were in stringfields and had to do with comparing
a pointer to an constant/interned string with NULL.  Since the
string was a constant, a pointer to it could never be NULL so
the comparison was always "true".  gcc now complains about that.

There were also a few issues where determining if there was
enough space for a memcpy or s(n)printf which were fixed
by defining some of the involved variables as "volatile".

There were also a few other miscellaneous fixes.

ASTERISK-30044

Change-Id: Ia081ca1bcfb329df6487c4660aaf1944309eb570
2022-05-09 07:49:52 -05:00
Maximilian Fridrich 4fec26923e core_unreal: Flip stream direction of second channel.
When a new unreal (local) channel is created, a second (;2) channel is
created as a counterpart which clones the topology of the first
channel. This creates issues when an outgoing stream is sendonly or
recvonly as the stream state of the inbound channel will be the same
as the stream state of the outbound channel.

Now the stream state is flipped for the streams of the 2nd channel in
ast_unreal_new_channels if the outgoing stream topology is recvonly or
sendonly.

ASTERISK-29655
Reported by: Michael Auracher

ASTERISK-29638
Reported by: Michael Auracher

Change-Id: I0cea29635bb20b7bf7fd0fb95498cd44dab98fbf
2022-05-05 08:16:30 -05:00
Naveen Albert 0c3f7c98e5 chan_dahdi: Document dial resource options.
Documents the Dial syntax for DAHDI, namely the channel group,
distinctive ring, answer confirmation, and digital call options
that are specified in the resource itself.

ASTERISK-24827 #close

Change-Id: Ib95e78497fb00dc5cbfde1c93a69f034bfd08c30
2022-05-02 15:47:17 -05:00
Naveen Albert 09e9efc4c6 chan_dahdi: Don't allow MWI FSK if channel not idle.
For lines that have mailboxes configured on them, with
FSK MWI, DAHDI will periodically try to dispatch FSK
to update MWI. However, this is never supposed to be
done when a channel is not idle.

There is currently an edge case where MWI FSK can
extraneously get spooled for the channel if a caller
hook flashes and hangs up, which triggers a recall ring.
After one ring, the on hook time threshold in this if
condition has been satisfied and an MWI update is spooled.
This means that when the phone is picked up again, the
answerer gets an FSK spill before being reconnected to
the party on hold.

To prevent this, we now explicitly check to ensure that
subchannel 0 has no owner. There is no owner when DAHDI
channels are idle, but if the channel is "in use" in some
way (such as in the aforementioned scenario), then there
is an owner, and we shouldn't process MWI at this time.

ASTERISK-28518 #close

Change-Id: Ia3904434fd81688d71742f7e84358b7e1c38e92a
2022-05-02 15:46:20 -05:00
Michael Cargile 72c8c263e8 apps/confbridge: Added hear_own_join_sound option to control who hears sound_join
Added the hear_own_join_sound option to the confbridge user profile to
control who hears the sound_join audio file. When set to 'yes' the user
entering the conference and the participants already in the conference
will hear the sound_join audio file. When set to 'no' the user entering
the conference will not hear the sound_join audio file, but the
participants already in the conference will hear the sound_join audio
file.

ASTERISK-29931
Added by Michael Cargile

Change-Id: I856bd66dc0dfa057323860a6418c1371d249abd2
2022-05-02 09:31:34 -05:00
Naveen Albert 2391af167b chan_iax2: Prevent crash if dialing RSA-only call without outkey.
Currently, if attempting to place a call to a peer that only allows
RSA authentication, if we fail to provide an outkey when placing
the call, Asterisk will crash.

This exposes the broader issue that IAX2 is prone to causing a crash
if encryption or decryption is attempted but we never initialized
the encryption and decryption keys. In other words, if the logic
to use encryption in chan_iax2 is not perfectly aligned with the
decision to build keys in the first place, then a crash is not
only possible but probable. This was demonstrated by ASTERISK_29264,
for instance.

This permanently prevents such events from causing a crash by explicitly
checking that keys are initialized properly before setting the flags
to use encryption for the call. Instead of crashing, the call will
now abort.

ASTERISK-30007 #close

Change-Id: If925c3d86099ceac7f621804f2532baac5050c9a
2022-05-02 08:56:46 -05:00
Naveen Albert aece339a22 chan_dahdi: Don't append cadences on dahdi restart.
Currently, if any custom ring cadences are specified, they are
appended to the array of cadences from wherever we left off
last time. This works properly the first time, but on subsequent
dahdi restarts, it means that the existing cadences are left
alone and (most likely) the same cadences are then re-added
afterwards. In short order, the cadence array gets maxed out
and the user begins seeing warnings that the array is full
and no more cadences may be added.

This buggy behavior persists until Asterisk is completely
restarted; however, if and when dahdi restart is run again,
then the same problem is reintroduced.

This fixes this behavior so that cadence parsing is more
idempotent, that is so running dahdi restart multiple times
starts adding cadences from the beginning, rather than from
wherever the last cadence was added.

As before, it is still not possible to revert to the default
cadences by simply removing all cadences in this manner, nor
is it possible to delete existing cadences. However, this
does make it possible to update existing cadences, which
was not possible before, and also ensures that the cadences
remain unchanged if the config remains unchanged.

ASTERISK-29990 #close

Change-Id: Ie32ea3e8a243b766756b1afce684d4a31ee7421d
2022-05-02 08:56:27 -05:00
Naveen Albert 2ba9ba349f menuselect: Don't erroneously recompile modules.
A bug in menuselect can cause modules that are disabled
by default to be recompiled every time a recompilation
occurs. This occurs for module categories that are NOT
positive output, as for these categories, the modules
contained in the makeopts file indicate modules which
should NOT be selected. The existing procedure of iterating
through these modules to mark modules as present is thus
insufficient. This has led to modules with a default_enabled
tag of "no" to get deleted and recompiled every time, even
when they haven't changed.

To fix this, we now modify the mark as present behavior
for module categories that are not positive output. For
these, we start by iterating through the module tree
and marking all modules as present, then go back and
mark anything contained in the makeopts file as not
present. This ensures that makeopt selections are actually
used properly, regardless of whether a module category
uses positive output or not.

ASTERISK-29728 #close

Change-Id: Idf2974c4ed8d0ba3738a92f08a6082b234277b95
2022-04-28 15:03:13 -05:00
Naveen Albert 1e29935131 app_meetme: Don't erroneously set global variables.
The admin_exec function in app_meetme is used by the SLA
applications for internal bridging. However, in these cases,
chan is NULL. Currently, this function will set some status
variables that are intended for a channel, but since channel
is NULL, this is erroneously creating meaningless global
variables, which shouldn't be happening. This sets these
variables only if chan is not NULL.

ASTERISK-30002 #close

Change-Id: I817df6c26f5bda131678e56791b0b61ba64fc6f7
2022-04-27 18:40:35 -05:00
Naveen Albert 7d80c8a49c asterisk.c: Warn of incompatibilities with remote console.
Some command line options to Asterisk only apply when Asterisk
is started and cannot be used with remote console mode. If a
user tries to use any of these, they are currently simply
silently ignored.

This prints out a warning if incompatible options are used,
informing users that an option used cannot be used with remote
console mode. Additionally, some clarifications are added to
the help text and man page.

ASTERISK-22246
ASTERISK-26582

Change-Id: I980a5380ef2c19e8ea348596396d5382893c4337
2022-04-27 12:38:49 -05:00
Naveen Albert 45ed328d08 func_db: Add function to return cardinality at prefix
Adds the DB_KEYCOUNT function, which can be used to retrieve
the number of keys at a given prefix in AstDB.

ASTERISK-29968 #close

Change-Id: Ib2393b77b7e962dbaae6192f8576bc3f6ba92d09
2022-04-27 11:42:15 -05:00
Naveen Albert 2c6ae41a97 chan_dahdi: Fix insufficient array size for round robin.
According to chan_dahdi.conf, up to 64 groups (numbered
0 through 63) can be used when dialing DAHDI channels.

However, currently dialing round robin with a group number
greater than 31 fails because the array for the round robin
structure is only size 32, instead of 64 as it should be.

This fixes that so the round robin array size is consistent
with the actual groups capacity.

ASTERISK-29994

Change-Id: I4caa08d7025f78ac75a0539f71aaf3eb3e85b3b7
2022-04-27 06:02:42 -05:00
Naveen Albert 942db8c58d func_evalexten: Extension evaluation function.
This adds the EVAL_EXTEN function, which may be used to retrieve
the variable-substituted data at any extension.

ASTERISK-29486

Change-Id: Iad81019689674c9f4ac77d235f5d7234adbb1432
2022-04-27 03:29:54 -05:00
Naveen Albert bbc27f835b documentation: Adds versioning information.
Adds version information for applications, functions,
and manager events/actions.

This is not completely exhaustive by any means but
covers most new things added that have release
versioning information in the issue tracker.

ASTERISK-29940 #close

Change-Id: I506401e93c799715dbbe97c0a8ba18af2bf5e131
2022-04-27 02:06:35 -05:00
Naveen Albert a3e7b2d010 samples: Remove obsolete sample configs.
Removes a couple sample config files for modules
which have since been removed from Asterisk.

ASTERISK-30008 #close

Change-Id: I6be89cafc6c575d98a5315e4912b61a833aacf52
2022-04-27 02:05:06 -05:00
Naveen Albert dc570ae623 cli: Add command to evaluate dialplan functions.
Adds the dialplan eval function commands to evaluate a dialplan
function from the CLI. The return value and function result are
printed out and can be used for testing or debugging.

ASTERISK-29820 #close

Change-Id: I833e97ea54c49336aca145330a2adeebfad05209
2022-04-27 02:04:04 -05:00
Naveen Albert ea401644fe file.c: Prevent formats from seeking negative offsets.
Currently, if a user uses an application like ControlPlayback
to try to rewind a file past the beginning, this can throw
warnings when the file format (e.g. PCM) tries to seek to
a negative offset.

Instead of letting file formats try (and fail) to seek a
negative offset, we instead now catch this in the rewind
function to ensure that we never seek an offset less than 0.
This prevents legitimate user actions from triggering warnings
from any particular file formats.

ASTERISK-29943 #close

Change-Id: Ia53f2623f57898f4b8e5c894b968b01e95426967
2022-04-27 02:03:06 -05:00
Mark Petersen 40df42fd03 chan_sip.c Session timers get removed on UPDATE
If Asterisk receives a SIP REFER with Session-Timers UAC
maintain Session-Timers when sending UPDATE"

ASTERISK-29843

Change-Id: I8e9a21c13bf757fa34d778f49ba3cf859b29ae5c
2022-04-26 19:44:05 -05:00
Naveen Albert 06756a1608 chan_pjsip: Add ability to send flash events.
PJSIP currently is capable of receiving flash events
and converting them to FLASH control frames, but it
currently lacks support for doing the reverse: taking
a FLASH control frame and converting it into a flash
event in the SIP domain.

This adds the ability for PJSIP to process flash control
frames by converting them into the appropriate SIP INFO
message, which can then be sent to the peer. This allows,
for example, flash events to be sent between Asterisk
systems using PJSIP.

ASTERISK-29941 #close

Change-Id: I1590221a4d238597f79672fa5825dd4a920c94dd
2022-04-26 18:37:45 -05:00
Mark Petersen 9ffc2f711c chan_pjsip: add allow_sending_180_after_183 option
added new global config option "allow_sending_180_after_183"
that if enabled will preserve 180 after a 183

ASTERISK-29842

Change-Id: I8a53f8c35595b6d16d8e86e241b5f110d92f3d18
2022-04-26 16:49:41 -05:00
Mark Petersen 73fb22714e chan_sip: SIP route header is missing on UPDATE
if Asterisk need to send an UPDATE before answer
on a channel that uses Record-Route:
it will not include a Route header

ASTERISK-29955

Change-Id: Id1920ecbfea7739a038b14dc94487ecfe7b57eef
2022-04-26 16:47:14 -05:00
Yury Kirsanov 1937f30202 bridge_simple.c: Unhold channels on join simple bridge.
Patch provided inline by Yury Kirsanov on the linked issue and
approved by Josh Colp.

ASTERISK-29253 #close

Change-Id: I5b9ccc67ebf06e875ed061d9e7fc21f47b0a4e1f
2022-04-26 15:08:56 -05:00
Kevin Harwell d1bfbb65eb res_aeap & res_speech_aeap: Add Asterisk External Application Protocol
Add framework to connect to, and read and write protocol based
messages from and to an external application using an Asterisk
External Application Protocol (AEAP). This has been divided into
several abstractions:

 1. transport - base communication layer (currently websocket only)
 2. message - AEAP description and data (currently JSON only)
 3. transaction - links/binds requests and responses
 4. aeap - transport, message, and transaction handler/manager

This patch also adds an AEAP implementation for speech to text.
Existing speech API callbacks for speech to text have been completed
making it possible for Asterisk to connect to a configured external
translator service and provide audio for STT. Results can also be
received from the external translator, and made available as speech
results in Asterisk.

Unit tests have also been created that test the AEAP framework, and
also the speech to text implementation.

ASTERISK-29726 #close

Change-Id: Iaa4b259f84aa63501e5fd2a6fb107f900b4d4ed2
2022-04-26 14:23:59 -05:00
Joshua C. Colp 18d2f273b5 manager: Terminate session on write error.
On a write error to an AMI session a flag was set to
indicate that the write error had occurred, with the
expected result being that the session be terminated.
This was not actually happening and instead writing
would continue to be attempted.

This change adds a check for the write error and causes
the session to actually terminate.

ASTERISK-29948

Change-Id: Icaf5d413d4c0d5dc78292a17287fecc8720a31a5
2022-04-26 14:12:49 -05:00
Ben Ford b42934d019 res_pjsip_stir_shaken.c: Fix enabled when not configured.
There was an issue with the conditional where STIR/SHAKEN would be
enabled even when not configured. It has been changed to ensure that if
a profile does not exist and stir_shaken is not set in pjsip.conf, then
the conditional will return from the function without performing
STIR/SHAKEN operations.

ASTERISK-30024

Change-Id: I41286a3d35b033ccbfbe4129427a62cb793a86e6
2022-04-26 11:11:10 -05:00
Joshua C. Colp 8584ad425a res_pjsip: Always set async_operations to 1.
The async_operations setting on a transport configures how
many simultaneous incoming packets the transport can handle
when multiple threads are polling and waiting on the transport.
As we only use a single thread this was needlessly creating
incoming packets when set to a non-default value, wasting memory.

ASTERISK-30006

Change-Id: I1915973ef352862dc2852a6ba4cfce2ed536e68f
2022-04-26 11:08:12 -05:00
Maximilian Fridrich 5d3125fa71 app_dial: Flip stream direction of outgoing channel.
When executing dial, the topology of the incoming channel is cloned and
used for the outgoing channel. This creates issues when an incoming
stream is sendonly or recvonly as the stream state of the outgoing
channel will be the same as the stream state of the incoming channel.

Now the stream state is flipped for the outgoing stream in
dial_exec_full if the incoming stream topology is recvonly or sendonly.

ASTERISK-29655
Reported by: Michael Auracher

ASTERISK-29638
Reported by: Michael Auracher

Change-Id: I294dc834ac9a5f048b101b691669959e9df630e1
2022-04-26 10:48:42 -05:00
Sean Bright f565982e0e config.h: Don't use C++ keywords as argument names.
ASTERISK-30021 #close

Change-Id: I70eb59b782a4946b979942e21422746b7563029c
2022-04-25 18:35:48 -05:00
Joshua C. Colp c7ca797922 pjsip: Increase maximum number of format attributes.
Chrome has added more attributes, causing the limit to be
exceeded. This raises it up some more.

ASTERISK-30015

Change-Id: I964957c005c4e6f7871b15ea1ccd9b4659c7ef32
2022-04-25 15:44:29 -05:00
Joshua C. Colp ebbbe78842 cdr_adaptive_odbc: Add support for SQL_DATETIME field type.
ASTERISK-30023

Change-Id: I0e1697f6af044e9eab7e07bbaeeffd1bb68ac34a
2022-04-20 07:42:46 -05:00
Asterisk Development Team 25431555d1 Update CHANGES and UPGRADE.txt for 19.3.2 2022-04-14 19:11:32 -03:00
Ben Ford aba30b11a6 AST-2022-002 - res_stir_shaken/curl: Add ACL checks for Identity header.
Adds a new configuration option, stir_shaken_profile, in pjsip.conf that
can be specified on a per endpoint basis. This option will reference a
stir_shaken_profile that can be configured in stir_shaken.conf. The type
of this option must be 'profile'. The stir_shaken option can be
specified on this object with the same values as before (attest, verify,
on), but it cannot be off since having the profile itself implies wanting
STIR/SHAKEN support. You can also specify an ACL from acl.conf (along
with permit and deny lines in the object itself) that will be used to
limit what interfaces Asterisk will attempt to retrieve information from
when reading the Identity header.

ASTERISK-29476

Change-Id: I87fa61f78a9ea0cd42530691a30da3c781842406
2022-04-14 16:59:17 -05:00
Joshua C. Colp 1e3ffda3db func_odbc: Add SQL_ESC_BACKSLASHES dialplan function.
Some databases depending on their configuration using backslashes
for escaping. When combined with the use of ' this can result in
a broken func_odbc query.

This change adds a SQL_ESC_BACKSLASHES dialplan function which can
be used to escape the backslashes.

This is done as a dialplan function instead of being always done
as some databases do not require this, and always doing it would
result in incorrect data being put into the database.

ASTERISK-29838

Change-Id: I152bf34899b96ddb09cca3e767254d8d78f0c83d
2022-04-14 16:57:19 -05:00
Ben Ford ca53a8a833 AST-2022-001 - res_stir_shaken/curl: Limit file size and check start.
Put checks in place to limit how much we will actually download, as well
as a check for the data we receive at the start to ensure it begins with
what we would expect a certificate to begin with.

ASTERISK-29872

Change-Id: Ifd3c6b8bd52b8b6192a04166ccce4fc8a8000b46
2022-04-14 12:22:59 -05:00
Naveen Albert 1873b7ece6 app_mf, app_sf: Return -1 if channel hangs up.
The ReceiveMF and ReceiveSF applications currently always
return 0, even if a channel has hung up. The call will still
end but generally applications are expected to return -1 if
the channel has hung up.

We now return -1 if a hangup occured to bring this behavior
in line with this norm. This has no functional impact, but
merely increases conformity with how these modules interact
with the PBX core.

ASTERISK-29951 #close

Change-Id: I234d755050ab8ed58f197c6925b968ba26b14033
2022-04-08 16:35:20 -05:00
Naveen Albert 3707f2e144 app_queue: Add music on hold option to Queue.
Adds the m option to the Queue application, which allows a
music on hold class to be specified at runtime which will
override the class configured in queues.conf.

This option functions like the m option to Dial.

ASTERISK-29876 #close

Change-Id: Ie25a48569cf8755c305c9438b1ed292c3adcf8d7
2022-04-08 16:33:38 -05:00
Naveen Albert 7a81f3ad35 app_meetme: Emit warning if conference not found.
Currently, if a user tries to access a non-dynamic
MeetMe conference and the conference is not found,
the call simply silent hangs up. There is no indication
to the user that anything went wrong at all.

This changes the relevant debug message to a warning
so that the user is notified of this invalidity.

ASTERISK-29954 #close

Change-Id: Iebcfae3755d00f2150d676ee211c57bc59530048
2022-04-08 11:24:12 -05:00
Boris P. Korzun dae30a301f res_pjsip_sdp_rtp: Improve detecting of lack of RTP activity
Change RTP timer behavior for detecting RTP only after two-way
SDP channel establishment. Ignore detecting after receiving 183
with SDP or while direct media is used.
Make rtp_timeout and rtp_timeout_hold options consistent to rtptimeout
and rtpholdtimeout options in chan_sip.

ASTERISK-26689 #close
ASTERISK-29929 #close

Change-Id: I07326d5b9c40f25db717fd6075f6f3a8d77279eb
2022-04-06 04:02:52 -05:00
Naveen Albert 96e0b79938 build: Remove obsolete leftover build references.
Removes some leftover build and config references to
modules that have since been removed from Asterisk.

ASTERISK-29935 #close

Change-Id: Iaefc73a23f4b2de3c6c14d928050135b6d0ef6af
2022-03-30 17:04:49 -05:00
Kevin Harwell 629ced6db0 res_pjsip_header_funcs: wrong pool used tdata headers
When adding headers to an outgoing request the headers were cloned using
the dialog's pool when they should have been cloned using tdata's pool.
Under certain circumstances it was possible for the dialog object, and
its pool to be freed while tdata is still active and available. Thus the
cloned header "disappeared", and when tdata tried to later access it a
crash would occur.

This patch makes it so all added headers are cloned appropriately using
tdata's pool.

ASTERISK-29411 #close
ASTERISK-29535 #close

Change-Id: I9852025b5ee93ce1c038209150ee9dba1e0767c5
2022-03-30 15:13:53 -05:00
Joshua C. Colp c812ad62f7 pjproject: Update bundled to 2.12 release.
This change removes patches which have been merged into
upstream and updates some existing ones. It also adds
some additional config_site.h changes to restore previous
behavior, as well as a patch to allow multiple Authorization
headers. There seems to be some confusion or disagreement
on language in RFC 8760 in regards to whether multiple
Authorization headers are supported. The RFC implies it
is allowed, as does some past sipcore discussion. There is
also the catch all of "local policy" to allow it. In
the case of Asterisk we allow it.

ASTERISK-29351

Change-Id: Id39ece02dedb7b9f739e0e37ea47d76854af7191
2022-03-30 07:33:51 -05:00
Naveen Albert 3e3e3f3ce5 pbx.c: Warn if there are too many includes in a context.
The PBX core uses the stack when it comes to includes, which
means that a context can only contain strictly fewer than
AST_PBX_MAX_STACK includes. If this is exceeded, then warnings
will be emitted for each number of includes beyond this if
searching for an extension in the including context, and if
the extension's inclusion is beyond the stack size, it will
simply not be found.

To address this, we now check if there are too many includes
in a context when the dialplan is reloaded so that if there
is an issue, the user is aware of at "compile time" as opposed
to "run time" only. Secondly, more details are printed out
when this message is encountered so it's clear what has happened.

ASTERISK-26719

Change-Id: Ia3700452e75a7af3391b3e82ee69f06a669f8958
2022-03-29 16:05:21 -05:00
George Joseph a3a9a48734 make_xml_documentation: Remove usage of get_sourceable_makeopts
get_sourceable_makeopts wasn't handling variables with embedded
double quotes in them very well.  One example was the DOWNLOAD
variable when curl was being used instead of wget.  Rather than
trying to fix get_sourceable_makeopts, it's just been removed.

ASTERISK-29986
Reported by: Stefan Ruijsenaars

Change-Id: Idf2a90902228c2558daa5be7a4f8327556099cd2
2022-03-29 12:42:01 -05:00
George Joseph 56a8d47586 Makefile: Disable XML doc validation
make_xml_documentation was being called with the --validate
flag set when it shouldn't have been.  This was causing
build failures if neither xmllint nor xmlstarlet were installed.
The correct behavior is to simply print a message that either
one of those tools should be installed for validation and
continue with the build.

ASTERISK-29988

Change-Id: Idc6c44114e7dd3fadae183a4e22f4fdba0b8a645
2022-03-29 11:48:11 -05:00
Naveen Albert 6474550175 chan_iax2: Fix spacing in netstats command
The iax2 show netstats command previously didn't contain
enough spacing in the header to properly align the table
header with the table body. This caused column headers
to not align with the values on longer channel names.

Some spacing is added to account for the longest channel
names that display (before truncation occurs) so that
columns are always properly aligned.

ASTERISK-29895 #close
patches:
  61205_misaligned2.patch submitted by Birger Harzenetter (license 5870)

Change-Id: I450ce6bb81157b9d6d149007e53b749f237b6d9f
2022-03-28 15:07:08 -05:00
Sean Bright 939a7c0dc3 openssl: Supress deprecation warnings from OpenSSL 3.0
There is work going on to update our OpenSSL usage to avoid the
deprecated functions but in the meantime make it possible to compile
in devmode.

Change-Id: Ib082eb8b3751f0185d8aa8fe127da664c93f0726
2022-03-28 12:23:09 -05:00
Marcel Wagner 459d6f7ad2 documentation: Add information on running install_prereq script in readme
Adding information in the readme about running the install_preqreq script to install components that the ./configure script might indicate as missing.

ASTERISK-29976 #close

Change-Id: Ic287b46300168729838bddd8f9265e98fc22bce6
2022-03-28 11:32:06 -05:00
Naveen Albert 0bf75aa0a2 res_agi: Fix xmldocs bug with set music.
The XML documentation for the SET MUSIC AGI
command is invalid, as the parameter does not
have a name and the on/off enum options for
the on/off argument are listed separately, which
is incorrect. The cumulative effect of these currently
is that the Asterisk Wiki documentation for SET MUSIC
is broken and external documentation generators crash
on SET MUSIC due to the malformed documentation.

These issues are corrected so that the documentation
can be successfully parsed as with other similar AGI
commands.

ASTERISK-29939 #close
ASTERISK-28891 #close

Change-Id: I8c3d59897531bcbc401cbc7b00c9e2829dcb35f8
(cherry picked from commit 37ece75677)
2022-03-25 18:26:41 -05:00
Naveen Albert 56ed64e086 chan_iax2: Fix perceived showing host address.
ASTERISK_22025 introduced a regression that shows
the host IP and port as the perceived IP and port
again, as opposed to showing the actual perceived
address. This fixes this by showing the correct
information.

ASTERISK-29048 #close

Change-Id: I0ad3e25bc6b449e83ce72ea5d1a1cdba72aa304a
2022-03-25 17:35:38 -05:00
Hugh McMaster d132184520 configure.ac: Use pkg-config to detect libxml2
Use pkg-config to detect libxml2, falling back to xml2-config if the
former is not available.

This patch ensures Asterisk continues to build on systems without
xml2-config installed.

The patch also updates the associated 'configure' files.

ASTERISK-29970 #close

Change-Id: I3c90dfe0b0590486cbb8e6d426a7c5c4199410c0
2022-03-25 14:26:29 -05:00
Philip Prindeville ed8ca6c38a time: add support for time64 libcs
Treat time_t's as entirely unique and use the POSIX API's for
converting to/from strings.

Lastly, a 64-bit integer formats as 20 digits at most in base10.
Don't need to have any 100 byte buffers to hold that.

ASTERISK-29674 #close

Signed-off-by: Philip Prindeville <philipp@redfish-solutions.com>
Change-Id: Id7b25bdca8f92e34229f6454f6c3e500f2cd6f56
2022-03-24 11:24:58 -05:00
Sean Bright bf825a5050 conversions.c: Specify that we only want to parse decimal numbers.
Passing 0 as the last argument to strtoimax() or strtoumax() causes
octal and hexadecimal to be accepted which was not originally
intended. So we now force to only accept decimal.

ASTERISK-29950 #close

Change-Id: I93baf0f273441e8280354630a463df263a8c0edd
2022-03-23 18:11:54 -05:00
Philip Prindeville 70a958a051 logger: workaround woefully small BUFSIZ in MUSL
MUSL defines BUFSIZ as 1024 which is not reasonable for log messages.

More broadly, BUFSIZ is the amount of buffering stdio.h does, which
is arbitrary and largely orthogonal to what logging should accept
as the maximum message size.

ASTERISK-29928

Signed-off-by: Philip Prindeville <philipp@redfish-solutions.com>
Change-Id: Iaa49fbbab029c64ae3d95e4b18270e0442cce170
2022-03-23 18:10:54 -05:00
Naveen Albert 297ceeb9e4 app_dial: Document DIALSTATUS return values.
Adds documentation for all of the possible return values
for the DIALSTATUS variable in the Dial application.

ASTERISK-25716

Change-Id: Id22593f1f1f7ea86e5734cee49516ec50848e8c0
2022-03-23 18:09:42 -05:00
Sean Bright b15d2f9e4b stasis_recording: Perform a complete match on requested filename.
Using the length of a file found on the filesystem rather than the
file being requested could result in filenames whose names are
substrings of another to be erroneously matched.

We now ensure a complete comparison before returning a positive
result.

ASTERISK-29960 #close

Change-Id: Id3ffc77681b9b75b8569062f3d952a128a21c71a
2022-03-23 18:08:07 -05:00
Sean Bright 5a30f0c6fe download_externals: Use HTTPS for downloads
ASTERISK-29980 #close

Change-Id: I7b347665822ea2774dd322276c09be67914d2065
2022-03-23 18:06:19 -05:00
Alexei Gradinari 4027626709 res_pjsip_pubsub: RLS 'uri' list attribute mismatch with SUBSCRIBE request
When asterisk generates the RLMI part of NOTIFY request,
the asterisk uses the local contact uri instead of the URI to which
the SUBSCRIBE request is sent.
Because of this mismatch some IP phones (for example Cisco 5XX) ignore
this list.

According
https://datatracker.ietf.org/doc/html/rfc4662#section-5.2
  The first mandatory <list> attribute is "uri", which contains the uri
  that corresponds to the list. Typically, this is the URI to which
  the SUBSCRIBE request was sent.
https://datatracker.ietf.org/doc/html/rfc4662#section-5.3
  The "uri" attribute identifies the resource to which the <resource>
  element corresponds. Typically, this will be a SIP URI that, if
  subscribed to, would return the state of the resource.

This patch makes asterisk to generate URI using SUBSCRIBE request URI.

ASTERISK-29961 #close

Change-Id: I1fcfc08fd589677f40608c59a4e143c45ee05f6c
2022-03-23 17:51:21 -05:00
Naveen Albert c5b49f1405 pbx_builtins: Add missing options documentation
BackGround and WaitExten both accept options that are not
currently documented. This adds documentation for these
options to the xml documentation for each application.

ASTERISK-29967 #close

Change-Id: If812a9f1ccbba3e4d427a0e7a6dea923c2f905f7
2022-03-23 16:05:29 -05:00
Asterisk Development Team 96f98908f9 Update CHANGES and UPGRADE.txt for 19.3.0 2022-03-17 10:26:57 -05:00
Ben Ford 0c07f94c00 AMI: Bump version for 19.3.0.
Change-Id: Ia41acd3f4f9589e8d3ecda3193764c83dade6186
2022-03-17 09:24:33 -05:00
Alexei Gradinari 49928fee53 res_pjsip_pubsub: update RLS to reflect the changes to the lists
This patch makes the Resource List Subscriptions (RLS) dynamic.
The asterisk updates the current subscriptions to reflect the changes
to the list on the subscriptions refresh. If list items are added,
removed, updated or do not exist anymore, the asterisk regenerates
the resource list.

ASTERISK-29906 #close

Change-Id: Icee8c00459a7aaa43c643d77ce6f16fb7ab037d3
2022-03-15 11:12:56 -05:00
Boris P. Korzun 00a7fa985e res_config_pgsql: Add text-type column check in require_pgsql()
Omit "unsupported column type 'text'" warning in logs while
using text-type column in the PgSQL backend.

ASTERISK-29924 #close

Change-Id: I48061a7d469426859670db07f1ed8af1eb814712
2022-03-14 09:11:57 -05:00
Kfir Itzhak 5edbc54c54 app_queue: Add QueueWithdrawCaller AMI action
This adds a new AMI action called QueueWithdrawCaller.
This AMI action makes it possible to withdraw a caller from a queue,
in a safe and a generic manner.
This can be useful for retrieving a specific call and
dispatching it to a specific extension.
It works by signaling the caller to exit the queue application
whenever it can. Therefore, it is not guaranteed
that the call will leave the queue.

ASTERISK-29909 #close

Change-Id: Ic15aa238e23b2884abdcaadff2fda7679e29b7ec
2022-03-11 08:48:04 -06:00
Kevin Harwell b81db677c9 AST-2022-006: pjproject - unconstrained malformed multipart SIP message
ASTERISK-29945 #close

Change-Id: Ic58957afc453195d53c2bd25c905df3d91d1abe6
2022-03-04 12:49:26 -06:00
Kevin Harwell f9cd83ff35 AST-2022-005: pjproject - undefined behavior after freeing a dialog set
ASTERISK-29945 #close

Change-Id: Ia8ce6d82b115c82c1138747c72a0adcaa42b718c
2022-03-04 12:46:28 -06:00
Kevin Harwell ac8de6e31d AST-2022-004: pjproject - possible integer underflow on STUN message
ASTERISK-29945 #close

Change-Id: I721cd254e4f8aa6d3a97a37529cca53519694c54
2022-03-04 12:35:00 -06:00
George Joseph 1dc792a312 xml.c, config,c: Add stylesheets and variable list string parsing
Added functions to open, close, and apply XML Stylesheets
to XML documents.  Although the presence of libxslt was already
being checked by configure, it was only happening if xmldoc was
enabled.  Now it's checked regardless.

Added ability to parse a string consisting of comma separated
name/value pairs into an ast_variable list.  The reverse of
ast_variable_list_join().

Change-Id: I1e1d149be22165a1fb8e88e2903a36bba1a6cf2e
2022-03-03 05:44:58 -06:00
George Joseph d00108df72 xmldoc: Fix issue with xmlstarlet validation
Added the missing xml-stylesheet and Xinclude namespace
declarations in pjsip_config.xml and pjsip_manager.xml.

Updated make_xml_documentation to show detailed errors when
xmlstarlet is the validator.  It's now run once with the '-q'
option to suppress harmless/expected messages and if it actually
fails, it's run again without '-q' but with '-e' to show
the actual errors.

Change-Id: I4bdc9d2ea6741e8d2e5eb82df60c68ccc59e1f5e
2022-03-01 11:04:01 -06:00
George Joseph 38df1c35ee core: Config and XML tweaks needed for geolocation
Added:

Replace a variable in a list:
int ast_variable_list_replace_variable(struct ast_variable **head,
    struct ast_variable *old, struct ast_variable *new);
Added test as well.

Create a "name=value" string from a variable list:
'name1="val1",name2="val2"', etc.
struct ast_str *ast_variable_list_join(
    const struct ast_variable *head, const char *item_separator,
    const char *name_value_separator, const char *quote_char,
    struct ast_str **str);
Added test as well.

Allow the name of an XML element to be changed.
void ast_xml_set_name(struct ast_xml_node *node, const char *name);

Change-Id: I330a5f63dc0c218e0d8dfc0745948d2812141ccb
2022-02-28 08:47:44 -06:00
George Joseph e29cd99975 Makefile: Allow XML documentation to exist outside source files
Moved the xmldoc build logic from the top-level Makefile into
its own script "make_xml_documentation" in the build_tools
directory.

Created a new utility script "get_sourceable_makeopts", also in
the build_tools directory, that dumps the top-level "makeopts"
file in a format that can be "sourced" from shell sscripts.
This allows scripts to easily get the values of common make
build variables such as the location of the GREP, SED, AWK, etc.
utilities as well as the AST* and library *_LIB and *_INCLUDE
variables.

Besides moving logic out of the Makefile, some optimizations
were done like removing "third-party" from the list of
subdirectories to be searched for documentation and changing some
assignments from "=" to ":=" so they're only evaluated once.
The speed increase is noticeable.

The makeopts.in file was updated to include the paths to
REALPATH and DIRNAME.  The ./conifgure script was setting them
but makeopts.in wasn't including them.

So...

With this change, you can now place documentation in any"c"
source file AND you can now place it in a separate XML file
altogether.  The following are examples of valid locations:

res/res_pjsip.c
    Using the existing /*** DOCUMENTATION ***/ fragment.

res/res_pjsip/pjsip_configuration.c
    Using the existing /*** DOCUMENTATION ***/ fragment.

res/res_pjsip/pjsip_doc.xml
    A fully-formed XML file.  The "configInfo", "manager",
    "managerEvent", etc. elements that would be in the "c"
    file DOCUMENTATION fragment should be wrapped in proper
    XML.  Example for "somemodule.xml":

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE docs SYSTEM "appdocsxml.dtd">
    <docs>
        <configInfo>
        ...
        </configInfo>
    </docs>

It's the "appdocsxml.dtd" that tells make_xml_documentation
that this is a documentation XML file and not some other XML file.
It also allows many XML-capable editors to do formatting and
validation.

Other than the ".xml" suffix, the name of the file is not
significant.

As a start... This change also moves the documentation that was
in res_pjsip.c to 2 new XML files in res/res_pjsip:
pjsip_config.xml and pjsip_manager.xml.  This cut the number of
lines in res_pjsip.c in half. :)

Change-Id: I486c16c0b5a44d7a8870008e10c941fb19b71ade
2022-02-28 08:17:40 -06:00
George Joseph ca18e68470 build: Refactor the earlier "basebranch" commit
Recap from earlier commit:  If you have a development branch for a
major project that will receive gerrit reviews it'll probably be
named something like "development/16/newproject" or a work branch
based on that "development" branch.  That will necessitate
setting "defaultbranch=development/16/newproject" in .gitreview.
The make_version script uses that variable to construct the
asterisk version however, which results in versions
like "GIT-development/16/newproject-ee582a8c7b" which is probably
not what you want.  It also constructs the URLs for downloading
external modules with that version, which will fail.

Fast-forward:

The earlier attempt at adding a "basebranch" variable to
.gitreview didn't work out too well in practice because changes
were made to .gitreview, which is a checked-in file.  So, if
you wanted to rebase your work branch on the base branch, rebase
would attempt to overwrite your .gitreview with the one from
the base branch and complain about a conflict.

This is a slighltly different approach that adds three methods to
determine the mainline branch:

1.  --- MAINLINE_BRANCH from the environment

If MAINLINE_BRANCH is already set in the environment, that will
be used.  This is primarily for the Jenkins jobs.

2.  --- .develvars

Instead of storing the basebranch in .gitreview, it can now be
stored in a non-checked-in ".develvars" file and keyed by the
current branch.  So, if you were working on a branch named
"new-feature-work" based on "development/16/new-feature" and wanted
 to push to that branch in Gerrit but wanted to pull the external
 modules for 16, you'd create the following .develvars file:

[branch "new-feature-work"]
    mainline-branch = 16

The .gitreview file would still look like:

[gerrit]
defaultbranch=development/16/new-feature

...which would cause any reviews pushed from "new-feature-work" to
go to the "development/16/new-feature" branch in Gerrit.

The key is that the .develvars file is NEVER checked in (it's been
added to .gitignore).

3.  --- Well Known Development Branch

If you're actually working in a branch named like
"development/<mainline_branch>/some-feature", the mainline branch
will be parsed from it.

4.  --- .gitreview

If none of the earlier conditions exist, the .gitreview
"defaultbranch" variable will be used just as before.

Change-Id: I1cdeeaa0944bba3f2e01d7a2039559d0c266f8c9
2022-02-28 07:41:48 -06:00
Joshua C. Colp 3d30f68fbc jansson: Update bundled to 2.14 version.
ASTERISK-29353

Change-Id: I4ea43eda1691565563a4c03ef37166952d211b2b
2022-02-25 15:34:14 -06:00
Naveen Albert 8a94702386 ami: Allow events to be globally disabled.
The disabledevents setting has been added to the general section
in manager.conf, which allows users to specify events that
should be globally disabled and not sent to any AMI listeners.

This allows for processing of these AMI events to end sooner and,
for frequent AMI events such as Newexten which users may not have
any need for, allows them to not be processed. Additionally, it also
cleans up core debug as previously when debug was 3 or higher,
the debug was constantly spammed by "Analyzing AMI event" messages
along with a complete dump of the event contents (often for Newexten).

ASTERISK-29853 #close

Change-Id: Id42b9a3722a1f460d745cad1ebc47c537fd4f205
2022-02-25 15:10:20 -06:00
Naveen Albert ff603d16c7 func_channel: Add lastcontext and lastexten.
Adds the lastcontext and lastexten channel fields to allow users
to access previous dialplan execution locations.

ASTERISK-29840 #close

Change-Id: Ib455fe300cc8e9a127686896ee2d0bd11e900307
2022-02-25 14:42:46 -06:00
Naveen Albert 51146db5fe channel.c: Clean up debug level 1.
Although there are 10 debugs levels, over time,
many current debug calls have come to use
inappropriately low debug levels. In particular,
a select few debug calls (currently all debug 1)
can result in thousands of debug messages per minute
for a single call.

This can adds a lot of noise to core debug
which dilutes the value in having different
debug levels in the first place, as these
log messages are from the core internals are
are better suited for higher debug levels.

Some debugs levels are thus adjusted so that
debug level 1 is not inappropriately overloaded
with these extremely high-volume and general
debug messages.

ASTERISK-29897 #close

Change-Id: I55a71598993552d3d64a401a35ee99474770d4b4
2022-02-25 14:16:28 -06:00
Naveen Albert e16fce2251 configs, LICENSE: remove pbx.digium.com.
pbx.digium.com no longer accepts IAX2 calls and
there are no plans for it to come back.

Accordingly, nonworking IAX2 URIs are removed from
both the LICENSE file and the sample config.

ASTERISK-29923 #close

Change-Id: I257c54d4d812ed6b4bd4cbec2cd7ebe2b87b5bad
2022-02-25 13:43:57 -06:00
Naveen Albert d5c72f35fd asterisk: Add macro for curl user agent.
Currently, each module that uses libcurl duplicates the standard
Asterisk curl user agent.

This adds a global macro for the Asterisk user agent used for
curl requests to eliminate this duplication.

ASTERISK-29861 #close

Change-Id: I9fc37935980384b4daf96ae54fa3c9adb962ed2d
2022-02-25 13:04:01 -06:00
Naveen Albert eb77229b53 documentation: Add since tag to xmldocs DTD
Adds the since tag to the documentation DTD so
that individual applications, functions, etc.
can now specify when they were added to Asterisk.

This tag is added at the individual application,
function, etc. level as opposed to at the module
level because modules can expand over time as new
functionality is added, and granularity only
to the module level would generally not be useful.

This enables the ability to more easily determine
when new functionality was added to Asterisk, down
to minor version as opposed to just by major version.
This makes it easier for users to write more portable
dialplan if desired to not use functionality that may
not be widely available yet.

ASTERISK-29896 #close

Change-Id: Ibbb35c702d8038bdc3fd0a944fbfa69384cc15d5
2022-02-24 06:37:44 -06:00
Naveen Albert 4cb4a3ed01 res_stir_shaken: refactor utility function
Refactors temp file utility function into file.c.

ASTERISK-29809 #close

Change-Id: Ife478708c8f2b127239cb73c1755ef18c0bf431b
2022-02-23 17:05:16 -06:00
Naveen Albert 19481fc1f0 app_voicemail: Emit warning if asking for nonexistent mailbox.
Currently, if VoiceMailMain is called with a mailbox, if that
mailbox doesn't exist, then the application silently falls back
to prompting the user for the mailbox, as if no arguments were
provided.

However, if a specific mailbox is requested and it doesn't exist,
then no warning at all is emitted.

This fixes this behavior to now warn if a specifically
requested mailbox could not be accessed, before falling back to
prompting the user for the correct mailbox.

ASTERISK-29920 #close

Change-Id: Ib4093b88cd661a2cabc5d685777d4e2f0ebd20a4
2022-02-23 16:41:40 -06:00
Alexei Gradinari 76f90bff75 res_pjsip_pubsub: fix Batched Notifications stop working
If Subscription refresh occurred between when the batched notification
was scheduled and the serialized notification was to be sent,
then new schedule notification task would never be added.

There are 2 threads:

thread #1. ast_sip_subscription_notify is called,
if notification_batch_interval then call schedule_notification.
1.1. The schedule_notification checks notify_sched_id > -1
not true, then
send_scheduled_notify = 1
notify_sched_id =
  ast_sched_add(sched, sub_tree->notification_batch_interval, sched_cb....
1.2. The sched_cb pushes task serialized_send_notify to serializer
and returns 0 which means no reschedule.
1.3. The serialized_send_notify checks send_scheduled_notify if it's false
the just returns. BUT notify_sched_id is still set, so no more ast_sched_add.

thread #2. pubsub_on_rx_refresh is called
2.1 it pushes serialized_pubsub_on_refresh_timeout to serializer
2.2. The serialized_pubsub_on_refresh_timeout calls pubsub_on_refresh_timeout
which calls send_notify
2.3. The send_notify set send_scheduled_notify = 0;

The serialized_send_notify should always unset notify_sched_id.

ASTERISK-29904 #close

Change-Id: Ifc50c00b213c396509e10326a1ed89d8cf8c7875
2022-02-23 16:09:27 -06:00
Naveen Albert 257590b4e2 func_db: Add validity check for key names when writing.
Adds a simple sanity check for key names when users are
writing data to AstDB. This captures four cases indicating
malformed keynames that generally result in bad data going
into the DB that the user didn't intend: an empty key name,
a key name beginning or ending with a slash, and a key name
containing two slashes in a row. Generally, this is the
result of a variable being used in the key name being empty.

If a malformed key name is detected, a warning is emitted
to indicate the bug in the dialplan.

ASTERISK-29925 #close

Change-Id: Ifc08a9fe532a519b1b80caca1aafed7611d573bf
2022-02-23 15:16:59 -06:00
Alexei Gradinari e85ee05e9d res_pjsip_pubsub: provide a display name for RLS subscriptions
Whereas BLFs allow to show a display name for each RLS entry,
the asterisk provides only the extension now.
This is not end user friendly.

This commit adds a new resource_list option, resource_display_name,
to indicate whether display name of resource or the resource name being
provided for RLS entries.
If this option is enabled, the Display Name will be provided.
This option is disabled by default to remain the previous behavior.
If the 'event' set to 'presence' or 'dialog' the non-empty HINT name
will be set as the Display Name.
The 'message-summary' is not supported yet.

ASTERISK-29891 #close

Change-Id: Ic5306bd5a7c73d03f5477fe235e9b0f41c69c681
2022-02-23 14:25:22 -06:00
Naveen Albert 57685c139b documentation: Adds missing default attributes.
The configObject tag contains a default attribute which
allows the default value to be specified, if applicable.
This allows for the default value to show up specially on
the wiki in a way that is clear to users.

There are a couple places in the tree where default values
are included in the description as opposed to as attributes,
which means these can't be parsed specially for the wiki.
These are changed to use the attribute instead of being
included in the text description.

ASTERISK-29898 #close

Change-Id: I9d7ea08f50075f41459ea7b76654906b674ec755
2022-02-23 13:47:53 -06:00
Naveen Albert e8f8d84ffd cli: Add core dump info to core show settings.
Adds two pieces of information to the core show settings command
which are useful in the context of getting backtraces.

The first is to display whether or not Asterisk would generate
a core dump if it were to crash.

The second is to show the current running directory of Asterisk.

ASTERISK-29866 #close

Change-Id: Ic42c0a9ecc233381aad274d86c62808d1ebb4d83
2022-02-23 13:38:05 -06:00
Naveen Albert b54060021f app_mp3: Document and warn about HTTPS incompatibility.
mpg123 doesn't support HTTPS, but the MP3Player application
doesn't document this or warn the user about this. HTTPS
streams have become more common nowadays and users could
reasonably try to play them without being aware they should
use the HTTP stream instead.

This adds documentation to note this limitation. It also
throws a warning if users try to use the HTTPS stream to
tell them to use the HTTP stream instead.

ASTERISK-29900 #close

Change-Id: Ie3b029be5258c5a701f71ed3b1a7a80d1e03b827
2022-02-23 12:21:37 -06:00
Naveen Albert ba2f780930 app_mf: Add max digits option to ReceiveMF.
Adds an option to the ReceiveMF application to allow specifying a
maximum number of digits.

Originally, this capability was not added to ReceiveMF as it was
with ReceiveSF because typically a ST digit is used to denote that
sending of digits is complete. However, there are certain signaling
protocols which simply transmit a digit (such as Expanded In-Band
Signaling) and for these, it's necessary to be able to read a
certain number of digits, as opposed to until receiving a ST digit.

This capability is added as an option, as opposed to as a parameter,
to remain compatible with existing usage (and not shift the
parameters).

ASTERISK-29877 #close

Change-Id: I4229167c9aa69b87402c3c2a9065bd8dfa973a0b
2022-02-17 11:21:52 -06:00
Mike Bradeen 5764414d10 taskprocessor.c: Prevent crash on graceful shutdown
When tps_shutdown is called as part of the cleanup process there is a
chance that one of the taskprocessors that references the
tps_singletons object is still running.  The change is to allow for
tps_shutdown to check tps_singleton's container count and give the
running taskprocessors a chance to finish.  If after
AST_TASKPROCESSOR_SHUTDOWN_MAX_WAIT (10) seconds there are still
container references we shutdown anyway as this is most likely a bug
due to a taskprocessor not being unreferenced.

ASTERISK-29365

Change-Id: Ia932fc003d316389b9c4fd15ad6594458c9727f1
2022-02-14 16:19:45 -06:00
Alexei Gradinari 5f22f586ff app_queue: load queues and members from Realtime when needed
There are a lot of Queue AMI actions and Queue applications
which do not load queue and queue members from Realtime.

AMI actions
QueuePause - if queue not in memory - response "Interface not found".
QueueStatus/QueueSummary - if queue not in memory - empty response.

Applications:
PauseQueueMember - if queue not in memory
	Attempt to pause interface %s, not found
UnpauseQueueMember - if queue not in memory
	Attempt to unpause interface xxxxx, not found

This patch adds a new function load_realtime_queues
which loads queue and queue members for desired queue
or all queues and all members if param 'queuename' is NULL or empty.
Calls the function load_realtime_queues when needed.

Also this patch fixes leak of ast_config in function set_member_value.

Also this patch fixes incorrect LOG_WARNING when pausing/unpausing
already paused/unpaused member.
The function ast_update_realtime returns 0 when no record modified.
So 0 is not an error to warn about.

ASTERISK-29873 #close
ASTERISK-18416 #close
ASTERISK-27597 #close

Change-Id: I554ee0eebde93bd8f49df7f84b74acb21edcb99c
2022-02-11 12:56:54 -06:00
Sean Bright 67eb7c9e85 manager.c: Simplify AMI ModuleCheck handling
This code was needlessly complex and would fail to properly delimit
the response message if LOW_MEMORY was defined.

Change-Id: Iae50bf09ef4bc34f9dc4b49435daa76f8b2c5b6e
2022-02-11 11:55:23 -06:00
Mark Petersen 97ac3c1385 res_prometheus.c: missing module dependency
added res_pjsip_outbound_registration to .requires in AST_MODULE_INFO
which fixes issue with module crashes on load "FRACK!, Failed assertion"

ASTERISK-29871

Change-Id: Ia0f49d048427a40e1b763296b834a52a03610096
2022-02-10 12:57:58 -06:00
Sean Bright dfbb547f6a res_pjsip.c: Correct minor typos in 'realm' documentation.
Change-Id: I886936b808def5540d40071321e72f6bfa19063a
2022-02-03 17:00:05 -06:00
Sean Bright b42dd930f4 manager.c: Generate valid XML if attribute names have leading digits.
The XML Manager Event Interface (amxml) now generates attribute names
that are compliant with the XML 1.1 specification. Previously, an
attribute name that started with a digit would be rendered as-is, even
though attribute names must not begin with a digit. We now prefix
attribute names that start with a digit with an underscore ('_') to
prevent XML validation failures.

This is not backwards compatible but my assumption is that compliant
XML parsers would already have been complaining about this.

ASTERISK-29886 #close

Change-Id: Icfaa56a131a082d803e9b7db5093806d455a0523
2022-02-03 07:55:57 -06:00
Asterisk Development Team 3d390c4df7 Update CHANGES and UPGRADE.txt for 19.2.0 2022-02-03 07:15:01 -05:00
Sean Bright 8b4531051b build_tools/make_version: Fix bashism in comparison.
In POSIX sh (which we indicate in the shebang), there is no ==
operator.

Change-Id: Ic03d38214d14cdf329b0ba272279a815bb532965
2022-02-01 14:26:15 -06:00
George Joseph 3f108867d6 bundled_pjproject: Add additional multipart search utils
Added the following APIs:
pjsip_multipart_find_part_by_header()
pjsip_multipart_find_part_by_header_str()
pjsip_multipart_find_part_by_cid_str()
pjsip_multipart_find_part_by_cid_uri()

Change-Id: I6aee3dcf59eb171f93aae0f0564ff907262ef40d
2022-02-01 10:46:23 -06:00
Mark Petersen 25edc8ba47 chan_sip.c Fix pickup on channel that are in AST_STATE_DOWN
resolve issue with pickup on device that uses "183" and not "180"

ASTERISK-29832

Change-Id: I4c7d223870f8ce9a7354e0f73d4e4cb2e8b58841
2022-02-01 08:19:49 -06:00
George Joseph 8bc6511c0c build: Add "basebranch" to .gitreview
If you have a development branch for a major project that
will receive gerrit reviews it'll probably be named something
like "development/16/newproject".  That will necessitate setting
"defaultbranch=development/16/newproject" in .gitreview.  The
make_version script uses that variable to construct the asterisk
version however, which results in versions like
"GIT-development/16/newproject-ee582a8c7b" which is probably not
what you want.  Worse, since the download_externals script uses
make_version to construct the URL to download the binary codecs
or DPMA.  Since it's expecting a simple numeric version, the
downloads will fail.

To get this to work, a new variable "basebranch" has been added
to .gitreview and make_version has been updated to use that instead
of defaultversion:

.gitreview:
defaultbranch=development/16/myproject
basebranch=16

Now git-review will send the reviews to the proper branch
(development/16/myproject) but the version will still be
constructed using the simple branch number (16).

If "basebranch" is missing from .gitreview, make_version will
fall back to using "defaultbranch".

Change-Id: I2941a3b21e668febeb6cfbc1a7bb51a67726fcc4
2022-02-01 07:39:07 -06:00
George Joseph 4142e548e8 res_pjsip_outbound_authenticator_digest: Prevent ABRT on cleanup
In dev mode, if you call pjsip_auth_clt_deinit() with an auth_sess
that hasn't been initialized, it'll assert and abort.  If
digest_create_request_with_auth() fails to find the proper
auth object however, it jumps to its cleanup which does exactly
that.  So now we no longer attempt to call pjsip_auth_clt_deinit()
if we never actually initialized it.

ASTERISK-29888

Change-Id: Ib6171c25c9fe8e61cc8d11129e324c021bc30b62
2022-02-01 05:27:35 -06:00
Naveen Albert 1a8d320a29 cdr: allow disabling CDR by default on new channels
Adds a new option, defaultenabled, to the CDR core to
control whether or not CDR is enabled on a newly created
channel. This allows CDR to be disabled by default on
new channels and require the user to explicitly enable
CDR if desired. Existing behavior remains unchanged.

ASTERISK-29808 #close

Change-Id: Ibb78c11974bda229bbb7004b64761980e0b2c6d1
2022-01-31 09:32:01 -06:00
Naveen Albert cf17b3d211 func_frame_drop: Fix typo referencing wrong buffer
In order to get around the issue of certain frames
having names that could overlap, func_frame_drop
surrounds names with commas for the purposes of
comparison.

The buffer is allocated and printed to properly,
but the original buffer is used for comparison.
In most cases, this wouldn't have had any effect,
but that was not the intention behind the buffer.
This updates the code to reference the modified
buffer instead.

ASTERISK-29854 #close

Change-Id: I430b52e14e712d0e62a23aa3b5644fe958b684a7
2022-01-31 08:56:50 -06:00
Naveen Albert d107ebd94a res_tonedetect: Fixes some logic issues and typos
Fixes some minor logic issues with the module:

Previously, the OPT_END_FILTER flag was getting
tested before options were parsed, so it could
never evaluate to true (wrong ordering).

Additionally, the initially parsed timeout (float)
needs to be compared with 0, not the result int
which is set afterwards (wrong variable).

ASTERISK-29857 #close

Change-Id: I0062bce3b391c15e5df7a714780eeaa96dd93d4c
2022-01-31 08:49:18 -06:00
Torrey Searle 34065c7d84 res/res_rtp_asterisk: fix skip in rtp sequence numbers after dtmf
When generating dtmfs, asterisk can incorrectly think packet loss
occured during the dtmf generation, resulting in a jump in sequence
numbers when forwarding voice frames resumes.  This patch forces
asterisk to re-learn the expected sequence number after each DTMF
to avoid this

ASTERISK-29869 #close

Change-Id: Icc7de3d947b207b82c99d3c327af8095884df853
2022-01-31 07:53:13 -06:00
Sean Bright 8d1858e570 build: Rebuild configure and autoconfig.h.in
autoconfigh.h.in was missed in the original review for this
issue. Additionally it looks like I have newer pkg-config autoconf
macros on my development machine.

ASTERISK-29817

Change-Id: I3c85a4de82c5d7d6e0e23dad4c33bb650a86a57b
2022-01-31 07:17:52 -06:00
Kevin Harwell 9f5c1d30ed res_http_websocket: Add a client connection timeout
Previously there was no way to specify a connection timeout when
attempting to connect a websocket client to a server. This patch
makes it possible to now do such.

Change-Id: I5812f6f28d3d13adbc246517f87af177fa20ee9d
2022-01-31 06:58:15 -06:00
Mike Bradeen c1ca028a0b sched: fix and test a double deref on delete of an executing call back
sched: Avoid a double deref when AST_SCHED_DEL_UNREF is called on an
executing call-back. This is done by adding a new variable 'rescheduled'
to the struct sched which is set in ast_sched_runq and checked in
ast_sched_del_nonrunning. ast_sched_del_nonrunning is a replacement for
now deprecated ast_sched_del which returns a new possible value -2
if called on an executing call-back with rescheduled set. ast_sched_del
is modified to call ast_sched_del_nonrunning to maintain existing code.
AST_SCHED_DEL_UNREF is also updated to look for the -2 in which case it
will not throw a warning or invoke refcall.
test_sched: Add a new unit test sched_test_freebird that will check the
reference count in the resolved scenario.

ASTERISK-29698

Change-Id: Icfb16b3acbc29cf5b4cef74183f7531caaefe21d
2022-01-21 10:06:38 -06:00
Mark Petersen 3522b07b64 app_queue.c: Queue don't play "thank-you" when here is no hold time announcements
if holdtime is (0 min, 0 sec) there is no hold time announcements
we should then also not playing queue-thankyou

ASTERISK-29831

Change-Id: Ic7e51dcde526b23f1cd8d24e1d1e2d81e10f9d2c
2022-01-20 11:30:57 -06:00
Luke Escude c3d571f335 res_pjsip_sdp_rtp.c: Support keepalive for video streams.
ASTERISK-28890 #close

Change-Id: Iad269a8dc36f892ede90fe8ceb3010560c0f70d1
2022-01-20 08:14:43 -06:00
Michał Górny 43661122f5 build_tools/make_version: Fix sed(1) syntax compatibility with NetBSD
Fix the sed(1) invocation used to process git-svn-id not to use "\s"
that is a GNU-ism and is not supported by NetBSD sed.  As a result,
this call did not work properly and make_version did output the full
git-svn-id line rather than the revision.

ASTERISK-29852

Change-Id: Ie4b406e2748920643446851a0a252a4ca7245772
2022-01-19 16:24:43 -06:00
Michał Górny de420bffa7 main/utils: Implement ast_get_tid() for NetBSD
Implement the ast_get_tid() function for NetBSD system.  NetBSD supports
getting the TID via _lwp_self().

ASTERISK-29850

Change-Id: If57fd3f9ea15ef5d010bfbdcbbbae9b379f72f8c
2022-01-19 11:42:20 -06:00
Michał Górny a7f7e5ab76 main: Enable rdtsc support on NetBSD
Enable the Linux rdtsc implementation on NetBSD as well.  The assembly
works correctly there.

ASTERISK-29851

Change-Id: I460ad9b4d971913420ecb84186f5ba5ab03f6f37
2022-01-19 11:16:46 -06:00
Michał Górny addb7278d4 include: Remove unimplemented HMAC declarations
Remove the HMAC declarations from the includes.  They are
not implemented nor used anywhere, and their presence breaks the build
on NetBSD that delivers an incompatible hmac() function in <stdlib.h>.

ASTERISK-29818

Change-Id: I0c4b88645e30174b1b63846a6b328625b69c2ea7
2022-01-19 10:35:05 -06:00
Naveen Albert c452cc3f22 res_rtp_asterisk: Fix typo in flag test/set
The code currently checks to see if an RFC3389
warning flag is set, except if it is, it merely
sets the flag again, the logic of which doesn't
make any sense.

This adjusts the if comparison to check if the
flag has NOT been set, and if so, emit a notice
log event and set the flag so that future frames
do not cause an event to be logged.

ASTERISK-29856 #close

Change-Id: Ib7098c947c63537d087a03b4646199fbb963f8e1
2022-01-19 10:34:53 -06:00
Michał Górny e32aec6c09 BuildSystem: Fix misdetection of gethostbyname_r() on NetBSD
Fix the configure script not to detect the presence of gethostbyname_r()
on NetBSD incorrectly.  NetBSD includes it as an internal libc symbol
that is not exposed in system headers and that is incompatible with
other implementations.  In order to avoid misdetecting it, perform
the symbol check only if the declaration is found in the public header
first.

ASTERISK-29817

Change-Id: Iafa359b09908251bcd299ff54be003ea129b9eda
2022-01-19 10:22:28 -06:00
Naveen Albert d3bd4a3a73 frame.h: Fix spelling typo
Fixes CNG description from "noice" to "noise".

ASTERISK-29855 #close

Change-Id: Ie7cbbd7d72b426693df7447384ff8700318cd36d
2022-01-19 09:34:53 -06:00
George Joseph 3a18886803 bundled_pjproject: Fix srtp detection
Reverted recent change that set '--with-external-srtp' instead
of '--without-external-srtp'.  Since Asterisk handles all SRTP,
we don't need it enabled in pjproject at all.

ASTERISK-29867

Change-Id: I2ce1bdd30abd21c062eac8f8fefe9b898787b801
2022-01-19 07:39:36 -06:00
George Joseph eb1e20cf89 res_pjsip: Make message_filter and session multipart aware
Neither pjsip_message_filter's filter_on_tx_message() nor
res_pjsip_session's session_outgoing_nat_hook() were multipart
aware and just assumed that an SDP would be the only thing in
a message body.  Both were changed to use the new
pjsip_get_sdp_info() function which searches for an sdp in
both single- and multi- part message bodies.

ASTERISK-29813

Change-Id: I8f5b8cfdc27f1d4bd3e7491ea9090951a4525c56
2022-01-17 10:39:34 -06:00
George Joseph f41cce9c12 build: Fix issues building pjproject
The change to allow easier hacking on bundled pjproject created
a few issues:

* The new Makefile was trying to run the bundled make even if
  PJPROJECT_BUNDLED=no.  third-party/Makefile now checks for
  PJPROJECT_BUNDLED and JANSSON_BUNDLED and skips them if they
  are "no".

* When building with bundled, config_site.h was being copied
  only if a full make or a "make main" was done.  A "make res"
  would fail all the pjsip modules because they couldn't find
  config_site.h.  The Makefile now copies config_site.h and
  asterisk_malloc_debug.h into the pjproject source tree
  when it's "configure" is performed.  This is how it used
  to be before the big change.

ASTERISK-29858

Change-Id: I9427264fa3cb8b3f59a95e5f9693eac236a6f76d
2022-01-17 08:54:37 -06:00
George Joseph a611c07dd4 res_pjsip: Add utils for checking media types
Added two new functions to assist checking media types...

* ast_sip_are_media_types_equal compares two pjsip_media_types.
* ast_sip_is_media_type_in tests if one media type is in a list
  of others.

Added static definitions for commonly used media types to
res_pjsip.h.

Changed several modules to use the new functions and static
definitions.

ASTERISK_29813
(not ready to close)

Change-Id: Ief77675235bd3bf00a6b095d4673fd878d0801b9
2022-01-17 08:27:30 -06:00
George Joseph 1ce57621de bundled_pjproject: Create generic pjsip_hdr_find functions
pjsip_msg_find_hdr(), pjsip_msg_find_hdr_by_name(), and
pjsip_msg_find_hdr_by_names() require a pjsip_msg to be passed in
so if you need to search a header list that's not in a pjsip_msg,
you have to do it yourself.  This commit adds generic versions of
those 3 functions that take in the actual header list head instead
of a pjsip_msg so if you need to search a list of headers in
something like a pjsip_multipart_part, you can do so easily.

Change-Id: I6f2c127170eafda48e5e0d5d4d187bcd52b4df07
2022-01-17 07:55:34 -06:00
Sean Bright 101a72d048 say.c: Prevent erroneous failures with 'say' family of functions.
A regression was introduced in ASTERISK~29531 that caused 'say'
functions to fail with file lists that would previously have
succeeded. This caused affected channels to hang up where previously
they would have continued.

We now explicitly check for the empty string to restore the previous
behavior.

ASTERISK-29859 #close

Change-Id: Ia2e5769868e2792313c2d7c07996efe009c6f8d5
2022-01-12 13:40:10 -06:00
Naveen Albert 23c7c101ed documentation: Document built-in system and channel vars
Documentation for built-in special system and channel
vars is currently outdated, and updating is a manual
process since there is no XML documentation for these
anywhere.

This adds documentation for system vars to func_env
and for channel vars to func_channel so that they
appear along with the corresponding fields that would
be accessed using a function.

ASTERISK-29848 #close

Change-Id: I6997f925c4a45fffe71321861f5898a8b7182fa9
2022-01-12 08:39:44 -06:00
Naveen Albert 84a596da5f pbx_variables: add missing ASTSBINDIR variable
Every config variable in the directories
section of asterisk.conf currently has a
counterpart built-in variable containing
the value of the config option, except
for the last one, astsbindir, which should
have an ASTSBINDIR variable.

However, the actual corresponding ASTSBINDIR
variable is missing in pbx_variables.c.

This adds the missing variable so that all
the config options have their corresponding
variable.

ASTERISK-29847 #close

Change-Id: I36006faf471825b36ebc8aa5e87a3bcb38d446fc
2022-01-11 09:29:56 -06:00
George Joseph d6cdfb8204 bundled_pjproject: Make it easier to hack
There are times when you need to troubleshoot issues with bundled
pjproject or add new features that need to be pushed upstream
but...

* The source directory created by extracting the pjproject tarball
  is not scanned for code changes so you have to keep forcing
  rebuilds.
* The source directory isn't a git repo so you can't easily create
  patches, do git bisects, etc.
* Accidentally doing a make distclean will ruin your day by wiping
  out the source directory, and your changes.
* etc.

This commit makes that easier.
See third-party/pjproject/README-hacking.md for the details.

ASTERISK-29824

Change-Id: Idb1251040affdab31d27cd272dda68676da9b268
2022-01-07 08:44:42 -06:00
Sean Bright 95fe90c746 utils.c: Remove all usages of ast_gethostbyname()
gethostbyname() and gethostbyname_r() are deprecated in favor of
getaddrinfo() which we use in the ast_sockaddr family of functions.

ASTERISK-29819 #close

Change-Id: Ie277c0ef768d753b169c121ef570a71665692ab7
2022-01-06 14:03:58 -06:00
Naveen Albert 8b6fca363e say.conf: fix 12pm noon logic
Fixes 12pm noon incorrectly returning 0/a.m.
Also fixes a misspelling typo in the config.

ASTERISK-29695 #close

Change-Id: Ie40f9618636eb4c483b449bd707a5dcffca5c406
2022-01-05 14:17:27 -06:00
Sean Bright cdd9b11a2d pjproject: Fix incorrect unescaping of tokens during parsing
ASTERISK-29664 #close

Change-Id: I29dcde52e9faeaf2609c604eada61c6a9e49d8f5
2022-01-05 13:12:51 -06:00
Mark Petersen 3f8ed7202f app_queue.c: Support for Nordic syntax in announcements
adding support for playing the correct en/et for nordic languages
by adding 'n' for neuter gender in the relevant ast_say_number

ASTERISK-29827

Change-Id: I03ebc827d2f0dc95132ab2f42799893c70edc5b1
2022-01-05 12:34:27 -06:00
Naveen Albert 09a0a952c6 dsp: Add define macro for DTMF_MATRIX_SIZE
Adds the macro DTMF_MATRIX_SIZE to replace
the magic number 4 sprinkled throughout
dsp.c.

ASTERISK-29815 #close

Change-Id: Ie3bddb92c6b16204ece0f758009e9490eb33b9ba
2022-01-05 12:12:24 -06:00
Naveen Albert 4794582c92 ami: Add AMI event for Wink
Adds an AMI event for a wink frame.

ASTERISK-29830 #close

Change-Id: I83e426de5e37baed79a4dbcc91e9e8d030ef1b56
2022-01-05 11:33:18 -06:00
Naveen Albert 4dcd77f6cc cli: Add module refresh command
Adds a command to the CLI to unload and then
load a module. This makes it easier to perform
these operations which are often done
subsequently to load a new version of a module.

"module reload" already refers to reloading of
configuration, so the name "refresh" is chosen
instead.

ASTERISK-29807 #close

Change-Id: I595f6f11774a0de2565a1fba38da22309ce93a2c
2022-01-05 11:32:10 -06:00
Naveen Albert dc7daf57b0 app_mp3: Throw warning on nonexistent stream
Currently, the MP3Player application doesn't
emit a warning if attempting to play a stream
which no longer exists. This can be a common
scenario as many mp3 streams are valid at some
point but can disappear at any time.

Now a warning is thrown if attempting to play
a nonexistent MP3 stream, instead of silently
exiting.

ASTERISK-29829 #close

Change-Id: I53a0bf1ed1740166655eb66fe7675f6f808bf535
2022-01-05 10:55:52 -06:00
Naveen Albert 3e7e1d1d05 documentation: Add missing AMI documentation
Adds missing documentation for some channel,
bridge, and queue events.

ASTERISK-24427
ASTERISK-29515

Change-Id: I92b06b88c8cadc0155f95ebe3e870b3e795a8c64
2022-01-05 10:31:38 -06:00
Kevin Harwell 935b8cb04e tcptls.c: refactor client connection to be more robust
The current TCP client connect code, blocks and does not handle EINTR
error case.

This patch makes the client socket non-blocking while connecting,
ensures a connect does not immediately fail due to EINTR "errors",
and adds a connect timeout option.

The original client start call sets the new timeout option to
"infinite", thus making sure old, orginal behavior is retained.

ASTERISK-29746 #close

Change-Id: I907571843a83e43c0742b95a64785f4411f02671
2022-01-05 09:40:51 -06:00
Naveen Albert 584118c7f0 app_sf: Add full tech-agnostic SF support
Adds tech-agnostic support for SF signaling
by adding SF sender and receiver applications
as well as Dial integration.

ASTERISK-29802 #close

Change-Id: I7ec50752e9a661af639425e5d1e339f17411bcad
2022-01-05 09:34:36 -06:00
Steve Davies 12d2c09dec app_queue: Fix hint updates, allow dup. hints
A previous patch for ASTERISK_29578 caused a 'leak' of
extension state information across queues, causing the
state of the first member of unrelated queues to be
updated in addition to the correct member. Which queues
and members depended on the order of queues in the
iterator.

Additionally, it is possible to use the same 'hint:' on
multiple queue members, so the update cannot break out
of the update loop early when a match is found.

ASTERISK-29806 #close

Change-Id: If2c1d1cc2a752afd9286d79710fc818596e7a7ad
2022-01-05 08:11:25 -06:00
Sean Bright c1d0e23b10 say.c: Honor requests for DTMF interruption.
SayAlpha, SayAlphaCase, SayDigits, SayMoney, SayNumber, SayOrdinal,
and SayPhonetic all claim to allow DTMF interruption if the
SAY_DTMF_INTERRUPT channel variable is set to a truthy value, but we
are failing to break out of a given 'say' application if DTMF actually
occurs.

ASTERISK-29816 #close

Change-Id: I6a96e0130560831d2cb45164919862b9bcb6287e
2022-01-05 08:05:14 -06:00
Florentin Mayer 9eacfda84d res_pjsip_sdp_rtp: Preserve order of RTP codecs
The ast_rtp_codecs_payloads functions do not preserve the order in which
the payloads were specified on an incoming SDP media line. This leads to
a problem with the codec negotiation functionality, as the format
capabilities of the stream are extracted from the ast_rtp_codecs. This
commit moves the ast_rtp_codec to ast_format conversion to the place
where the order is still known.

ASTERISK-28863
ASTERISK-29320

Change-Id: I3aabcfed3f379c36654f59c1872c313d0cb57e25
2022-01-05 07:14:14 -06:00
Joshua C. Colp 220e885bcc bridge: Unlock channel during Local peer check.
It's not safe to keep the channel locked while locking
the peer Local channel, as it can result in a deadlock.

This change unlocks it during this time but keeps the
bridge locked to ensure nothing changes about the bridge.

ASTERISK-29821

Change-Id: Ib68eb7037e5a479bcc2aceee77337cdde1fbdde6
2022-01-05 07:10:54 -06:00
Josh Soref b738e119f2 test_time.c: Tolerate DST transitions
When test_timezone_watch runs very near a DST transition,
two time zones that would otherwise be expected to report the same
time can differ because of the DST transition.

Instead of having the test fail when this happens, report the
times, time zones, and dst flags.

ASTERISK-29722

Change-Id: Id59bdac8b277e14343ccdf0c99b89e92f79f316a
2022-01-04 05:55:25 -06:00
George Joseph 09b70525e0 bundled_pjproject: Add more support for multipart bodies
Adding upstream patch for pull request...
https://github.com/pjsip/pjproject/pull/2920
---------------------------------------------------------------

sip_inv:  Additional multipart support (#2919)

sip_inv.c:inv_check_sdp_in_incoming_msg() deals with multipart
message bodies in rdata correctly. In the case where early media is
involved though, the existing sdp has to be retrieved from the last
tdata sent in this transaction. This, however, always assumes that
the sdp sent is in a non-multipart body. While there's a function
to retrieve the sdp from multipart and non-multpart rdata bodies,
no similar function for tdata exists.  So...

* The existing pjsip_rdata_get_sdp_info2 was refactored to
  find the sdp in any body, multipart or non-multipart, and
  from either an rdata or tdata.  The new function is
  pjsip_get_sdp_info.  This new function detects whether the
  pjsip_msg->body->data is the text representation of the sdp
  from an rdata or an existing pjmedia_sdp_session object
  from a tdata, or whether pjsip_msg->body is a multipart
  body containing either of the two sdp formats.

* The exsting pjsip_rdata_get_sdp_info and pjsip_rdata_get_sdp_info2
  functions are now wrappers that get the body and Content-Type
  header from the rdata and call pjsip_get_sdp_info.

* Two new wrappers named pjsip_tdata_get_sdp_info and
  pjsip_tdata_get_sdp_info2 have been created that get the body
  from the tdata and call pjsip_get_sdp_info.

* inv_offer_answer_test.c was updated to test multipart scenarios.

ASTERISK-29804

Change-Id: I483c7c3d413280c9e247a96ad581278347f9c71b
2021-12-22 09:46:58 -05:00
Frederic Van Espen 669b50983f ast_coredumper: Fix deleting results when output dir is set
When OUTPUTDIR is set to another directory and the
--delete-results-after is set, the resulting txt files are
not deleted.

ASTERISK-29794 #close

Change-Id: I1c0071f6809a1e3f5cfc455d6eb08378bc0d7286
2021-12-15 12:35:50 -06:00
Naveen Albert 5452ab997d pbx_variables: initialize uninitialized variable
The variable cp4 in a variable substitution function
can potentially be used without being initialized
currently. This causes Asterisk to no longer compile.

This initializes cp4 to NULL to make the compiler
happy.

ASTERISK-29803 #close

Change-Id: I392579cbb76db2795d5820c9427cf55fbcee9e72
2021-12-15 10:58:05 -06:00
Mark Petersen 476b8aa4e4 app_queue.c: added DIALEDPEERNUMBER on outgoing channel
added that we set DIALEDPEERNUMBER on the outgoing channels
so it is avalible in b(content^extension^line)
this add the same behaviour as Dial

ASTERISK-29795

Change-Id: Icbc589ea2066f0c401a892bf478f6b2fd44e62f6
2021-12-15 10:16:53 -06:00
Kevin Harwell df355eeb87 http.c: Add ability to create multiple HTTP servers
Previously, it was only possible to have one HTTP server in Asterisk.
With this patch it is now possible to have multiple HTTP servers
listening on different addresses.

Note, this behavior has only been made available through an API call
from within the TEST_FRAMEWORK. Specifically, this feature has been
added in order to allow unit test to create/start and stop servers,
if one has not been enabled through configuration.

Change-Id: Ic5fb5f11e62c019a1c51310f4667b32a4dae52f5
2021-12-15 10:02:29 -06:00
Naveen Albert ee163da56d app.c: Throw warnings for nonexistent options
Currently, Asterisk doesn't throw warnings if options
are passed into applications that don't accept them.
This can confuse users if they're unaware that they
are doing something wrong.

This adds an additional check to parse_options so that
a warning is thrown anytime an option is parsed that
doesn't exist in the parsing application, so that users
are notified of the invalid usage.

ASTERISK-29801 #close

Change-Id: Id029274a57135caca193c913307a63fd75e24679
2021-12-14 18:12:15 -06:00
Mark Petersen c8c9496600 app_voicemail.c: Support for Danish syntax in VM
added support for playing the correct plural sound file
dependen on where you have 1 or multipe messages
based on the existing SE/NO code

ASTERISK-29797

Change-Id: I88aa814d02f3772bb80b474204b1ffb26fe438c2
2021-12-14 05:35:48 -05:00
Naveen Albert e2e38798f0 strings: Fix enum names in comment examples
The enum values for ast_strsep_flags includes
AST_STRSEP_STRIP. However, some comments reference
AST_SEP_STRIP, which doesn't exist. This fixes
these comments to use the correct value.

ASTERISK-29800 #close

Change-Id: If7bbd0c0e6226a211d25ddf9d1629347e2674943
2021-12-14 04:19:22 -06:00
Naveen Albert bf3043ac14 configs: Updates to sample configs
Includes some minor updates to extensions.conf
and iax.conf. In particular, the demonstration
of macros in extensions.conf is removed, as
Macro is deprecated and will be removed soon.
These examples have been replaced with examples
demonstrating the usage of Gosub instead.

The older exten => ...,n syntax is also mostly
replaced with the same keyword to demonstrate the
newer, more concise way of defining extensions.

IAXTEL no longer exists, so this example is replaced
with something more generic.

Some documentation is also added to extensions.conf
and iax.conf to clarify some of the new expanded
encryption capabilities with IAX2.

ASTERISK-29758 #close

Change-Id: I04fba9671aa1ee9ba1bd5027061f80bbe38e7b46
2021-12-13 15:16:16 -06:00
Naveen Albert eaa3e32f0c app_sendtext: Add ReceiveText application
Adds a ReceiveText application that can be used in
conjunction with SendText. Currently, there is no
way in Asterisk to receive text in the dialplan
(or anywhere else, really). This allows for Asterisk
to be the recipient of text instead of just the sender.

ASTERISK-29759 #close

Change-Id: Ica2c354a42bff69f323a0493d3a7cd0fb129d52d
2021-12-13 14:03:46 -06:00
Naveen Albert 10f50f1e30 pbx_variables: Increase parsing capabilities of MSet
Currently MSet can only parse a maximum of 24 variables.
If more variables are provided to MSet, the 24th variable
will simply contain the remainder of the string and the
remaining variables thereafter will never get set.

This increases the number of variables that can be parsed
in one go from 24 to 99. Additionally, documentation is added
since this limitation is currently undocumented and is
confusing to users who encounter this limitation.

ASTERISK-29766 #close

Change-Id: I3fe35b462dedec0a452fd9ea7f92c920a3939f16
2021-12-13 13:46:06 -06:00
Naveen Albert 0f9bf737b2 chan_sip: Fix crash when accessing RURI before initiating outgoing call
Attempting to access ${CHANNEL(ruri)} in a pre-dial handler before
initiating an outgoing call will cause Asterisk to crash. This is
because a null field is accessed, resulting in an offset from null and
subsequent memory access violation.

Since RURI is not guaranteed to exist, we now check if the base
pointer is non-null before calculating an offset.

ASTERISK-29772

Change-Id: Icd3b02f07256bbe6615854af5717074087b95a83
2021-12-13 13:05:14 -06:00
Naveen Albert d93a776476 func_json: Adds JSON_DECODE function
Adds the JSON_DECODE function for parsing JSON in the
dialplan. JSON parsing already exists in the Asterisk
core and is used for many different things. This
function exposes the basic parsing capability to
the user in the dialplan, for instance, in conjunction
with CURL for using API responses.

ASTERISK-29706 #close

Change-Id: Iea60c49a7358dfdc2db60803cdc9a742f808ba2c
2021-12-13 12:34:13 -06:00
Naveen Albert 828eb997b1 pbx: Add variable substitution API for extensions
Currently, variable substitution involving dialplan
extensions is quite clunky since it entails obtaining
the current dialplan location, backing it up, storing
the desired variables for substitution on the channel,
performing substitution, then restoring the original
location.

In addition to being clunky, things could also go wrong
if an async goto were to occur and change the dialplan
location during a substitution.

Fundamentally, there's no reason it needs to be done this
way, so new API is added to allow for directly passing in
the dialplan location for the purposes of variable
substitution so we don't need to mess with the channel
information anymore. Existing API is not changed.

ASTERISK-29745 #close

Change-Id: I23273bf27fa0efb64a606eebf9aa8e2f41a065e4
2021-12-13 12:27:26 -06:00
Sean Bright a507049eb5 CHANGES: Correct reference to configuration file.
Change-Id: I22a788ebf11168fff7fbf9ea956ebcd705ab63dd
2021-12-13 11:21:30 -06:00
Naveen Albert 50716bb3e4 app_mf: Add full tech-agnostic MF support
Adds tech-agnostic support for MF signaling by adding
MF sender and receiver applications as well as Dial
integration.

ASTERISK-29496-mf #do-not-close

Change-Id: I61962b359b8ec4cfd05df877ddf9f5b8f71927a4
2021-12-13 10:04:49 -06:00
Alexander Traud e3ff42aee6 xmldoc: Avoid whitespace around value for parameter/required.
Otherwise, the value 'false' was not found in the enumerated set of
the XML DTD for the XML attribute 'required' in the XML element
'parameter'. Therefore, DTD validation of the runtime XML failed.

ASTERISK-29790

Change-Id: Id13f230ad65a70dd8c2e3ae9ac85d1e841aed03e
2021-12-13 09:11:41 -06:00
Alexander Traud 6cda1db595 progdocs: Fix Doxygen left-overs.
Change-Id: I5b5cf9c9cbbe00ba8b379a8d162ac67445d39016
2021-12-13 08:57:54 -06:00
Alexander Traud 81a9b566e8 xmldoc: Correct definition for XML element 'matchInfo'.
ASTERISK-29791

Change-Id: I7c656498427fcadd0a5d61a54ff67e6036609725
2021-12-13 08:08:25 -06:00
Alexander Traud 8261e0f0da progdocs: Update Makefile.
In developer mode, use internal documentation as well.
This should produce no warnings. Fix yours!

In noisy mode, output all possible warnings of Doxygen.
This creates zillion of warnings. Double-check your current module!

Any warnings are in the file './doxygen.log'. Beside that, this change
avoids deprecated parameters because the configuration file for Doxygen
contains only those parameters which differ from the default. This
avoids the need to update the file on each run. Furthermore, it adds
AST_VECTOR to be expanded. Finally, the default name for that file is
Doxyfile. Therefore, let us use that!

ASTERISK-26991
ASTERISK-20259

Change-Id: I4129092a199d5e24c319a09cd088614b121015af
2021-12-08 11:25:39 -05:00
Alexander Traud bba2f14c59 res_pjsip_sdp_rtp: Do not warn on unknown sRTP crypto suites.
res_sdp_crypto_parse_offer(.) emits many log messages already.

ASTERISK-29785

Change-Id: I1a191ebe4fec1102946d4e31887e5197ca02dfe8
2021-12-06 10:56:58 -06:00
Sean Bright 4195949e07 channel: Short-circuit ast_channel_get_by_name() on empty arg.
We know that passing a NULL or empty argument to
ast_channel_get_by_name() will never result in a matching channel and
will always result in an error being emitted, so just short-circuit
out in that case.

ASTERISK-28219 #close

Change-Id: I88eadc748e9c6996fc17467b0a05881bbfd00bce
2021-12-06 10:19:42 -06:00
Mike Bradeen b0a3951849 res_rtp_asterisk: Addressing possible rtp range issues
res/res_rtp_asterisk.c: Adding 1 to rtpstart if it is deteremined
that rtpstart was configured to be an odd value. Also adding a loop
counter to prevent a possible infinite loop when looking for a free
port.

ASTERISK-27406

Change-Id: I90f07deef0716da4a30206e9f849458b2dbe346b
2021-12-06 10:04:44 -06:00
Mark Petersen fc321db1f8 apps/app_dial.c: HANGUPCAUSE reason code for CANCEL is set to AST_CAUSE_NORMAL_CLEARING
changed that when we recive a CANCEL that we set HANGUPCAUSE to AST_CAUSE_NORMAL_CLEARING

ASTERISK-28053
Reported by: roadkill

Change-Id: Ib653aec2282f55b59d87484391cc07c8e6612b89
2021-12-06 09:22:14 -06:00
Alexander Traud f872750add res: Fix for Doxygen.
These are the remaining issues found in /res.

ASTERISK-29761

Change-Id: I572e6019c422780dde5ce8448b6c85c77af6046d
2021-12-03 10:42:50 -06:00
Dustin Marquess 78e19885e8 res_fax_spandsp: Add spandsp 3.0.0+ compatibility
Newer versions of spandsp did refactoring of code to add new features
like color FAXing. This refactoring broke backwards compatibility.
Add support for the new version while retaining support for 0.0.6.

ASTERISK-29729 #close

Change-Id: I3bd74550604ebcf0304528d647fa39abc62fbaa1
2021-12-03 07:47:55 -06:00
Alexander Traud edaf3a6c77 main: Fix for Doxygen.
ASTERISK-29763

Change-Id: Ib8359e3590a9109eb04a5376559d040e5e21867e
2021-12-02 15:03:16 -06:00
Asterisk Development Team 8d0852552b Update CHANGES and UPGRADE.txt for 19.1.0 2021-12-02 13:00:53 -05:00
Alexander Traud 30d2c99698 progdocs: Fix for Doxygen, the hidden parts.
ASTERISK-29779

Change-Id: If338163488498f65fa7248b60e80299c0a928e4b
2021-12-02 10:38:05 -06:00
Alexander Traud fb08c717aa progdocs: Fix grouping for latest Doxygen.
Since Doxygen 1.8.16, a special comment block is required. Otherwise
(pure C comment), the group command is ignored. Additionally, several
unbalanced group commands were fixed.

ASTERISK-29732

Change-Id: I4687857b9d56e6f44fd440b73af156691660202e
2021-12-02 10:16:01 -06:00
Naveen Albert bfac8fbeed documentation: Standardize examples
Most examples in the XML documentation use the
example tag to demonstrate examples, which gets
parsed specially in the Wiki to make it easier
to follow for users.

This fixes a few modules to use the example
tag instead of vanilla para tags to bring them
in line with the standard syntax.

ASTERISK-29777 #close

Change-Id: I9acb6cc5faf1d220e73c6dd28592371d768d279b
2021-12-02 09:13:24 -06:00
Sean Bright dbc1a15146 config.c: Prevent UB in ast_realtime_require_field.
A backend's implementation of the realtime 'require' function may call
va_arg() and then fail, leaving the va_list in an undefined
state. Pass a copy of the va_list instead.

ASTERISK-29771 #close

Change-Id: I555565a72af84e96d49f62fe8cb66ba5a78461f4
2021-11-30 12:57:54 -06:00
Naveen Albert 05032c7cab app_voicemail: Refactor email generation functions
Refactors generic functions used for email generation
into utils.c so that they can be used by multiple
modules, including app_voicemail and app_minivm,
to avoid code duplication.

ASTERISK-29715 #close

Change-Id: I1de0ed3483623e9599711129edc817c45ad237ee
2021-11-30 09:40:34 -06:00
Alexander Traud 657252b132 stir/shaken: Avoid a compiler extension of GCC.
ASTERISK-29776

Change-Id: I86e5eca66fb775a5744af0c929fb269e70575a73
2021-11-29 09:47:24 -06:00
Alexander Traud 275ea6c111 progdocs: Remove outdated references in doxyref.h.
ASTERISK-29773

Change-Id: Ica93160d9158cc0e80c5fda829b80d1b49a6b9b9
2021-11-29 09:34:09 -06:00
Alexander Traud 849daee910 xmldoc: Fix for Doxygen.
ASTERISK-29765

Change-Id: I654ba0debe8351038d4433716434a09370f04c9d
2021-11-29 09:05:46 -06:00
Jaco Kroon bee73b7c84 logger: use __FUNCTION__ instead of __PRETTY_FUNCTION__
This avoids a few long-name overflows, at the cost of less instructive
names in the case of C++ (specifically overloaded functions and class
methods).  This in turn is offset against the fact that we're logging
the filename and line numbers in any case.

Change-Id: I54101a0bb5f8cb9ef63ec12c5e0d4c8edafff9ed
Signed-off-by: Jaco Kroon <jaco@uls.co.za>
2021-11-22 02:12:45 -05:00
Alexander Traud e8c18eeb28 channels: Fix for Doxygen.
ASTERISK-29762

Change-Id: Ia8811ac12b93ff8c18164699c6fbc604cb0a23f7
2021-11-19 09:11:38 -06:00
Mike Bradeen 07d73dbc76 astobj2.c: Fix core when ref_log enabled
In the AO2_ALLOC_OPT_LOCK_NOLOCK case the referenced obj
structure is freed, but is then referenced later if ref_log is
enabled. The change is to store the obj->priv_data.options value
locally and reference it instead of the value from the freed obj

ASTERISK-29730

Change-Id: I60cc5dc1f5a4330e7ad56976fc38a42de0ab6072
2021-11-19 09:06:02 -06:00
Joshua C. Colp 426ee9a607 bridge: Deny full Local channel pair in bridge.
Local channels are made up of two pairs - the 1 and 2
sides. When a frame goes in one side, it comes out the
other. Back and forth. When both halves are in a
bridge this creates an infinite loop of frames.

This change makes it so that bridging no longer
allows both of these sides to exist in the same
bridge.

ASTERISK-29748

Change-Id: I29928b6de87cd9be996a77daccefd7c360fef651
2021-11-19 08:42:46 -06:00
Naveen Albert fbf03832da res_tonedetect: Add call progress tone detection
Makes basic call progress tone detection available
in a tech-agnostic manner with the addition of the
ToneScan application. This can determine if the channel
has encountered a busy signal, SIT tones, dial tone,
modem, fax machine, etc. A few basic async progress
tone detect options are also added to the TONE_DETECT
function.

ASTERISK-29720 #close

Change-Id: Ia02437e0450473031e294798b8cb421fb8f24e90
2021-11-19 08:09:50 -06:00
Alexander Traud c37e1ceb5a odbc: Fix for Doxygen.
ASTERISK-29754

Change-Id: Ia09eb68d283d201d9a6fbeccfc0efe83fe0502a5
2021-11-19 07:13:19 -06:00
Boris P. Korzun f800f23d9c rtp_engine: Add type field for JSON RTCP Report stasis messages
ASTERISK-29727 #close

Change-Id: I2eca8aeb591cb63ac2238d08eab662367453cb82
2021-11-18 17:39:16 -06:00
Alexander Traud 5aec2bfee1 parking: Fix for Doxygen.
ASTERISK-29753

Change-Id: I7a61974584f6169502e6860fc711919fe7bbfaa7
2021-11-18 16:45:50 -06:00
Alexander Traud 015c594fcc res_ari: Fix for Doxygen.
ASTERISK-29756

Change-Id: I2f1c1eea1c902492b77b74de9950f20ebbb7e758
2021-11-18 16:25:05 -06:00
Alexander Traud aaa1509fad ari-stubs: Avoid 'is' as comparism with an literal.
Python 3.9.7 gave a syntax warning.

Change-Id: I3e3a982fe720726bc0015bcdb0e638a626ec89d4
2021-11-18 16:24:08 -06:00
Alexander Traud 0119f59ac3 frame: Fix for Doxygen.
ASTERISK-29755

Change-Id: I8240013ec3db0669c0acf67e26bf6c9cbb5b72af
2021-11-18 16:12:33 -06:00
Alexander Traud fa3c079c55 channel: Fix for Doxygen.
ASTERISK-29751

Change-Id: Ie04da5029c57ebee44733bdf05013156abe80176
2021-11-18 14:47:57 -06:00
Alexander Traud 14c309a6c5 app: Fix for Doxygen.
ASTERISK-29752

Change-Id: If40cbd01d47a6cfd620b18206dedb8460216c8af
2021-11-18 14:45:18 -06:00
Alexander Traud 244790e040 BuildSystem: Consistently allow 'ye' even for Jansson.
Furthermore, consistently use not 'No' but ':' for non-existent file
paths. Finally, use the same pattern for checking file paths:
  a)  = ":"
  b) != "x:"

Change-Id: I0c80c76d2cc98b0e5c859131290f4e3141a1a544
2021-11-18 14:38:05 -06:00
Alexander Traud 72e1234168 stasis: Fix for Doxygen.
ASTERISK-29750

Change-Id: Iea50173e785b2e9d49bc24c0af7111cfd96d44a9
2021-11-18 13:44:31 -06:00
Alexander Traud 76a019c377 res_xmpp: Fix for Doxygen.
ASTERISK-29749

Change-Id: I7885793b63bdeaa883e76edb899bbba9660eb1c5
2021-11-18 12:49:52 -06:00
Alexander Traud a44fa27db4 addons: Fix for Doxygen.
ASTERISK-29742

Change-Id: Ie752cb9638ced1ebe3a55d710c6c18ef6bd0aafc
2021-11-18 12:47:49 -06:00
Alexander Traud f71c0e7500 res_pjsip: Fix for Doxygen.
ASTERISK-29747

Change-Id: Ic7a1e9453f805a6264fe86c96b7d18b87b376084
2021-11-18 12:15:34 -06:00
Alexander Traud 52b99811a8 chan_iax2: Fix for Doxygen.
ASTERISK-29737

Change-Id: I282003cc553989fd5c19ceeac9e478fa4ee06cec
2021-11-18 12:04:48 -06:00
Alexander Traud 46162d2d64 bridges: Fix for Doxygen.
ASTERISK-29743

Change-Id: I6e1bbbaa5875e19994a328ab40a5d429c6010e8b
2021-11-18 11:18:32 -06:00
Alexander Traud 0bcf649a37 apps: Fix for Doxygen.
ASTERISK-29740

Change-Id: Icb6fbcfea0a5f1c82caa5001902b6a786adbf307
2021-11-18 10:37:39 -06:00
Alexander Traud 95976be293 tests: Fix for Doxygen.
ASTERISK-29741

Change-Id: I012d72b237bda2ef2d0f86307dfc6dc7add4b54b
2021-11-18 10:19:51 -06:00
Alexander Traud d2a8d37af4 bridge_channel: Fix for Doxygen.
ASTERISK-29736

Change-Id: Ia5370289e6526001a6b52754b533bcea1a9d7e5c
2021-11-18 09:22:19 -06:00
Alexander Traud 6e0ce3fde3 progdocs: Use Doxygen \example correctly.
ASTERISK-29734

Change-Id: I83b51e85cd71867645ab3a8a820f8fd1f065abd2
2021-11-18 09:14:24 -06:00
Alexander Traud 2ff4b7dd2f progdocs: Avoid multiple use of section labels.
ASTERISK-29735

Change-Id: I56935e73f7bd1d4ae2721d11040f4835da64b810
2021-11-18 09:13:41 -06:00
Alexander Traud dfdbf5007d progdocs: Avoid 'name' with Doxygen \file.
Fixes four misuses of the parameter 'name'. Additionally, for
consistency and to avoid such an issue in future, those few other
places, which used '\file name', were changed just to '\file'. Then,
Doxygen uses the name of the current file.

ASTERISK-29733

Change-Id: I0c18b4c863c6988b138c77448057349a9ee7052d
2021-11-18 08:20:38 -06:00
Josh Soref 8c0b7fd45a rest-api-templates: Spelling fixes
Correct typos of the following word families:

overwritten
descendants

ASTERISK-29714

Change-Id: I2307e35887a3437e50317a4b86f0893f25f9fd3b
(cherry picked from commit ff11d74331)
2021-11-17 04:38:06 -06:00
Josh Soref bff338bf88 bridges: Spelling fixes
Correct typos of the following word families:

multiplication
potentially
iteration
interaction
virtual
synthesis
convolve
initializes
overlap

ASTERISK-29714

Change-Id: Ia40f1aca8f2996ab407c6ed9d24cb10a67c6684b
(cherry picked from commit 2a8fb4695e)
2021-11-17 04:37:51 -06:00
Naveen Albert 02b7af8cdf app_morsecode: Fix deadlock
Fixes a deadlock in app_morsecode caused by locking
the channel twice when reading variables from the
channel. The duplicate lock is simply removed.

ASTERISK-29744 #close

Change-Id: I204000701f123361d7f85e0498fedc90243c75e4
2021-11-16 18:42:14 -06:00
Naveen Albert 45c132a375 app_read: Fix custom terminator functionality regression
Currently, when the t option is specified with no arguments,
the # character is still treated as a terminator, even though
no character should be treated as a terminator.

This is because a previous regression fix was modified to
remove the use of NULL as a default altogether. However,
NULL and an empty string actually refer to different
arrangements and should be treated differently. NULL is the
default terminator (#), while an empty string removes the
terminator altogether. This is the behavior being used by
the rest of the core.

Additionally, since S_OR catches empty strings as well as
NULL (not intended), this is changed to a ternary operator
instead, which fixes the behavior.

ASTERISK-29705 #close

Change-Id: I9b6b72196dd04f5b1e0ab5aa1b0adf627725e086
2021-11-16 15:44:37 -06:00
Naveen Albert b2256ea993 res_pjsip_callerid: Fix OLI parsing
Fix parsing of ANI2/OLI information, since it was previously
parsing the user, when it should have been parsing other_param.

Also improves the parsing by using pjproject native functions
rather than trying to parse the parameters ourselves like
chan_sip did. A previous attempt at this caused a crash, but
this works correctly now.

ASTERISK-29703 #close

Change-Id: I8f3c79032d9ea1a21d16f8e11f22bd8d887738a1
2021-11-16 12:47:01 -06:00
Josh Soref 22db079aaf utils: Spelling fixes
Correct typos of the following word families:

command-line
immediately
extensions
momentarily
mustn't
numbered
bytes
caching

ASTERISK-29714

Change-Id: I8b2b125c5d4d2f9e87a58515c97468ad47ca44f8
2021-11-16 06:34:09 -06:00
Josh Soref bf7b327edd build_tools: Spelling fixes
Correct typos of the following word families:

binutils

ASTERISK-29714

Change-Id: I2f676ab48cd50edc400c43307cb53679e4c09b97
2021-11-16 05:42:24 -06:00
Josh Soref 6b03525827 res: Spelling fixes
Correct typos of the following word families:

identifying
structures
actcount
initializer
attributes
statement
enough
locking
declaration
userevent
provides
unregister
session
execute
searches
verification
suppressed
prepared
passwords
recipients
event
because
brief
unidentified
redundancy
character
the
module
reload
operation
backslashes
accurate
incorrect
collision
initializing
instance
interpreted
buddies
omitted
manually
requires
queries
generator
scheduler
configuration has
owner
resource
performed
masquerade
apparently
routable

ASTERISK-29714

Change-Id: I88485116d2c59b776aa2e1f8b4ce8239a21decda
2021-11-16 05:41:35 -06:00
Josh Soref acf74178b1 configs: Spelling fixes
Correct typos of the following word families:

password
excludes
undesirable
checksums
through
screening
interpreting
database
causes
initiation
member
busydetect
defined
severely
throughput
recognized
counter
require
indefinitely
accounts

ASTERISK-29714

Change-Id: Ie8f2a7b274a162dd627ee6a2165f5e8a3876527e
2021-11-16 05:40:43 -06:00
Josh Soref d081fc1784 CREDITS: Spelling fixes
Correct typos of the following word families:

contributors

ASTERISK-29714

Change-Id: I6f46dae8bf8125a21ce8ff318380b2b412d9d2f9
2021-11-16 05:40:28 -06:00
Josh Soref 99b079f551 funcs: Spelling fixes
Correct typos of the following word families:

effectively
emitted
expect
anthony

ASTERISK-29714

Change-Id: Ic16f9ec855bb6d14ec8e170b90af9a36b06d488a
2021-11-16 05:40:15 -06:00
Josh Soref ccf5835e49 menuselect: Spelling fixes
Correct typos of the following word families:

dependency
unless
random
dependencies
delimited
randomly
modules

ASTERISK-29714

Change-Id: I3920603a8dc7c0a1852d2f885e06b1144692d40e
2021-11-16 05:39:27 -06:00
Josh Soref 02f40c1f01 formats: Spelling fixes
Correct typos of the following word families:

truncate

ASTERISK-29714

Change-Id: I6507760c72b919873cff7cac22b3781036cd4955
2021-11-16 05:37:10 -06:00
Josh Soref b6295840d7 codecs: Spelling fixes
Correct typos of the following word families:

voiced
denumerator
codeword
upsampling
constructed
residual
subroutine
conditional
quantizing
courtesy
number

ASTERISK-29714

Change-Id: I471fb8086a5277d8f05047fedee22cfa97a4252d
2021-11-16 05:35:05 -06:00
Josh Soref 50a43ab987 pbx: Spelling fixes
Correct typos of the following word families:

process
populate
with
africa
accessing
contexts
exercise
university
organizations
withhold
maintaining
independent
rotation
ignore
eventname

ASTERISK-29714

Change-Id: I90eacc5bc3dcf75a9c898cfb85164f37dec08345
2021-11-16 05:34:50 -06:00
Josh Soref 706258db54 contrib: Spelling fixes
Correct typos of the following word families:

standard
increase
comments
valgrind
promiscuous
editing
libtonezone
storage
aggressive
whitespace
russellbryant
consecutive
peternixon

ASTERISK-29714

Change-Id: I9cafbf41b579c9c0c84c81719d2c4f900beec245
2021-11-16 05:34:15 -06:00
Josh Soref c03a3e4d4a include: Spelling fixes
Correct typos of the following word families:

activities
forward
occurs
unprepared
association
compress
extracted
doubly
callback
prometheus
underlying
keyframe
continue
convenience
calculates
ignorepattern
determine
subscribers
subsystem
synthetic
applies
example
manager
established
result
microseconds
occurrences
unsuccessful
accommodates
related
signifying
unsubscribe
greater
fastforward
itself
unregistering
using
translator
sorcery
implementation
serializers
asynchronous
unknowingly
initialization
determining
category
these
persistent
propagate
outputted
string
allocated
decremented
second
cacheability
destructor
impaired
decrypted
relies
signaling
based
suspended
retrieved
functions
search
auth
considered

ASTERISK-29714

Change-Id: I542ce887a16603f886a915920d5710d4a0a1358d
2021-11-15 23:20:46 -06:00
Josh Soref 617cb9dbc4 Makefile: Spelling fixes
Correct typos of the following word families:

libraries
install
overwrite

ASTERISK-29714

Change-Id: I6488814f79186d6c23dfd7b7f9bba0a046126174
2021-11-15 23:19:37 -06:00
Josh Soref 08a3eae879 channels: Spelling fixes
Correct typos of the following word families:

appease
permanently
overriding
residue
silliness
extension
channels
globally
reference
japanese
group
coordinate
registry
information
inconvenience
attempts
cadence
payloads
presence
provisioning
mimics
behavior
width
natively
syslabel
not owning
unquelch
mostly
constants
interesting
active
unequipped
brodmann
commanding
backlogged
without
bitstream
firmware
maintain
exclusive
practically
structs
appearance
range
retransmission
indication
provisional
associating
always
whether
cyrillic
distinctive
components
reinitialized
initialized
capability
switches
occurring
happened
outbound

ASTERISK-29714

Change-Id: Ife52ee89cd2170b684fa651ca72b1cb911a57339
2021-11-15 23:17:49 -06:00
Josh Soref 0c7c6a3d5d agi: Spelling fixes
Correct typos of the following word families:

pretend
speech

ASTERISK-29714

Change-Id: I7d0527c329cda07552247ea11b2d7db207a3d87d
2021-11-15 22:27:58 -06:00
Josh Soref 5ad9ec2447 apps: Spelling fixes
Correct typos of the following word families:

simultaneously
administrator
directforward
attachfmt
dailplan
automatically
applicable
nouns
explicit
outside
sponsored
attachment
audio
spied
doesn't
counting
encoded
implements
recursively
emailaddress
arguments
queuerules
members
priority
output
advanced
silencethreshold
brazilian
debugging
argument
meadmin
formatting
integrated
sneakiness

ASTERISK-29714

Change-Id: Ie5ecaec91c00b26309da4e51cfc0991a5bb7d092
2021-11-15 22:22:03 -06:00
Josh Soref ec877e0c27 main: Spelling fixes
Correct typos of the following word families:

analysis
nuisance
converting
although
transaction
desctitle
acquire
update
evaluate
thousand
this
dissolved
management
integrity
reconstructed
decrement
further on
irrelevant
currently
constancy
anyway
unconstrained
featuregroups
right
larger
evaluated
encumbered
languages
digits
authoritative
framing
blindxfer
tolerate
traverser
exclamation
perform
permissions
rearrangement
performing
processing
declension
happily
duplicate
compound
hundred
returns
elicit
allocate
actually
paths
inheritance
atxferdropcall
earlier
synchronization
multiplier
acknowledge
across
against
thousands
joyous
manipulators
guaranteed
emulating
soundfile

ASTERISK-29714

Change-Id: I926ba4b11e9f6dd3fdd93170ab1f9b997910be70
2021-11-15 19:45:26 -06:00
Josh Soref 31aaceac01 doc: Spelling fixes
Correct typos of the following word families:

transparent
roughly

ASTERISK-29714

Change-Id: I2b90c68dfde4aa3f0d58f64f8187465336acb1b3
2021-11-15 18:23:43 -06:00
Josh Soref 09691e2bfb CHANGES: Spelling fixes
Correct typos of the following word families:

issuing
execution
bridging
alert
respective
unlikely
confbridge
offered
negotiation
announced
engineer
systems
inherited
passthrough
functionality
supporting
conflicts
semantically
monitor
specify
specifiable

ASTERISK-29714

Change-Id: Ia6b1cf634f52c5f7b1b8769dc54dae78106ed98c
2021-11-15 15:42:15 -06:00
Josh Soref 49e317924e UPGRADE.txt: Spelling fixes
Correct typos of the following word families:

themselves
support
received

ASTERISK-29714

Change-Id: Ibd0a7996d5801c754d3d44fba31fe788a13dba95
2021-11-15 15:33:32 -06:00
Josh Soref c06342a3cb tests: Spelling fixes
Correct typos of the following word families:

mounting
jitterbuffer
thrashing
original
manipulating
entries
actual
possibility
tasks
options
positives
taskprocessor
other
dynamic
declarative

ASTERISK-29714

Change-Id: I6b94659d045eec5d8d020fce2e9b6e2f593dfeb6
2021-11-15 14:44:43 -06:00
Josh Soref 42ba751f5a addons: Spelling fixes
Correct typos of the following word families:

definition
listener
fastcopy
logical
registration
classify
documentation
explicitly
dialed
endpoint
elements
arithmetic
might
prepend
byte
terminal
inquiry
skipping
aliases
calling
absent
authentication
transmit
their
ericsson
disconnecting
redir
items
client
adapter
transmitter
existing
satisfies
pointer
interval
supplied

ASTERISK-29714

Change-Id: I8548438246f7b718d88e0b9e0a1eb384bbec88e4
2021-11-15 09:30:53 -05:00
George Joseph fa839616fd CI: Rename 'master' node to 'built-in'
Jenkins renamed the 'master' node to 'built-in' in version
2.319 so we have to adjust as well.

Change-Id: Ice663c3a66d0eedf76e8e5fe530328455991ec25
2021-11-09 09:01:37 -06:00
Alexander Traud 9970b8df7c BuildSystem: In POSIX sh, == in place of = is undefined.
ASTERISK-29724

Change-Id: I59aa0e52effdc16992f3a736ccf73430a6ef135b
2021-11-08 13:19:44 -06:00
Naveen Albert 53fff3ec7c sig_analog: Fix truncated buffer copy
Fixes compiler warning caused by a truncated copy of the ANI2 into a
buffer of size 10. This could prevent the null terminator from being
copied if the copy value exceeds the size of the buffer. This increases
the buffer size to 101 to ensure there is no way for truncation to occur.

ASTERISK-29702 #close

Change-Id: Ief9052212952840fa44de6463b8699fdb3e163d0
2021-11-08 13:08:55 -06:00
Sean Bright a7ce06b098 pbx.c: Don't remove dashes from hints on reload.
When reloading dialplan, hints created dynamically would lose any dash
characters. Now we ignore those dashes if we are dealing with a hint
during a reload.

ASTERISK-28040 #close

Change-Id: I95e48f5a268efa3c6840ab69798525d3dce91636
2021-11-08 12:27:02 -06:00
Naveen Albert 656880a4b1 app_voicemail: Fix phantom voicemail bug on rerecord
If users are able to press # for options while leaving
a message and then press 3 to rerecord the message, if
the caller hangs up during the rerecord prompt but before
Asterisk starts recording a message, then an "empty"
voicemail gets processed whereby an email gets sent out
notifying the user of a 0:00 duration message. The file
doesn't actually exist, so playback will fail since there
was no message to begin with.

This adds a check after the streaming of the rerecord
announcement to see if the caller has hung up. If so,
we bail out early so that we can clean up properly.

ASTERISK-29391 #close

Change-Id: Id965d72759a2fd3b39afb76fec08aaebebe75c31
2021-11-08 11:28:36 -06:00
Naveen Albert cf422d35a5 chan_iax2: Allow both secret and outkey at dial time
Historically, the dial syntax for IAX2 has held that
an outkey (used only for RSA authenticated calls)
and a secret (used only for plain text and MD5 authenticated
calls, historically) were mutually exclusive, and thus
the same position in the dial string was used for both
values.

Now that encryption is possible with RSA authentication,
this poses a limitation, since encryption requires a
secret and RSA authentication requires an outkey. Thus,
the dial syntax is extended so that both a secret and
an outkey can be specified.

The new extended syntax is backwards compatible with the
old syntax. However, a secret can now be specified after
the outkey, or the outkey can be specified after the secret.
This makes it possible to spawn an encrypted RSA authenticated
call without a corresponding peer being predefined in iax.conf.

ASTERISK-29707 #close

Change-Id: I1f8149313ed760169d604afbb07720a8b07dd00e
2021-11-08 10:34:11 -06:00
Alexander Traud 9660d2e182 res_snmp: As build tool, prefer pkg-config over net-snmp-config.
ASTERISK-29709

Change-Id: Ie169df878bdfc3a06b3097c5c38d185b480f54d4
2021-11-04 10:49:23 -05:00
Alexander Traud 85049ab55a res_config_sqlite: Remove deprecated module.
ASTERISK-29717

Change-Id: I64b914eef744542528f7d4396bd06715898fbc55
2021-11-04 05:25:12 -05:00
Alexander Traud 5e5afe2a5b stasis: Avoid 'dispatched' as unused variable in normal mode.
ASTERISK-29710

Change-Id: Ia849f1172e4e694c5d5d7f0cad449f936ee12216
2021-11-01 12:54:57 -05:00
Sean Bright c206203a5c various: Fix GCC 11.2 compilation issues.
* Initialize some variables that are never used anyway.

* Use valid pointers instead of integers cast to void pointers when
  calling pthread_setspecific().

ASTERISK-29711 #close
ASTERISK-29713 #close

Change-Id: I8728cd6f2f4b28e0e48113c5da450b768c2a6683
2021-10-29 12:17:40 -05:00
George Joseph 9ff0c31335 ast_coredumper: Refactor to better find things
The search for a running asterisk when --running is used
has been greatly simplified and in the event it doesn't
work, you can now specify a pid to use on the command
line with --pid.

The search for asterisk modules when --tarball-coredumps
is used has been enhanced to have a better chance of finding
them and in the event it doesn't work, you can now specify
--libdir on the command line to indicate the library directory
where they were installed.

The DATEFORMAT variable was renamed to DATEOPTS and is now
passed to the 'date' utility rather than running DATEFORMAT
as a command.

The coredump and output files are now renamed with DATEOPTS.
This can be disabled by specifying --no-rename.

Several confusing and conflicting options were removed:
--append-coredumps
--conffile
--no-default-search
--tarball-uniqueid

The script was re-structured to make it easier for follow.

Change-Id: I674be64bdde3ef310b6a551d4911c3b600ffee59
2021-10-28 13:50:28 -05:00
Kevin Harwell ed384e652c strings/json: Add string delimter match, and object create with vars methods
Add a function to check if there is an exact match a one string between
delimiters in another string.

Add a function that will create an ast_json object out of a list of
Asterisk variables. An excludes string can also optionally be passed
in.

Also, add a macro to make it easier to get object integers.

Change-Id: I5f34f18e102126aef3997f19a553a266d70d6226
2021-10-28 08:56:09 -05:00
Ben Ford ba3f6c0b1e STIR/SHAKEN: Option split and response codes.
The stir_shaken configuration option now has 4 different choices to pick
from: off, attest, verify, and on. Off and on behave the same way they
do now. Attest will only perform attestation on the endpoint, and verify
will only perform verification on the endpoint.

Certain responses are required to be sent based on certain conditions
for STIR/SHAKEN. For example, if we get a Date header that is outside of
the time range that is considered valid, a 403 Stale Date response
should be sent. This and several other responses have been added.

Change-Id: I4ac1ecf652cd0e336006b0ca638dc826b5b1ebf7
2021-10-27 09:55:42 -05:00
Rodrigo Ramírez Norambuena d81d5ad832 app_queue: Add LoginTime field for member in a queue.
Add a time_t logintime to storage a time when a member is added into a
queue.

Also, includes show this time (in seconds) using a 'queue show' command
and the field LoginTime for response for AMI events.

ASTERISK-18069 #close

Change-Id: Ied6c3a300f78d78eebedeb3e16a1520fc3fff190
2021-10-25 08:31:21 -05:00
Kevin Harwell cf0fa9b82f res_speech: Add a type conversion, and new engine unregister methods
Add a new function that converts a speech results type to a string.
Also add another function to unregister an engine, but returns a
pointer to the unregistered engine object instead of a success/fail
integer.

Change-Id: I0f7de17cb411021c09fb03988bc2b904e1380192
2021-10-21 16:25:12 -05:00
Mike Bradeen 6b094e905b various: Fix GCC 11 compilation issues.
test_voicemail_api: Use empty char* for empty_msg_ids.
chan_skinny: Fix size of calledParty to be maximum extension.
menuselect: Change Makefile to stop deprecated warnings. Added comments
test_linkedlist: 'bogus' variable was manually allocated from a macro
and the test fails if this happens but the compiler couldn't 'see' this
and returns a warning. memset to all 0's after allocation.
chan_ooh323: Fixed various indentation issues that triggered misleading
 indentation warnings.

ASTERISK-29682
Reported by: George Joseph

Change-Id: If4fe42222c8444dc16828a42731ee53b4ce5cbbe
2021-10-21 11:39:37 -05:00
Shloime Rosenblum 154c592799 apps/app_playback.c: Add 'mix' option to app_playback
I am adding a mix option that will play by filename and say.conf unlike
say option that will only play with say.conf. It
will look on the format of the name, if it is like say it play with
say.conf if not it will play the file name.

ASTERISK-29662

Change-Id: I815816916a308f0fa8f165140dc15772dcbd547a
2021-10-21 10:43:12 -05:00
George Joseph 2b9cddc7d0 BuildSystem: Check for alternate openssl packages
OpenSSL is one of those packages that often have alternatives
with later versions.  For instance, CentOS/EL 7 has an
openssl package at version 1.0.2 but there's an openssl11
package from the epel repository that has 1.1.1.  This gets
installed to /usr/include/openssl11 and /usr/lib64/openssl11.
Unfortunately, the existing --with-ssl and --with-crypto
./configure options expect to point to a source tree and
don't work in this situation.  Also unfortunately, the
checks in ./configure don't use pkg-config.

In order to make this work with the existing situation, you'd
have to run...
./configure --with-ssl=/usr/lib64/openssl11 \
    --with-crypto=/usr/lib64/openssl11 \
    CFLAGS=-I/usr/include/openssl11

BUT...  those options don't get passed down to bundled pjproject
so when you run make, you have to include the CFLAGS again
which is a big pain.

Oh...  To make matters worse, although you can specify
PJPROJECT_CONFIGURE_OPTS on the ./configure command line,
they don't get saved so if you do a make clean, which will
force a re-configure of bundled pjproject, those options
don't get used.

So...

* In configure.ac... Since pkg-config is installed by install_prereq
  anyway, we now use it to check for the system openssl >= 1.1.0.
  If that works, great.  If not, we check for the openssl11
  package. If that works, great.  If not, we fall back to just
  checking for any openssl.  If pkg-config isn't installed for some
  reason, or --with-ssl=<dir> or --with-crypto=<dir> were specified
  on the ./configure command line, we fall back to the existing
  logic that uses AST_EXT_LIB_CHECK().

* The whole OpenSSL check process has been moved up before
  THIRD_PARTY_CONFIGURE(), which does the initial pjproject
  bundled configure, is run.  This way the results of the above
  checks, which may result in new include or library directories,
  is included.

* Although not strictly needed for openssl, We now save the value of
  PJPROJECT_CONFIGURE_OPTS in the makeopts file so it can be used
  again if a re-configure is triggered.

ASTERISK-29693

Change-Id: I341ab7603e6b156aa15a66f43675ac5029d5fbde
2021-10-20 12:23:40 -06:00
Sean Bright 093fabba84 func_talkdetect.c: Fix logical errors in silence detection.
There are 3 separate changes here:

1. The documentation erroneously stated that the dsp_talking_threshold
   argument was a number of milliseconds when it is actually an energy
   level used by the DSP code to classify talking vs. silence.

2. Fixes a copy paste error in the argument handling code.

3. Don't erroneously switch to the talking state if we aren't actively
   handling a frame we've classified as talking.

Patch inspired by one provided by Moritz Fain (License #6961).

ASTERISK-27816 #close

Change-Id: I5953fd570b98b49c41cee55bfe3b941753fb2511
2021-10-19 10:25:00 -05:00
Mike Bradeen 702484431d build: prevent binary downloads for non x86 architectures
download_externals: Add check for i686 and i386 (in addition
to the current x86_64) and exit if not one of the three.

ASTERISK-26497

Change-Id: Ia4d429fcefa5b2f5b6e99159d4607de8e8325b2f
2021-10-15 13:39:35 -05:00
Sean Bright ce9cb32307 configure: Remove unused OpenSSL SRTP check.
Discovered while looking at ASTERISK~29684. Usage was removed in change
I3c77c7b00b2ffa2e935632097fa057b9fdf480c0.

Change-Id: Iaf2f7a16ea5a7eee6375319347e4b40b8e7b10e3
2021-10-15 10:47:42 -05:00
Sebastien Duthil 4bc7a5ac53 main/stun.c: fix crash upon STUN request timeout
Some ast_stun_request users do not provide a destination address when
sending to a connection-mode socket.

ASTERISK-29691

Change-Id: Idd9114c3380216ba48abfc3c68619e79ad37defc
2021-10-14 11:50:55 -05:00
Asterisk Development Team 9ff955f4d1 Update CHANGES and UPGRADE.txt for 19.0.0 2021-10-13 05:21:51 -05:00
Sean Bright 9175012a12 Makefile: Use basename in a POSIX-compliant way.
If you aren't using GNU coreutils, chances are that your basename
doesn't know about the -s argument. Luckily for us, basename does what
we need it do even without the -s argument.

Change-Id: I8b81a429bb037b997ee6640ff8a2b5e860962bb7
2021-10-11 10:03:00 -05:00
Mark Murawski 1f5ac24fa3 pbx_ael: Fix crash and lockup issue regarding 'ael reload'
Avoid infinite recursion and crash

Change-Id: I8ed05ec3aa2806c50c77edc5dd0cd4e4fa08b3f4
2021-10-08 09:41:04 -05:00
Naveen Albert 32ea7c7ca5 chan_iax2: Add encryption for RSA authentication
Adds support for encryption to RSA-authenticated
calls. Also prevents crashes if an RSA IAX2 call
is initiated to a switch requiring encryption
but no secret is provided.

ASTERISK-20219

Change-Id: I18f1f9d7c59b4f9cffa00f3b94a4c875846efd40
2021-10-07 18:23:37 -05:00
Matthew Kern 9d04535bbd res_pjsip_t38: bind UDPTL sessions like RTP
In res_pjsip_sdp_rtp, the bind_rtp_to_media_address option and the
fallback use of the transport's bind address solve problems sending
media on systems that cannot send ipv4 packets on ipv6 sockets, and
certain other situations. This change extends both of these behaviors
to UDPTL sessions as well in res_pjsip_t38, to fix fax-specific
problems on these systems, introducing a new option
endpoint/t38_bind_udptl_to_media_address.

ASTERISK-29402

Change-Id: I87220c0e9cdd2fe9d156846cb906debe08c63557
2021-10-01 08:58:27 -05:00
Naveen Albert 60bbfe4572 app_read: Fix null pointer crash
If the terminator character is not explicitly specified
and an indications tone is used for reading a digit,
there is no null pointer check so Asterisk crashes.
This prevents null usage from occuring.

ASTERISK-29673 #close

Change-Id: Ie941833e123c3dbfb88371b5de5edbbe065514ac
2021-09-30 11:09:36 -05:00
Jean Aunis 576119e076 res_rtp_asterisk: fix memory leak
Add missing reference decrement in rtp_deallocate_transport()

ASTERISK-29671

Change-Id: I8d22dbedb90e8dade0829b7a28372f404b07caa9
2021-09-30 04:17:24 -05:00
Shloime Rosenblum f3ff893310 main/say.c: Support future dates with Q and q format params
The current versions do not support future dates in all say application when using the 'Q' or 'q' format parameter and says "today" for everything that is greater than today

ASTERISK-29637

Change-Id: I1fb1cef0ce3c18d87b1fc94ea309d13bc344af02
2021-09-28 12:08:28 -05:00
Joseph Nadiv 6a04c43035 res_pjsip_registrar: Remove unavailable contacts if exceeds max_contacts
The behavior of max_contacts and remove_existing are connected.  If
remove_existing is enabled, the soonest expiring contacts are removed.
This may occur when there is an unavailable contact.  Similarly,
when remove_existing is not enabled, registrations from good
endpoints are rejected in favor of retaining unavailable contacts.

This commit adds a new AOR option remove_unavailable, and the effect
of this setting will depend on remove_existing.  If remove_existing
is set to no, we will still remove unavailable contacts when they
exceed max_contacts, if there are any. If remove_existing is set to
yes, we will prioritize the removal of unavailable contacts before
those that are expiring soonest.

ASTERISK-29525

Change-Id: Ia2711b08f2b4d1177411b1be23e970d7fdff5784
2021-09-24 11:48:22 -05:00
Joshua C. Colp 35a94ec708 ari: Ignore invisible bridges when listing bridges.
When listing bridges we go through the ones present in
ARI, get their snapshot, turn it into JSON, and add it
to the payload we ultimately return.

An invisible "dial bridge" exists within ARI that would
also try to be added to this payload if the channel
"create" and "dial" routes were used. This would ultimately
fail due to invisible bridges having no snapshot
resulting in the listing of bridges failing.

This change makes it so that the listing of bridges
ignores invisible ones.

ASTERISK-29668

Change-Id: I14fa4b589b4657d1c2a5226b0f527f45a0cd370a
2021-09-23 09:19:28 -05:00
Naveen Albert 13ec117595 func_vmcount: Add support for multiple mailboxes
Allows multiple mailboxes to be specified for VMCOUNT
instead of just one.

ASTERISK-29661 #close

Change-Id: I9108528300795fd5b607efa9d4dd7b74be031813
2021-09-22 10:49:32 -05:00
Sean Bright 52b5821694 message.c: Support 'To' header override with AMI's MessageSend.
The MessageSend AMI action has been updated to allow the Destination
and the To addresses to be provided separately. This brings the
MessageSend manager command in line with the capabilities of the
MessageSend dialplan application.

ASTERISK-29663 #close

Change-Id: I8513168d3e189a9fed88aaab6f5547ccb50d332c
2021-09-22 10:44:28 -05:00
Naveen Albert f38c7d67d3 func_channel: Add CHANNEL_EXISTS function.
Adds a function to check for the existence of a channel by
name or by UNIQUEID.

ASTERISK-29656 #close

Change-Id: Ib464e9eb6e13dc683a846286798fecff4fd943cb
2021-09-21 18:20:35 -05:00
Naveen Albert eff78c8549 app_queue: Fix hint updates for included contexts
Previously, if custom hints were used with the hint:
format in app_queue, when device state changes occured,
app_queue would only do a literal string comparison of
the context used for the hint in app_queue and the context
of the hint which just changed state. This caused hints
to not update and become stale if the context associated
with the agent included the context which actually changes
state, essentially completely breaking device state for
any such agents defined in this manner.

This fix adds an additional check to ensure that included
contexts are also compared against the context which changed
state, so that the behavior is correct no matter whether the
context is specified to app_queue directly or indirectly.

ASTERISK-29578 #close

Change-Id: I8caf2f8da8157ef3d9ea71a8568c1eec95592b78
2021-09-21 17:22:15 -05:00
Sean Bright ff493d6f7d res_http_media_cache.c: Compare unaltered MIME types.
Rather than stripping parameters from Content-Type headers before
comparison, first try to compare the whole string. If no match is
found, strip the parameters and try that way.

ASTERISK-29275 #close

Change-Id: I2963c8ecbb3a9605b78b6421c415108d77a66a0f
2021-09-21 13:08:04 -05:00
Naveen Albert eb874f92db logger: Add custom logging capabilities
Adds the ability for users to log to custom log levels
by providing custom log level names in logger.conf. Also
adds a logger show levels CLI command.

ASTERISK-29529

Change-Id: If082703cf81a436ae5a565c75225fa8c0554b702
2021-09-21 12:10:10 -05:00
Sean Bright 245778a756 app_externalivr.c: Fix mixed leading whitespace in source code.
No functional changes.

Change-Id: I46514152c0af67f395526374aaa847ccd6a85378
2021-09-21 11:48:51 -05:00
Guido Falsi 675adbf0f5 res_rtp_asterisk.c: Fix build failure when not building with pjproject.
Some code has been added referencing symbols defined in a block
protected by #ifdef HAVE_PJPROJECT. Protect those code parts in
ifdef blocks too.

ASTERISK-29660

Change-Id: Ib18d4392d51ac80ca5481dabf6e498a4e3e49e6f
2021-09-20 15:49:10 -05:00
George Joseph 3d6e133ccf pjproject: Add patch to fix trailing whitespace issue in rtpmap
An issue was found where a particular manufacturer's phones add a
trailing space to the end of the rtpmap attribute when specifying
a payload type that has a "param" after the format name and clock
rate. For example:

a=rtpmap:120 opus/48000/2 \r\n

Because pjmedia_sdp_attr_get_rtpmap currently takes everything after
the second '/' up to the line end as the param, the space is
included in future comparisons, which then fail if the param being
compared to doesn't also have the space.

We now use pj_scan_get() to parse the param part of rtpmap so
trailing whitespace is automatically stripped.

ASTERISK-29654

Change-Id: Ibd0a4e243a69cde7ba9312275b13ab62ab86bc1b
2021-09-15 12:21:02 -05:00
Carlos Oliva ad1f7fae70 app_mp3: Force output to 16 bits in mpg123
In new mpg123 versions (since 1.26) the default output is 32 bits
Asterisk expects the output in 16 bits, so we force the output to be on 16 bits.
It will work wit new and old versions of mpg123.
Thanks Thomas Orgis <thomas-forum@orgis.org> for giving the key!

ASTERISK-29635 #close

Change-Id: I88c7740118b5af4e895bd8b765b68ed5c11fc816
2021-09-15 12:16:24 -05:00
Naveen Albert 203e73f5af app_mf: Add channel agnostic MF sender
Adds a SendMF application and PlayMF manager
event to send arbitrary R1 MF tones on the
current or specified channel.

ASTERISK-29496

Change-Id: I5d89afdbccee3f86cc702ed96d882f3d351327a4
2021-09-15 10:21:53 -05:00
Naveen Albert f8bf5e7b47 res_pjsip_caller_id: Add ANI2/OLI parsing
Adds parsing of ANI II digits (Originating
Line Information) to PJSIP, on par with
what currently exists in chan_sip.

ASTERISK-29472

Change-Id: Ifc938a7a7d45ce33999ebf3656a542226f6d3847
2021-09-13 13:10:37 -05:00
Naveen Albert 5fe3a745e4 app_stack: Include current location if branch fails
Previously, the error emitted when app_stack tries
to branch to a dialplan location that doesn't exist
has included only the information about the attempted
branch in the error log. This adds the current location
as well so users can see where the branch failed in
the logs.

ASTERISK-29626

Change-Id: Ia23502ab2ad21485a1ac74295063a8f25a6df5ce
2021-09-13 07:16:44 -05:00
Sean Bright f26505d615 test_http_media_cache.c: Fix copy/paste error during test deregistration.
Change-Id: I9a3a978b2f818be464e062d97b93831b127ef28c
2021-09-13 07:15:48 -05:00
Naveen Albert d5a53efb4f func_strings: Add STRBETWEEN function
Adds the STRBETWEEN function, which can be used to insert a
substring between each character in a string. For instance,
this can be used to insert pauses between DTMF tones in a
string of digits.

ASTERISK-29627

Change-Id: Ice23009d4a8e9bb9718d2b2301d405567087d258
2021-09-10 16:31:33 -05:00
Sungtae Kim 4d9ba65c53 resource_channels.c: Fix external media data option
Fixed the external media creation handle to handle the 'data' option correctly.

ASTERISK-29629

Change-Id: I22e57fe8ebf3d3e08fb2121aa4a8a52cc62e8129
2021-09-10 16:03:04 -05:00
Sean Bright 085cc94f16 test_abstract_jb.c: Fix put and put_out_of_order memory leaks.
We can't rely on RAII_VAR(...) to properly clean up data that is
allocated within a loop.

ASTERISK-27176 #close

Change-Id: Ib575616101230c4f603519114ec62ebf3936882c
2021-09-10 14:26:37 -05:00
Naveen Albert 71b021433f func_env: Add DIRNAME and BASENAME functions
Adds the DIRNAME and BASENAME functions, which are
wrappers around the corresponding C library functions.
These can be used to safely and conveniently work with
file paths and names in the dialplan.

ASTERISK-29628 #close

Change-Id: Id3aeb907f65c0ff96b6e57751ff0cb49d61db7f3
2021-09-10 11:47:54 -05:00
Naveen Albert 0b8ae58e67 func_sayfiles: Retrieve say file names
Up until now, all of the logic used to translate
arguments to the Say applications has been
directly coupled to playback, preventing other
modules from using this logic.

This refactors code in say.c and adds a SAYFILES
function that can be used to retrieve the file
names that would be played. These can then be
used in other applications or for other purposes.

Additionally, a SayMoney application and a SayOrdinal
application are added. Both SayOrdinal and SayNumber
are also expanded to support integers greater than
one billion.

ASTERISK-29531

Change-Id: If9718c89353b8e153d84add3cc4637b79585db19
2021-09-10 11:45:52 -05:00
Naveen Albert a94b51ee60 res_tonedetect: Tone detection module
dsp.c contains arbitrary tone detection functionality
which is currently only used for fax tone recognition.
This change makes this functionality publicly
accessible so that other modules can take advantage
of this.

Additionally, a WaitForTone and TONE_DETECT app and
function are included to allow users to do their
own tone detection operations in the dialplan.

ASTERISK-29546

Change-Id: Ie38c395000f4fd4d04e942e8658e177f8f499b26
2021-09-10 11:08:23 -05:00
George Joseph df63a99337 res_snmp: Add -fPIC to _ASTCFLAGS
With gcc 11, res/res_snmp.c and res/snmp/agent.c need the
-fPIC option added to its _ASTCFLAGS.

ASTERISK-29634

Change-Id: I34649c85e075fd954e578378fabf798c3f038f50
2021-09-10 10:42:52 -05:00
Sean Bright 61136fd297 term.c: Add support for extended number format terminfo files.
ncurses 6.1 introduced an extended number format for terminfo files
which the terminfo parsing in Asterisk is not able to parse. This
results in some TERM values that do support color (screen-256color on
Ubuntu 20.04 for example) to not get a color console.

ASTERISK-29630 #close

Change-Id: I27a4fcfab502219924af2d6b1c46feba92903cb3
2021-09-09 06:48:17 -05:00
Sean Bright f67b72093e app_voicemail.c: Ability to silence instructions if greeting is present.
There is an option to silence voicemail instructions but it does not
take into consideration if a recorded greeting exists or not. Add a
new 'S' option that does that.

ASTERISK-29632 #close

Change-Id: I03f2f043a9beb9d99deab302247e2a8686066fb4
2021-09-08 19:18:14 -05:00
Jasper Hafkenscheid f1e1f9f37f res_srtp: Disable parsing of not enabled cryptos
When compiled without extended srtp crypto suites also disable parsing
these from received SDP. This prevents using these, as some client
implementations are not stable.

ASTERISK-29625

Change-Id: I7dafb29be1cdaabdc984002573f4bea87520533a
2021-09-08 18:28:59 -05:00
Sean Bright 5a5ea06ffc dns.c: Load IPv6 DNS resolvers if configured.
IPv6 nameserver addresses are stored in different part of the
__res_state structure, so look there if we appear to have support for
it.

ASTERISK-28004 #close

Change-Id: I67067077d8a406ee996664518d9c8fbf11f6977d
2021-09-08 18:18:18 -05:00
George Joseph 0070b9184c bridge_softmix: Suppress error on topology change failure
There are conditions under which a failure to change topology
is expected so there's no need to print an ERROR message.

ASTERISK-29618
Reported by: Alexander

Change-Id: Idc168b8588e018bf3a23769f08c4ad646086d481
2021-09-08 07:55:51 -05:00
sungtae kim 3c31b6aaa2 resource_channels.c: Fix wrong external media parameter parse
Fixed ARI external media handler to accept body parameters.

ASTERISK-29622

Change-Id: I49509c48a6cbc0fb4165bfa4f834b5e8b9ace20d
2021-09-02 15:53:20 -05:00
Sean Bright 16b0f460f6 config_options: Handle ACO arrays correctly in generated XML docs.
There are 3 separate changes here but they are all closely related:

* Only try to set matchfield attributes on 'field' nodes

* We need to adjust how we treat the category pointer based on the
  value of the category_match, to avoid memory corruption. We now
  generate a regex-like string when match types other than
  ACO_WHITELIST and ACO_BLACKLIST are used.

* Switch app_agent_pool from ACO_BLACKLIST_ARRAY to
  ACO_BLACKLIST_EXACT since we only have one category we need to
  ignore, not two.

ASTERISK-29614 #close

Change-Id: I7be7bdb1bb9814f942bc6bb4fdd0a55a7b7efe1e
2021-09-02 15:17:16 -05:00
Naveen Albert 29770520b3 chan_iax2: Add ANI2/OLI information element
Adds an information element for ANI2 so that
Originating Line Information can be transmitted
over IAX2 channels.

ASTERISK-29605 #close

Change-Id: Iaeacdf6ccde18eaff7f776a0f49fee87dcb549d2
2021-09-02 14:17:04 -05:00
Mark Murawski 185321066f pbx_ael: Fix crash and lockup issue regarding 'ael reload'
Currently pbx_ael does not check if a reload is currently pending
before proceeding with a reload. This can cause multiple threads to
operate at the same time on what should be mutex protected data. This
change adds protection to reloading to ensure only one ael reload is
executing at a time.

ASTERISK-29609 #close

Change-Id: I5ed392ad226f6e4e7696ad742076d3e45c57af35
2021-09-02 14:16:16 -05:00
Naveen Albert 0e4a1c5079 app_read: Allow reading # as a digit
Allows for the digit # to be read as a digit,
just like any other DTMF digit, as opposed to
forcing it to be used as an end of input
indicator. The default behavior remains
unchanged.

ASTERISK-18454 #close

Change-Id: I3033432adb9d296ad227e76b540b8b4a2417665b
2021-09-01 10:31:07 -05:00
Sebastien Duthil 18189ff594 res_rtp_asterisk: Automatically refresh stunaddr from DNS
This allows the STUN server to change its IP address without having to
reload the res_rtp_asterisk module.

The refresh of the name resolution occurs first when the module is
loaded, then recurringly, slightly after the previous DNS answer TTL
expires.

ASTERISK-29508 #close

Change-Id: I7955a046293f913ba121bbd82153b04439e3465f
2021-09-01 10:29:30 -05:00
Naveen Albert 4301fe20d1 bridge_basic: Change warning to verbose if transfer cancelled
The attended transfer feature will emit a warning if the user
cancels the transfer or the attended transfer doesn't complete
for any reason. Changes the warning to a verbose message,
since nothing is actually wrong here.

ASTERISK-29612 #close

Change-Id: I64c93cdb21360a0a8d45e9cb6db3af8168f66e6d
2021-08-26 08:52:03 -05:00
Naveen Albert 9e947b0463 app_queue: Don't reset queue stats on reload
Prevents reloads of app_queue from also resetting
queue statistics.

Also preserves individual queue agent statistics
if we're just reloading members.

ASTERISK-28701

Change-Id: Ib5d4cdec175e44de38ef0f6ede4a7701751766f1
2021-08-25 18:34:08 -05:00
Alexander Traud f22b413ece dialplan: Add one static and fix two whitespace errors.
Change-Id: Ia14d515ab63e773097adc6af772ca7123a392f83
2021-08-25 12:34:17 -05:00
Alexander Traud e65e1c5c6c res_rtp_asterisk: sqrt(.) requires the header math.h.
ASTERISK-29616

Change-Id: I6c01623926bf10ccac32612687a50fdab3ba0900
2021-08-25 09:24:29 -05:00
Sarah Autumn db4a3b117d sig_analog: Changes to improve electromechanical signalling compatibility
This changeset is intended to address compatibility issues encountered
when interfacing Asterisk to electromechanical telephone switches that
implement ANI-B, ANI-C, or ANI-D.

In particular the behaviours that this impacts include:

 - FGC-CAMA did not work at all when using MF signaling. Modified the
   switch case block to send calls to the correct part of the
   signaling-handling state machine.

 - For FGC-CAMA operation, the delay between called number ST and
   second wink for ANI spill has been made configurable; previously
   all calls were made to wait for one full second.

 - After the ANI spill, previous behavior was to require a 'ST' tone
   to advance the call.  This has been changed to allow 'STP' 'ST2P'
   or 'ST3P' as well, for compatibility with ANI-D.

 - Store ANI2 (ANI INFO) digits in the CALLERID(ANI2) channel variable.

 - For calls with an ANI failure, No. 1 Crossbar switches will send
   forward a single-digit failure code, with no calling number digits
   and no ST pulse to terminate the spill.  I've made the ANI timeout
   configurable so to reduce dead air time on calls with ANI fail.

 - ANI info digits configurable.  Modern digital switches will send 2
   digits, but ANI-B sends only a single info digit.  This caused the
   ANI reported by Asterisk to be misaligned.

 - Changed a confusing log message to be more informative.

ASTERISK-29518

Change-Id: Ib7e27d987aee4ed9bc3663c57ef413e21b404256
2021-08-20 15:31:08 -05:00
George Joseph a662d75556 res_pjproject: Allow mapping to Asterisk TRACE level
Allow mapping pjproject log messages to the Asterisk TRACE
log level.  The defaults were also changes to log pjproject
levels 3,4 to DEBUG and 5,6 to TRACE.  Previously 3,4,5,6
all went to DEBUG.

ASTERISK-29582

Change-Id: I859a37a8dec263ed68099709cfbd3e665324c72d
2021-08-20 09:42:15 -05:00
Andre Barbosa 2451dfd89f media_cache: Don't lock when curl the remote file
When playing a remote sound file, which is not in cache, first we need
to download it with ast_bucket_file_retrieve.

This can take a while if the remote host is slow. The current CURL
timeout is 180secs, so in extreme situations, it can take 3 minutes to
return.

Because ast_media_cache_retrieve has a lock on all function, while we
are waiting for the delayed download, Asterisk is not able to play any
more files, even the files already cached locally.

ASTERISK-29544 #close

Change-Id: I8d4142b463ae4a1d4c41bff2bf63324821567408
2021-08-20 09:36:32 -05:00
Naveen Albert e01a6c026d func_scramble: Audio scrambler function
Adds a function to scramble audio on a channel using
whole spectrum frequency inversion. This can be used
as a privacy enhancement with applications like
ChanSpy or other potentially sensitive audio.

ASTERISK-29542

Change-Id: I01020769d91060a1f56a708eb405f87648d1a67e
2021-08-19 11:19:30 -05:00
Naveen Albert d6034df64a func_math: Return integer instead of float if possible
The MIN, MAX, and ABS functions all support float
arguments, but currently return floats even if the
arguments are all integers and the response is
a whole number, in which case the user is likely
expecting an integer. This casts the float to an integer
before printing into the response buffer if possible.

ASTERISK-29495

Change-Id: I902d29eacf3ecd0f8a6a5e433c97f0421d205488
2021-08-19 11:13:56 -05:00
Naveen Albert b5044586f7 app_morsecode: Add American Morse code
Previously, the Morsecode application only supported international
Morse code. This adds support for American Morse code and adds an
option to configure the frequency used in off intervals.

Additionally, the application checks for hangup between tones
to prevent application execution from continuing after hangup.

ASTERISK-29541

Change-Id: I172431a2e18e6527d577e74adfb05b154cba7bd4
2021-08-19 10:32:10 -05:00
Naveen Albert 3f9ef427b5 app_milliwatt: Timing fix
The Milliwatt application uses incorrect tone timings
that cause it to play the 1004 Hz tone constantly.

This adds an option to enable the correct timing
behavior, so that the Milliwatt application can
be used for milliwatt test lines. The default behavior
remains unchanged for compatability reasons, even
though it is incorrect.

ASTERISK-29575 #close

Change-Id: I73ccc6c6fcaa31931c6fff3b85ad1805b2ce9d8c
2021-08-19 09:37:51 -05:00
Naveen Albert 2394757e55 app_originate: Add ability to set codecs
A list of codecs to use for dialplan-originated calls can
now be specified in Originate, similar to the ability
in call files and the manager action.

Additionally, we now default to just using the slin codec
for originated calls, rather than all the slin* codecs up
through slin192, which has been known to cause issues
and inconsistencies from AMI and call file behavior.

ASTERISK-29543

Change-Id: I96a1aeb83d54b635b7a51e1b4680f03791622883
2021-08-19 09:09:11 -05:00
Alexander Traud 73e2288db7 BuildSystem: Remove two dead exceptions for compiler Clang.
Commit 305ce3d added -Wno-parentheses-equality to Makefile.rules,
turning the previous two warning suppressions from commit e9520db
redundant. Let us remove the latter.

Change-Id: I0b471254b31e6e05902062761dded4b3e626c7ac
2021-08-19 09:03:27 -05:00
Naveen Albert 432fe9dc2a chan_alsa, chan_sip: Add replacement to moduleinfo
Adds replacement modules to the moduleinfo for
chan_alsa and chan_sip.

ASTERISK-29601 #close

Change-Id: I7a4877b0d5c0c17e088e8fa8ebbfa9a195223cbc
2021-08-19 07:58:24 -05:00
Joshua C. Colp ecf699c325 res_monitor: Disable building by default.
ASTERISK-29602

Change-Id: I6f0af0a959409cdbc6b185b1604301bafc872a5a
2021-08-18 11:15:14 -05:00
Joshua C. Colp daca793ad4 muted: Remove deprecated application.
ASTERISK-29600

Change-Id: I0ae1c6a2996da43217126f094de90761314dcf82
2021-08-17 10:47:07 -03:00
Joshua C. Colp 650cf0b444 conf2ael: Remove deprecated application.
ASTERISK-29599

Change-Id: I75dc77162926fb17e7c6caf8f04e3aabd792fb0c
2021-08-17 10:47:01 -03:00
Joshua C. Colp 368aa47962 res_config_sqlite: Remove deprecated module.
ASTERISK-29598

Change-Id: I8ef17023f55bf01f2e309b06f4778a8ca7252c91
2021-08-17 10:46:54 -03:00
Joshua C. Colp 9d5f55a5f3 chan_vpb: Remove deprecated module.
ASTERISK-29597

Change-Id: I19bb39eed0257ddfef453eb2df5646d073d50fe1
2021-08-17 10:46:47 -03:00
Joshua C. Colp 72a2140a50 chan_misdn: Remove deprecated module.
ASTERISK-29596

Change-Id: Ibae9490c1b35cadbf7028d24610f745277c8535e
2021-08-17 10:46:42 -03:00
Joshua C. Colp 7b0d3d3550 chan_nbs: Remove deprecated module.
ASTERISK-29595

Change-Id: Ib5c7d43a780f2fb94cee90738e4c1af211ae4a33
2021-08-17 10:46:36 -03:00
Joshua C. Colp 7361a52820 chan_phone: Remove deprecated module.
ASTERISK-29594

Change-Id: I79a9961cb5062fadbccb0ea93f087bdd32685316
2021-08-17 10:46:25 -03:00
Joshua C. Colp d0ad32c7cf chan_oss: Remove deprecated module.
ASTERISK-29593

Change-Id: Ib53a42ad974c63871344b95078c61c188e43da99
2021-08-17 10:46:18 -03:00
Joshua C. Colp e4b6f24a1d cdr_syslog: Remove deprecated module.
ASTERISK-29592

Change-Id: Ic8eb6a2100ad5bc3b48338a6d0a6cfa70ecbc50f
2021-08-17 10:46:12 -03:00
Joshua C. Colp f18107f191 app_dahdiras: Remove deprecated module.
ASTERISK-29591

Change-Id: I021d37b729631d40f84e35bb21e2893777be1858
2021-08-17 10:46:06 -03:00
Joshua C. Colp b1e5b1874c app_nbscat: Remove deprecated module.
ASTERISK-29590

Change-Id: I87cf0f536b77d222c8eda003376ac47fae86ed43
2021-08-17 10:46:00 -03:00
Joshua C. Colp 7ee6fb0372 app_image: Remove deprecated module.
ASTERISK-29589

Change-Id: I8057eb2ca1ca4c3b27ed2fe04bea10e9cb551cdd
2021-08-17 10:45:54 -03:00
Joshua C. Colp 0b3a149001 app_url: Remove deprecated module.
ASTERISK-29588

Change-Id: If846d40b37c5b646bcd7326111db280529a5971b
2021-08-17 10:45:48 -03:00
Joshua C. Colp 41afcb9422 app_fax: Remove deprecated module.
ASTERISK-29587

Change-Id: I038237bbb56b1161d7d5e20cda11ed32e13d3ca2
2021-08-17 10:45:41 -03:00
Joshua C. Colp 83cad340fc app_ices: Remove deprecated module.
ASTERISK-29586

Change-Id: I1e0a4535135b00938b609fe0ccba9bbddbac93ad
2021-08-17 10:45:34 -03:00
Joshua C. Colp 1961a1b83e app_mysql: Remove deprecated module.
ASTERISK-29585

Change-Id: I262930d0387d043f2a3345e8a977b314528059bf
2021-08-17 10:45:27 -03:00
Joshua C. Colp 3e07b1ff62 cdr_mysql: Remove deprecated module.
ASTERISK-29584

Change-Id: I4bd3695d089121f810d692a82361d39d2f97ae39
2021-08-17 10:45:20 -03:00
Sean Bright 41ed46f474 mgcp: Remove dead debug code
ASTERISK-20339 #close

Change-Id: I36f364aaa1971241d8f3ea1a5909b463d185a2d5
2021-08-16 12:16:30 -05:00
Joshua C. Colp 141dc519b0 policy: Deprecate modules and add versions to others.
app_meetme is deprecated in 19, to be removed in 21.
app_osplookup is deprecated in 19, to be removed in 21.
chan_alsa is deprecated in 19, to be removed in 21.
chan_mgcp is deprecated in 19, to be removed in 21.
chan_skinny is deprecated in 19, to be removed in 21.
res_pktccops is deprecated in 19, to be removed in 21.
app_macro was deprecated in 16, to be removed in 21.
chan_sip was deprecated in 17, to be removed in 21.
res_monitor was deprecated in 16, to be removed in 21.

ASTERISK-29548
ASTERISK-29549
ASTERISK-29550
ASTERISK-29551
ASTERISK-29552
ASTERISK-29553
ASTERISK-29558
ASTERISK-29567
ASTERISK-29572

Change-Id: Ic3bee31a10d42c4b3bbc913d893f7b2a28a27131
2021-08-11 10:14:14 -03:00
Naveen Albert 7383f74dfc func_frame_drop: New function
Adds function to selectively drop specified frames
in the TX or RX direction on a channel, including
control frames.

ASTERISK-29478

Change-Id: I8147c9d55d74e2e48861edba6b22f930920541ec
2021-08-09 07:51:30 -05:00
Alexander Traud 835ab50724 aelparse: Accept an included context with timings.
With Asterisk 1.6.0, in the main parser for the configuration file
extensions.conf, the separator was changed from vertical bar to comma.
However, the first separator was not changed in aelparse; it still had
to be a vertical bar, and no comma was allowed.

Additionally, this change allows the vertical bar for the first and
last parameter again, even in the main parser, because the vertical bar
was still accepted for the other parameters.

ASTERISK-29540

Change-Id: I882e17c73adf4bf2f20f9046390860d04a9f8d81
2021-08-06 09:20:04 -05:00
Kevin Harwell 37f7d19c8c format_ogg_speex: Implement a "not supported" write handler
This format did not specify a "write" handler, so when attempting to write
to it (ast_writestream) a crash would occur.

This patch adds a default handler that simply issues a "not supported"
warning, thus no longer crashing.

ASTERISK-29539

Change-Id: I8f6ddc7cc3b15da30803be3b1cf68e2ba0fbce91
2021-08-05 14:29:38 -05:00
Naveen Albert 4c49c84dee cdr_adaptive_odbc: Prevent filter warnings
Previously, if CDR filters were used so that
not all CDR records used all sections defined
in cdr_adaptive_odbc.conf, then warnings will
always be emitted (if each CDR record is unique
to a particular section, n-1 warnings to be
specific).

This turns the offending warning log into
a verbose message like the other one, since
this behavior is intentional and not
indicative of anything wrong.

ASTERISK-29494

Change-Id: Ifd314fa9298722bc99494d5ca2658a5caa94a5f8
2021-08-04 07:59:55 -05:00
Naveen Albert 0975cff6c0 app_queue: Allow streaming multiple announcement files
Allows multiple files comprising an agent announcement
to be played by separating on the ampersand, similar
to the multi-file support in other Asterisk applications.

ASTERISK-29528

Change-Id: Iec600d8cd5ba14aa1e4e37f906accb356cd7891a
2021-08-03 14:19:09 -05:00
Igor Goncharovsky ac958b0f50 res_pjsip_header_funcs: Add PJSIP_HEADERS() ability to read header by pattern
PJSIP currently does not provide a function to replace SIP_HEADERS() function to get a list of headers from INVITE request.
It may be used to get all X- headers in case the actual set and names of headers unknown.

ASTERISK-29389

Change-Id: Ic09d395de71a0021e0d6c5c29e1e19d689079f8b
2021-08-03 09:40:01 -05:00
Rijnhard Hessel f13eef719c res_statsd: handle non-standard meter type safely
Meter types are not well supported,
lacking support in telegraf, datadog and the official statsd servers.
We deprecate meters and provide a compliant fallback for any existing usages.

A flag has been introduced to allow meters to fallback to counters.


ASTERISK-29513

Change-Id: I5fcb385983a1b88f03696ff30a26b55c546a1dd7
2021-08-03 08:15:29 -05:00
Sean Bright 382143e58e res_http_media_cache: Cleanup audio format lookup in HTTP requests
Asterisk first looks at the end of the URL to determine the file
extension of the returned audio, which in many cases will not work
because the URL may end with a query string or a URL fragment. If that
fails, Asterisk then looks at the Content-Type header and then finally
parses the URL to get the extension.

The order has been changed such that we look at the Content-Type
header first, followed by looking for the extension of the parsed
URL. We no longer look at the end of the URL, which was error prone.

ASTERISK-29527 #close

Change-Id: I1e3f83b339ef2b80661704717c23568536511032
2021-08-03 07:16:01 -05:00
under ff8ca2c9f1 codec_builtin.c: G729 audio gets corrupted by Asterisk due to smoother
If Asterisk gets G.729 6-byte VAD frames inbound, then at outbound Asterisk sends this G.729 stream with non-continuous timestamps.
This makes the audio stream not-playable at the receiver side.
Linphone isn't able to play such an audio - lots of disruptions are heard.
Also I had complains of bad audio from users which use other types of phones.

After debugging, I found this is a regression connected with RTP Smoother (main/smoother.c).

Smoother has a special code to handle G.729 VAD frames (search for AST_SMOOTHER_FLAG_G729 in smoother.c).

However, this flag is never set in Asterisk-12 and newer.
Previously it has been set (see Asterisk-11).

ASTERISK-29526 #close

Change-Id: I6f51ecb1a3ecd9c6d59ec5a6811a27446e17065d
2021-08-03 07:14:32 -05:00
Naveen Albert 6645cf8d45 app_dtmfstore: New application to store digits
Adds application to asynchronously collect digits
dialed on a channel in the TX or RX direction
using a framehook and stores them in a specified
variable, up to a configurable number of digits.

ASTERISK-29477

Change-Id: I51aa93fc9507f7636ac44806c4420ce690423e6f
2021-08-02 12:44:31 -05:00
Joshua C. Colp 90c9c90b11 docs: Remove embedded macro in WaitForCond XML documentation.
Change-Id: I40c6514e1843e320f3cbe0b2c70d4a98c0e35b9c
2021-07-27 07:55:24 -05:00
Kevin Harwell 56f9c28a50 AST-2021-008 - chan_iax2: remote crash on unsupported media format
If chan_iax2 received a packet with an unsupported media format, for
example vp9, then it would set the frame's format to NULL. This could
then result in a crash later when an attempt was made to access the
format.

This patch makes it so chan_iax2 now ignores/drops frames received
with unsupported media format types.

ASTERISK-29392 #close

Change-Id: Ifa869a90dafe33eed8fd9463574fe6f1c0ad3eb1
(cherry picked from commit 2a141a58b6)
2021-07-23 08:23:14 -05:00
Joshua C. Colp 45af7e9984 AST-2021-007 - res_pjsip_session: Don't offer if no channel exists.
If a re-INVITE is received after we have sent a BYE request then it
is possible for no channel to be present on the session. If this
occurs we allow PJSIP to produce the offer instead. Since the call
is being hung up if it produces an incorrect offer it doesn't
actually matter. This also ensures that code which produces SDP
does not need to handle if a channel is not present.

ASTERISK-29381

Change-Id: I673cb88c432f38f69b2e0851d55cc57a62236042
(cherry picked from commit 523a795289)
2021-07-23 08:23:11 -05:00
Kevin Harwell 151bdbc658 AST-2021-009 - pjproject-bundled: Avoid crash during handshake for TLS
If an SSL socket parent/listener was destroyed during the handshake,
depending on timing, it was possible for the handling callback to
attempt access of it after the fact thus causing a crash.

ASTERISK-29415 #close

Change-Id: I105dacdcd130ea7fdd4cf2010ccf35b5eaf1432d
(cherry picked from commit 3025ef4f6e)
2021-07-23 07:32:13 -05:00
Ben Ford 0ac346ec47 Update default branch for Asterisk 19.
Changed default branch to correct version for Asterisk 19.

Change-Id: I6244c8ac14b9c0eb8bdf07fe58db24dc95cb1086
2021-07-21 10:20:24 -05:00
911 changed files with 163106 additions and 63906 deletions

2
.gitignore vendored
View File

@ -37,4 +37,4 @@ doxygen.log
out/
*.orig
tests/CI/output
.develvars

View File

@ -1,5 +1,6 @@
[gerrit]
defaultbranch=master
defaultbranch=19
basebranch=19
#
# 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 @@
19.8.0

1032
CHANGES

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,7 @@
rewrite of SIP transfers
=== WISHLIST CONTRIBUTERS ===
=== WISHLIST CONTRIBUTORS ===
We'd like to thank the following for contributing to our wishlist

103753
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

View File

@ -45,7 +45,7 @@ redistribution of Asterisk source code obtained from Digium, you
should contact our licensing department to determine the necessary
steps you must take. For more information on this policy, please read:
http://www.digium.com/en/company/profile/trademarkpolicy.php
https://www.sangoma.com/wp-content/uploads/Sangoma-Trademark-Policy.pdf
If you have any questions regarding our licensing policy, please
contact us:
@ -53,7 +53,6 @@ contact us:
+1.877.344.4861 (via telephone in the USA)
+1.256.428.6000 (via telephone outside the USA)
+1.256.864.0464 (via FAX inside or outside the USA)
IAX2/pbx.digium.com (via IAX2)
licensing@digium.com (via email)
Digium, Inc.

127
Makefile
View File

@ -21,7 +21,7 @@
# on a single object just for that object
# SOLINK - linker flags used only for creating dynamically loadable modules
# as .so files
# DYLINK - linker flags used only for creating shared libaries
# DYLINK - linker flags used only for creating shared libraries
# (.so files on Unix-type platforms, .dylib on Darwin)
#
# Values for ASTCFLAGS and ASTLDFLAGS can be specified in the
@ -101,6 +101,11 @@ export TAR
export PATCH
export SED
export NM
export FIND
export BASENAME
export DIRNAME
export XMLLINT
export XMLSTARLET
# makeopts is required unless the goal is just {dist{-}}clean
ifeq ($(MAKECMDGOALS),clean)
@ -135,7 +140,7 @@ empty:=
space:=$(empty) $(empty)
ASTTOPDIR:=$(subst $(space),\$(space),$(CURDIR))
# Overwite config files on "make samples" or other config installation targets
# Overwrite config files on "make samples" or other config installation targets
OVERWRITE=y
# Include debug and macro symbols in the executables (-g) and profiling info (-pg)
@ -322,6 +327,9 @@ else
SUBMAKE:=$(MAKE) --quiet --no-print-directory
endif
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
mkfile_dir := $(dir $(mkfile_path))
# $(MAKE) is printed in several places, and we want it to be a
# fixed size string. Define a variable whose name has also the
# same size, so we can easily align text.
@ -442,7 +450,7 @@ distclean: $(SUBDIRS_DIST_CLEAN) _clean
rm -f include/asterisk/autoconfig.h
rm -f include/asterisk/buildopts.h
rm -rf doc/api
rm -f doc/asterisk-ng-doxygen
rm -f doc/Doxyfile
rm -f build_tools/menuselect-deps
datafiles: _all $(CORE_XMLDOC)
@ -475,60 +483,24 @@ endif
$(INSTALL) -m 644 $$x "$(DESTDIR)$(ASTDATADIR)/rest-api" ; \
done
ifeq ($(GREP),)
else ifeq ($(GREP),:)
else
XML_core_en_US = $(foreach dir,$(MOD_SUBDIRS),$(shell $(GREP) -l "language=\"en_US\"" $(dir)/*.c $(dir)/*.cc 2>/dev/null))
endif
DOC_MOD_SUBDIRS := $(filter-out third-party,$(MOD_SUBDIRS))
XML_core_en_US := $(shell build_tools/make_xml_documentation --command=print_dependencies --source-tree=. --mod-subdirs="$(DOC_MOD_SUBDIRS)")
# core-en_US.xml is the normal documentation created with asterisk builds.
doc/core-en_US.xml: makeopts .lastclean $(XML_core_en_US)
@printf "Building Documentation For: "
@echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > $@
@echo "<!DOCTYPE docs SYSTEM \"appdocsxml.dtd\">" >> $@
@echo "<?xml-stylesheet type=\"text/xsl\" href=\"appdocsxml.xslt\"?>" >> $@
@echo "<docs xmlns:xi=\"http://www.w3.org/2001/XInclude\">" >> $@
@for x in $(MOD_SUBDIRS); do \
printf "$$x " ; \
for i in `find $$x -name '*.c'`; do \
MODULEINFO=$$($(AWK) -f build_tools/get_moduleinfo $$i) ; \
if [ -n "$$MODULEINFO" ] ; \
then \
echo "<module language=\"en_US\" name=\"`$(BASENAME) -s .c $$i`\">" >> $@ ; \
echo "$$MODULEINFO" >> $@ ; \
echo "</module>" >> $@ ; \
fi ; \
$(AWK) -f build_tools/get_documentation $$i >> $@ ; \
done ; \
done
@echo
@echo "</docs>" >> $@
@build_tools/make_xml_documentation --command=create_xml --source-tree=. --mod-subdirs="$(DOC_MOD_SUBDIRS)" \
--with-moduleinfo --output-file=$@
ifeq ($(GREP),)
else ifeq ($(GREP),:)
else
XML_full_en_US = $(foreach dir,$(MOD_SUBDIRS),$(shell $(GREP) -l "language=\"en_US\"" $(dir)/*.c $(dir)/*.cc 2>/dev/null))
endif
doc/full-en_US.xml: makeopts .lastclean $(XML_full_en_US)
# The full-en_US.xml target is only called by the wiki documentation generation process
# and does special post-processing in preparation for uploading to the wiki.
# It creates full-en_US.xml but then re-creates core-en_US.xml as well.
doc/full-en_US.xml: makeopts .lastclean $(XML_core_en_US)
ifeq ($(PYTHON),:)
@echo "--------------------------------------------------------------------------"
@echo "--- Please install python to build full documentation ---"
@echo "--------------------------------------------------------------------------"
else
@printf "Building Documentation For: "
@echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" > $@
@echo "<!DOCTYPE docs SYSTEM \"appdocsxml.dtd\">" >> $@
@echo "<?xml-stylesheet type=\"text/xsl\" href=\"appdocsxml.xslt\"?>" >> $@
@echo "<docs xmlns:xi=\"http://www.w3.org/2001/XInclude\">" >> $@
@for x in $(filter-out third-party,$(MOD_SUBDIRS)); do \
printf "$$x " ; \
for i in `find $$x -name '*.c'`; do \
$(PYTHON) build_tools/get_documentation.py < $$i >> $@ ; \
done ; \
done
@echo
@echo "</docs>" >> $@
@$(PYTHON) build_tools/post_process_documentation.py -i $@ -o "doc/core-en_US.xml"
@build_tools/make_xml_documentation --command=create_xml --source-tree=. --mod-subdirs="$(DOC_MOD_SUBDIRS)" \
--for-wiki --output-file=$@ --core-output-file=./doc/core-en_US.xml
endif
validate-docs: doc/core-en_US.xml
@ -589,9 +561,9 @@ bininstall: _all installdirs $(SUBDIRS_INSTALL) main-bininstall
$(INSTALL) -m 755 contrib/scripts/astversion "$(DESTDIR)$(ASTSBINDIR)/"
$(INSTALL) -m 755 contrib/scripts/astgenkey "$(DESTDIR)$(ASTSBINDIR)/"
$(INSTALL) -m 755 contrib/scripts/autosupport "$(DESTDIR)$(ASTSBINDIR)/"
if [ ! -f /sbin/launchd ]; then \
./build_tools/install_subst contrib/scripts/safe_asterisk "$(DESTDIR)$(ASTSBINDIR)/safe_asterisk"; \
fi
ifneq ($(HAVE_SBIN_LAUNCHD),1)
./build_tools/install_subst contrib/scripts/safe_asterisk "$(DESTDIR)$(ASTSBINDIR)/safe_asterisk";
endif
ifneq ($(DISABLE_XMLDOC),yes)
$(INSTALL) -m 644 doc/core-*.xml "$(DESTDIR)$(ASTDATADIR)/documentation"
@ -724,7 +696,17 @@ ifneq ($(filter ~%,$(DESTDIR)),)
@exit 1
endif
install: badshell bininstall datafiles
versioncheck:
ifeq ($(ASTERISKVERSION),UNKNOWN__git_check_fail)
@echo "Asterisk Version is unknown due to a git error. If you are running make"
@echo "as a different user than the project owner, this can be resolved by"
@echo "running the following command as the user currently executing make: "$$USER
@echo "git config --global --add safe.directory "$(mkfile_dir:/=)
@exit 1
endif
install: badshell versioncheck bininstall datafiles
@if [ -x /usr/sbin/asterisk-post-install ]; then \
/usr/sbin/asterisk-post-install "$(DESTDIR)" . ; \
fi
@ -891,29 +873,36 @@ webvmail:
@echo " +-------------------------------------------+"
progdocs:
# Note, Makefile conditionals must not be tabbed out. Wasted hours with that.
@cp doc/asterisk-ng-doxygen.in doc/asterisk-ng-doxygen
ifeq ($(DOXYGEN),:)
@echo "Doxygen is not installed. Please install and re-run the configuration script."
else
@cp doc/Doxyfile.in doc/Doxyfile
ifeq ($(DOT),:)
@echo "DOT is not installed. Doxygen will not produce any diagrams. Please install and re-run the configuration script."
else
# Enable DOT
@echo "HAVE_DOT = YES" >> doc/asterisk-ng-doxygen
@echo "HAVE_DOT = YES" >> doc/Doxyfile
endif
# Set Doxygen PROJECT_NUMBER variable
ifneq ($(ASTERISKVERSION),UNKNOWN__and_probably_unsupported)
@echo "PROJECT_NUMBER = $(ASTERISKVERSION)" >> doc/asterisk-ng-doxygen
ifneq ($(NOISY_BUILD),yes)
@echo "EXTRACT_ALL = YES" >> doc/Doxyfile
endif
ifeq ($(AST_DEVMODE),yes)
@echo "INTERNAL_DOCS = YES" >> doc/Doxyfile
@echo "WARN_NO_PARAMDOC = YES" >> doc/Doxyfile
endif
ifeq ($(ASTERISKVERSION),UNKNOWN__and_probably_unsupported)
@echo "Asterisk Version is unknown, not configuring Doxygen PROJECT_NUMBER."
else ifeq ($(ASTERISKVERSION),UNKNOWN__git_check_fail)
@echo "Asterisk Version is unknown due to a git error. If you are running make"
@echo "as a different user than the project owner, this can be resolved by"
@echo "running the following command as the user currently executing make: "$$USER
@echo "git config --global --add safe.directory "$(mkfile_dir:/=)
@echo "not configuring Doxygen PROJECT_NUMBER."
else
echo "Asterisk Version is unknown, not configuring Doxygen PROJECT_NUMBER."
@echo "PROJECT_NUMBER = $(ASTERISKVERSION)" >> doc/Doxyfile
endif
# Validate and auto-update local copy
@doxygen -u doc/asterisk-ng-doxygen
# Run Doxygen
@doxygen doc/asterisk-ng-doxygen
# Remove configuration backup file
@rm -f doc/asterisk-ng-doxygen.bak
@echo "Generating C-API documentation. This will take a while."
@doxygen doc/Doxyfile
@echo "Generation complete. Any warnings are in ./doxygen.log."
endif
install-logrotate:
@ -998,6 +987,7 @@ sounds:
@$(MAKE) clean
@[ -f "$(DESTDIR)$(ASTDBDIR)/astdb.sqlite3" ] || [ ! -f "$(DESTDIR)$(ASTDBDIR)/astdb" ] || [ ! -f menuselect.makeopts ] || grep -q MENUSELECT_UTILS=.*astdb2sqlite3 menuselect.makeopts || (sed -i.orig -e's/MENUSELECT_UTILS=\(.*\)/MENUSELECT_UTILS=\1 astdb2sqlite3/' menuselect.makeopts && echo "Updating menuselect.makeopts to include astdb2sqlite3" && echo "Original version backed up to menuselect.makeopts.orig")
$(SUBDIRS_UNINSTALL):
+@DESTDIR="$(DESTDIR)" ASTSBINDIR="$(ASTSBINDIR)" ASTDATADIR="$(ASTDATADIR)" $(SUBMAKE) -C $(@:-uninstall=) uninstall
@ -1154,6 +1144,7 @@ check-alembic: makeopts
.PHONY: uninstall-headers
.PHONY: badshell
.PHONY: installdirs
.PHONY: progdocs
.PHONY: validate-docs
.PHONY: _clean
.PHONY: ari-stubs

View File

@ -204,4 +204,19 @@ endif
$(ECHO_PREFIX) echo " [LD] $^ -> $@"
$(CMD_PREFIX) $(CXX) -o $@ $(PTHREAD_CFLAGS) $(_ASTLDFLAGS) $^ $(CXX_LIBS) $(ASTLDFLAGS)
# These CC commands just create an object file with the input file embedded in it.
# It can be access from code as follows:
# If your input file is named abc_def.xml...
#
# extern const uint8_t _binary_abc_def_xml_start[];
# extern const uint8_t _binary_abc_def_xml_end[];
# extern const size_t _binary_abc_def_xml_size;
%.o: %.xml
$(ECHO_PREFIX) echo " [LD] $^ -> $@"
$(CMD_PREFIX) $(CC) -g -nostartfiles -nodefaultlibs -nostdlib -r -Wl,-b,binary -o $@ $^
%.o: %.xslt
$(ECHO_PREFIX) echo " [LD] $^ -> $@"
$(CMD_PREFIX) $(CC) -g -nostartfiles -nodefaultlibs -nostdlib -r -Wl,-b,binary -o $@ $^
dist-clean:: clean

View File

@ -91,7 +91,10 @@ guides in the [configs] directory.
2. Run `./configure`
Execute the configure script to guess values for system-dependent
variables used during compilation.
variables used during compilation. If the script indicates that some required
components are missing, you can run `./contrib/scripts/install_prereq install`
to install the necessary components. Note that this will install all dependencies for every functionality of Asterisk. After running the script, you will need
to rerun `./configure`.
3. Run `make menuselect` _\[optional]_

View File

@ -18,6 +18,290 @@
===
===========================================================
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 19.7.0 to Asterisk 19.8.0 ------------
------------------------------------------------------------------------------
AMI (Asterisk Manager Interface)
------------------
* Previously, GetConfig and UpdateConfig were able to access files outside of
the Asterisk configuration directory. Now this access is put behind the
live_dangerously configuration option in asterisk.conf, which is disabled by
default. If access to configuration files outside of the Asterisk configuation
directory is required via AMI, then the live_dangerously configuration option
must be set to yes.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 19.6.0 to Asterisk 19.7.0 ------------
------------------------------------------------------------------------------
res_crypto
------------------
* In addition to only paying attention to files ending with .key or .pub
in the keys directory, we now also ignore any files which aren't regular
files.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 19.4.0 to Asterisk 19.5.0 ------------
------------------------------------------------------------------------------
res_pjsip
------------------
* The 'async_operations' setting on transports is no longer
obeyed and instead is always set to 1. This is due to the
functionality not being applicable to Asterisk and causing
excess unnecessary memory usage. This setting will now be
ignored but can also be removed from the configuration file.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 19.2.0 to Asterisk 19.3.0 ------------
------------------------------------------------------------------------------
AMI
------------------
* The XML Manager Event Interface (amxml) now generates attribute names
that are compliant with the XML 1.1 specification. Previously, an
attribute name that started with a digit would be rendered as-is, even
though attribute names must not begin with a digit. We now prefix
attribute names that start with a digit with an underscore ('_') to
prevent XML validation failures.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 19.0.0 to Asterisk 19.1.0 ------------
------------------------------------------------------------------------------
STIR/SHAKEN
------------------
* The STIR/SHAKEN configuration option has been split into
4 different choices: off, attest, verify, and on. Off and
on behave the same way as before. Attest will only perform
attestation on the endpoint, and verify will only perform
verification on the endpoint.
------------------------------------------------------------------------------
--- New functionality introduced in Asterisk 19.0.0 --------------------------
------------------------------------------------------------------------------
Log Rotate
------------------
* The sample logger files have been changed to have .log as their file
extension. This was done so that when attached to issues on the issue
tracker, they are able to be opened in the browser for convenience.
Because of this, the asterisk.logrotate script has been updated to look
for .log extensions instead of no extension for files such as full
and messages.
app_dahdiras
------------------
* This module was deprecated in Asterisk 16
and is now being removed in accordance with
the Asterisk Module Deprecation policy.
app_fax
------------------
* This module was deprecated in Asterisk 16
and is now being removed in accordance with
the Asterisk Module Deprecation policy.
app_ices
------------------
* This module was deprecated in Asterisk 16
and is now being removed in accordance with
the Asterisk Module Deprecation policy.
app_image
------------------
* This module was deprecated in Asterisk 16
and is now being removed in accordance with
the Asterisk Module Deprecation policy.
app_meetme
------------------
* This module is now deprecated and will no
longer be built by default. It is scheduled
to be removed as of Asterisk 21.
app_mysql
------------------
* This module was deprecated in Asterisk 1.8
and is now being removed in accordance with
the Asterisk Module Deprecation policy.
app_nbscat
------------------
* This module was deprecated in Asterisk 16
and is now being removed in accordance with
the Asterisk Module Deprecation policy.
app_osplookup
------------------
* This module is now deprecated and will no
longer be built by default. It is scheduled
to be removed as of Asterisk 21.
app_url
------------------
* This module was deprecated in Asterisk 16
and is now being removed in accordance with
the Asterisk Module Deprecation policy.
cdr_mysql
------------------
* This module was deprecated in Asterisk 1.8
and is now being removed in accordance with
the Asterisk Module Deprecation policy.
cdr_syslog
------------------
* This module was deprecated in Asterisk 16
and is now being removed in accordance with
the Asterisk Module Deprecation policy.
chan_alsa
------------------
* This module is now deprecated and will no
longer be built by default. It is scheduled
to be removed as of Asterisk 21.
chan_mgcp
------------------
* This module is now deprecated and will no
longer be built by default. It is scheduled
to be removed as of Asterisk 21.
chan_misdn
------------------
* This module was deprecated in Asterisk 16
and is now being removed in accordance with
the Asterisk Module Deprecation policy.
chan_nbs
------------------
* This module was deprecated in Asterisk 16
and is now being removed in accordance with
the Asterisk Module Deprecation policy.
chan_oss
------------------
* This module was deprecated in Asterisk 16
and is now being removed in accordance with
the Asterisk Module Deprecation policy.
chan_phone
------------------
* This module was deprecated in Asterisk 16
and is now being removed in accordance with
the Asterisk Module Deprecation policy.
chan_sip
------------------
* chan_sip is no longer built by default. To build it, make sure to
enable it when running 'make menuselect'
chan_skinny
------------------
* This module is now deprecated and will no
longer be built by default. It is scheduled
to be removed as of Asterisk 21.
chan_vpb
------------------
* This module was deprecated in Asterisk 16
and is now being removed in accordance with
the Asterisk Module Deprecation policy.
conf2ael
------------------
* This application was deprecated in Asterisk 16
and is now being removed in accordance with
the Asterisk Module Deprecation policy.
muted
------------------
* This application was deprecated in Asterisk 16
and is now being removed in accordance with
the Asterisk Module Deprecation policy.
res_config_sqlite
------------------
* This module was deprecated in Asterisk 16
and is now being removed in accordance with
the Asterisk Module Deprecation policy.
res_monitor
------------------
* This module is no longer built by default in
accordance with the Module Deprecation Policy.
If you require this functionality you will need
to enable it for building in menuselect. Note
that in the future res_monitor will be removed.
res_pktccops
------------------
* This module is now deprecated and will no
longer be built by default. It is scheduled
to be removed as of Asterisk 21.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 18.0.0 to Asterisk 19.0.0 ------------
------------------------------------------------------------------------------
STIR/SHAKEN
------------------
* The configuration option public_key_url in stir_shaken.conf
has been renamed to public_cert_url to better fit what it
contains. Only the name has changed - functionality is the
same.
* STIR/SHAKEN originally needed an origid to be specified in
stir_shaken.conf under the certificate config object in
order to work. Now, one is automatically created by
generating a UUID, as recommended by RFC8588. Any origid
you have in your stir_shaken.conf will need to be removed
for the module to read in certificates.
chan_iax2
------------------
* Encryption is now supported for RSA authentication.
Currently, these auth configurations will cause a crash:
auth = md5,rsa
auth = plaintext,md5,rsa
With a patched peer, the following will cause a crash:
auth = rsa
auth = md5,rsa
auth = plaintext,md5,rsa
If both the peer and user are patches, no crash occurs.
Existing good configurations should continue to work.
menuselect
------------------
* menuselect --enable, --disable, --enable-category and --disable-category will
now fail with a non-zero exit code instead of silently failing if an invalid
option or category is specified.
res_http_media_cache
------------------
* When fetching a file for playback from a URL, Asterisk will now first
use the value of the Content-Type header in the HTTP response to
determine the format of the audio data, and only if it is unable to do
that will it attempt to parse the URL and extract the extension from
the path portion. Previously Asterisk would first look at the end of
the URL, which may have included query string parameters or a URL
fragment, which was error prone.
res_srtp
------------------
* SRTP replay protection has been added to res_srtp and
a new configuration option "srtpreplayprotection" has
been added to the rtp.conf config file. For security
reasons, the default setting is "yes". Buggy clients
may not handle this correctly which could result in
no, or one way, audio and Asterisk error messages like
"replay check failed".
------------------------------------------------------------------------------
--- New functionality introduced in Asterisk 18.0.0 --------------------------
------------------------------------------------------------------------------
@ -610,7 +894,7 @@ chan_unistim:
values used inside Unistim protocol
- Added 'dtmf_duration' option with changing default operation to disable
receivied dtmf playback on unistim phone
received dtmf playback on unistim phone
Core:
@ -1528,7 +1812,7 @@ UDPTL:
From 10.4 to 10.5:
* The complex processor detection and optimization has been removed from
the makefile in favor of using native optimization suppport when available.
the makefile in favor of using native optimization support when available.
BUILD_NATIVE can be disabled via menuselect under "Compiler Flags".
From 10.2 to 10.3:
@ -1601,7 +1885,7 @@ From 1.8.13 to 1.8.14:
From 1.8.12 to 1.8.13:
* The complex processor detection and optimization has been removed from
the makefile in favor of using native optimization suppport when available.
the makefile in favor of using native optimization support when available.
BUILD_NATIVE can be disabled via menuselect under "Compiler Flags".
From 1.8.10 to 1.8.11:
@ -2380,7 +2664,7 @@ Applications:
the 'm' option now provides the functionality of "initially muted".
In practice, most existing dialplans using the 'm' flag should not notice
any difference, unless the keypad menu is enabled, allowing the user
to unmute themsleves.
to unmute themselves.
* ast_play_and_record would attempt to cancel the recording if a DTMF
'0' was received. This behavior was not documented in most of the

View File

@ -16,10 +16,12 @@ renamed; the new names are:
chan_zap.so -> chan_dahdi.so
app_zapbarge.so -> app_dahdibarge.so
app_zapras.so -> app_dahdiras.so
app_zapscan.so -> app_dahdiscan.so
codec_zap.so -> codec_dahdi.so
The following modules have been removed:
app_zapras.so -> app_dahdiras.so
Second, the behavior of many modules has changed due to the switch to
DAHDI; the changes are listed below.
@ -46,7 +48,8 @@ app_dahdibarge.so:
app_dahdiras.so:
The ZapRAS application has been renamed to DAHDIRAS.
The ZapRAS application was renamed to DAHDIRAS. This application has
since been removed.
app_dahdiscan.so:

View File

@ -28,9 +28,7 @@ H323SOURCE:=$(addprefix ooh323c/src/,$(OOH323C)) ooh323cDriver.c
H323CFLAGS:=-Iooh323c/src -Iooh323c/src/h323
ALL_C_MODS:=app_mysql \
cdr_mysql \
chan_mobile \
ALL_C_MODS:=chan_mobile \
chan_ooh323 \
format_mp3 \
res_config_mysql
@ -64,6 +62,10 @@ chan_ooh323.so: _ASTCFLAGS+=$(H323CFLAGS)
$(call MOD_ADD_C,chan_ooh323,$(H323SOURCE))
ifneq ($(wildcard mp3/Makefile),)
# At the current time, the fate of mp3 is in flux so it didn't make sense to
# add configure/makeopts processing for array-bounds since this is the only
# source file that needs that warning suppressed.
mp3/layer3.o: _ASTCFLAGS+=-Wno-array-bounds
$(call MOD_ADD_C,format_mp3,mp3/common.c mp3/dct64_i386.c mp3/decode_ntom.c mp3/layer3.c mp3/tabinit.c mp3/interface.c)
.PHONY: check_mp3

View File

@ -1,667 +0,0 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2004, Constantine Filin and Christos Ricudis
*
* Christos Ricudis <ricudis@itc.auth.gr>
* Constantine Filin <cf@intermedia.net>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*!
* \file
* \brief MYSQL dialplan application
* \ingroup applications
*/
/*! \li \ref app_mysql.c uses the configuration file \ref app_mysql.conf
* \addtogroup configuration_file Configuration Files
*/
/*!
* \page app_mysql.conf app_mysql.conf
* \verbinclude app_mysql.conf.sample
*/
/*** MODULEINFO
<depend>mysqlclient</depend>
<defaultenabled>no</defaultenabled>
<support_level>deprecated</support_level>
<replacement>func_odbc</replacement>
***/
#include "asterisk.h"
#include <mysql/mysql.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/linkedlists.h"
#include "asterisk/chanvars.h"
#include "asterisk/lock.h"
#include "asterisk/options.h"
#include "asterisk/app.h"
#include "asterisk/config.h"
#define EXTRA_LOG 0
enum { NULLSTRING, NULLVALUE, EMPTYSTRING } nullvalue = NULLSTRING;
static const char app[] = "MYSQL";
static const char synopsis[] = "Do several mySQLy things";
static const char descrip[] =
"MYSQL(): Do several mySQLy things\n"
"Syntax:\n"
" MYSQL(Set timeout <num>)\n"
" Set the connection timeout, in seconds.\n"
" MYSQL(Connect connid dhhost[:dbport] dbuser dbpass dbname [dbcharset])\n"
" Connects to a database. Arguments contain standard MySQL parameters\n"
" passed to function mysql_real_connect. Optional parameter dbcharset\n"
" defaults to 'latin1'. Connection identifer returned in ${connid}\n"
" MYSQL(Query resultid ${connid} query-string)\n"
" Executes standard MySQL query contained in query-string using established\n"
" connection identified by ${connid}. Result of query is stored in ${resultid}.\n"
" MYSQL(Nextresult resultid ${connid}\n"
" If last query returned more than one result set, it stores the next\n"
" result set in ${resultid}. It's useful with stored procedures\n"
" MYSQL(Fetch fetchid ${resultid} var1 var2 ... varN)\n"
" Fetches a single row from a result set contained in ${result_identifier}.\n"
" Assigns returned fields to ${var1} ... ${varn}. ${fetchid} is set TRUE\n"
" if additional rows exist in result set.\n"
" MYSQL(Clear ${resultid})\n"
" Frees memory and datastructures associated with result set.\n"
" MYSQL(Disconnect ${connid})\n"
" Disconnects from named connection to MySQL.\n"
" On exit, always returns 0. Sets MYSQL_STATUS to 0 on success and -1 on error.\n";
/*
EXAMPLES OF USE :
exten => s,2,MYSQL(Connect connid localhost asterisk mypass credit utf8)
exten => s,3,MYSQL(Query resultid ${connid} SELECT username,credit FROM credit WHERE callerid=${CALLERIDNUM})
exten => s,4,MYSQL(Fetch fetchid ${resultid} datavar1 datavar2)
exten => s,5,GotoIf(${fetchid}?6:8)
exten => s,6,Festival("User ${datavar1} currently has credit balance of ${datavar2} dollars.")
exten => s,7,Goto(s,4)
exten => s,8,MYSQL(Clear ${resultid})
exten => s,9,MYSQL(Disconnect ${connid})
*/
AST_MUTEX_DEFINE_STATIC(_mysql_mutex);
#define MYSQL_CONFIG "app_mysql.conf"
#define MYSQL_CONFIG_OLD "mysql.conf"
#define AST_MYSQL_ID_DUMMY 0
#define AST_MYSQL_ID_CONNID 1
#define AST_MYSQL_ID_RESID 2
#define AST_MYSQL_ID_FETCHID 3
static int autoclear = 0;
static void mysql_ds_destroy(void *data);
static void mysql_ds_fixup(void *data, struct ast_channel *oldchan, struct ast_channel *newchan);
static const struct ast_datastore_info mysql_ds_info = {
.type = "APP_ADDON_SQL_MYSQL",
.destroy = mysql_ds_destroy,
.chan_fixup = mysql_ds_fixup,
};
struct ast_MYSQL_id {
struct ast_channel *owner;
int identifier_type; /* 0=dummy, 1=connid, 2=resultid */
int identifier;
void *data;
AST_LIST_ENTRY(ast_MYSQL_id) entries;
} *ast_MYSQL_id;
AST_LIST_HEAD(MYSQLidshead,ast_MYSQL_id) _mysql_ids_head;
static void mysql_ds_destroy(void *data)
{
/* Destroy any IDs owned by the channel */
struct ast_MYSQL_id *i;
if (AST_LIST_LOCK(&_mysql_ids_head)) {
ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
} else {
AST_LIST_TRAVERSE_SAFE_BEGIN(&_mysql_ids_head, i, entries) {
if (i->owner == data) {
AST_LIST_REMOVE_CURRENT(entries);
if (i->identifier_type == AST_MYSQL_ID_CONNID) {
/* Drop connection */
mysql_close(i->data);
} else if (i->identifier_type == AST_MYSQL_ID_RESID) {
/* Drop result */
mysql_free_result(i->data);
}
ast_free(i);
}
}
AST_LIST_TRAVERSE_SAFE_END
AST_LIST_UNLOCK(&_mysql_ids_head);
}
}
static void mysql_ds_fixup(void *data, struct ast_channel *oldchan, struct ast_channel *newchan)
{
/* Destroy any IDs owned by the channel */
struct ast_MYSQL_id *i;
if (AST_LIST_LOCK(&_mysql_ids_head)) {
ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
} else {
AST_LIST_TRAVERSE_SAFE_BEGIN(&_mysql_ids_head, i, entries) {
if (i->owner == data) {
AST_LIST_REMOVE_CURRENT(entries);
if (i->identifier_type == AST_MYSQL_ID_CONNID) {
/* Drop connection */
mysql_close(i->data);
} else if (i->identifier_type == AST_MYSQL_ID_RESID) {
/* Drop result */
mysql_free_result(i->data);
}
ast_free(i);
}
}
AST_LIST_TRAVERSE_SAFE_END
AST_LIST_UNLOCK(&_mysql_ids_head);
}
}
/* helpful procs */
static void *find_identifier(int identifier, int identifier_type)
{
struct MYSQLidshead *headp = &_mysql_ids_head;
struct ast_MYSQL_id *i;
void *res=NULL;
int found=0;
if (AST_LIST_LOCK(headp)) {
ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
} else {
AST_LIST_TRAVERSE(headp, i, entries) {
if ((i->identifier == identifier) && (i->identifier_type == identifier_type)) {
found = 1;
res = i->data;
break;
}
}
if (!found) {
ast_log(LOG_WARNING, "Identifier %d, identifier_type %d not found in identifier list\n", identifier, identifier_type);
}
AST_LIST_UNLOCK(headp);
}
return res;
}
static int add_identifier(struct ast_channel *chan, int identifier_type, void *data)
{
struct ast_MYSQL_id *i = NULL, *j = NULL;
struct MYSQLidshead *headp = &_mysql_ids_head;
int maxidentifier = 0;
if (AST_LIST_LOCK(headp)) {
ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
return -1;
} else {
i = ast_malloc(sizeof(*i));
AST_LIST_TRAVERSE(headp, j, entries) {
if (j->identifier > maxidentifier) {
maxidentifier = j->identifier;
}
}
i->identifier = maxidentifier + 1;
i->identifier_type = identifier_type;
i->data = data;
i->owner = chan;
AST_LIST_INSERT_HEAD(headp, i, entries);
AST_LIST_UNLOCK(headp);
}
return i->identifier;
}
static int del_identifier(int identifier, int identifier_type)
{
struct ast_MYSQL_id *i;
struct MYSQLidshead *headp = &_mysql_ids_head;
int found = 0;
if (AST_LIST_LOCK(headp)) {
ast_log(LOG_WARNING, "Unable to lock identifiers list\n");
} else {
AST_LIST_TRAVERSE(headp, i, entries) {
if ((i->identifier == identifier) &&
(i->identifier_type == identifier_type)) {
AST_LIST_REMOVE(headp, i, entries);
ast_free(i);
found = 1;
break;
}
}
AST_LIST_UNLOCK(headp);
}
if (found == 0) {
ast_log(LOG_WARNING, "Could not find identifier %d, identifier_type %d in list to delete\n", identifier, identifier_type);
return -1;
} else {
return 0;
}
}
static int set_asterisk_int(struct ast_channel *chan, char *varname, int id)
{
if (id >= 0) {
char s[12] = "";
snprintf(s, sizeof(s), "%d", id);
ast_debug(5, "MYSQL: setting var '%s' to value '%s'\n", varname, s);
pbx_builtin_setvar_helper(chan, varname, s);
}
return id;
}
static int add_identifier_and_set_asterisk_int(struct ast_channel *chan, char *varname, int identifier_type, void *data)
{
return set_asterisk_int(chan, varname, add_identifier(chan, identifier_type, data));
}
static int safe_scan_int(char **data, char *delim, int def)
{
char *end;
int res = def;
char *s = strsep(data, delim);
if (s) {
res = strtol(s, &end, 10);
if (*end)
res = def; /* not an integer */
}
return res;
}
static int aMYSQL_set(struct ast_channel *chan, const char *data)
{
char *var, *tmp, *parse;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(set);
AST_APP_ARG(variable);
AST_APP_ARG(value);
);
parse = ast_strdupa(data);
AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
if (args.argc == 3) {
var = ast_alloca(6 + strlen(args.variable) + 1);
sprintf(var, "MYSQL_%s", args.variable);
/* Make the parameter case-insensitive */
for (tmp = var + 6; *tmp; tmp++)
*tmp = toupper(*tmp);
pbx_builtin_setvar_helper(chan, var, args.value);
}
return 0;
}
/* MYSQL operations */
static int aMYSQL_connect(struct ast_channel *chan, const char *data)
{
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(connect);
AST_APP_ARG(connid);
AST_APP_ARG(dbhost);
AST_APP_ARG(dbuser);
AST_APP_ARG(dbpass);
AST_APP_ARG(dbname);
AST_APP_ARG(dbcharset);
);
MYSQL *mysql;
int timeout;
const char *ctimeout;
unsigned int port = 0;
char *port_str;
char *parse = ast_strdupa(data);
AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
if (args.argc < 6) {
ast_log(LOG_WARNING, "MYSQL_connect is missing some arguments\n");
return -1;
}
if (!(mysql = mysql_init(NULL))) {
ast_log(LOG_WARNING, "mysql_init returned NULL\n");
return -1;
}
ctimeout = pbx_builtin_getvar_helper(chan, "MYSQL_TIMEOUT");
if (ctimeout && sscanf(ctimeout, "%30d", &timeout) == 1) {
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (void *)&timeout);
}
if(args.dbcharset && strlen(args.dbcharset) > 2){
char set_names[255];
char statement[512];
snprintf(set_names, sizeof(set_names), "SET NAMES %s", args.dbcharset);
mysql_real_escape_string(mysql, statement, set_names, sizeof(set_names));
mysql_options(mysql, MYSQL_INIT_COMMAND, set_names);
mysql_options(mysql, MYSQL_SET_CHARSET_NAME, args.dbcharset);
}
if ((port_str = strchr(args.dbhost, ':'))) {
*port_str++ = '\0';
if (sscanf(port_str, "%u", &port) != 1) {
ast_log(LOG_WARNING, "Invalid port: '%s'\n", port_str);
port = 0;
}
}
if (!mysql_real_connect(mysql, args.dbhost, args.dbuser, args.dbpass, args.dbname, port, NULL,
#ifdef CLIENT_MULTI_STATEMENTS
CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS
#elif defined(CLIENT_MULTI_QUERIES)
CLIENT_MULTI_QUERIES
#else
0
#endif
)) {
ast_log(LOG_WARNING, "mysql_real_connect(mysql,%s,%s,dbpass,%s,...) failed(%d): %s\n",
args.dbhost, args.dbuser, args.dbname, mysql_errno(mysql), mysql_error(mysql));
return -1;
}
add_identifier_and_set_asterisk_int(chan, args.connid, AST_MYSQL_ID_CONNID, mysql);
return 0;
}
static int aMYSQL_query(struct ast_channel *chan, const char *data)
{
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(query);
AST_APP_ARG(resultid);
AST_APP_ARG(connid);
AST_APP_ARG(sql);
);
MYSQL *mysql;
MYSQL_RES *mysqlres;
int connid;
int mysql_query_res;
char *parse = ast_strdupa(data);
AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
if (args.argc != 4 || (connid = atoi(args.connid)) == 0) {
ast_log(LOG_WARNING, "missing some arguments\n");
return -1;
}
if (!(mysql = find_identifier(connid, AST_MYSQL_ID_CONNID))) {
ast_log(LOG_WARNING, "Invalid connection identifier %s passed in aMYSQL_query\n", args.connid);
return -1;
}
if ((mysql_query_res = mysql_query(mysql, args.sql)) != 0) {
ast_log(LOG_WARNING, "aMYSQL_query: mysql_query failed. Error: %s\n", mysql_error(mysql));
return -1;
}
if ((mysqlres = mysql_store_result(mysql))) {
add_identifier_and_set_asterisk_int(chan, args.resultid, AST_MYSQL_ID_RESID, mysqlres);
return 0;
} else if (!mysql_field_count(mysql)) {
return 0;
} else
ast_log(LOG_WARNING, "mysql_store_result() failed on query %s\n", args.sql);
return -1;
}
static int aMYSQL_nextresult(struct ast_channel *chan, const char *data)
{
MYSQL *mysql;
MYSQL_RES *mysqlres;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(nextresult);
AST_APP_ARG(resultid);
AST_APP_ARG(connid);
);
int connid = -1;
char *parse = ast_strdupa(data);
AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
sscanf(args.connid, "%30d", &connid);
if (args.argc != 3 || connid <= 0) {
ast_log(LOG_WARNING, "missing some arguments\n");
return -1;
}
if (!(mysql = find_identifier(connid, AST_MYSQL_ID_CONNID))) {
ast_log(LOG_WARNING, "Invalid connection identifier %d passed in aMYSQL_query\n", connid);
return -1;
}
if (mysql_more_results(mysql)) {
mysql_next_result(mysql);
if ((mysqlres = mysql_store_result(mysql))) {
add_identifier_and_set_asterisk_int(chan, args.resultid, AST_MYSQL_ID_RESID, mysqlres);
return 0;
} else if (!mysql_field_count(mysql)) {
return 0;
} else
ast_log(LOG_WARNING, "mysql_store_result() failed on storing next_result\n");
} else
ast_log(LOG_WARNING, "mysql_more_results() result set has no more results\n");
return 0;
}
static int aMYSQL_fetch(struct ast_channel *chan, const char *data)
{
MYSQL_RES *mysqlres;
MYSQL_ROW mysqlrow;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(fetch);
AST_APP_ARG(resultvar);
AST_APP_ARG(fetchid);
AST_APP_ARG(vars);
);
char *s5, *parse;
int resultid = -1, numFields, j;
parse = ast_strdupa(data);
AST_NONSTANDARD_APP_ARGS(args, parse, ' ');
sscanf(args.fetchid, "%30d", &resultid);
if (args.resultvar && (resultid >= 0) ) {
if ((mysqlres = find_identifier(resultid, AST_MYSQL_ID_RESID)) != NULL) {
/* Grab the next row */
if ((mysqlrow = mysql_fetch_row(mysqlres)) != NULL) {
numFields = mysql_num_fields(mysqlres);
for (j = 0; j < numFields; j++) {
s5 = strsep(&args.vars, " ");
if (s5 == NULL) {
ast_log(LOG_WARNING, "ast_MYSQL_fetch: More fields (%d) than variables (%d)\n", numFields, j);
break;
}
pbx_builtin_setvar_helper(chan, s5, mysqlrow[j] ? mysqlrow[j] :
nullvalue == NULLSTRING ? "NULL" :
nullvalue == EMPTYSTRING ? "" :
NULL);
}
ast_debug(5, "ast_MYSQL_fetch: numFields=%d\n", numFields);
set_asterisk_int(chan, args.resultvar, 1); /* try more rows */
} else {
ast_debug(5, "ast_MYSQL_fetch : EOF\n");
set_asterisk_int(chan, args.resultvar, 0); /* no more rows */
}
return 0;
} else {
set_asterisk_int(chan, args.resultvar, 0);
ast_log(LOG_WARNING, "aMYSQL_fetch: Invalid result identifier %d passed\n", resultid);
}
} else {
ast_log(LOG_WARNING, "aMYSQL_fetch: missing some arguments\n");
}
return -1;
}
static int aMYSQL_clear(struct ast_channel *chan, const char *data)
{
MYSQL_RES *mysqlres;
int id;
char *parse = ast_strdupa(data);
strsep(&parse, " "); /* eat the first token, we already know it :P */
id = safe_scan_int(&parse, " \n", -1);
if ((mysqlres = find_identifier(id, AST_MYSQL_ID_RESID)) == NULL) {
ast_log(LOG_WARNING, "Invalid result identifier %d passed in aMYSQL_clear\n", id);
} else {
mysql_free_result(mysqlres);
del_identifier(id, AST_MYSQL_ID_RESID);
}
return 0;
}
static int aMYSQL_disconnect(struct ast_channel *chan, const char *data)
{
MYSQL *mysql;
int id;
char *parse = ast_strdupa(data);
strsep(&parse, " "); /* eat the first token, we already know it :P */
id = safe_scan_int(&parse, " \n", -1);
if ((mysql = find_identifier(id, AST_MYSQL_ID_CONNID)) == NULL) {
ast_log(LOG_WARNING, "Invalid connection identifier %d passed in aMYSQL_disconnect\n", id);
} else {
mysql_close(mysql);
del_identifier(id, AST_MYSQL_ID_CONNID);
}
return 0;
}
static int MYSQL_exec(struct ast_channel *chan, const char *data)
{
int result;
char sresult[10];
ast_debug(5, "MYSQL: data=%s\n", data);
if (!data) {
ast_log(LOG_WARNING, "MYSQL requires an argument (see manual)\n");
return -1;
}
result = 0;
if (autoclear) {
struct ast_datastore *mysql_store = NULL;
ast_channel_lock(chan);
mysql_store = ast_channel_datastore_find(chan, &mysql_ds_info, NULL);
if (!mysql_store) {
if (!(mysql_store = ast_datastore_alloc(&mysql_ds_info, NULL))) {
ast_log(LOG_WARNING, "Unable to allocate new datastore.\n");
} else {
mysql_store->data = chan;
ast_channel_datastore_add(chan, mysql_store);
}
}
ast_channel_unlock(chan);
}
ast_mutex_lock(&_mysql_mutex);
if (strncasecmp("connect", data, strlen("connect")) == 0) {
result = aMYSQL_connect(chan, data);
} else if (strncasecmp("query", data, strlen("query")) == 0) {
result = aMYSQL_query(chan, data);
} else if (strncasecmp("nextresult", data, strlen("nextresult")) == 0) {
result = aMYSQL_nextresult(chan, data);
} else if (strncasecmp("fetch", data, strlen("fetch")) == 0) {
result = aMYSQL_fetch(chan, data);
} else if (strncasecmp("clear", data, strlen("clear")) == 0) {
result = aMYSQL_clear(chan, data);
} else if (strncasecmp("disconnect", data, strlen("disconnect")) == 0) {
result = aMYSQL_disconnect(chan, data);
} else if (strncasecmp("set", data, 3) == 0) {
result = aMYSQL_set(chan, data);
} else {
ast_log(LOG_WARNING, "Unknown argument to MYSQL application : %s\n", data);
result = -1;
}
ast_mutex_unlock(&_mysql_mutex);
snprintf(sresult, sizeof(sresult), "%d", result);
pbx_builtin_setvar_helper(chan, "MYSQL_STATUS", sresult);
return 0;
}
static int unload_module(void)
{
return ast_unregister_application(app);
}
/*!
* \brief Load the module
*
* Module loading including tests for configuration or dependencies.
* This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
* or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
* tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
* configuration file or other non-critical problem return
* AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
*/
static int load_module(void)
{
struct MYSQLidshead *headp = &_mysql_ids_head;
struct ast_flags config_flags = { 0 };
struct ast_config *cfg = ast_config_load(MYSQL_CONFIG, config_flags);
const char *temp;
if (!cfg) {
/* Backwards compatibility ftw */
cfg = ast_config_load(MYSQL_CONFIG_OLD, config_flags);
}
if (cfg) {
if ((temp = ast_variable_retrieve(cfg, "general", "nullvalue"))) {
if (!strcasecmp(temp, "nullstring")) {
nullvalue = NULLSTRING;
} else if (!strcasecmp(temp, "emptystring")) {
nullvalue = EMPTYSTRING;
} else if (!strcasecmp(temp, "null")) {
nullvalue = NULLVALUE;
} else {
ast_log(LOG_WARNING, "Illegal value for 'nullvalue': '%s' (must be 'nullstring', 'null', or 'emptystring')\n", temp);
}
}
if ((temp = ast_variable_retrieve(cfg, "general", "autoclear")) && ast_true(temp)) {
autoclear = 1;
}
ast_config_destroy(cfg);
}
AST_LIST_HEAD_INIT(headp);
return ast_register_application(app, MYSQL_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD_DEPRECATED(ASTERISK_GPL_KEY, "Simple Mysql Interface");

View File

@ -1,758 +0,0 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* James Sharp <jsharp@psychoses.org>
*
* Modified August 2003
* Tilghman Lesher <asterisk__cdr__cdr_mysql__200308@the-tilghman.com>
*
* Modified August 6, 2005
* Joseph Benden <joe@thrallingpenguin.com>
* Added mysql connection timeout parameter
* Added an automatic reconnect as to not lose a cdr record
* Cleaned up the original code to match the coding guidelines
*
* Modified Juli 2006
* Martin Portmann <map@infinitum.ch>
* Added mysql ssl support
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*!
* \file
* \brief MySQL CDR backend
* \ingroup cdr_drivers
*/
/*** MODULEINFO
<depend>mysqlclient</depend>
<defaultenabled>no</defaultenabled>
<support_level>deprecated</support_level>
<replacement>cdr_adaptive_odbc</replacement>
***/
#include "asterisk.h"
#include <mysql/mysql.h>
#include <mysql/errmsg.h>
#include "asterisk/config.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"
#include "asterisk/cli.h"
#include "asterisk/strings.h"
#include "asterisk/linkedlists.h"
#include "asterisk/threadstorage.h"
#define DATE_FORMAT "%Y-%m-%d %T"
#ifndef MYSQL_PORT
# ifdef MARIADB_PORT
# define MYSQL_PORT MARIADB_PORT
# else
# define MYSQL_PORT 3306
# endif
#endif
AST_THREADSTORAGE(sql1_buf);
AST_THREADSTORAGE(sql2_buf);
AST_THREADSTORAGE(escape_buf);
static const char desc[] = "MySQL CDR Backend";
static const char name[] = "mysql";
static const char config[] = "cdr_mysql.conf";
static struct ast_str *hostname = NULL, *dbname = NULL, *dbuser = NULL, *password = NULL, *dbsock = NULL, *dbtable = NULL, *dbcharset = NULL, *cdrzone = NULL;
static struct ast_str *ssl_ca = NULL, *ssl_cert = NULL, *ssl_key = NULL;
static int dbport = 0;
static int connected = 0;
static time_t connect_time = 0;
static int records = 0;
static int totalrecords = 0;
static int timeout = 0;
static int calldate_compat = 0;
AST_MUTEX_DEFINE_STATIC(mysql_lock);
struct unload_string {
AST_LIST_ENTRY(unload_string) entry;
struct ast_str *str;
};
static AST_LIST_HEAD_STATIC(unload_strings, unload_string);
struct column {
char *name;
char *cdrname;
char *staticvalue;
char *type;
AST_LIST_ENTRY(column) list;
};
/* Protected with mysql_lock */
static AST_RWLIST_HEAD_STATIC(columns, column);
static MYSQL mysql = { { NULL }, };
static char *handle_cli_cdr_mysql_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
switch (cmd) {
case CLI_INIT:
e->command = "cdr mysql status";
e->usage =
"Usage: cdr mysql status\n"
" Shows current connection status for cdr_mysql\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 3)
return CLI_SHOWUSAGE;
if (connected) {
char status[256];
char status2[100] = "";
char buf[362]; /* 256+100+" for "+NULL */
int ctime = time(NULL) - connect_time;
if (dbport)
snprintf(status, 255, "Connected to %s@%s, port %d", ast_str_buffer(dbname), ast_str_buffer(hostname), dbport);
else if (dbsock)
snprintf(status, 255, "Connected to %s on socket file %s", ast_str_buffer(dbname), S_OR(ast_str_buffer(dbsock), "default"));
else
snprintf(status, 255, "Connected to %s@%s", ast_str_buffer(dbname), ast_str_buffer(hostname));
if (ast_str_strlen(dbuser))
snprintf(status2, 99, " with username %s", ast_str_buffer(dbuser));
if (ast_str_strlen(dbtable))
snprintf(status2, 99, " using table %s", ast_str_buffer(dbtable));
snprintf(buf, sizeof(buf), "%s%s for ", status, status2);
ast_cli_print_timestr_fromseconds(a->fd, ctime, buf);
if (records == totalrecords)
ast_cli(a->fd, " Wrote %d records since last restart.\n", totalrecords);
else
ast_cli(a->fd, " Wrote %d records since last restart and %d records since last reconnect.\n", totalrecords, records);
} else {
ast_cli(a->fd, "Not currently connected to a MySQL server.\n");
}
return CLI_SUCCESS;
}
static struct ast_cli_entry cdr_mysql_status_cli[] = {
AST_CLI_DEFINE(handle_cli_cdr_mysql_status, "Show connection status of cdr_mysql"),
};
static void configure_connection_charset(void)
{
if (ast_str_strlen(dbcharset)) {
const char *charset = ast_str_buffer(dbcharset);
if (mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, charset)) {
ast_log(LOG_WARNING, "Failed to set connection charset. Data inserted might be invalid.\n");
}
}
}
static int mysql_log(struct ast_cdr *cdr)
{
struct ast_str *sql1 = ast_str_thread_get(&sql1_buf, 1024), *sql2 = ast_str_thread_get(&sql2_buf, 1024);
int retries = 5;
#ifdef HAVE_MYSQLCLIENT_BOOL
bool my_bool_true = 1;
#elif HAVE_MYSQLCLIENT_MY_BOOL
my_bool my_bool_true = 1;
#endif
if (!sql1 || !sql2) {
ast_log(LOG_ERROR, "Memory error\n");
return -1;
}
ast_mutex_lock(&mysql_lock);
db_reconnect:
if ((!connected) && (hostname || dbsock) && dbuser && password && dbname && dbtable ) {
/* Attempt to connect */
mysql_init(&mysql);
/* Add option to quickly timeout the connection */
if (timeout && mysql_options(&mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&timeout) != 0) {
ast_log(LOG_ERROR, "mysql_options returned (%d) %s\n", mysql_errno(&mysql), mysql_error(&mysql));
}
#if MYSQL_VERSION_ID >= 50013
/* Add option for automatic reconnection */
if (mysql_options(&mysql, MYSQL_OPT_RECONNECT, &my_bool_true) != 0) {
ast_log(LOG_ERROR, "mysql_options returned (%d) %s\n", mysql_errno(&mysql), mysql_error(&mysql));
}
#endif
if (ssl_ca || ssl_cert || ssl_key) {
mysql_ssl_set(&mysql, ssl_key ? ast_str_buffer(ssl_key) : NULL, ssl_cert ? ast_str_buffer(ssl_cert) : NULL, ssl_ca ? ast_str_buffer(ssl_ca) : NULL, NULL, NULL);
}
configure_connection_charset();
if (mysql_real_connect(&mysql, ast_str_buffer(hostname), ast_str_buffer(dbuser), ast_str_buffer(password), ast_str_buffer(dbname), dbport, dbsock && ast_str_strlen(dbsock) ? ast_str_buffer(dbsock) : NULL, ssl_ca ? CLIENT_SSL : 0)) {
connected = 1;
connect_time = time(NULL);
records = 0;
} else {
ast_log(LOG_ERROR, "Cannot connect to database server %s: (%d) %s\n", ast_str_buffer(hostname), mysql_errno(&mysql), mysql_error(&mysql));
connected = 0;
}
} else {
/* Long connection - ping the server */
int error;
if ((error = mysql_ping(&mysql))) {
connected = 0;
records = 0;
switch (mysql_errno(&mysql)) {
case CR_SERVER_GONE_ERROR:
case CR_SERVER_LOST:
ast_log(LOG_ERROR, "Server has gone away. Attempting to reconnect.\n");
break;
default:
ast_log(LOG_ERROR, "Unknown connection error: (%d) %s\n", mysql_errno(&mysql), mysql_error(&mysql));
}
retries--;
if (retries) {
goto db_reconnect;
} else {
ast_log(LOG_ERROR, "Retried to connect five times, giving up.\n");
}
}
}
if (connected) {
int column_count = 0;
char *cdrname;
char workspace[2048], *value = NULL;
struct column *entry;
struct ast_str *escape = ast_str_thread_get(&escape_buf, 16);
ast_str_set(&sql1, 0, "INSERT INTO %s (", AS_OR(dbtable, "cdr"));
ast_str_set(&sql2, 0, ") VALUES (");
AST_RWLIST_RDLOCK(&columns);
AST_RWLIST_TRAVERSE(&columns, entry, list) {
if (!strcmp(entry->name, "calldate")) {
/*!\note
* For some dumb reason, "calldate" used to be formulated using
* the datetime the record was posted, rather than the start
* time of the call. If someone really wants the old compatible
* behavior, it's provided here.
*/
if (calldate_compat) {
struct timeval tv = ast_tvnow();
struct ast_tm tm;
char timestr[128];
ast_localtime(&tv, &tm, ast_str_strlen(cdrzone) ? ast_str_buffer(cdrzone) : NULL);
ast_strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
value = ast_strdupa(timestr);
cdrname = "calldate";
} else {
cdrname = "start";
}
} else {
cdrname = entry->cdrname;
}
/* Construct SQL */
/* Need the type and value to determine if we want the raw value or not */
if (entry->staticvalue) {
value = ast_strdupa(entry->staticvalue);
} else if ((!strcmp(cdrname, "disposition") ||
!strcmp(cdrname, "amaflags")) &&
(strstr(entry->type, "int") ||
strstr(entry->type, "dec") ||
strstr(entry->type, "float") ||
strstr(entry->type, "double") ||
strstr(entry->type, "real") ||
strstr(entry->type, "numeric") ||
strstr(entry->type, "fixed"))) {
ast_cdr_format_var(cdr, cdrname, &value, workspace, sizeof(workspace), 1);
} else if (!strcmp(cdrname, "start") || !strcmp(cdrname, "answer") ||
!strcmp(cdrname, "end")) {
struct ast_tm tm;
char timestr[128];
ast_localtime(&cdr->start, &tm, ast_str_strlen(cdrzone) ? ast_str_buffer(cdrzone) : NULL);
ast_strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm);
value = ast_strdupa(timestr);
} else if (!strcmp(cdrname, "calldate")) {
/* Skip calldate - the value has already been dup'd */
} else {
ast_cdr_format_var(cdr, cdrname, &value, workspace, sizeof(workspace), 0);
}
if (value) {
size_t valsz;
if (column_count++) {
ast_str_append(&sql1, 0, ",");
ast_str_append(&sql2, 0, ",");
}
if (!strcasecmp(cdrname, "billsec") &&
(strstr(entry->type, "float") ||
strstr(entry->type, "double") ||
strstr(entry->type, "decimal") ||
strstr(entry->type, "numeric") ||
strstr(entry->type, "real"))) {
if (!ast_tvzero(cdr->answer)) {
snprintf(workspace, sizeof(workspace), "%lf",
(double) (ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0));
} else {
ast_copy_string(workspace, "0", sizeof(workspace));
}
if (!ast_strlen_zero(workspace)) {
value = workspace;
}
}
if (!strcasecmp(cdrname, "duration") &&
(strstr(entry->type, "float") ||
strstr(entry->type, "double") ||
strstr(entry->type, "decimal") ||
strstr(entry->type, "numeric") ||
strstr(entry->type, "real"))) {
snprintf(workspace, sizeof(workspace), "%lf",
(double) (ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0));
if (!ast_strlen_zero(workspace)) {
value = workspace;
}
}
ast_str_make_space(&escape, (valsz = strlen(value)) * 2 + 1);
mysql_real_escape_string(&mysql, ast_str_buffer(escape), value, valsz);
ast_str_append(&sql1, 0, "`%s`", entry->name);
ast_str_append(&sql2, 0, "'%s'", ast_str_buffer(escape));
}
}
AST_RWLIST_UNLOCK(&columns);
ast_debug(1, "Inserting a CDR record.\n");
ast_str_append(&sql1, 0, "%s)", ast_str_buffer(sql2));
ast_debug(1, "SQL command as follows: %s\n", ast_str_buffer(sql1));
if (mysql_real_query(&mysql, ast_str_buffer(sql1), ast_str_strlen(sql1))) {
ast_log(LOG_ERROR, "Failed to insert into database: (%d) %s\n", mysql_errno(&mysql), mysql_error(&mysql));
mysql_close(&mysql);
connected = 0;
} else {
records++;
totalrecords++;
}
}
ast_mutex_unlock(&mysql_lock);
return 0;
}
static void free_strings(void)
{
struct unload_string *us;
AST_LIST_LOCK(&unload_strings);
while ((us = AST_LIST_REMOVE_HEAD(&unload_strings, entry))) {
ast_free(us->str);
ast_free(us);
}
AST_LIST_UNLOCK(&unload_strings);
}
static int my_unload_module(int reload)
{
struct column *entry;
if (!reload) {
if (ast_cdr_unregister(name)) {
/* If we can't unregister the backend, we can't unload the module */
return -1;
}
}
ast_cli_unregister_multiple(cdr_mysql_status_cli, sizeof(cdr_mysql_status_cli) / sizeof(struct ast_cli_entry));
if (connected) {
mysql_close(&mysql);
connected = 0;
records = 0;
}
free_strings();
if (!reload) {
AST_RWLIST_WRLOCK(&columns);
}
while ((entry = AST_RWLIST_REMOVE_HEAD(&columns, list))) {
ast_free(entry);
}
if (!reload) {
AST_RWLIST_UNLOCK(&columns);
}
dbport = 0;
if (reload) {
return ast_cdr_backend_suspend(name);
} else {
/* We unregistered earlier */
return 0;
}
}
static int my_load_config_string(struct ast_config *cfg, const char *category, const char *variable, struct ast_str **field, const char *def)
{
struct unload_string *us;
const char *tmp;
if (!(us = ast_calloc(1, sizeof(*us))))
return -1;
if (!(*field = ast_str_create(16))) {
ast_free(us);
return -1;
}
tmp = ast_variable_retrieve(cfg, category, variable);
ast_str_set(field, 0, "%s", tmp ? tmp : def);
us->str = *field;
AST_LIST_LOCK(&unload_strings);
AST_LIST_INSERT_HEAD(&unload_strings, us, entry);
AST_LIST_UNLOCK(&unload_strings);
return 0;
}
static int my_load_config_number(struct ast_config *cfg, const char *category, const char *variable, int *field, int def)
{
const char *tmp;
tmp = ast_variable_retrieve(cfg, category, variable);
if (!tmp || sscanf(tmp, "%30d", field) < 1)
*field = def;
return 0;
}
/** Connect to MySQL. Initializes the connection.
*
* * Assumes the read-write lock for columns is held.
* * Caller should allocate and free cfg
* */
static int my_connect_db(struct ast_config *cfg)
{
struct ast_variable *var;
char *temp;
MYSQL_ROW row;
MYSQL_RES *result;
char sqldesc[128];
#ifdef HAVE_MYSQLCLIENT_BOOL
bool my_bool_true = 1;
#elif HAVE_MYSQLCLIENT_MY_BOOL
my_bool my_bool_true = 1;
#endif
mysql_init(&mysql);
if (timeout && mysql_options(&mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&timeout) != 0) {
ast_log(LOG_ERROR, "cdr_mysql: mysql_options returned (%d) %s\n", mysql_errno(&mysql), mysql_error(&mysql));
}
#if MYSQL_VERSION_ID >= 50013
/* Add option for automatic reconnection */
if (mysql_options(&mysql, MYSQL_OPT_RECONNECT, &my_bool_true) != 0) {
ast_log(LOG_ERROR, "cdr_mysql: mysql_options returned (%d) %s\n", mysql_errno(&mysql), mysql_error(&mysql));
}
#endif
if ((ssl_ca && ast_str_strlen(ssl_ca)) || (ssl_cert && ast_str_strlen(ssl_cert)) || (ssl_key && ast_str_strlen(ssl_key))) {
mysql_ssl_set(&mysql,
ssl_key ? ast_str_buffer(ssl_key) : NULL,
ssl_cert ? ast_str_buffer(ssl_cert) : NULL,
ssl_ca ? ast_str_buffer(ssl_ca) : NULL,
NULL, NULL);
}
temp = dbsock && ast_str_strlen(dbsock) ? ast_str_buffer(dbsock) : NULL;
configure_connection_charset();
if (!mysql_real_connect(&mysql, ast_str_buffer(hostname), ast_str_buffer(dbuser), ast_str_buffer(password), ast_str_buffer(dbname), dbport, temp, ssl_ca && ast_str_strlen(ssl_ca) ? CLIENT_SSL : 0)) {
ast_log(LOG_ERROR, "Failed to connect to mysql database %s on %s.\n", ast_str_buffer(dbname), ast_str_buffer(hostname));
connected = 0;
records = 0;
return AST_MODULE_LOAD_SUCCESS; /* May be reconnected later */
}
ast_debug(1, "Successfully connected to MySQL database.\n");
connected = 1;
records = 0;
connect_time = time(NULL);
/* Get table description */
snprintf(sqldesc, sizeof(sqldesc), "DESC %s", dbtable ? ast_str_buffer(dbtable) : "cdr");
if (mysql_query(&mysql, sqldesc)) {
ast_log(LOG_ERROR, "Unable to query table description!! Logging disabled.\n");
mysql_close(&mysql);
connected = 0;
return AST_MODULE_LOAD_DECLINE;
}
if (!(result = mysql_store_result(&mysql))) {
ast_log(LOG_ERROR, "Unable to query table description!! Logging disabled.\n");
mysql_close(&mysql);
connected = 0;
return AST_MODULE_LOAD_DECLINE;
}
while ((row = mysql_fetch_row(result))) {
struct column *entry;
char *cdrvar = "", *staticvalue = "";
ast_debug(1, "Got a field '%s' of type '%s'\n", row[0], row[1]);
/* Check for an alias or a static value */
for (var = ast_variable_browse(cfg, "columns"); var; var = var->next) {
if (strncmp(var->name, "alias", 5) == 0 && strcasecmp(var->value, row[0]) == 0 ) {
char *alias = ast_strdupa(var->name + 5);
cdrvar = ast_strip(alias);
ast_verb(3, "Found alias %s for column %s\n", cdrvar, row[0]);
break;
} else if (strncmp(var->name, "static", 6) == 0 && strcasecmp(var->value, row[0]) == 0) {
char *item = ast_strdupa(var->name + 6);
item = ast_strip(item);
if (item[0] == '"' && item[strlen(item) - 1] == '"') {
/* Remove surrounding quotes */
item[strlen(item) - 1] = '\0';
item++;
}
staticvalue = item;
}
}
entry = ast_calloc(sizeof(char), sizeof(*entry) + strlen(row[0]) + 1 + strlen(cdrvar) + 1 + strlen(staticvalue) + 1 + strlen(row[1]) + 1);
if (!entry) {
ast_log(LOG_ERROR, "Out of memory creating entry for column '%s'\n", row[0]);
mysql_free_result(result);
return AST_MODULE_LOAD_DECLINE;
}
entry->name = (char *)entry + sizeof(*entry);
strcpy(entry->name, row[0]);
if (!ast_strlen_zero(cdrvar)) {
entry->cdrname = entry->name + strlen(row[0]) + 1;
strcpy(entry->cdrname, cdrvar);
} else { /* Point to same place as the column name */
entry->cdrname = (char *)entry + sizeof(*entry);
}
if (!ast_strlen_zero(staticvalue)) {
entry->staticvalue = entry->cdrname + strlen(entry->cdrname) + 1;
strcpy(entry->staticvalue, staticvalue);
ast_debug(1, "staticvalue length: %d\n", (int) strlen(staticvalue) );
entry->type = entry->staticvalue + strlen(entry->staticvalue) + 1;
} else {
entry->type = entry->cdrname + strlen(entry->cdrname) + 1;
}
strcpy(entry->type, row[1]);
ast_debug(1, "Entry name '%s'\n", entry->name);
ast_debug(1, " cdrname '%s'\n", entry->cdrname);
ast_debug(1, " static '%s'\n", entry->staticvalue);
ast_debug(1, " type '%s'\n", entry->type);
AST_LIST_INSERT_TAIL(&columns, entry, list);
}
mysql_free_result(result);
return AST_MODULE_LOAD_SUCCESS;
}
static int my_load_module(int reload)
{
int res;
struct ast_config *cfg;
struct ast_variable *var;
/* CONFIG_STATUS_FILEUNCHANGED is impossible when config_flags is always 0,
* and it has to be zero, so a reload can be sent to tell the driver to
* rescan the table layout. */
struct ast_flags config_flags = { 0 };
struct column *entry;
struct ast_str *compat;
/* Cannot use a conditionally different flag, because the table layout may
* have changed, which is not detectable by config file change detection,
* but should still cause the configuration to be re-parsed. */
cfg = ast_config_load(config, config_flags);
if (cfg == CONFIG_STATUS_FILEMISSING) {
ast_log(LOG_WARNING, "Unable to load config for mysql CDR's: %s\n", config);
return AST_MODULE_LOAD_SUCCESS;
} else if (cfg == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_ERROR, "Unable to load configuration file '%s'\n", config);
return AST_MODULE_LOAD_DECLINE;
}
if (reload) {
AST_RWLIST_WRLOCK(&columns);
my_unload_module(1);
}
var = ast_variable_browse(cfg, "global");
if (!var) {
/* nothing configured */
if (reload) {
AST_RWLIST_UNLOCK(&columns);
}
ast_config_destroy(cfg);
return AST_MODULE_LOAD_SUCCESS;
}
res = 0;
res |= my_load_config_string(cfg, "global", "hostname", &hostname, "localhost");
res |= my_load_config_string(cfg, "global", "dbname", &dbname, "astriskcdrdb");
res |= my_load_config_string(cfg, "global", "user", &dbuser, "root");
res |= my_load_config_string(cfg, "global", "sock", &dbsock, "");
res |= my_load_config_string(cfg, "global", "table", &dbtable, "cdr");
res |= my_load_config_string(cfg, "global", "password", &password, "");
res |= my_load_config_string(cfg, "global", "charset", &dbcharset, "");
res |= my_load_config_string(cfg, "global", "ssl_ca", &ssl_ca, "");
res |= my_load_config_string(cfg, "global", "ssl_cert", &ssl_cert, "");
res |= my_load_config_string(cfg, "global", "ssl_key", &ssl_key, "");
res |= my_load_config_number(cfg, "global", "port", &dbport, MYSQL_PORT);
res |= my_load_config_number(cfg, "global", "timeout", &timeout, 0);
res |= my_load_config_string(cfg, "global", "compat", &compat, "no");
res |= my_load_config_string(cfg, "global", "cdrzone", &cdrzone, "");
if (ast_str_strlen(cdrzone) == 0) {
for (; var; var = var->next) {
if (!strcasecmp(var->name, "usegmtime") && ast_true(var->value)) {
ast_str_set(&cdrzone, 0, "UTC");
}
}
}
if (ast_true(ast_str_buffer(compat))) {
calldate_compat = 1;
} else {
calldate_compat = 0;
}
if (res < 0) {
if (reload) {
AST_RWLIST_UNLOCK(&columns);
}
ast_config_destroy(cfg);
free_strings();
return AST_MODULE_LOAD_DECLINE;
}
/* Check for any aliases */
if (!reload) {
/* Lock, if not already */
AST_RWLIST_WRLOCK(&columns);
}
while ((entry = AST_LIST_REMOVE_HEAD(&columns, list))) {
ast_free(entry);
}
ast_debug(1, "Got hostname of %s\n", ast_str_buffer(hostname));
ast_debug(1, "Got port of %d\n", dbport);
ast_debug(1, "Got a timeout of %d\n", timeout);
if (ast_str_strlen(dbsock)) {
ast_debug(1, "Got sock file of %s\n", ast_str_buffer(dbsock));
}
ast_debug(1, "Got user of %s\n", ast_str_buffer(dbuser));
ast_debug(1, "Got dbname of %s\n", ast_str_buffer(dbname));
ast_debug(1, "Got password of %s\n", ast_str_buffer(password));
ast_debug(1, "%sunning in calldate compatibility mode\n", calldate_compat ? "R" : "Not r");
ast_debug(1, "Dates and times are localized to %s\n", S_OR(ast_str_buffer(cdrzone), "local timezone"));
if (ast_str_strlen(dbcharset)) {
ast_debug(1, "Got DB charset of %s\n", ast_str_buffer(dbcharset));
}
res = my_connect_db(cfg);
AST_RWLIST_UNLOCK(&columns);
ast_config_destroy(cfg);
if (res != AST_MODULE_LOAD_SUCCESS) {
my_unload_module(0);
return res;
}
if (!reload) {
res = ast_cdr_register(name, desc, mysql_log);
} else {
res = ast_cdr_backend_unsuspend(name);
}
if (res) {
ast_log(LOG_ERROR, "Unable to register MySQL CDR handling\n");
} else {
res = ast_cli_register_multiple(cdr_mysql_status_cli, sizeof(cdr_mysql_status_cli) / sizeof(struct ast_cli_entry));
}
if (res) {
my_unload_module(0);
return AST_MODULE_LOAD_DECLINE;
}
return AST_MODULE_LOAD_SUCCESS;
}
static int load_module(void)
{
return my_load_module(0);
}
static int unload_module(void)
{
return my_unload_module(0);
}
static int reload(void)
{
int ret;
ast_mutex_lock(&mysql_lock);
ret = my_load_module(1);
ast_mutex_unlock(&mysql_lock);
return ret;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "MySQL CDR Backend",
.support_level = AST_MODULE_SUPPORT_DEPRECATED,
.load = load_module,
.unload = unload_module,
.reload = reload,
.requires = "cdr",
);

View File

@ -102,7 +102,7 @@ struct adapter_pvt {
char id[31]; /* the 'name' from mobile.conf */
bdaddr_t addr; /* adddress of adapter */
unsigned int inuse:1; /* are we in use ? */
unsigned int alignment_detection:1; /* do alignment detection on this adpater? */
unsigned int alignment_detection:1; /* do alignment detection on this adapter? */
struct io_context *io; /*!< io context for audio connections */
struct io_context *accept_io; /*!< io context for sco listener */
int *sco_id; /*!< the io context id of the sco listener socket */
@ -2006,7 +2006,7 @@ static int at_match_prefix(char *buf, char *prefix)
}
/*!
* \brief Read an AT message and clasify it.
* \brief Read an AT message and classify it.
* \param rsock an rfcomm socket
* \param buf the buffer to store the result in
* \param count the size of the buffer or the maximum number of characters to read
@ -2156,10 +2156,12 @@ static inline const char *at_msg2str(at_message_t msg)
* \param buf the buffer to parse (null terminated)
* \return -1 on error (parse error) or a ECAM value on success
*
* Example string: *ECAV: <ccid>,<ccstatus>,<calltype>[,<processid>]
* [,exitcause][,<number>,<type>]
* Example:
* \verbatim *ECAV: <ccid>,<ccstatus>,<calltype>[,<processid>]
[,exitcause][,<number>,<type>] \endverbatim
*
* Example indicating busy: *ECAV: 1,7,1
* Example indicating busy:
* \verbatim *ECAV: 1,7,1 \endverbatim
*/
static int hfp_parse_ecav(struct hfp_pvt *hfp, char *buf)
{
@ -2176,7 +2178,7 @@ static int hfp_parse_ecav(struct hfp_pvt *hfp, char *buf)
}
/*!
* \brief Enable Sony Erricson extensions / indications.
* \brief Enable Sony Ericsson extensions / indications.
* \param hfp an hfp_pvt struct
*/
static int hfp_send_ecam(struct hfp_pvt *hfp)
@ -3040,7 +3042,7 @@ static void msg_queue_free_and_pop(struct mbl_pvt *pvt)
}
/*!
* \brief Remove all itmes from the queue and free them.
* \brief Remove all items from the queue and free them.
* \param pvt a mbl_pvt structure
*/
static void msg_queue_flush(struct mbl_pvt *pvt)
@ -3347,7 +3349,7 @@ static int handle_response_ok(struct mbl_pvt *pvt, char *buf)
}
break;
case AT_CLIP:
ast_debug(1, "[%s] caling line indication enabled\n", pvt->id);
ast_debug(1, "[%s] calling line indication enabled\n", pvt->id);
if (hfp_send_ecam(pvt->hfp) || msg_queue_push(pvt, AT_OK, AT_ECAM)) {
ast_debug(1, "[%s] error enabling Sony Ericsson call monitoring extensions\n", pvt->id);
goto e_return;
@ -3567,7 +3569,7 @@ static int handle_response_ciev(struct mbl_pvt *pvt, char *buf)
if (pvt->owner) {
ast_debug(1, "[%s] hanging up owner\n", pvt->id);
if (mbl_queue_hangup(pvt)) {
ast_log(LOG_ERROR, "[%s] error queueing hangup, disconnectiong...\n", pvt->id);
ast_log(LOG_ERROR, "[%s] error queueing hangup, disconnecting...\n", pvt->id);
return -1;
}
}
@ -3601,7 +3603,7 @@ static int handle_response_ciev(struct mbl_pvt *pvt, char *buf)
handle_response_busy(pvt);
}
if (mbl_queue_hangup(pvt)) {
ast_log(LOG_ERROR, "[%s] error queueing hangup, disconnectiong...\n", pvt->id);
ast_log(LOG_ERROR, "[%s] error queueing hangup, disconnecting...\n", pvt->id);
return -1;
}
}
@ -4431,7 +4433,7 @@ static struct adapter_pvt *mbl_load_adapter(struct ast_config *cfg, const char *
/* bind the sco listener socket */
if (sco_bind(adapter) < 0) {
ast_log(LOG_ERROR, "Skipping adapter %s. Error binding audio connection listerner socket.\n", adapter->id);
ast_log(LOG_ERROR, "Skipping adapter %s. Error binding audio connection listener socket.\n", adapter->id);
goto e_destroy_io;
}
@ -4443,7 +4445,7 @@ static struct adapter_pvt *mbl_load_adapter(struct ast_config *cfg, const char *
/* start the sco listener for this adapter */
if (ast_pthread_create_background(&adapter->sco_listener_thread, NULL, do_sco_listen, adapter)) {
ast_log(LOG_ERROR, "Skipping adapter %s. Error creating audio connection listerner thread.\n", adapter->id);
ast_log(LOG_ERROR, "Skipping adapter %s. Error creating audio connection listener thread.\n", adapter->id);
goto e_remove_sco;
}
@ -4499,7 +4501,7 @@ static struct mbl_pvt *mbl_load_device(struct ast_config *cfg, const char *cat)
}
AST_RWLIST_UNLOCK(&adapters);
if (!adapter) {
ast_log(LOG_ERROR, "Skiping device %s. Unknown adapter '%s' specified.\n", cat, adapter_str);
ast_log(LOG_ERROR, "Skipping device %s. Unknown adapter '%s' specified.\n", cat, adapter_str);
goto e_return;
}

View File

@ -2055,7 +2055,7 @@ int onOutgoingCall(ooCallData *call)
}
ooCallAddAliasDialedDigits(call, p->caller_dialedDigits);
} else if (!ast_strlen_zero(p->callerid_num)) {
if (ooIsDailedDigit(p->callerid_num)) {
if (ooIsDialedDigit(p->callerid_num)) {
if (gH323Debug) {
ast_verb(0, "setting callid number %s\n", p->callerid_num);
}
@ -2136,7 +2136,7 @@ int onNewCallCreated(ooCallData *call)
}
ooCallAddAliasDialedDigits(call, p->caller_dialedDigits);
} else if (!ast_strlen_zero(p->callerid_num)) {
if (ooIsDailedDigit(p->callerid_num)) {
if (ooIsDialedDigit(p->callerid_num)) {
if (gH323Debug) {
ast_verb(0, "setting callid number %s\n", p->callerid_num);
}
@ -2148,7 +2148,7 @@ int onNewCallCreated(ooCallData *call)
if (!ast_strlen_zero(p->exten)) {
if (ooIsDailedDigit(p->exten)) {
if (ooIsDialedDigit(p->exten)) {
ooCallSetCalledPartyNumber(call, p->exten);
ooCallAddRemoteAliasDialedDigits(call, p->exten);
} else {

View File

@ -75,7 +75,7 @@ To run the stack test application chansetup
3. For running calling instance
./h323peer [--use-ip ip] -n <number of calls> -duration <call duration>
-interval <inetrval between successive calls> destination
-interval <interval between successive calls> destination
where all times are in seconds. Interval of 0 means next call will be placed
after current call finishes. "destination" is the dotted ip address of the

View File

@ -417,7 +417,7 @@ int decodeDynBitString (OOCTXT* pctxt, ASN1DynBitStr* pBitStr)
ASN1OCTET* ptmp;
int nbits, stat = ASN_OK;
/* If "fast copy" option is not set (ASN1FATSCOPY) or if constructed,
/* If "fast copy" option is not set (ASN1FASTCOPY) or if constructed,
* copy the bit string value into a dynamic memory buffer;
* otherwise, store the pointer to the value in the decode
* buffer in the data pointer argument. */

View File

@ -1007,7 +1007,7 @@ int encode2sCompBinInt (OOCTXT* pctxt, ASN1INT value)
{
/* 10.4.6 A minimum octet 2's-complement-binary-integer encoding */
/* of the whole number has a field width that is a multiple of 8 */
/* bits and also satisifies the condition that the leading 9 bits */
/* bits and also satisfies the condition that the leading 9 bits */
/* field shall not be all zeros and shall not be all ones. */
/* first encode integer value into a local buffer */
@ -1048,7 +1048,7 @@ static int encodeNonNegBinInt (OOCTXT* pctxt, ASN1UINT value)
/* 10.3.6 A minimum octet non-negative binary integer encoding of */
/* the whole number (which does not predetermine the number of */
/* octets to be used for the encoding) has a field which is a */
/* multiple of 8 bits and also satisifies the condition that the */
/* multiple of 8 bits and also satisfies the condition that the */
/* leading eight bits of the field shall not be zero unless the */
/* field is precisely 8 bits long. */

View File

@ -49,7 +49,7 @@ extern "C" {
* SEQUENCE OF, SET OF, or CHOICE construct is parsed.
*
* @param name For SEQUENCE, SET, or CHOICE, this is the name of the
* element as defined in the ASN.1 defination. For
* element as defined in the ASN.1 definition. For
* SEQUENCE OF or SET OF, this is set to the name
* "element".
* @param index For SEQUENCE, SET, or CHOICE, this is not used and is
@ -68,7 +68,7 @@ typedef void (*StartElement) (const char* name, int index) ;
* SEQUENCE, SET, SEQUENCE OF, SET OF, or CHOICE construct.
*
* @param name For SEQUENCE, SET, or CHOICE, this is the name of the
* element as defined in the ASN.1 defination. For
* element as defined in the ASN.1 definition. For
* SEQUENCE OF or SET OF, this is set to the name
* "element".
* @param index For SEQUENCE, SET, or CHOICE, this is not used and is
@ -194,7 +194,7 @@ typedef void (*EnumValue) (ASN1UINT value) ;
* within a decode function when an ASN.1 open type is parsed.
*
* @param numocts Number of octets in the parsed value.
* @param data Pointer to byet array contain in tencoded ASN.1
* @param data Pointer to byte array contain in tencoded ASN.1
* value.
* @return - none
*/

View File

@ -1926,7 +1926,7 @@ typedef struct EXTERN H225SecurityCapabilities {
} m;
H225NonStandardParameter nonStandard;
H225SecurityServiceMode encryption;
H225SecurityServiceMode authenticaton;
H225SecurityServiceMode authentication;
H225SecurityServiceMode integrity;
} H225SecurityCapabilities;

View File

@ -6357,14 +6357,14 @@ EXTERN int asn1PD_H225SecurityCapabilities (OOCTXT* pctxt, H225SecurityCapabilit
invokeEndElement (pctxt, "encryption", -1);
/* decode authenticaton */
/* decode authentication */
invokeStartElement (pctxt, "authenticaton", -1);
invokeStartElement (pctxt, "authentication", -1);
stat = asn1PD_H225SecurityServiceMode (pctxt, &pvalue->authenticaton);
stat = asn1PD_H225SecurityServiceMode (pctxt, &pvalue->authentication);
if (stat != ASN_OK) return stat;
invokeEndElement (pctxt, "authenticaton", -1);
invokeEndElement (pctxt, "authentication", -1);
/* decode integrity */

View File

@ -4408,9 +4408,9 @@ EXTERN int asn1PE_H225SecurityCapabilities (OOCTXT* pctxt, H225SecurityCapabilit
stat = asn1PE_H225SecurityServiceMode (pctxt, &pvalue->encryption);
if (stat != ASN_OK) return stat;
/* encode authenticaton */
/* encode authentication */
stat = asn1PE_H225SecurityServiceMode (pctxt, &pvalue->authenticaton);
stat = asn1PE_H225SecurityServiceMode (pctxt, &pvalue->authentication);
if (stat != ASN_OK) return stat;
/* encode integrity */

View File

@ -265,7 +265,7 @@ void* memHeapAlloc (void** ppvMemHeap, int nbytes)
if (nunits <= (ASN1UINT)pElem_nunits (pElem)) {
RTMEMDIAG3
("memHeapAlloc: "
"found an exisiting free element 0x%x, size %d\n",
"found an existing free element 0x%x, size %d\n",
pElem, (pElem_nunits (pElem) * 8u));
if (pMemBlk->freeElemOff ==
@ -373,7 +373,7 @@ void* memHeapAlloc (void** ppvMemHeap, int nbytes)
CHECKMEMBLOCK (pMemHeap, pMemBlk);
}
else {
ast_mutex_unlock(&pMemHeap->pLock);
ast_mutex_unlock(&pMemHeap->pLock);
return NULL;
}
}
@ -753,9 +753,10 @@ void* memHeapRealloc (void** ppvMemHeap, void* mem_p, int nbytes_)
if (newMemBlk == 0)
return 0;
pMemLink->pMemBlk = newMemBlk;
}
else
}
else {
return 0;
}
*(int*)(((char*)pMemLink) + sizeof (OSMemLink)) = nbytes_;
return pMemLink->pMemBlk;
}
@ -1132,7 +1133,7 @@ void* memHeapMarkSaved (void** ppvMemHeap, const void* mem_p,
RTMEMDIAG2 ("memHeapMarkSaved: the element 0x%x is "
"already free!\n", pElem);
ast_mutex_unlock(&pMemHeap->pLock);
ast_mutex_unlock(&pMemHeap->pLock);
return 0;
}
@ -1151,9 +1152,10 @@ void* memHeapMarkSaved (void** ppvMemHeap, const void* mem_p,
CLEAR_SAVED (pMemBlk, pElem);
nsaved = pMemBlk->nsaved;
}
else
ast_mutex_unlock(&pMemHeap->pLock);
return 0;
else {
ast_mutex_unlock(&pMemHeap->pLock);
}
return 0;
}
if (saved && nsaved > 0)
pMemLink->blockType |= RTMEMSAVED;
@ -1212,7 +1214,7 @@ static OSMemLink* memHeapAddBlock (OSMemLink** ppMemLink,
/* if pMemBlk has RTMEMLINK flags it means that it is allocated
* cooperatively with OSMemLink, and we don't need to do additional
* allocations for it. Just use pointer's arithemtic. */
* allocations for it. Just use pointer's arithmetic. */
if (blockType & RTMEMLINK)
pMemLink = (OSMemLink*) (((ASN1OCTET*)pMemBlk) - sizeof (OSMemLink));

View File

@ -783,7 +783,7 @@ OOH323CallData* ooFindCallByToken(const char *callToken)
/* Checks whether session with suplied ID and direction is already active*/
/* Checks whether session with supplied ID and direction is already active*/
ASN1BOOL ooIsSessionEstablished(OOH323CallData *call, int sessionID, char* dir)
{
OOLogicalChannel * temp = NULL;

View File

@ -294,7 +294,7 @@ EXTERN int ooCapabilityDisableDTMFQ931Keypad(struct OOH323CallData *call);
* and txframes parameters to the endpoint or call.(ex. G711, G728, G723.1,
* G729)
* @param call Handle to a call. If this is not Null, then
* capability is added to call's remote enpoint
* capability is added to call's remote endpoint
* capability list, else it is added to local H323
* endpoint list.
* @param cap Type of G711 capability to be added.
@ -326,7 +326,7 @@ EXTERN int ooCapabilityAddSimpleCapability
* to local endpoints capability list or to remote endpoints capability list or
* to a call's capability list.
* @param call Handle to a call. If this is not Null, then
* capability is added to call's remote enpoint
* capability is added to call's remote endpoint
* capability list, else it is added to local H323
* endpoint list.
* @param cap Type of GSM capability to be added.
@ -357,7 +357,7 @@ int ooCapabilityAddGSMCapability(struct OOH323CallData *call, int cap,
* capability list or to remote endpoints capability list or to a call's
* capability list.
* @param call Handle to a call. If this is not Null, then
* capability is added to call's remote enpoint
* capability is added to call's remote endpoint
* capability list, else it is added to local H323
* endpoint list.
* @param sqcifMPI Minimum picture interval for encoding/decoding
@ -396,7 +396,7 @@ EXTERN int ooCapabilityAddH263VideoCapability(struct OOH323CallData *call,
/**
* This function is an helper function to ooCapabilityAddH263VideoCapability.
* @param call Handle to a call. If this is not Null, then
* capability is added to call's remote enpoint
* capability is added to call's remote endpoint
* capability list, else it is added to local H323
* endpoint list.
* @param sqcifMPI Minimum picture interval for encoding/decoding
@ -717,11 +717,11 @@ EXTERN int ooAppendCapToCapPrefs(struct OOH323CallData *call, int cap);
EXTERN int ooChangeCapPrefOrder(struct OOH323CallData *call, int cap, int pos);
/**
* This function is used to preppend a particular capability to preference
* This function is used to prepend a particular capability to preference
* list.
* @param call Handle to call, if call's preference list has to be modified
* else NULL, to modify endpoint's preference list.
* @param cap Capability to be preppended.
* @param cap Capability to be prepended.
*
* @return OO_OK, on success. OO_FAILED, otherwise.
*/

View File

@ -186,7 +186,7 @@ int ooReadAndProcessStackCommand()
if(!pCall) {
OOTRACEINFO2("Call \"%s\" does not exist\n",
(char*)cmd.param1);
OOTRACEINFO1("Call migth be cleared/closed\n");
OOTRACEINFO1("Call might be cleared/closed\n");
}
else {
ooSendProgress(ooFindCallByToken((char*)cmd.param1));
@ -200,7 +200,7 @@ int ooReadAndProcessStackCommand()
if(!pCall) {
OOTRACEINFO2("Call \"%s\" does not exist\n",
(char*)cmd.param1);
OOTRACEINFO1("Call migth be cleared/closed\n");
OOTRACEINFO1("Call might be cleared/closed\n");
}
else {
ooSendAlerting(ooFindCallByToken((char*)cmd.param1));

View File

@ -1231,7 +1231,7 @@ int ooGkClientHandleRegistrationConfirm
(&pGkClient->ctxt, sizeof(ooGkClientTimerCb));
if(!cbData)
{
OOTRACEERR1("Error:Failed to allocate memory for Regisration timer."
OOTRACEERR1("Error:Failed to allocate memory for Registration timer."
"\n");
pGkClient->state = GkClientFailed;
return OO_FAILED;
@ -1927,7 +1927,7 @@ int ooGkClientSendAdmissionRequest
(&pGkClient->ctxt, sizeof(ooGkClientTimerCb));
if(!cbData)
{
OOTRACEERR1("Error:Failed to allocate memory for Regisration timer."
OOTRACEERR1("Error:Failed to allocate memory for Registration timer."
"\n");
pGkClient->state = GkClientFailed;
ast_mutex_unlock(&pGkClient->Lock);

View File

@ -318,7 +318,7 @@ EXTERN int ooGkClientHandleRASMessage
/**
* This function is used to send a message on Gatekeeper clien't RAS channel.
* This function is used to send a message on Gatekeeper client RAS channel.
* @param pGkClient Handle to the gatekeeper client.
* @param pRasMsg Handle to Ras message to be sent.
*

View File

@ -78,7 +78,7 @@ OOLogicalChannel* ooAddNewLogicalChannel(OOH323CallData *call, int channelNo,
OOTRACEDBGC3("Using configured media info (%s, %s)\n", call->callType,
call->callToken);
pNewChannel->localRtpPort = pMediaInfo->lMediaRedirPort ? pMediaInfo->lMediaRedirPort : pMediaInfo->lMediaPort;
/* check MediaRedirPort here because RedirCPort is ReditPort + 1 and can't be 0 ;) */
/* check MediaRedirPort here because RedirCPort is RedirPort + 1 and can't be 0 ;) */
pNewChannel->localRtcpPort = pMediaInfo->lMediaRedirPort ? pMediaInfo->lMediaRedirCPort : pMediaInfo->lMediaCntrlPort;
/* If user application has not specified a specific ip and is using
multihomed mode, substitute appropriate ip.

View File

@ -537,8 +537,6 @@ int ooPDWrite(struct pollfd *pfds, int nfds, int fd)
int ooGetLocalIPAddress(char * pIPAddrs)
{
int ret;
struct hostent *hp;
struct ast_hostent phost;
char hostname[100];
if(pIPAddrs == NULL)
@ -546,20 +544,11 @@ int ooGetLocalIPAddress(char * pIPAddrs)
ret = gethostname(hostname, 100);
if(ret == 0)
{
if ((hp = ast_gethostbyname(hostname, &phost))) {
if (hp->h_addrtype == AF_INET6) {
struct in6_addr i;
memcpy(&i, hp->h_addr, sizeof(i));
strcpy(pIPAddrs, (inet_ntop(AF_INET6, &i,
hostname, sizeof(hostname))) == NULL ? "::1" :
inet_ntop(AF_INET6, &i, hostname, sizeof(hostname)));
} else {
struct in_addr i;
memcpy(&i, hp->h_addr, sizeof(i));
strcpy(pIPAddrs, (ast_inet_ntoa(i) == NULL) ? "127.0.0.1" : ast_inet_ntoa(i));
}
} else {
struct ast_sockaddr addr = { {0,} };
if (ast_sockaddr_resolve_first_af(&addr, hostname, PARSE_PORT_FORBID, AF_UNSPEC)) {
return -1;
} else {
strcpy(pIPAddrs, ast_sockaddr_stringify_addr(&addr));
}
}
else{

View File

@ -318,7 +318,7 @@ EXTERN int ooSocketSendTo(OOSOCKET socket, const ASN1OCTET* pdata,
/**
* This function is used for synchronous monitoring of multiple sockets.
* For more information refer to documnetation of "select" system call.
* For more information refer to documentation of "select" system call.
*
* @param nfds The highest numbered descriptor to be monitored
* plus one.

View File

@ -30,7 +30,7 @@ OOBOOL ooUtilsIsStrEmpty (const char* str)
}
OOBOOL ooIsDailedDigit(const char* str)
OOBOOL ooIsDialedDigit(const char* str)
{
if(str == NULL || *str =='\0') { return FALSE; }
while(*str != '\0')

View File

@ -48,6 +48,6 @@ EXTERN OOBOOL ooUtilsIsStrEmpty (const char * str);
* @param str String to test
* @return TRUE if string contains all digits; FALSE otherwise
*/
EXTERN OOBOOL ooIsDailedDigit(const char* str);
EXTERN OOBOOL ooIsDialedDigit(const char* str);
#endif

View File

@ -607,7 +607,7 @@ EXTERN int initContextBuffer
/**
* This function initializes a context block. It makes sure that if the block
* was not previosly initialized, that all key working parameters are set to
* thier correct initial state values (i.e. declared within a function as a
* their correct initial state values (i.e. declared within a function as a
* normal working variable), it is required that they invoke this function
* before using it.
*

View File

@ -297,7 +297,7 @@ int ooCreateH225Connection(OOH323CallData *call)
{
call->pH225Channel->sock = channelSocket;
OOTRACEINFO3("H2250 transmiter channel creation - successful "
OOTRACEINFO3("H2250 transmitter channel creation - successful "
"(%s, %s)\n", call->callType, call->callToken);
/* If multihomed, get ip from socket */

View File

@ -2559,7 +2559,7 @@ int ooOnReceivedRequestChannelClose(OOH323CallData *call,
if (lChannel->state == OO_LOGICALCHAN_ESTABLISHED) {
ret = ooSendCloseLogicalChannel(call, lChannel);
if (ret != OO_OK) {
OOTRACEERR3("ERROR:Failed to build CloseLgicalChannel message(%s, %s)\n",
OOTRACEERR3("ERROR:Failed to build CloseLogicalChannel message(%s, %s)\n",
call->callType, call->callToken);
return OO_FAILED;
}

View File

@ -174,7 +174,7 @@ EXTERN int ooSendMasterSlaveDeterminationReject (struct OOH323CallData* call);
* MasterSlaveDetermination procedure.
* @param call Handle to the call for which MasterSlaveReject is
* received.
* @param reject Poinetr to the received reject message.
* @param reject Pointer to the received reject message.
*
* @return OO_OK, on success. OO_FAILED, on failure.
*/
@ -271,7 +271,7 @@ EXTERN int ooOnReceivedUserInputIndication
(OOH323CallData *call, H245UserInputIndication *indication);
/**
* This function is called on receiving a TreminalCapabilitySetAck message.
* This function is called on receiving a TerminalCapabilitySetAck message.
* If the MasterSlaveDetermination process is also over, this function
* initiates the process of opening logical channels.
* @param call Pointer to call for which TCSAck is received.

View File

@ -616,7 +616,7 @@ int ooOnReceivedSetup(OOH323CallData *call, Q931Message *q931Msg)
removeEventHandler(call->pctxt);
return OO_FAILED;
}
/* For now, just add decoded fast start elemts to list. This list
/* For now, just add decoded fast start elements to list. This list
will be processed at the time of sending CONNECT message. */
dListAppend(call->pctxt, &call->remoteFastStartOLCs, olc);
}
@ -1062,16 +1062,17 @@ int ooOnReceivedAlerting(OOH323CallData *call, Q931Message *q931Msg)
if(q931Msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent &&
q931Msg->userInfo->h323_uu_pdu.h245Tunneling &&
OO_TESTFLAG (call->flags, OO_M_TUNNELING)) {
if (alerting->m.h245AddressPresent)
if (alerting->m.h245AddressPresent) {
OOTRACEINFO3("Tunneling and h245address provided."
"Giving preference to Tunneling (%s, %s)\n",
call->callType, call->callToken);
if (call->h225version >= 4) {
ret =ooSendTCSandMSD(call);
}
if (ret != OO_OK)
return ret;
}
if (call->h225version >= 4) {
ret =ooSendTCSandMSD(call);
}
if (ret != OO_OK) {
return ret;
}
} else if(alerting->m.h245AddressPresent) {
if (OO_TESTFLAG (call->flags, OO_M_TUNNELING))
{
@ -1314,15 +1315,17 @@ int ooOnReceivedProgress(OOH323CallData *call, Q931Message *q931Msg)
if(q931Msg->userInfo->h323_uu_pdu.m.h245TunnelingPresent &&
q931Msg->userInfo->h323_uu_pdu.h245Tunneling &&
OO_TESTFLAG (call->flags, OO_M_TUNNELING)) {
if (progress->m.h245AddressPresent)
if (progress->m.h245AddressPresent) {
OOTRACEINFO3("Tunneling and h245address provided."
"Giving preference to Tunneling (%s, %s)\n",
call->callType, call->callToken);
if (call->h225version >= 4) {
ret =ooSendTCSandMSD(call);
}
if (ret != OO_OK)
}
if (call->h225version >= 4) {
ret =ooSendTCSandMSD(call);
}
if (ret != OO_OK) {
return ret;
}
} else if(progress->m.h245AddressPresent) {
if (OO_TESTFLAG (call->flags, OO_M_TUNNELING))
{

View File

@ -65,7 +65,7 @@ int ooH323EpInitialize
}
/* Initialize default port ranges that will be used by stack.
Apps can override these by explicitely setting port ranges
Apps can override these by explicitly setting port ranges
*/
gH323ep.tcpPorts.start = TCPPORTSSTART;

View File

@ -192,11 +192,13 @@ EXTERN int ooQ931Decode
screening indicators ;-) */
if(ie->discriminator == Q931CallingPartyNumberIE)
{
int numoffset=1;
OOTRACEDBGB1(" CallingPartyNumber IE = {\n");
if(ie->length < OO_MAX_NUMBER_LENGTH)
if(!(0x80 & ie->data[0])) numoffset = 2;
if( (ie->length >= numoffset) &&
(ie->length < OO_MAX_NUMBER_LENGTH) )
{
int numoffset=1;
if(!(0x80 & ie->data[0])) numoffset = 2;
memcpy(number, ie->data+numoffset,ie->length-numoffset);
number[ie->length-numoffset]='\0';
OOTRACEDBGB2(" %s\n", number);
@ -204,7 +206,7 @@ EXTERN int ooQ931Decode
ooCallSetCallingPartyNumber(call, number);
}
else{
OOTRACEERR3("Error:Calling party number too long. (%s, %s)\n",
OOTRACEERR3("Error:Calling party number outside range. (%s, %s)\n",
call->callType, call->callToken);
}
OOTRACEDBGB1(" }\n");
@ -214,7 +216,8 @@ EXTERN int ooQ931Decode
if(ie->discriminator == Q931CalledPartyNumberIE)
{
OOTRACEDBGB1(" CalledPartyNumber IE = {\n");
if(ie->length < OO_MAX_NUMBER_LENGTH)
if( (ie->length >= 1) &&
(ie->length < OO_MAX_NUMBER_LENGTH) )
{
memcpy(number, ie->data+1,ie->length-1);
number[ie->length-1]='\0';
@ -223,7 +226,7 @@ EXTERN int ooQ931Decode
ooCallSetCalledPartyNumber(call, number);
}
else{
OOTRACEERR3("Error:Calling party number too long. (%s, %s)\n",
OOTRACEERR3("Error:Calling party number outside range. (%s, %s)\n",
call->callType, call->callToken);
}
OOTRACEDBGB1(" }\n");
@ -1210,7 +1213,7 @@ int ooSetFastStartResponse(OOH323CallData *pCall, Q931Message *pQ931msg,
pChannel = ooFindLogicalChannelByLogicalChannelNo
(pCall, olc->forwardLogicalChannelNumber);
/* start receive and tramsmit channel listening */
/* start receive and transmit channel listening */
if(dir & OORX)
{
strcpy(pChannel->remoteIP, remoteMediaControlIP);
@ -2025,7 +2028,7 @@ int ooSendStatusInquiry(OOH323CallData *call)
/* OOCTXT *pctxt = &gH323ep.msgctxt; */
OOCTXT *pctxt = call->msgctxt;
OOTRACEDBGC3("Building StatusInquryMsg (%s, %s)\n", call->callType,
OOTRACEDBGC3("Building StatusInquiryMsg (%s, %s)\n", call->callType,
call->callToken);
ret = ooCreateQ931Message(pctxt, &q931msg, Q931StatusEnquiryMsg);
if(ret != OO_OK)
@ -2987,7 +2990,7 @@ int ooH323MakeCall_helper(OOH323CallData *call)
}
if(!epCap)
{
OOTRACEWARN4("Warn:Preferred capability %s is abscent in "
OOTRACEWARN4("Warn:Preferred capability %s is absent in "
"capability list. (%s, %s)\n",
ooGetCapTypeText(call->capPrefs.order[k]),
call->callType, call->callToken);

View File

@ -582,7 +582,7 @@ EXTERN int ooH323MakeCall_helper(struct OOH323CallData *call);
* @param dest Destination string to be parsed.
* @param parsedIP Pointer to buffer in which parsed ip:port will be returned.
* @param len Length of the buffer passed.
* @param aliasList Aliase List in which new aliases will be added.
* @param aliasList Aliases List in which new aliases will be added.
*
* @return OO_OK, on success. OO_FAILED, on failure.
*/

View File

@ -93,7 +93,7 @@ static char *wait_result(void)
fprintf(stderr, "Got %d/%d bytes of audio\n", res, bytes);
#endif
bytes += res;
/* Prentend we detected some audio after 3 seconds */
/* Pretend we detected some audio after 3 seconds */
if (bytes > 16000 * 3) {
return "Sample Message";
bytes = 0;

View File

@ -348,7 +348,7 @@ sub music_dir_cache {
}
# this function will fill the @masterCacheList of all the files that
# need to have text2speeced ulaw files of their names generated
# need to have text2speech ulaw files of their names generated
sub music_dir_cache_genlist {
my $dir = shift;
if (!opendir(THEDIR, rmts($MUSIC.$dir))) {

View File

@ -24,8 +24,14 @@
*
* See Also:
* \arg \ref AstCREDITS
* \arg \ref Config_agent
* \arg \ref agents.conf "Config_agent"
*/
/*!
* \page agents.conf agents.conf
* \verbinclude agents.conf.sample
*/
/*** MODULEINFO
<support_level>core</support_level>
***/
@ -456,17 +462,11 @@ struct agents_cfg {
struct ao2_container *agents;
};
static const char *agent_type_blacklist[] = {
"general",
"agents",
NULL,
};
static struct aco_type agent_type = {
.type = ACO_ITEM,
.name = "agent-id",
.category_match = ACO_BLACKLIST_ARRAY,
.category = (const char *)agent_type_blacklist,
.category_match = ACO_BLACKLIST_EXACT,
.category = "general",
.item_alloc = agent_cfg_alloc,
.item_find = agent_cfg_find,
.item_offset = offsetof(struct agents_cfg, agents),
@ -652,8 +652,6 @@ static struct ao2_container *agents;
* \brief Lock the agent.
*
* \param agent Agent to lock
*
* \return Nothing
*/
#define agent_lock(agent) _agent_lock(agent, __FILE__, __PRETTY_FUNCTION__, __LINE__, #agent)
static inline void _agent_lock(struct agent_pvt *agent, const char *file, const char *function, int line, const char *var)
@ -665,8 +663,6 @@ static inline void _agent_lock(struct agent_pvt *agent, const char *file, const
* \brief Unlock the agent.
*
* \param agent Agent to unlock
*
* \return Nothing
*/
#define agent_unlock(agent) _agent_unlock(agent, __FILE__, __PRETTY_FUNCTION__, __LINE__, #agent)
static inline void _agent_unlock(struct agent_pvt *agent, const char *file, const char *function, int line, const char *var)
@ -684,8 +680,6 @@ static inline void _agent_unlock(struct agent_pvt *agent, const char *file, cons
* \note Assumes the agent lock is already obtained.
*
* \note Defined locking order is channel lock then agent lock.
*
* \return Nothing
*/
static struct ast_channel *agent_lock_logged(struct agent_pvt *agent)
{
@ -750,8 +744,6 @@ static enum ast_device_state agent_pvt_devstate_get(const char *agent_id)
* \since 12.0.0
*
* \param agent_id Which agent needs the device state updated.
*
* \return Nothing
*/
static void agent_devstate_changed(const char *agent_id)
{
@ -1011,8 +1003,6 @@ AST_MUTEX_DEFINE_STATIC(agent_holding_lock);
* \param payload_size Size of the payload if payload is non-NULL. A number otherwise.
*
* \note The payload MUST NOT have any resources that need to be freed.
*
* \return Nothing
*/
static void clear_agent_status(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
{
@ -1028,8 +1018,6 @@ static void clear_agent_status(struct ast_bridge_channel *bridge_channel, const
* \param agent Which agent is connecting to the caller.
*
* \note The agent is locked on entry and not locked on exit.
*
* \return Nothing
*/
static void agent_connect_caller(struct ast_bridge_channel *bridge_channel, struct agent_pvt *agent)
{
@ -1363,8 +1351,6 @@ static int bridge_agent_hold_push(struct ast_bridge *self, struct ast_bridge_cha
* bridge_channel->bridge_pvt.
*
* \note On entry, self is already locked.
*
* \return Nothing
*/
static void bridge_agent_hold_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
{
@ -1382,8 +1368,6 @@ static void bridge_agent_hold_pull(struct ast_bridge *self, struct ast_bridge_ch
* references to the bridge so it can be destroyed.
*
* \note On entry, self must NOT be locked.
*
* \return Nothing
*/
static void bridge_agent_hold_dissolving(struct ast_bridge *self)
{
@ -1475,8 +1459,6 @@ static void send_agent_logoff(struct ast_channel *chan, const char *agent, long
* \param agent Which agent logging out.
*
* \note On entry agent is already locked. On exit it is no longer locked.
*
* \return Nothing
*/
static void agent_logout(struct agent_pvt *agent)
{
@ -1514,8 +1496,6 @@ static void agent_logout(struct agent_pvt *agent)
*
* \param agent Which agent.
* \param logged The logged in channel.
*
* \return Nothing
*/
static void agent_run(struct agent_pvt *agent, struct ast_channel *logged)
{
@ -2034,8 +2014,6 @@ static int agent_request_exec(struct ast_channel *chan, const char *data)
*
* \param agent What to setup channel config values on.
* \param chan Channel logging in as an agent.
*
* \return Nothing
*/
static void agent_login_channel_config(struct agent_pvt *agent, struct ast_channel *chan)
{

View File

@ -158,7 +158,7 @@ static const char app[] = "AlarmReceiver";
events to the standard input of the application.
The configuration file also contains settings for DTMF timing, and for the loudness of the
acknowledgement tones.</para>
<note><para>Few Ademco DTMF signalling formats are detected automaticaly: Contact ID, Express 4+1,
<note><para>Few Ademco DTMF signalling formats are detected automatically: Contact ID, Express 4+1,
Express 4+2, High Speed and Super Fast.</para></note>
<para>The application is affected by the following variables:</para>
<variablelist>
@ -203,7 +203,6 @@ static char event_file[14] = "/event-XXXXXX";
* family, then create it and set its value to 1.
*
* \param key A database key to increment
* \return Nothing
*/
static void database_increment(char *key)
{

View File

@ -92,6 +92,12 @@
<para>Is the maximum duration of a word to accept.</para>
<para>If exceeded, then the result is detection as a MACHINE</para>
</parameter>
<parameter name="audioFile" required="false">
<para>Is an audio file to play to the caller while AMD is in progress.</para>
<para>By default, no audio file is played.</para>
<para>If an audio file is configured in amd.conf, then that file will be used
if one is not specified here. That file may be overridden by this argument.</para>
</parameter>
</syntax>
<description>
<para>This application attempts to detect answering machines at the beginning
@ -155,6 +161,9 @@ static int dfltBetweenWordsSilence = 50;
static int dfltMaximumNumberOfWords = 2;
static int dfltSilenceThreshold = 256;
static int dfltMaximumWordLength = 5000; /* Setting this to a large default so it is not used unless specify it in the configs or command line */
static char *dfltAudioFile = NULL;
static ast_mutex_t config_lock;
/* Set to the lowest ms value provided in amd.conf or application parameters */
static int dfltMaxWaitTimeForFrame = 50;
@ -179,7 +188,7 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
char amdCause[256] = "", amdStatus[256] = "";
char *parse = ast_strdupa(data);
/* Lets set the initial values of the variables that will control the algorithm.
/* Let's set the initial values of the variables that will control the algorithm.
The initial values are the default ones. If they are passed as arguments
when invoking the application, then the default values will be overwritten
by the ones passed as parameters. */
@ -193,6 +202,7 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
int silenceThreshold = dfltSilenceThreshold;
int maximumWordLength = dfltMaximumWordLength;
int maxWaitTimeForFrame = dfltMaxWaitTimeForFrame;
const char *audioFile = NULL;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(argInitialSilence);
@ -204,8 +214,15 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
AST_APP_ARG(argMaximumNumberOfWords);
AST_APP_ARG(argSilenceThreshold);
AST_APP_ARG(argMaximumWordLength);
AST_APP_ARG(audioFile);
);
ast_mutex_lock(&config_lock);
if (!ast_strlen_zero(dfltAudioFile)) {
audioFile = ast_strdupa(dfltAudioFile);
}
ast_mutex_unlock(&config_lock);
ast_verb(3, "AMD: %s %s %s (Fmt: %s)\n", ast_channel_name(chan),
S_COR(ast_channel_caller(chan)->ani.number.valid, ast_channel_caller(chan)->ani.number.str, "(N/A)"),
S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, "(N/A)"),
@ -233,6 +250,9 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
silenceThreshold = atoi(args.argSilenceThreshold);
if (!ast_strlen_zero(args.argMaximumWordLength))
maximumWordLength = atoi(args.argMaximumWordLength);
if (!ast_strlen_zero(args.audioFile)) {
audioFile = args.audioFile;
}
} else {
ast_debug(1, "AMD using the default parameters.\n");
}
@ -280,6 +300,11 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
/* Set our start time so we can tie the loop to real world time and not RTP updates */
amd_tvstart = ast_tvnow();
/* Optional audio file to play to caller while AMD is doing its thing. */
if (!ast_strlen_zero(audioFile)) {
ast_streamfile(chan, audioFile, ast_channel_language(chan));
}
/* Now we go into a loop waiting for frames from the channel */
while ((res = ast_waitfor(chan, 2 * maxWaitTimeForFrame)) > -1) {
int ms = 0;
@ -462,10 +487,14 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
/* Free the DSP used to detect silence */
ast_dsp_free(silenceDetector);
/* If we were playing something to pass the time, stop it now. */
if (!ast_strlen_zero(audioFile)) {
ast_stopstream(chan);
}
return;
}
static int amd_exec(struct ast_channel *chan, const char *data)
{
isAnsweringMachine(chan, data);
@ -516,7 +545,16 @@ static int load_config(int reload)
dfltMaximumNumberOfWords = atoi(var->value);
} else if (!strcasecmp(var->name, "maximum_word_length")) {
dfltMaximumWordLength = atoi(var->value);
} else if (!strcasecmp(var->name, "playback_file")) {
ast_mutex_lock(&config_lock);
if (dfltAudioFile) {
ast_free(dfltAudioFile);
dfltAudioFile = NULL;
}
if (!ast_strlen_zero(var->value)) {
dfltAudioFile = ast_strdup(var->value);
}
ast_mutex_unlock(&config_lock);
} else {
ast_log(LOG_WARNING, "%s: Cat:%s. Unknown keyword %s at line %d of amd.conf\n",
app, cat, var->name, var->lineno);
@ -539,6 +577,12 @@ static int load_config(int reload)
static int unload_module(void)
{
ast_mutex_lock(&config_lock);
if (dfltAudioFile) {
ast_free(dfltAudioFile);
}
ast_mutex_unlock(&config_lock);
ast_mutex_destroy(&config_lock);
return ast_unregister_application(app);
}
@ -554,6 +598,7 @@ static int unload_module(void)
*/
static int load_module(void)
{
ast_mutex_init(&config_lock);
if (load_config(0) || ast_register_application_xml(app, amd_exec)) {
return AST_MODULE_LOAD_DECLINE;
}

View File

@ -100,6 +100,9 @@
<para>Automatically exit the bridge and return to the PBX after
<emphasis>duration</emphasis> seconds.</para>
</option>
<option name="n">
<para>Do not automatically answer the channel.</para>
</option>
</optionlist>
</parameter>
</syntax>
@ -108,7 +111,7 @@
The channel will then wait in the holding bridge until some event occurs
which removes it from the holding bridge.</para>
<note><para>This application will answer calls which haven't already
been answered.</para></note>
been answered, unless the n option is provided.</para></note>
</description>
</application>
***/
@ -186,6 +189,7 @@ enum bridgewait_flags {
MUXFLAG_MOHCLASS = (1 << 0),
MUXFLAG_ENTERTAINMENT = (1 << 1),
MUXFLAG_TIMEOUT = (1 << 2),
MUXFLAG_NOANSWER = (1 << 3),
};
enum bridgewait_args {
@ -199,6 +203,7 @@ AST_APP_OPTIONS(bridgewait_opts, {
AST_APP_OPTION_ARG('e', MUXFLAG_ENTERTAINMENT, OPT_ARG_ENTERTAINMENT),
AST_APP_OPTION_ARG('m', MUXFLAG_MOHCLASS, OPT_ARG_MOHCLASS),
AST_APP_OPTION_ARG('S', MUXFLAG_TIMEOUT, OPT_ARG_TIMEOUT),
AST_APP_OPTION('n', MUXFLAG_NOANSWER),
});
static int bridgewait_timeout_callback(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
@ -391,17 +396,6 @@ static void wait_wrapper_removal(struct wait_bridge_wrapper *wrapper)
ao2_cleanup(wrapper);
}
/*!
* \internal
* \since 12.0.0
* \brief Application callback for the bridgewait application
*
* \param chan channel running the application
* \param data Arguments to the application
*
* \retval 0 Ran successfully and the call didn't hang up
* \retval -1 Failed or the call was hung up by the time the channel exited the holding bridge
*/
static enum wait_bridge_roles validate_role(const char *role)
{
if (!strcmp(role, "participant")) {
@ -413,6 +407,17 @@ static enum wait_bridge_roles validate_role(const char *role)
}
}
/*!
* \internal
* \since 12.0.0
* \brief Application callback for the bridgewait application
*
* \param chan channel running the application
* \param data Arguments to the application
*
* \retval 0 Ran successfully and the call didn't hang up
* \retval -1 Failed or the call was hung up by the time the channel exited the holding bridge
*/
static int bridgewait_exec(struct ast_channel *chan, const char *data)
{
char *bridge_name = DEFAULT_BRIDGE_NAME;
@ -458,7 +463,7 @@ static int bridgewait_exec(struct ast_channel *chan, const char *data)
}
/* Answer the channel if needed */
if (ast_channel_state(chan) != AST_STATE_UP) {
if (ast_channel_state(chan) != AST_STATE_UP && !ast_test_flag(&flags, MUXFLAG_NOANSWER)) {
ast_answer(chan);
}

View File

@ -559,7 +559,7 @@ static int pack_channel_into_message(struct ast_channel *chan, const char *role,
* \brief Publish the chanspy message over Stasis-Core
* \param spyer The channel doing the spying
* \param spyee Who is being spied upon
* \start start If non-zero, the spying is starting. Otherwise, the spyer is
* \param start If non-zero, the spying is starting. Otherwise, the spyer is
* finishing
*/
static void publish_chanspy_message(struct ast_channel *spyer,
@ -899,7 +899,7 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
signed char zero_volume = 0;
int waitms;
int res;
int num_spyed_upon = 1;
int num_spied_upon = 1;
struct ast_channel_iterator *iter = NULL;
if (ast_test_flag(flags, OPTION_EXIT)) {
@ -926,7 +926,7 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
struct ast_autochan *autochan = NULL, *next_autochan = NULL;
struct ast_channel *prev = NULL;
if (!ast_test_flag(flags, OPTION_QUIET) && num_spyed_upon) {
if (!ast_test_flag(flags, OPTION_QUIET) && num_spied_upon) {
res = ast_streamfile(chan, "beep", ast_channel_language(chan));
if (!res)
res = ast_waitstream(chan, "");
@ -991,7 +991,7 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
/* reset for the next loop around, unless overridden later */
waitms = 100;
num_spyed_upon = 0;
num_spied_upon = 0;
for (autochan = next_channel(iter, chan);
autochan;
@ -1146,7 +1146,7 @@ static int common_exec(struct ast_channel *chan, struct ast_flags *flags,
}
res = channel_spy(chan, autochan, &volfactor, fd, user_options, flags, exitcontext);
num_spyed_upon++;
num_spied_upon++;
if (res == -1) {
ast_autochan_destroy(autochan);

View File

@ -128,9 +128,15 @@
<ref type="application">ConfKick</ref>
<ref type="function">CONFBRIDGE</ref>
<ref type="function">CONFBRIDGE_INFO</ref>
<ref type="function">CONFBRIDGE_CHANNELS</ref>
</see-also>
</application>
<application name="ConfKick" language="en_US">
<since>
<version>16.19.0</version>
<version>18.5.0</version>
<version>19.0.0</version>
</since>
<synopsis>
Kicks channel(s) from the requested ConfBridge.
</synopsis>
@ -159,6 +165,7 @@
<ref type="application">ConfBridge</ref>
<ref type="function">CONFBRIDGE</ref>
<ref type="function">CONFBRIDGE_INFO</ref>
<ref type="function">CONFBRIDGE_CHANNELS</ref>
</see-also>
</application>
<function name="CONFBRIDGE" language="en_US">
@ -191,23 +198,29 @@
<para>---- Example 1 ----</para>
<para>In this example the custom user profile set on the channel will
automatically be used by the ConfBridge application.</para>
<para>exten => 1,1,Answer()</para>
<example title="Example 1">
exten => 1,1,Answer()
</example>
<para>; In this example the effect of the following line is</para>
<para>; implied:</para>
<para>; same => n,Set(CONFBRIDGE(user,template)=default_user)</para>
<para>same => n,Set(CONFBRIDGE(user,announce_join_leave)=yes)</para>
<para>same => n,Set(CONFBRIDGE(user,startmuted)=yes)</para>
<para>same => n,ConfBridge(1) </para>
<example title="Example 1b">
same => n,Set(CONFBRIDGE(user,template)=default_user)
same => n,Set(CONFBRIDGE(user,announce_join_leave)=yes)
same => n,Set(CONFBRIDGE(user,startmuted)=yes)
same => n,ConfBridge(1)
</example>
<para>---- Example 2 ----</para>
<para>This example shows how to use a predefined user profile in
<filename>confbridge.conf</filename> as a template for a dynamic profile.
Here we make an admin/marked user out of the <literal>my_user</literal>
profile that you define in <filename>confbridge.conf</filename>.</para>
<para>exten => 1,1,Answer()</para>
<para>same => n,Set(CONFBRIDGE(user,template)=my_user)</para>
<para>same => n,Set(CONFBRIDGE(user,admin)=yes)</para>
<para>same => n,Set(CONFBRIDGE(user,marked)=yes)</para>
<para>same => n,ConfBridge(1)</para>
<example title="Example 2">
exten => 1,1,Answer()
same => n,Set(CONFBRIDGE(user,template)=my_user)
same => n,Set(CONFBRIDGE(user,admin)=yes)
same => n,Set(CONFBRIDGE(user,marked)=yes)
same => n,ConfBridge(1)
</example>
</description>
</function>
<function name="CONFBRIDGE_INFO" language="en_US">
@ -243,6 +256,50 @@
<para>This function returns a non-negative integer for valid conference
names and an empty string for invalid conference names.</para>
</description>
<see-also>
<ref type="function">CONFBRIDGE_CHANNELS</ref>
</see-also>
</function>
<function name="CONFBRIDGE_CHANNELS" language="en_US">
<since>
<version>16.26.0</version>
<version>18.12.0</version>
<version>19.4.0</version>
</since>
<synopsis>
Get a list of channels in a ConfBridge conference.
</synopsis>
<syntax>
<parameter name="type" required="true">
<para>What conference information is requested.</para>
<enumlist>
<enum name="admins">
<para>Get the number of admin users in the conference.</para>
</enum>
<enum name="marked">
<para>Get the number of marked users in the conference.</para>
</enum>
<enum name="parties">
<para>Get the number of total users in the conference.</para>
</enum>
<enum name="active">
<para>Get the number of active users in the conference.</para>
</enum>
<enum name="waiting">
<para>Get the number of waiting users in the conference.</para>
</enum>
</enumlist>
</parameter>
<parameter name="conf" required="true">
<para>The name of the conference being referenced.</para>
</parameter>
</syntax>
<description>
<para>This function returns a comma-separated list of channels in a ConfBridge conference, optionally filtered by a type of participant.</para>
</description>
<see-also>
<ref type="function">CONFBRIDGE_INFO</ref>
</see-also>
</function>
<manager name="ConfbridgeList" language="en_US">
<synopsis>
@ -336,6 +393,37 @@
ConfbridgeListRoomsComplete.</para>
</description>
</manager>
<managerEvent language="en_US" name="ConfbridgeListRooms">
<managerEventInstance class="EVENT_FLAG_REPORTING">
<synopsis>Raised as part of the ConfbridgeListRooms action response list.</synopsis>
<syntax>
<parameter name="Conference">
<para>The name of the Confbridge conference.</para>
</parameter>
<parameter name="Parties">
<para>Number of users in the conference.</para>
<para>This includes both active and waiting users.</para>
</parameter>
<parameter name="Marked">
<para>Number of marked users in the conference.</para>
</parameter>
<parameter name="Locked">
<para>Is the conference locked?</para>
<enumlist>
<enum name="Yes"/>
<enum name="No"/>
</enumlist>
</parameter>
<parameter name="Muted">
<para>Is the conference muted?</para>
<enumlist>
<enum name="Yes"/>
<enum name="No"/>
</enumlist>
</parameter>
</syntax>
</managerEventInstance>
</managerEvent>
<manager name="ConfbridgeMute" language="en_US">
<synopsis>
Mute a Confbridge user.
@ -797,8 +885,8 @@ struct confbridge_conference *conf_find_bridge(const char *conference_name)
*
* \note Must be called with the conference locked
*
* \retval 1, conference is recording.
* \retval 0, conference is NOT recording.
* \retval 1 conference is recording.
* \retval 0 conference is NOT recording.
*/
static int conf_is_recording(struct confbridge_conference *conference)
{
@ -909,7 +997,7 @@ static int conf_start_record(struct confbridge_conference *conference)
return 0;
}
/* \brief Playback the given filename and monitor for any dtmf interrupts.
/*! \brief Playback the given filename and monitor for any dtmf interrupts.
*
* This function is used to playback sound files on a given channel and optionally
* allow dtmf interrupts to occur.
@ -923,7 +1011,9 @@ static int conf_start_record(struct confbridge_conference *conference)
* \param channel Optional channel to play file on if bridge_channel not given
* \param filename The file name to playback
*
* \retval -1 failure during playback, 0 on file was fully played, 1 on dtmf interrupt.
* \retval -1 failure during playback.
* \retval 0 on file was fully played.
* \retval 1 on dtmf interrupt.
*/
static int play_file(struct ast_bridge_channel *bridge_channel, struct ast_channel *channel,
const char *filename)
@ -980,7 +1070,8 @@ static int sound_file_exists(const char *filename)
* \param bridge_channel The bridged channel involved
*
* \note if caller is NULL, the announcment will be sent to all participants in the conference.
* \return Returns 0 on success, -1 if the user hung up
* \retval 0 on success.
* \retval -1 if the user hung up.
*/
static int announce_user_count(struct confbridge_conference *conference, struct confbridge_user *user,
struct ast_bridge_channel *bridge_channel)
@ -1030,7 +1121,9 @@ static int announce_user_count(struct confbridge_conference *conference, struct
* \param user User to play audio prompt to
* \param filename Prompt to play
*
* \return Returns 0 on success, -1 if the user hung up
* \retval 0 on success.
* \retval -1 if the user hung up.
*
* \note Generally this should be called when the conference is unlocked to avoid blocking
* the entire conference while the sound is played. But don't unlock the conference bridge
* in the middle of a state transition.
@ -1167,8 +1260,6 @@ static void hangup_data_destroy(struct hangup_data *hangup)
* \brief Destroy a conference bridge
*
* \param obj The conference bridge object
*
* \return Returns nothing
*/
static void destroy_conference_bridge(void *obj)
{
@ -1305,7 +1396,7 @@ void conf_update_user_mute(struct confbridge_user *user)
ast_channel_name(user->chan));
}
/*
/*!
* \internal
* \brief Mute/unmute a single user.
*/
@ -1389,8 +1480,6 @@ void conf_moh_start(struct confbridge_user *user)
* \brief Unsuspend MOH for the conference user.
*
* \param user Conference user to unsuspend MOH on.
*
* \return Nothing
*/
static void conf_moh_unsuspend(struct confbridge_user *user)
{
@ -1406,8 +1495,6 @@ static void conf_moh_unsuspend(struct confbridge_user *user)
* \brief Suspend MOH for the conference user.
*
* \param user Conference user to suspend MOH on.
*
* \return Nothing
*/
static void conf_moh_suspend(struct confbridge_user *user)
{
@ -1682,7 +1769,7 @@ static struct confbridge_conference *join_conference_bridge(const char *conferen
struct post_join_action *action;
int max_members_reached = 0;
/* We explictly lock the conference bridges container ourselves so that other callers can not create duplicate conferences at the same */
/* We explicitly lock the conference bridges container ourselves so that other callers can not create duplicate conferences at the same time */
ao2_lock(conference_bridges);
ast_debug(1, "Trying to find conference bridge '%s'\n", conference_name);
@ -1748,7 +1835,6 @@ static struct confbridge_conference *join_conference_bridge(const char *conferen
ast_bridge_set_talker_src_video_mode(conference->bridge);
} else if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_VIDEO_SRC_SFU)) {
ast_bridge_set_sfu_video_mode(conference->bridge);
ast_bridge_set_video_update_discard(conference->bridge, conference->b_profile.video_update_discard);
ast_bridge_set_remb_send_interval(conference->bridge, conference->b_profile.remb_send_interval);
if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE)) {
ast_brige_set_remb_behavior(conference->bridge, AST_BRIDGE_VIDEO_SFU_REMB_AVERAGE);
@ -1768,6 +1854,9 @@ static struct confbridge_conference *join_conference_bridge(const char *conferen
}
}
/* Always set the minimum interval between video updates, to avoid infinite video updates. */
ast_bridge_set_video_update_discard(conference->bridge, conference->b_profile.video_update_discard);
if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_ENABLE_EVENTS)) {
ast_bridge_set_send_sdp_label(conference->bridge, 1);
}
@ -2721,17 +2810,24 @@ static int confbridge_exec(struct ast_channel *chan, const char *data)
ast_autoservice_stop(chan);
}
/* Play the Join sound to both the conference and the user entering. */
if (!quiet) {
const char *join_sound = conf_get_sound(CONF_SOUND_JOIN, conference->b_profile.sounds);
if (strcmp(conference->b_profile.language, ast_channel_language(chan))) {
ast_stream_and_wait(chan, join_sound, "");
/* if hear_own_join_sound is enabled play the Join sound to everyone */
if (ast_test_flag(&user.u_profile, USER_OPT_HEAR_OWN_JOIN_SOUND) ) {
if (strcmp(conference->b_profile.language, ast_channel_language(chan))) {
ast_stream_and_wait(chan, join_sound, "");
ast_autoservice_start(chan);
play_sound_file(conference, join_sound);
ast_autoservice_stop(chan);
} else {
async_play_sound_file(conference, join_sound, chan);
}
/* if hear_own_join_sound is disabled only play the Join sound to just the conference */
} else {
ast_autoservice_start(chan);
play_sound_file(conference, join_sound);
ast_autoservice_stop(chan);
} else {
async_play_sound_file(conference, join_sound, chan);
}
}
@ -3494,7 +3590,7 @@ static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct
return CLI_SHOWUSAGE;
}
/* \internal
/*! \internal
* \brief finds a conference by name and locks/unlocks.
*
* \retval 0 success
@ -3518,7 +3614,7 @@ static int generic_lock_unlock_helper(int lock, const char *conference_name)
return res;
}
/* \internal
/*! \internal
* \brief finds a conference user by channel name and mutes/unmutes them.
*
* \retval 0 success
@ -3818,6 +3914,90 @@ static struct ast_custom_function confbridge_info_function = {
.read = func_confbridge_info,
};
static int func_confbridge_channels(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
char *parse, *outbuf;
struct confbridge_conference *conference;
struct confbridge_user *user;
int bytes, count = 0;
size_t outlen;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(type);
AST_APP_ARG(confno);
);
/* parse all the required arguments and make sure they exist. */
if (ast_strlen_zero(data)) {
return -1;
}
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
if (ast_strlen_zero(args.confno) || ast_strlen_zero(args.type)) {
ast_log(LOG_WARNING, "Usage: %s(category,confno)", cmd);
return -1;
}
conference = ao2_find(conference_bridges, args.confno, OBJ_KEY);
if (!conference) {
ast_debug(1, "No such conference: %s\n", args.confno);
return -1;
}
outbuf = buf;
outlen = len;
ao2_lock(conference);
if (!strcasecmp(args.type, "parties")) {
AST_LIST_TRAVERSE(&conference->active_list, user, list) {
bytes = snprintf(outbuf, outlen, "%s%s", count++ ? "," : "", ast_channel_name(user->chan));
outbuf += bytes;
outlen -= bytes;
}
AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
bytes = snprintf(outbuf, outlen, "%s%s", count++ ? "," : "", ast_channel_name(user->chan));
outbuf += bytes;
outlen -= bytes;
}
} else if (!strcasecmp(args.type, "active")) {
AST_LIST_TRAVERSE(&conference->active_list, user, list) {
bytes = snprintf(outbuf, outlen, "%s%s", count++ ? "," : "", ast_channel_name(user->chan));
outbuf += bytes;
outlen -= bytes;
}
} else if (!strcasecmp(args.type, "waiting")) {
AST_LIST_TRAVERSE(&conference->waiting_list, user, list) {
bytes = snprintf(outbuf, outlen, "%s%s", count++ ? "," : "", ast_channel_name(user->chan));
outbuf += bytes;
outlen -= bytes;
}
} else if (!strcasecmp(args.type, "admins")) {
AST_LIST_TRAVERSE(&conference->active_list, user, list) {
if (ast_test_flag(&user->u_profile, USER_OPT_ADMIN)) {
bytes = snprintf(outbuf, outlen, "%s%s", count++ ? "," : "", ast_channel_name(user->chan));
outbuf += bytes;
outlen -= bytes;
}
}
} else if (!strcasecmp(args.type, "marked")) {
AST_LIST_TRAVERSE(&conference->active_list, user, list) {
if (ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)) {
bytes = snprintf(outbuf, outlen, "%s%s", count++ ? "," : "", ast_channel_name(user->chan));
outbuf += bytes;
outlen -= bytes;
}
}
} else {
ast_log(LOG_ERROR, "Invalid keyword '%s' passed to %s.\n", args.type, cmd);
}
ao2_unlock(conference);
ao2_ref(conference, -1);
return 0;
}
static struct ast_custom_function confbridge_channels_function = {
.name = "CONFBRIDGE_CHANNELS",
.read = func_confbridge_channels,
};
static int action_confbridgelist_item(struct mansession *s, const char *id_text, struct confbridge_conference *conference, struct confbridge_user *user, int waiting)
{
struct ast_channel_snapshot *snapshot;
@ -3842,6 +4022,7 @@ static int action_confbridgelist_item(struct mansession *s, const char *id_text,
"MarkedUser: %s\r\n"
"WaitMarked: %s\r\n"
"EndMarked: %s\r\n"
"EndMarkedAny: %s\r\n"
"Waiting: %s\r\n"
"Muted: %s\r\n"
"Talking: %s\r\n"
@ -3854,6 +4035,7 @@ static int action_confbridgelist_item(struct mansession *s, const char *id_text,
AST_YESNO(ast_test_flag(&user->u_profile, USER_OPT_MARKEDUSER)),
AST_YESNO(ast_test_flag(&user->u_profile, USER_OPT_WAITMARKED)),
AST_YESNO(ast_test_flag(&user->u_profile, USER_OPT_ENDMARKED)),
AST_YESNO(ast_test_flag(&user->u_profile, USER_OPT_ENDMARKEDANY)),
AST_YESNO(waiting),
AST_YESNO(user->muted),
AST_YESNO(user->talking),
@ -4355,8 +4537,6 @@ void conf_remove_user_waiting(struct confbridge_conference *conference, struct c
* \since 12.0.0
*
* \param tech What to unregister.
*
* \return Nothing
*/
static void unregister_channel_tech(struct ast_channel_tech *tech)
{
@ -4397,6 +4577,7 @@ static int unload_module(void)
ast_custom_function_unregister(&confbridge_function);
ast_custom_function_unregister(&confbridge_info_function);
ast_custom_function_unregister(&confbridge_channels_function);
ast_cli_unregister_multiple(cli_confbridge, ARRAY_LEN(cli_confbridge));
@ -4468,6 +4649,7 @@ static int load_module(void)
res |= ast_custom_function_register_escalating(&confbridge_function, AST_CFE_WRITE);
res |= ast_custom_function_register(&confbridge_info_function);
res |= ast_custom_function_register(&confbridge_channels_function);
res |= ast_cli_register_multiple(cli_confbridge, ARRAY_LEN(cli_confbridge));

View File

@ -1,231 +0,0 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Execute an ISDN RAS
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>dahdi</depend>
<support_level>deprecated</support_level>
***/
#include "asterisk.h"
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <signal.h>
#include <fcntl.h>
#include <dahdi/user.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
/*** DOCUMENTATION
<application name="DAHDIRAS" language="en_US">
<synopsis>
Executes DAHDI ISDN RAS application.
</synopsis>
<syntax>
<parameter name="args" required="true">
<para>A list of parameters to pass to the pppd daemon,
separated by <literal>,</literal> characters.</para>
</parameter>
</syntax>
<description>
<para>Executes a RAS server using pppd on the given channel.
The channel must be a clear channel (i.e. PRI source) and a DAHDI
channel to be able to use this function (No modem emulation is included).</para>
<para>Your pppd must be patched to be DAHDI aware.</para>
</description>
</application>
***/
static const char app[] = "DAHDIRAS";
#define PPP_MAX_ARGS 32
#define PPP_EXEC "/usr/sbin/pppd"
static pid_t spawn_ras(struct ast_channel *chan, char *args)
{
pid_t pid;
char *c;
char *argv[PPP_MAX_ARGS];
int argc = 0;
char *stringp=NULL;
/* Start by forking */
pid = ast_safe_fork(1);
if (pid) {
return pid;
}
/* Execute RAS on File handles */
dup2(ast_channel_fd(chan, 0), STDIN_FILENO);
/* Drop high priority */
if (ast_opt_high_priority)
ast_set_priority(0);
/* Close other file descriptors */
ast_close_fds_above_n(STDERR_FILENO);
/* Reset all arguments */
memset(argv, 0, sizeof(argv));
/* First argument is executable, followed by standard
arguments for DAHDI PPP */
argv[argc++] = PPP_EXEC;
argv[argc++] = "nodetach";
/* And all the other arguments */
stringp=args;
c = strsep(&stringp, ",");
while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) {
argv[argc++] = c;
c = strsep(&stringp, ",");
}
if (geteuid() == 0) {
argv[argc++] = "plugin";
argv[argc++] = "dahdi.so";
}
argv[argc++] = "stdin";
/* Finally launch PPP */
execv(PPP_EXEC, argv);
fprintf(stderr, "Failed to exec PPPD!\n");
exit(1);
}
static void run_ras(struct ast_channel *chan, char *args)
{
pid_t pid;
int status;
int res;
int signalled = 0;
struct dahdi_bufferinfo savebi;
int x;
res = ioctl(ast_channel_fd(chan, 0), DAHDI_GET_BUFINFO, &savebi);
if(res) {
ast_log(LOG_WARNING, "Unable to check buffer policy on channel %s\n", ast_channel_name(chan));
return;
}
pid = spawn_ras(chan, args);
if (pid < 0) {
ast_log(LOG_WARNING, "Failed to spawn RAS\n");
} else {
for (;;) {
res = waitpid(pid, &status, WNOHANG);
if (!res) {
/* Check for hangup */
if (ast_check_hangup(chan) && !signalled) {
ast_debug(1, "Channel '%s' hungup. Signalling RAS at %d to die...\n", ast_channel_name(chan), pid);
kill(pid, SIGTERM);
signalled=1;
}
/* Try again */
sleep(1);
continue;
}
if (res < 0) {
ast_log(LOG_WARNING, "waitpid returned %d: %s\n", res, strerror(errno));
}
if (WIFEXITED(status)) {
ast_verb(3, "RAS on %s terminated with status %d\n", ast_channel_name(chan), WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
ast_verb(3, "RAS on %s terminated with signal %d\n",
ast_channel_name(chan), WTERMSIG(status));
} else {
ast_verb(3, "RAS on %s terminated weirdly.\n", ast_channel_name(chan));
}
/* Throw back into audio mode */
x = 1;
ioctl(ast_channel_fd(chan, 0), DAHDI_AUDIOMODE, &x);
/* Restore saved values */
res = ioctl(ast_channel_fd(chan, 0), DAHDI_SET_BUFINFO, &savebi);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set buffer policy on channel %s\n", ast_channel_name(chan));
}
break;
}
}
ast_safe_fork_cleanup();
}
static int dahdiras_exec(struct ast_channel *chan, const char *data)
{
int res=-1;
char *args;
struct dahdi_params dahdip;
if (!data)
data = "";
args = ast_strdupa(data);
/* Answer the channel if it's not up */
if (ast_channel_state(chan) != AST_STATE_UP)
ast_answer(chan);
if (strcasecmp(ast_channel_tech(chan)->type, "DAHDI")) {
/* If it's not a DAHDI channel, we're done. Wait a couple of
seconds and then hangup... */
ast_verb(2, "Channel %s is not a DAHDI channel\n", ast_channel_name(chan));
sleep(2);
} else {
memset(&dahdip, 0, sizeof(dahdip));
if (ioctl(ast_channel_fd(chan, 0), DAHDI_GET_PARAMS, &dahdip)) {
ast_log(LOG_WARNING, "Unable to get DAHDI parameters\n");
} else if (dahdip.sigtype != DAHDI_SIG_CLEAR) {
ast_verb(2, "Channel %s is not a clear channel\n", ast_channel_name(chan));
} else {
/* Everything should be okay. Run PPP. */
ast_verb(3, "Starting RAS on %s\n", ast_channel_name(chan));
/* Execute RAS */
run_ras(chan, args);
}
}
return res;
}
static int unload_module(void)
{
return ast_unregister_application(app);
}
static int load_module(void)
{
return ((ast_register_application_xml(app, dahdiras_exec)) ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS);
}
AST_MODULE_INFO_STANDARD_DEPRECATED(ASTERISK_GPL_KEY, "DAHDI ISDN Remote Access Server");

View File

@ -86,6 +86,7 @@
<para>If you need more than one enter them as
Technology2/Resource2&amp;Technology3/Resource3&amp;.....</para>
</argument>
<xi:include xpointer="xpointer(/docs/info[@name='Dial_Resource'])" />
</parameter>
<parameter name="timeout" required="false">
<para>Specifies the number of seconds we attempt to dial the specified devices.</para>
@ -156,6 +157,10 @@
<argument name="called" />
<argument name="calling" />
<argument name="progress" />
<argument name="mfprogress" />
<argument name="mfwink" />
<argument name="sfprogress" />
<argument name="sfwink" />
<para>Send the specified DTMF strings <emphasis>after</emphasis> the called
party has answered, but before the call gets bridged. The
<replaceable>called</replaceable> DTMF string is sent to the called party, and the
@ -163,6 +168,20 @@
can be used alone. If <replaceable>progress</replaceable> is specified, its DTMF is sent
to the called party immediately after receiving a <literal>PROGRESS</literal> message.</para>
<para>See <literal>SendDTMF</literal> for valid digits.</para>
<para>If <replaceable>mfprogress</replaceable> is specified, its MF is sent
to the called party immediately after receiving a <literal>PROGRESS</literal> message.
If <replaceable>mfwink</replaceable> is specified, its MF is sent
to the called party immediately after receiving a <literal>WINK</literal> message.</para>
<para>See <literal>SendMF</literal> for valid digits.</para>
<para>If <replaceable>sfprogress</replaceable> is specified, its SF is sent
to the called party immediately after receiving a <literal>PROGRESS</literal> message.
If <replaceable>sfwink</replaceable> is specified, its SF is sent
to the called party immediately after receiving a <literal>WINK</literal> message.</para>
<para>See <literal>SendSF</literal> for valid digits.</para>
</option>
<option name="E">
<para>Enable echoing of sent MF or SF digits back to caller (e.g. "hearpulsing").
Used in conjunction with the D option.</para>
</option>
<option name="e">
<para>Execute the <literal>h</literal> extension for peer after the call ends</para>
@ -353,7 +372,7 @@
</argument>
<para>Enables <emphasis>operator services</emphasis> mode. This option only
works when bridging a DAHDI channel to another DAHDI channel
only. if specified on non-DAHDI interfaces, it will be ignored.
only. If specified on non-DAHDI interfaces, it will be ignored.
When the destination answers (presumably an operator services
station), the originator no longer has control of their line.
They may hang up, but the switch will not release their line
@ -499,7 +518,6 @@
answered, if it has not already been answered. These two channels will then
be active in a bridged call. All other channels that were requested will then
be hung up.</para>
<para>Unless there is a timeout specified, the Dial application will wait
indefinitely until one of the called channels answers, the user hangs up, or
if all of the called channels are busy or unavailable. Dialplan execution will
@ -512,7 +530,6 @@
If the <variable>OUTBOUND_GROUP_ONCE</variable> variable is set, all peer channels created by this
application will be put into that group (as in <literal>Set(GROUP()=...</literal>). Unlike <variable>OUTBOUND_GROUP</variable>,
however, the variable will be unset after use.</para>
<example title="Dial with 30 second timeout">
same => n,Dial(PJSIP/alice,30)
</example>
@ -534,28 +551,22 @@
</example>
<example title="Dial with pre-dial subroutines">
[default]
exten => callee_channel,1,NoOp(ARG1=${ARG1} ARG2=${ARG2})
same => n,Log(NOTICE, I'm called on channel ${CHANNEL} prior to it starting the dial attempt)
same => n,Return()
exten => called_channel,1,NoOp(ARG1=${ARG1} ARG2=${ARG2})
same => n,Log(NOTICE, I'm called on outbound channel ${CHANNEL} prior to it being used to dial someone)
same => n,Return()
exten => _X.,1,NoOp()
same => n,Dial(PJSIP/alice,,b(default^called_channel^1(my_gosub_arg1^my_gosub_arg2))B(default^callee_channel^1(my_gosub_arg1^my_gosub_arg2)))
same => n,Hangup()
</example>
<example title="Dial with post-answer subroutine executed on outbound channel">
[my_gosub_routine]
exten => s,1,NoOp(ARG1=${ARG1} ARG2=${ARG2})
same => n,Playback(hello)
same => n,Return()
[default]
exten => _X.,1,NoOp()
same => n,Dial(PJSIP/alice,,U(my_gosub_routine^my_gosub_arg1^my_gosub_arg2))
same => n,Hangup()
@ -603,12 +614,31 @@
</variable>
<variable name="DIALSTATUS">
<para>This is the status of the call</para>
<value name="CHANUNAVAIL" />
<value name="CONGESTION" />
<value name="NOANSWER" />
<value name="BUSY" />
<value name="ANSWER" />
<value name="CANCEL" />
<value name="CHANUNAVAIL">
Either the dialed peer exists but is not currently reachable, e.g.
endpoint is not registered, or an attempt was made to call a
nonexistent location, e.g. nonexistent DNS hostname.
</value>
<value name="CONGESTION">
Channel or switching congestion occured when routing the call.
This can occur if there is a slow or no response from the remote end.
</value>
<value name="NOANSWER">
Called party did not answer.
</value>
<value name="BUSY">
The called party was busy or indicated a busy status.
Note that some SIP devices will respond with 486 Busy if their Do Not Disturb
modes are active. In this case, you can use DEVICE_STATUS to check if the
endpoint is actually in use, if needed.
</value>
<value name="ANSWER">
The call was answered.
Any other result implicitly indicates the call was not answered.
</value>
<value name="CANCEL">
Dial was cancelled before call was answered or reached some other terminating event.
</value>
<value name="DONTCALL">
For the Privacy and Screening Modes.
Will be set if the called party chooses to send the calling party to the 'Go Away' script.
@ -617,7 +647,9 @@
For the Privacy and Screening Modes.
Will be set if the called party chooses to send the calling party to the 'torture' script.
</value>
<value name="INVALIDARGS" />
<value name="INVALIDARGS">
Dial failed due to invalid syntax.
</value>
</variable>
</variablelist>
</description>
@ -717,6 +749,7 @@ enum {
#define OPT_PREDIAL_CALLER (1LLU << 42)
#define OPT_RING_WITH_EARLY_MEDIA (1LLU << 43)
#define OPT_HANGUPCAUSE (1LLU << 44)
#define OPT_HEARPULSING (1LLU << 45)
enum {
OPT_ARG_ANNOUNCE = 0,
@ -752,6 +785,7 @@ AST_APP_OPTIONS(dial_exec_options, BEGIN_OPTIONS
AST_APP_OPTION('c', OPT_CANCEL_ELSEWHERE),
AST_APP_OPTION('d', OPT_DTMF_EXIT),
AST_APP_OPTION_ARG('D', OPT_SENDDTMF, OPT_ARG_SENDDTMF),
AST_APP_OPTION('E', OPT_HEARPULSING),
AST_APP_OPTION('e', OPT_PEER_H),
AST_APP_OPTION_ARG('f', OPT_FORCECLID, OPT_ARG_FORCECLID),
AST_APP_OPTION_ARG('F', OPT_CALLEE_GO_ON, OPT_ARG_CALLEE_GO_ON),
@ -930,7 +964,7 @@ static const char *get_cid_name(char *name, int namelen, struct ast_channel *cha
* XXX this code is highly suspicious, as it essentially overwrites
* the outgoing channel without properly deleting it.
*
* \todo eventually this function should be intergrated into and replaced by ast_call_forward()
* \todo eventually this function should be integrated into and replaced by ast_call_forward()
*/
static void do_forward(struct chanlist *o, struct cause_args *num,
struct ast_flags64 *peerflags, int single, int caller_entertained, int *to,
@ -1146,6 +1180,7 @@ struct privacy_args {
char privcid[256];
char privintro[1024];
char status[256];
int canceled;
};
static void publish_dial_end_event(struct ast_channel *in, struct dial_head *out_chans, struct ast_channel *exception, const char *status)
@ -1167,8 +1202,6 @@ static void publish_dial_end_event(struct ast_channel *in, struct dial_head *out
* \param chan Channel to get connected line updated.
* \param peer Channel providing connected line information.
* \param is_caller Non-zero if chan is the calling channel.
*
* \return Nothing
*/
static void update_connected_line_from_peer(struct ast_channel *chan, struct ast_channel *peer, int is_caller)
{
@ -1209,6 +1242,9 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
char *opt_args[],
struct privacy_args *pa,
const struct cause_args *num_in, int *result, char *dtmf_progress,
char *mf_progress, char *mf_wink,
char *sf_progress, char *sf_wink,
const int hearpulsing,
const int ignore_cc,
struct ast_party_id *forced_clid, struct ast_party_id *stored_clid,
struct ast_bridge_config *config)
@ -1228,7 +1264,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
int cc_frame_received = 0;
int num_ringing = 0;
int sent_ring = 0;
int sent_progress = 0;
int sent_progress = 0, sent_wink = 0;
struct timeval start = ast_tvnow();
SCOPE_ENTER(3, "%s\n", ast_channel_name(in));
@ -1289,7 +1325,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
if (is_cc_recall) {
ast_cc_failed(cc_recall_core_id, "Everyone is busy/congested for the recall. How sad");
}
SCOPE_EXIT_RTN_VALUE(NULL, "%s: No outging channels available\n", ast_channel_name(in));
SCOPE_EXIT_RTN_VALUE(NULL, "%s: No outgoing channels available\n", ast_channel_name(in));
}
winner = ast_waitfor_n(watchers, pos, to);
AST_LIST_TRAVERSE(out_chans, o, node) {
@ -1566,6 +1602,22 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_channel_unlock(in);
sent_progress = 1;
if (!ast_strlen_zero(mf_progress)) {
ast_verb(3,
"Sending MF '%s' to %s as result of "
"receiving a PROGRESS message.\n",
mf_progress, hearpulsing ? "parties" : "called party");
ast_mf_stream(c, (hearpulsing ? NULL : in),
(hearpulsing ? in : NULL), mf_progress, 50, 55, 120, 65, 0);
}
if (!ast_strlen_zero(sf_progress)) {
ast_verb(3,
"Sending SF '%s' to %s as result of "
"receiving a PROGRESS message.\n",
sf_progress, (hearpulsing ? "parties" : "called party"));
ast_sf_stream(c, (hearpulsing ? NULL : in),
(hearpulsing ? in : NULL), sf_progress, 0, 0);
}
if (!ast_strlen_zero(dtmf_progress)) {
ast_verb(3,
"Sending DTMF '%s' to the called party as result of "
@ -1576,6 +1628,29 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
}
ast_channel_publish_dial(in, c, NULL, "PROGRESS");
break;
case AST_CONTROL_WINK:
ast_verb(3, "%s winked, passing it to %s\n", ast_channel_name(c), ast_channel_name(in));
if (!sent_wink) {
sent_wink = 1;
if (!ast_strlen_zero(mf_wink)) {
ast_verb(3,
"Sending MF '%s' to %s as result of "
"receiving a WINK message.\n",
mf_wink, (hearpulsing ? "parties" : "called party"));
ast_mf_stream(c, (hearpulsing ? NULL : in),
(hearpulsing ? in : NULL), mf_wink, 50, 55, 120, 65, 0);
}
if (!ast_strlen_zero(sf_wink)) {
ast_verb(3,
"Sending SF '%s' to %s as result of "
"receiving a WINK message.\n",
sf_wink, (hearpulsing ? "parties" : "called party"));
ast_sf_stream(c, (hearpulsing ? NULL : in),
(hearpulsing ? in : NULL), sf_wink, 0, 0);
}
}
ast_indicate(in, AST_CONTROL_WINK);
break;
case AST_CONTROL_VIDUPDATE:
case AST_CONTROL_SRCUPDATE:
case AST_CONTROL_SRCCHANGE:
@ -1720,6 +1795,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
/* Got hung up */
*to = -1;
strcpy(pa->status, "CANCEL");
pa->canceled = 1;
publish_dial_end_event(in, out_chans, NULL, pa->status);
if (f) {
if (f->data.uint32) {
@ -1744,6 +1820,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
*to = 0;
*result = f->subclass.integer;
strcpy(pa->status, "CANCEL");
pa->canceled = 1;
publish_dial_end_event(in, out_chans, NULL, pa->status);
ast_frfree(f);
ast_channel_unlock(in);
@ -1761,6 +1838,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_verb(3, "User requested call disconnect.\n");
*to = 0;
strcpy(pa->status, "CANCEL");
pa->canceled = 1;
publish_dial_end_event(in, out_chans, NULL, pa->status);
ast_frfree(f);
if (is_cc_recall) {
@ -1815,6 +1893,10 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
ast_verb(3, "Call on %s left from hold\n", ast_channel_name(o->chan));
ast_indicate(o->chan, AST_CONTROL_UNHOLD);
break;
case AST_CONTROL_FLASH:
ast_verb(3, "Hook flash on %s\n", ast_channel_name(o->chan));
ast_indicate(o->chan, AST_CONTROL_FLASH);
break;
case AST_CONTROL_VIDUPDATE:
case AST_CONTROL_SRCUPDATE:
case AST_CONTROL_SRCCHANGE:
@ -2130,9 +2212,7 @@ static int setup_privacy_args(struct privacy_args *pa,
/* the file doesn't exist yet. Let the caller submit his
vocal intro for posterity */
/* priv-recordintro script:
"At the tone, please say your name:"
*/
int silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
ast_answer(chan);
@ -2210,8 +2290,6 @@ static int dial_handle_playtones(struct ast_channel *chan, const char *data)
* \param peer Peer channel for bridge.
* \param opts Dialing option flags.
* \param opt_args Dialing option argument strings.
*
* \return Nothing
*/
static void setup_peer_after_bridge_goto(struct ast_channel *chan, struct ast_channel *peer, struct ast_flags64 *opts, char *opt_args[])
{
@ -2245,15 +2323,18 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
struct ast_channel *peer = NULL;
int to; /* timeout */
struct cause_args num = { chan, 0, 0, 0 };
int cause;
int cause, hanguptreecause = -1;
struct ast_bridge_config config = { { 0, } };
struct timeval calldurationlimit = { 0, };
char *dtmfcalled = NULL, *dtmfcalling = NULL, *dtmf_progress=NULL;
char *dtmfcalled = NULL, *dtmfcalling = NULL, *dtmf_progress = NULL;
char *mf_progress = NULL, *mf_wink = NULL;
char *sf_progress = NULL, *sf_wink = NULL;
struct privacy_args pa = {
.sentringing = 0,
.privdb_val = 0,
.status = "INVALIDARGS",
.canceled = 0,
};
int sentringing = 0, moh = 0;
const char *outbound_group = NULL;
@ -2384,9 +2465,13 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
}
if (ast_test_flag64(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) {
dtmf_progress = opt_args[OPT_ARG_SENDDTMF];
dtmfcalled = strsep(&dtmf_progress, ":");
dtmfcalling = strsep(&dtmf_progress, ":");
sf_wink = opt_args[OPT_ARG_SENDDTMF];
dtmfcalled = strsep(&sf_wink, ":");
dtmfcalling = strsep(&sf_wink, ":");
dtmf_progress = strsep(&sf_wink, ":");
mf_progress = strsep(&sf_wink, ":");
mf_wink = strsep(&sf_wink, ":");
sf_progress = strsep(&sf_wink, ":");
}
if (ast_test_flag64(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
@ -2527,9 +2612,11 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
struct ast_channel *tc; /* channel for this destination */
char *number;
char *tech;
int i;
size_t tech_len;
size_t number_len;
struct ast_stream_topology *topology;
struct ast_stream *stream;
cur = ast_strip(cur);
if (ast_strlen_zero(cur)) {
@ -2595,13 +2682,29 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
ast_channel_unlock(chan);
for (i = 0; i < ast_stream_topology_get_count(topology); ++i) {
stream = ast_stream_topology_get_stream(topology, i);
/* For both recvonly and sendonly the stream state reflects our state, that is we
* are receiving only and we are sending only. Since we are requesting a
* channel for the peer, we need to swap this to reflect what we will be doing.
* That is, if we are receiving from Alice then we want to be sending to Bob,
* so swap recvonly to sendonly and vice versa.
*/
if (ast_stream_get_state(stream) == AST_STREAM_STATE_RECVONLY) {
ast_stream_set_state(stream, AST_STREAM_STATE_SENDONLY);
} else if (ast_stream_get_state(stream) == AST_STREAM_STATE_SENDONLY) {
ast_stream_set_state(stream, AST_STREAM_STATE_RECVONLY);
}
}
tc = ast_request_with_stream_topology(tmp->tech, topology, NULL, chan, tmp->number, &cause);
ast_stream_topology_free(topology);
if (!tc) {
/* If we can't, just go on to the next call */
ast_log(LOG_WARNING, "Unable to create channel of type '%s' (cause %d - %s)\n",
/* Failure doesn't necessarily mean user error. DAHDI channels could be busy. */
ast_log(LOG_NOTICE, "Unable to create channel of type '%s' (cause %d - %s)\n",
tmp->tech, cause, ast_cause2str(cause));
handle_cause(cause, &num);
if (!rest) {
@ -2739,7 +2842,9 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
AST_LIST_INSERT_TAIL(&out_chans, tmp, node);
}
if (AST_LIST_EMPTY(&out_chans)) {
/* As long as we attempted to dial valid peers, don't throw a warning. */
/* If a DAHDI peer is busy, out_chans will be empty so checking list size is misleading. */
if (!num_dialed) {
ast_verb(3, "No devices or endpoints to dial (technology/resource)\n");
if (continue_exec) {
/* There is no point in having RetryDial try again */
@ -2863,7 +2968,9 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
}
peer = wait_for_answer(chan, &out_chans, &to, peerflags, opt_args, &pa, &num, &result,
dtmf_progress, ignore_cc, &forced_clid, &stored_clid, &config);
dtmf_progress, mf_progress, mf_wink, sf_progress, sf_wink,
(ast_test_flag64(&opts, OPT_HEARPULSING) ? 1 : 0),
ignore_cc, &forced_clid, &stored_clid, &config);
if (!peer) {
if (result) {
@ -3354,11 +3461,16 @@ out:
}
ast_channel_early_bridge(chan, NULL);
/* forward 'answered elsewhere' if we received it */
hanguptree(&out_chans, NULL,
ast_channel_hangupcause(chan) == AST_CAUSE_ANSWERED_ELSEWHERE
|| ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE)
? AST_CAUSE_ANSWERED_ELSEWHERE : -1);
/* forward 'answered elsewhere' if we received it */
if (ast_channel_hangupcause(chan) == AST_CAUSE_ANSWERED_ELSEWHERE || ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE)) {
hanguptreecause = AST_CAUSE_ANSWERED_ELSEWHERE;
} else if (pa.canceled) { /* Caller canceled */
if (ast_channel_hangupcause(chan))
hanguptreecause = ast_channel_hangupcause(chan);
else
hanguptreecause = AST_CAUSE_NORMAL_CLEARING;
}
hanguptree(&out_chans, NULL, hanguptreecause);
pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status);

View File

@ -361,7 +361,6 @@ static int disa_exec(struct ast_channel *chan, const char *data)
if (k == 3) {
int recheck = 0;
struct ast_app *app_reset_cdr;
if (!ast_exists_extension(chan, args.context, exten, 1,
S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
@ -386,10 +385,7 @@ static int disa_exec(struct ast_channel *chan, const char *data)
ast_channel_unlock(chan);
}
app_reset_cdr = pbx_findapp("ResetCDR");
if (app_reset_cdr) {
pbx_exec(chan, app_reset_cdr, special_noanswer ? "" : "e");
} else {
if (ast_pbx_exec_application(chan, "ResetCDR", special_noanswer ? "" : "e")) {
ast_log(AST_LOG_NOTICE, "ResetCDR application not found; CDR will not be reset\n");
}
ast_explicit_goto(chan, args.context, exten, 1);

297
apps/app_dtmfstore.c Normal file
View File

@ -0,0 +1,297 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2021, Naveen Albert
*
* Naveen Albert <asterisk@phreaknet.org>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Technology independent asynchronous DTMF collection
*
* \author Naveen Albert <asterisk@phreaknet.org>
*
* \ingroup functions
*
*/
/*** MODULEINFO
<support_level>extended</support_level>
***/
#include "asterisk.h"
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/framehook.h"
#include "asterisk/app.h"
#include "asterisk/conversions.h"
/*** DOCUMENTATION
<application name="StoreDTMF" language="en_US">
<since>
<version>16.20.0</version>
<version>18.6.0</version>
<version>19.0.0</version>
</since>
<synopsis>
Stores DTMF digits transmitted or received on a channel.
</synopsis>
<syntax>
<parameter name="direction" required="true">
<para>Must be <literal>TX</literal> or <literal>RX</literal> to
store digits, or <literal>remove</literal> to disable.</para>
</parameter>
</syntax>
<description>
<para>The StoreDTMF function can be used to obtain digits sent in the
<literal>TX</literal> or <literal>RX</literal> direction of any channel.</para>
<para>The arguments are:</para>
<para><replaceable>var_name</replaceable>: Name of variable to which to append
digits.</para>
<para><replaceable>max_digits</replaceable>: The maximum number of digits to
store in the variable. Defaults to 0 (no maximum). After reading <literal>
maximum</literal> digits, no more digits will be stored.</para>
<example title="Store digits in CDR variable">
same => n,StoreDTMF(TX,CDR(digits))
</example>
<example title="Store up to 24 digits">
same => n,StoreDTMF(RX,testvar,24)
</example>
<example title="Disable digit collection">
same => n,StoreDTMF(remove)
</example>
</description>
</application>
***/
static char *app = "StoreDTMF";
/*! \brief Private data structure used with the function's datastore */
struct dtmf_store_data {
int framehook_id;
char *rx_var;
char *tx_var;
int maxdigits;
};
static void datastore_destroy_cb(void *data) {
struct dtmf_store_data *d;
d = data;
if (d) {
if (d->rx_var) {
ast_free(d->rx_var);
}
if (d->tx_var) {
ast_free(d->tx_var);
}
ast_free(data);
}
}
/*! \brief The channel datastore the function uses to store state */
static const struct ast_datastore_info dtmf_store_datastore = {
.type = "dtmf_store",
.destroy = datastore_destroy_cb
};
/*! \internal \brief Store digits tx/rx on the channel */
static int remove_dtmf_store(struct ast_channel *chan)
{
struct ast_datastore *datastore = NULL;
struct dtmf_store_data *data;
SCOPED_CHANNELLOCK(chan_lock, chan);
datastore = ast_channel_datastore_find(chan, &dtmf_store_datastore, NULL);
if (!datastore) {
ast_log(AST_LOG_WARNING, "Cannot remove StoreDTMF from %s: StoreDTMF not currently enabled\n",
ast_channel_name(chan));
return -1;
}
data = datastore->data;
if (ast_framehook_detach(chan, data->framehook_id)) {
ast_log(AST_LOG_WARNING, "Failed to remove StoreDTMF framehook from channel %s\n",
ast_channel_name(chan));
return -1;
}
if (ast_channel_datastore_remove(chan, datastore)) {
ast_log(AST_LOG_WARNING, "Failed to remove StoreDTMF datastore from channel %s\n",
ast_channel_name(chan));
return -1;
}
ast_datastore_free(datastore);
return 0;
}
/*! \brief Frame hook that is called to intercept digit/undigit */
static struct ast_frame *dtmf_store_framehook(struct ast_channel *chan,
struct ast_frame *f, enum ast_framehook_event event, void *data)
{
char currentdata[512];
char varnamesub[64];
char *varname = NULL;
struct dtmf_store_data *framedata = data;
int len;
if (!f || !framedata) {
return f;
}
if ((event != AST_FRAMEHOOK_EVENT_WRITE) && (event != AST_FRAMEHOOK_EVENT_READ)) {
return f;
}
if (f->frametype != AST_FRAME_DTMF_END) {
return f;
}
/* If this is DTMF then store the digits */
if (event == AST_FRAMEHOOK_EVENT_READ && framedata->rx_var) { /* coming from source */
varname = framedata->rx_var;
} else if (event == AST_FRAMEHOOK_EVENT_WRITE && framedata->tx_var) { /* going to source */
varname = framedata->tx_var;
}
if (!varname) {
return f;
}
sprintf(varnamesub, "${%s}", varname);
pbx_substitute_variables_helper(chan, varnamesub, currentdata, 511);
/* pbx_builtin_getvar_helper works for regular vars but not CDR vars */
if (ast_strlen_zero(currentdata)) { /* var doesn't exist yet */
ast_debug(3, "Creating new digit store: %s\n", varname);
}
len = strlen(currentdata);
if (framedata->maxdigits > 0 && len >= framedata->maxdigits) {
ast_debug(3, "Reached digit limit: %d\n", framedata->maxdigits);
remove_dtmf_store(chan); /* reached max digit count, stop now */
return f;
} else {
char newdata[len + 2]; /* one more char + terminator */
if (len > 0) {
ast_copy_string(newdata, currentdata, len + 2);
}
newdata[len] = (unsigned) f->subclass.integer;
newdata[len + 1] = '\0';
ast_debug(3, "Appending to digit store: now %s\n", newdata);
pbx_builtin_setvar_helper(chan, varname, newdata);
}
return f;
}
/*! \internal \brief Enable digit interception on the channel */
static int dtmfstore_exec(struct ast_channel *chan, const char *appdata)
{
struct ast_datastore *datastore;
struct dtmf_store_data *data;
static struct ast_framehook_interface digit_framehook_interface = {
.version = AST_FRAMEHOOK_INTERFACE_VERSION,
.event_cb = dtmf_store_framehook,
.disable_inheritance = 1,
};
char *parse = ast_strdupa(appdata);
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(direction);
AST_APP_ARG(varname);
AST_APP_ARG(maxdigits);
);
SCOPED_CHANNELLOCK(chan_lock, chan);
AST_STANDARD_APP_ARGS(args, parse);
if (ast_strlen_zero(appdata)) {
ast_log(AST_LOG_WARNING, "StoreDTMF requires an argument\n");
return -1;
}
if (!strcasecmp(args.direction, "remove")) {
return remove_dtmf_store(chan);
}
datastore = ast_channel_datastore_find(chan, &dtmf_store_datastore, NULL);
if (datastore) {
ast_log(AST_LOG_WARNING, "StoreDTMF already set on '%s'\n",
ast_channel_name(chan));
return 0;
}
datastore = ast_datastore_alloc(&dtmf_store_datastore, NULL);
if (!datastore) {
return -1;
}
data = ast_calloc(1, sizeof(*data));
if (!data) {
ast_datastore_free(datastore);
return -1;
}
digit_framehook_interface.data = data;
data->rx_var = NULL;
data->tx_var = NULL;
data->maxdigits = 0;
if (!strcasecmp(args.direction, "tx")) {
data->tx_var = ast_strdup(args.varname);
} else if (!strcasecmp(args.direction, "rx")) {
data->rx_var = ast_strdup(args.varname);
} else {
ast_log(LOG_ERROR, "Direction must be either RX or TX\n");
return -1;
}
if (!ast_strlen_zero(args.maxdigits)) {
if (ast_str_to_int(args.maxdigits,&(data->maxdigits))) {
ast_log(LOG_ERROR, "Invalid integer: %s\n", args.maxdigits);
return -1;
}
if (data->maxdigits < 0) {
ast_log(LOG_ERROR, "Invalid natural number: %d\n", data->maxdigits);
return -1;
} else if (data->maxdigits == 0) {
ast_log(LOG_WARNING, "No maximum digit count set\n");
}
}
data->framehook_id = ast_framehook_attach(chan, &digit_framehook_interface);
if (data->framehook_id < 0) {
ast_log(AST_LOG_WARNING, "Failed to attach StoreDTMF framehook to '%s'\n",
ast_channel_name(chan));
ast_datastore_free(datastore);
ast_free(data);
return -1;
}
datastore->data = data;
ast_channel_datastore_add(chan, datastore);
return 0;
}
static int unload_module(void)
{
return ast_unregister_application(app);
}
static int load_module(void)
{
return ast_register_application_xml(app, dtmfstore_exec);
}
AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "Technology independent async DTMF storage");

View File

@ -254,9 +254,9 @@ static struct ast_frame *gen_readframe(struct gen_state *state)
if (!(state->stream && (f = ast_readframe(state->stream)))) {
if (state->current) {
/* remove finished file from playlist */
AST_LIST_LOCK(&u->playlist);
AST_LIST_REMOVE_HEAD(&u->playlist, list);
AST_LIST_UNLOCK(&u->playlist);
AST_LIST_LOCK(&u->playlist);
AST_LIST_REMOVE_HEAD(&u->playlist, list);
AST_LIST_UNLOCK(&u->playlist);
/* add finished file to finishlist */
AST_LIST_LOCK(&u->finishlist);
AST_LIST_INSERT_TAIL(&u->finishlist, state->current, list);
@ -581,7 +581,7 @@ static int app_exec(struct ast_channel *chan, const char *data)
}
}
exit:
exit:
if (u->gen_active) {
ast_deactivate_generator(chan);
}
@ -622,21 +622,21 @@ static int app_exec(struct ast_channel *chan, const char *data)
}
static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u,
struct ast_iostream *eivr_events,
struct ast_iostream *eivr_commands,
struct ast_iostream *eivr_errors,
const struct ast_str *args, const struct ast_flags flags)
struct ast_iostream *eivr_events,
struct ast_iostream *eivr_commands,
struct ast_iostream *eivr_errors,
const struct ast_str *args, const struct ast_flags flags)
{
char input[1024];
struct playlist_entry *entry;
struct ast_frame *f;
int ms;
int exception;
int ready_fd;
int exception;
int ready_fd;
int waitfds[2];
int r;
struct ast_channel *rchan;
int res = -1;
struct ast_channel *rchan;
int res = -1;
int hangup_info_sent = 0;
waitfds[0] = ast_iostream_get_fd(eivr_commands);
@ -645,78 +645,78 @@ static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u,
while (1) {
if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_ZOMBIE)) {
ast_chan_log(LOG_ERROR, chan, "Is a zombie\n");
break;
}
if (!hangup_info_sent && !(ast_test_flag(&flags, run_dead)) && ast_check_hangup(chan)) {
break;
}
if (!hangup_info_sent && !(ast_test_flag(&flags, run_dead)) && ast_check_hangup(chan)) {
if (ast_test_flag(&flags, ignore_hangup)) {
ast_verb(3, "Got check_hangup, but ignore_hangup set so sending 'I' command\n");
send_eivr_event(eivr_events, 'I', "HANGUP", chan);
hangup_info_sent = 1;
} else {
ast_verb(3, "Got check_hangup\n");
send_eivr_event(eivr_events, 'H', NULL, chan);
break;
ast_verb(3, "Got check_hangup\n");
send_eivr_event(eivr_events, 'H', NULL, chan);
break;
}
}
}
ready_fd = 0;
ms = 100;
errno = 0;
exception = 0;
ready_fd = 0;
ms = 100;
errno = 0;
exception = 0;
rchan = ast_waitfor_nandfds(&chan, 1, waitfds, (eivr_errors) ? 2 : 1, &exception, &ready_fd, &ms);
if (ast_channel_state(chan) == AST_STATE_UP && !AST_LIST_EMPTY(&u->finishlist)) {
AST_LIST_LOCK(&u->finishlist);
while ((entry = AST_LIST_REMOVE_HEAD(&u->finishlist, list))) {
send_eivr_event(eivr_events, 'F', entry->filename, chan);
ast_free(entry);
}
AST_LIST_UNLOCK(&u->finishlist);
}
if (ast_channel_state(chan) == AST_STATE_UP && !AST_LIST_EMPTY(&u->finishlist)) {
AST_LIST_LOCK(&u->finishlist);
while ((entry = AST_LIST_REMOVE_HEAD(&u->finishlist, list))) {
send_eivr_event(eivr_events, 'F', entry->filename, chan);
ast_free(entry);
}
AST_LIST_UNLOCK(&u->finishlist);
}
if (ast_channel_state(chan) == AST_STATE_UP && !(ast_check_hangup(chan)) && rchan) {
/* the channel has something */
f = ast_read(chan);
if (!f) {
ast_verb(3, "Returned no frame\n");
send_eivr_event(eivr_events, 'H', NULL, chan);
break;
}
if (f->frametype == AST_FRAME_DTMF) {
send_eivr_event(eivr_events, f->subclass.integer, NULL, chan);
if (u->option_autoclear) {
AST_LIST_LOCK(&u->playlist);
if (!u->abort_current_sound && !u->playing_silence) {
if (ast_channel_state(chan) == AST_STATE_UP && !(ast_check_hangup(chan)) && rchan) {
/* the channel has something */
f = ast_read(chan);
if (!f) {
ast_verb(3, "Returned no frame\n");
send_eivr_event(eivr_events, 'H', NULL, chan);
break;
}
if (f->frametype == AST_FRAME_DTMF) {
send_eivr_event(eivr_events, f->subclass.integer, NULL, chan);
if (u->option_autoclear) {
AST_LIST_LOCK(&u->playlist);
if (!u->abort_current_sound && !u->playing_silence) {
/* send interrupted file as T data */
if ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
send_eivr_event(eivr_events, 'T', entry->filename, chan);
if ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
send_eivr_event(eivr_events, 'T', entry->filename, chan);
ast_free(entry);
}
}
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
send_eivr_event(eivr_events, 'D', entry->filename, chan);
ast_free(entry);
}
if (!u->playing_silence)
u->abort_current_sound = 1;
AST_LIST_UNLOCK(&u->playlist);
}
} else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_HANGUP)) {
ast_verb(3, "Got AST_CONTROL_HANGUP\n");
send_eivr_event(eivr_events, 'H', NULL, chan);
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
send_eivr_event(eivr_events, 'D', entry->filename, chan);
ast_free(entry);
}
if (!u->playing_silence)
u->abort_current_sound = 1;
AST_LIST_UNLOCK(&u->playlist);
}
} else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_HANGUP)) {
ast_verb(3, "Got AST_CONTROL_HANGUP\n");
send_eivr_event(eivr_events, 'H', NULL, chan);
if (f->data.uint32) {
ast_channel_hangupcause_set(chan, f->data.uint32);
}
ast_frfree(f);
break;
}
ast_frfree(f);
} else if (ready_fd == waitfds[0]) {
if (exception) {
ast_chan_log(LOG_ERROR, chan, "Child process went away\n");
break;
}
ast_frfree(f);
break;
}
ast_frfree(f);
} else if (ready_fd == waitfds[0]) {
if (exception) {
ast_chan_log(LOG_ERROR, chan, "Child process went away\n");
break;
}
r = ast_iostream_gets(eivr_commands, input, sizeof(input));
if (r <= 0) {
@ -784,112 +784,112 @@ static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u,
u->abort_current_sound = 1;
}
AST_LIST_UNLOCK(&u->playlist);
} else if (input[0] == EIVR_CMD_SQUE) {
} else if (input[0] == EIVR_CMD_SQUE) {
if (ast_channel_state(chan) != AST_STATE_UP || ast_check_hangup(chan)) {
ast_chan_log(LOG_WARNING, chan, "Queue re'S'et called on unanswered channel\n");
send_eivr_event(eivr_events, 'Z', NULL, chan);
continue;
}
if (!ast_fileexists(&input[2], NULL, ast_channel_language(u->chan))) {
ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
send_eivr_event(eivr_events, 'Z', &input[2], chan);
} else {
AST_LIST_LOCK(&u->playlist);
if (!u->abort_current_sound && !u->playing_silence) {
if (!ast_fileexists(&input[2], NULL, ast_channel_language(u->chan))) {
ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
send_eivr_event(eivr_events, 'Z', &input[2], chan);
} else {
AST_LIST_LOCK(&u->playlist);
if (!u->abort_current_sound && !u->playing_silence) {
/* send interrupted file as T data */
if ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
send_eivr_event(eivr_events, 'T', entry->filename, chan);
if ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
send_eivr_event(eivr_events, 'T', entry->filename, chan);
ast_free(entry);
}
}
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
send_eivr_event(eivr_events, 'D', entry->filename, chan);
ast_free(entry);
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
send_eivr_event(eivr_events, 'D', entry->filename, chan);
ast_free(entry);
}
if (!u->playing_silence) {
u->abort_current_sound = 1;
if (!u->playing_silence) {
u->abort_current_sound = 1;
}
entry = make_entry(&input[2]);
if (entry) {
AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
entry = make_entry(&input[2]);
if (entry) {
AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
}
AST_LIST_UNLOCK(&u->playlist);
AST_LIST_UNLOCK(&u->playlist);
}
} else if (input[0] == EIVR_CMD_APND) {
} else if (input[0] == EIVR_CMD_APND) {
if (ast_channel_state(chan) != AST_STATE_UP || ast_check_hangup(chan)) {
ast_chan_log(LOG_WARNING, chan, "Queue 'A'ppend called on unanswered channel\n");
send_eivr_event(eivr_events, 'Z', NULL, chan);
continue;
}
if (!ast_fileexists(&input[2], NULL, ast_channel_language(u->chan))) {
ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
send_eivr_event(eivr_events, 'Z', &input[2], chan);
} else {
entry = make_entry(&input[2]);
if (entry) {
AST_LIST_LOCK(&u->playlist);
AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
AST_LIST_UNLOCK(&u->playlist);
if (!ast_fileexists(&input[2], NULL, ast_channel_language(u->chan))) {
ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
send_eivr_event(eivr_events, 'Z', &input[2], chan);
} else {
entry = make_entry(&input[2]);
if (entry) {
AST_LIST_LOCK(&u->playlist);
AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
AST_LIST_UNLOCK(&u->playlist);
}
}
} else if (input[0] == EIVR_CMD_GET) {
char response[2048];
}
} else if (input[0] == EIVR_CMD_GET) {
char response[2048];
ast_verb(4, "Retriving Variables from channel: %s\n", &input[2]);
ast_eivr_getvariable(chan, &input[2], response, sizeof(response));
send_eivr_event(eivr_events, 'G', response, chan);
} else if (input[0] == EIVR_CMD_SVAR) {
ast_eivr_getvariable(chan, &input[2], response, sizeof(response));
send_eivr_event(eivr_events, 'G', response, chan);
} else if (input[0] == EIVR_CMD_SVAR) {
ast_verb(4, "Setting Variables in channel: %s\n", &input[2]);
ast_eivr_setvariable(chan, &input[2]);
} else if (input[0] == EIVR_CMD_LOG) {
ast_chan_log(LOG_NOTICE, chan, "Log message from EIVR: %s\n", &input[2]);
} else if (input[0] == EIVR_CMD_XIT) {
ast_chan_log(LOG_NOTICE, chan, "Exiting: %s\n", &input[2]);
ast_eivr_setvariable(chan, &input[2]);
} else if (input[0] == EIVR_CMD_LOG) {
ast_chan_log(LOG_NOTICE, chan, "Log message from EIVR: %s\n", &input[2]);
} else if (input[0] == EIVR_CMD_XIT) {
ast_chan_log(LOG_NOTICE, chan, "Exiting: %s\n", &input[2]);
ast_chan_log(LOG_WARNING, chan, "e'X'it command is depricated, use 'E'xit instead\n");
res = 0;
break;
res = 0;
break;
} else if (input[0] == EIVR_CMD_EXIT) {
ast_chan_log(LOG_NOTICE, chan, "Exiting: %s\n", &input[2]);
send_eivr_event(eivr_events, 'E', NULL, chan);
res = 0;
break;
} else if (input[0] == EIVR_CMD_HGUP) {
ast_chan_log(LOG_NOTICE, chan, "Hanging up: %s\n", &input[2]);
send_eivr_event(eivr_events, 'H', NULL, chan);
break;
} else if (input[0] == EIVR_CMD_OPT) {
ast_chan_log(LOG_NOTICE, chan, "Exiting: %s\n", &input[2]);
send_eivr_event(eivr_events, 'E', NULL, chan);
res = 0;
break;
} else if (input[0] == EIVR_CMD_HGUP) {
ast_chan_log(LOG_NOTICE, chan, "Hanging up: %s\n", &input[2]);
send_eivr_event(eivr_events, 'H', NULL, chan);
break;
} else if (input[0] == EIVR_CMD_OPT) {
if (ast_channel_state(chan) != AST_STATE_UP || ast_check_hangup(chan)) {
ast_chan_log(LOG_WARNING, chan, "Option called on unanswered channel\n");
send_eivr_event(eivr_events, 'Z', NULL, chan);
continue;
}
if (!strcasecmp(&input[2], "autoclear"))
u->option_autoclear = 1;
else if (!strcasecmp(&input[2], "noautoclear"))
u->option_autoclear = 0;
else
ast_chan_log(LOG_WARNING, chan, "Unknown option requested: %s\n", &input[2]);
}
} else if (ready_fd == waitfds[1]) {
if (exception) {
ast_chan_log(LOG_ERROR, chan, "Child process went away\n");
break;
}
r = ast_iostream_gets(eivr_errors, input, sizeof(input));
if (r > 0) {
ast_chan_log(LOG_NOTICE, chan, "stderr: %s\n", ast_strip(input));
} else if (r == 0) {
ast_chan_log(LOG_ERROR, chan, "Child process went away\n");
break;
if (!strcasecmp(&input[2], "autoclear"))
u->option_autoclear = 1;
else if (!strcasecmp(&input[2], "noautoclear"))
u->option_autoclear = 0;
else
ast_chan_log(LOG_WARNING, chan, "Unknown option requested: %s\n", &input[2]);
}
} else if (ready_fd == waitfds[1]) {
if (exception) {
ast_chan_log(LOG_ERROR, chan, "Child process went away\n");
break;
}
} else if ((ready_fd < 0) && ms) {
if (errno == 0 || errno == EINTR)
continue;
ast_chan_log(LOG_ERROR, chan, "Wait failed (%s)\n", strerror(errno));
break;
}
}
r = ast_iostream_gets(eivr_errors, input, sizeof(input));
if (r > 0) {
ast_chan_log(LOG_NOTICE, chan, "stderr: %s\n", ast_strip(input));
} else if (r == 0) {
ast_chan_log(LOG_ERROR, chan, "Child process went away\n");
break;
}
} else if ((ready_fd < 0) && ms) {
if (errno == 0 || errno == EINTR)
continue;
ast_chan_log(LOG_ERROR, chan, "Wait failed (%s)\n", strerror(errno));
break;
}
}
return res;
}

File diff suppressed because it is too large Load Diff

View File

@ -281,8 +281,6 @@ static int festival_exec(struct ast_channel *chan, const char *vdata)
int usecache;
int res = 0;
struct sockaddr_in serv_addr;
struct hostent *serverhost;
struct ast_hostent ahp;
int fd;
FILE *fs;
const char *host;
@ -398,15 +396,17 @@ static int festival_exec(struct ast_channel *chan, const char *vdata)
if ((serv_addr.sin_addr.s_addr = inet_addr(host)) == -1) {
/* its a name rather than an ipnum */
serverhost = ast_gethostbyname(host, &ahp);
struct ast_sockaddr addr = { {0,} };
if (serverhost == NULL) {
ast_log(LOG_WARNING, "festival_client: gethostbyname failed\n");
if (ast_sockaddr_resolve_first_af(&addr, host, PARSE_PORT_FORBID, AF_INET)) {
ast_log(LOG_WARNING, "festival_client: ast_sockaddr_resolve_first_af() failed\n");
ast_config_destroy(cfg);
close(fd);
return -1;
}
memmove(&serv_addr.sin_addr, serverhost->h_addr, serverhost->h_length);
/* We'll overwrite port and family in a sec */
ast_sockaddr_to_sin(&addr, &serv_addr);
}
serv_addr.sin_family = AF_INET;
@ -433,7 +433,7 @@ static int festival_exec(struct ast_channel *chan, const char *vdata)
}
readcache = 0;
writecache = 0;
if (strlen(cachedir) + strlen(MD5Hex) + 1 <= MAXFESTLEN && (usecache == -1)) {
if (strlen(cachedir) + sizeof(MD5Hex) + 1 <= MAXFESTLEN && (usecache == -1)) {
snprintf(cachefile, sizeof(cachefile), "%s/%s", cachedir, MD5Hex);
fdesc = open(cachefile, O_RDWR);
if (fdesc == -1) {

View File

@ -2,7 +2,7 @@
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Anthony Minessale anthmct@yahoo.com
* Development of this app Sponsered/Funded by TAAN Softworks Corp
* Development of this app Sponsored/Funded by TAAN Softworks Corp
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact

View File

@ -1,214 +0,0 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Stream to an icecast server via ICES (see contrib/asterisk-ices.xml)
*
* \author Mark Spencer <markster@digium.com>
*
* ICES - http://www.icecast.org/ices.php
*
* \ingroup applications
*/
/*** MODULEINFO
<support_level>deprecated</support_level>
***/
#include "asterisk.h"
#include <signal.h>
#include <fcntl.h>
#include <sys/time.h>
#include "asterisk/paths.h" /* use ast_config_AST_CONFIG_DIR */
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/frame.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/app.h"
#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="ICES" language="en_US">
<synopsis>
Encode and stream using 'ices'.
</synopsis>
<syntax>
<parameter name="config" required="true">
<para>ICES configuration file.</para>
</parameter>
</syntax>
<description>
<para>Streams to an icecast server using ices (available separately).
A configuration file must be supplied for ices (see contrib/asterisk-ices.xml).</para>
<note><para>ICES version 2 client and server required.</para></note>
</description>
</application>
***/
#define path_BIN "/usr/bin/"
#define path_LOCAL "/usr/local/bin/"
static char *app = "ICES";
static int icesencode(char *filename, int fd)
{
int res;
res = ast_safe_fork(0);
if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n");
if (res) {
return res;
}
if (ast_opt_high_priority)
ast_set_priority(0);
dup2(fd, STDIN_FILENO);
ast_close_fds_above_n(STDERR_FILENO);
/* Most commonly installed in /usr/local/bin
* But many places has it in /usr/bin
* As a last-ditch effort, try to use PATH
*/
execl(path_LOCAL "ices2", "ices", filename, SENTINEL);
execl(path_BIN "ices2", "ices", filename, SENTINEL);
execlp("ices2", "ices", filename, SENTINEL);
ast_debug(1, "Couldn't find ices version 2, attempting to use ices version 1.\n");
execl(path_LOCAL "ices", "ices", filename, SENTINEL);
execl(path_BIN "ices", "ices", filename, SENTINEL);
execlp("ices", "ices", filename, SENTINEL);
ast_log(LOG_WARNING, "Execute of ices failed, could not find command.\n");
close(fd);
_exit(0);
}
static int ices_exec(struct ast_channel *chan, const char *data)
{
int res = 0;
int fds[2];
int ms = -1;
int pid = -1;
struct ast_format *oreadformat;
struct ast_frame *f;
char filename[256]="";
char *c;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n");
return -1;
}
if (pipe(fds)) {
ast_log(LOG_WARNING, "Unable to create pipe\n");
return -1;
}
ast_fd_set_flags(fds[1], O_NONBLOCK);
ast_stopstream(chan);
if (ast_channel_state(chan) != AST_STATE_UP)
res = ast_answer(chan);
if (res) {
close(fds[0]);
close(fds[1]);
ast_log(LOG_WARNING, "Answer failed!\n");
return -1;
}
oreadformat = ao2_bump(ast_channel_readformat(chan));
res = ast_set_read_format(chan, ast_format_slin);
if (res < 0) {
close(fds[0]);
close(fds[1]);
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
ao2_cleanup(oreadformat);
return -1;
}
if (((char *)data)[0] == '/')
ast_copy_string(filename, (char *) data, sizeof(filename));
else
snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_CONFIG_DIR, (char *)data);
/* Placeholder for options */
c = strchr(filename, '|');
if (c)
*c = '\0';
res = icesencode(filename, fds[0]);
if (res >= 0) {
pid = res;
for (;;) {
/* Wait for audio, and stream */
ms = ast_waitfor(chan, -1);
if (ms < 0) {
ast_debug(1, "Hangup detected\n");
res = -1;
break;
}
f = ast_read(chan);
if (!f) {
ast_debug(1, "Null frame == hangup() detected\n");
res = -1;
break;
}
if (f->frametype == AST_FRAME_VOICE) {
res = write(fds[1], f->data.ptr, f->datalen);
if (res < 0) {
if (errno != EAGAIN) {
ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));
res = -1;
ast_frfree(f);
break;
}
}
}
ast_frfree(f);
}
}
close(fds[0]);
close(fds[1]);
if (pid > -1)
kill(pid, SIGKILL);
if (!res && oreadformat)
ast_set_read_format(chan, oreadformat);
ao2_cleanup(oreadformat);
return res;
}
static int unload_module(void)
{
return ast_unregister_application(app);
}
static int load_module(void)
{
return ast_register_application_xml(app, ices_exec);
}
AST_MODULE_INFO_STANDARD_DEPRECATED(ASTERISK_GPL_KEY, "Encode and Stream via icecast and ices");

View File

@ -1,107 +0,0 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief App to transmit an image
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
/*** MODULEINFO
<support_level>deprecated</support_level>
***/
#include "asterisk.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/image.h"
static char *app = "SendImage";
/*** DOCUMENTATION
<application name="SendImage" language="en_US">
<synopsis>
Sends an image file.
</synopsis>
<syntax>
<parameter name="filename" required="true">
<para>Path of the filename (image) to send.</para>
</parameter>
</syntax>
<description>
<para>Send an image file on a channel supporting it.</para>
<para>Result of transmission will be stored in <variable>SENDIMAGESTATUS</variable></para>
<variablelist>
<variable name="SENDIMAGESTATUS">
<value name="SUCCESS">
Transmission succeeded.
</value>
<value name="FAILURE">
Transmission failed.
</value>
<value name="UNSUPPORTED">
Image transmission not supported by channel.
</value>
</variable>
</variablelist>
</description>
<see-also>
<ref type="application">SendText</ref>
<ref type="application">SendURL</ref>
</see-also>
</application>
***/
static int sendimage_exec(struct ast_channel *chan, const char *data)
{
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "SendImage requires an argument (filename)\n");
return -1;
}
if (!ast_supports_images(chan)) {
/* Does not support transport */
pbx_builtin_setvar_helper(chan, "SENDIMAGESTATUS", "UNSUPPORTED");
return 0;
}
if (!ast_send_image(chan, data)) {
pbx_builtin_setvar_helper(chan, "SENDIMAGESTATUS", "SUCCESS");
} else {
pbx_builtin_setvar_helper(chan, "SENDIMAGESTATUS", "FAILURE");
}
return 0;
}
static int unload_module(void)
{
return ast_unregister_application(app);
}
static int load_module(void)
{
return ast_register_application_xml(app, sendimage_exec);
}
AST_MODULE_INFO_STANDARD_DEPRECATED(ASTERISK_GPL_KEY, "Image Transmission Application");

View File

@ -615,8 +615,6 @@ static int queue_voice_frame(struct jack_data *jack_data, struct ast_frame *f)
* Read data from the input ringbuffer, which is the properly resampled audio
* that was read from the jack input port. Write it to the channel in 20 ms frames,
* or fill up an output frame instead if one is provided.
*
* \return Nothing.
*/
static void handle_jack_audio(struct ast_channel *chan, struct jack_data *jack_data,
struct ast_frame *out_frame)

View File

@ -29,6 +29,8 @@
<defaultenabled>no</defaultenabled>
<support_level>deprecated</support_level>
<replacement>app_stack (GoSub)</replacement>
<deprecated_in>16</deprecated_in>
<removed_in>21</removed_in>
***/
#include "asterisk.h"
@ -73,7 +75,7 @@
of nesting (macro calling macro calling macro, etc.); It may be possible that stack-intensive
applications in deeply nested macros could cause asterisk to crash earlier than this limit.
It is advised that if you need to deeply nest macro calls, that you use the Gosub application
(now allows arguments like a Macro) with explict Return() calls instead.</para></warning>
(now allows arguments like a Macro) with explicit Return() calls instead.</para></warning>
<warning><para>Use of the application <literal>WaitExten</literal> within a macro will not function
as expected. Please use the <literal>Read</literal> application in order to read DTMF from a channel
currently executing a macro.</para></warning>

View File

@ -41,8 +41,10 @@
/*** MODULEINFO
<depend>dahdi</depend>
<defaultenabled>no</defaultenabled>
<support_level>extended</support_level>
<support_level>deprecated</support_level>
<replacement>app_confbridge</replacement>
<deprecated_in>19</deprecated_in>
<removed_in>21</removed_in>
***/
#include "asterisk.h"
@ -637,6 +639,82 @@
</syntax>
</managerEventInstance>
</managerEvent>
<managerEvent language="en_US" name="MeetmeList">
<managerEventInstance class="EVENT_FLAG_CALL">
<synopsis>Raised in response to a MeetmeList command.</synopsis>
<syntax>
<parameter name="Conference">
<para>Conference ID.</para>
</parameter>
<parameter name="UserNumber">
<para>User ID.</para>
</parameter>
<parameter name="CallerIDNum">
<para>Caller ID number.</para>
</parameter>
<parameter name="CallerIDName">
<para>Caller ID name.</para>
</parameter>
<parameter name="ConnectedLineNum">
<para>Connected Line number.</para>
</parameter>
<parameter name="ConnectedLineName">
<para>Connected Line name.</para>
</parameter>
<parameter name="Channel">
<para>Channel name</para>
</parameter>
<parameter name="Admin">
<para>Whether or not the user is an admin.</para>
</parameter>
<parameter name="Role">
<para>User role. Can be "Listen only", "Talk only", or "Talk and listen".</para>
</parameter>
<parameter name="MarkedUser">
<para>Whether or not the user is a marked user.</para>
</parameter>
<parameter name="Muted">
<para>Whether or not the user is currently muted.</para>
</parameter>
<parameter name="Talking">
<para>Whether or not the user is currently talking.</para>
</parameter>
</syntax>
<see-also>
<ref type="manager">MeetmeList</ref>
<ref type="application">MeetMe</ref>
</see-also>
</managerEventInstance>
</managerEvent>
<managerEvent language="en_US" name="MeetmeListRooms">
<managerEventInstance class="EVENT_FLAG_CALL">
<synopsis>Raised in response to a MeetmeListRooms command.</synopsis>
<syntax>
<parameter name="Conference">
<para>Conference ID.</para>
</parameter>
<parameter name="Parties">
<para>Number of parties in the conference.</para>
</parameter>
<parameter name="Marked">
<para>Number of marked users in the conference.</para>
</parameter>
<parameter name="Activity">
<para>Total duration of conference in HH:MM:SS format.</para>
</parameter>
<parameter name="Creation">
<para>How the conference was created: "Dyanmic" or "Static".</para>
</parameter>
<parameter name="Locked">
<para>Whether or not the conference is locked.</para>
</parameter>
</syntax>
<see-also>
<ref type="manager">MeetmeListRooms</ref>
<ref type="application">MeetMe</ref>
</see-also>
</managerEventInstance>
</managerEvent>
***/
#define CONFIG_FILE_NAME "meetme.conf"
@ -1334,7 +1412,7 @@ static struct ast_json *status_to_json(int on)
* \brief Generate a stasis message associated with a meetme event
* \since 12.0.0
*
* \param meetme_confere The conference responsible for generating this message
* \param meetme_conference The conference responsible for generating this message
* \param chan The channel involved in the message (NULL allowed)
* \param user The conference user involved in the message (NULL allowed)
* \param message_type the type the stasis message being generated
@ -2834,7 +2912,7 @@ static void meetme_menu_normal(enum menu_modes *menu_mode, int *dtmf, struct ast
}
/*! \internal
* \brief Processes menu options for the adminstrator menu (accessible through the 's' option for app_meetme)
* \brief Processes menu options for the administrator menu (accessible through the 's' option for app_meetme)
*
* \param menu_mode a pointer to the currently active menu_mode.
* \param dtmf a pointer to the dtmf value currently being processed against the menu.
@ -2961,7 +3039,8 @@ static void meetme_menu_admin(enum menu_modes *menu_mode, int *dtmf, struct ast_
* \param confflags flags used by conf for various options
* \param chan ast_channel belonging to the user who called the menu
* \param user which meetme conference user invoked the menu
* \param recordingtmp character buffer which may hold the name of the conference recording file
* \param recordingtmp, recordingtmp_size character buffer which may hold the name of the conference recording file
* \param cap_slin
*/
static void meetme_menu_admin_extended(enum menu_modes *menu_mode, int *dtmf,
struct ast_conference *conf, struct ast_flags64 *confflags, struct ast_channel *chan,
@ -3148,7 +3227,8 @@ static void meetme_menu_admin_extended(enum menu_modes *menu_mode, int *dtmf,
* \param confflags flags used by conf for various options
* \param chan ast_channel belonging to the user who called the menu
* \param user which meetme conference user invoked the menu
* \param recordingtmp character buffer which may hold the name of the conference recording file
* \param recordingtmp,recordingtmp_size character buffer which may hold the name of the conference recording file
* \param cap_slin
*/
static void meetme_menu(enum menu_modes *menu_mode, int *dtmf,
struct ast_conference *conf, struct ast_flags64 *confflags, struct ast_channel *chan,
@ -4757,7 +4837,7 @@ static struct ast_conference *find_conf(struct ast_channel *chan, char *confno,
}
}
if (!var) {
ast_debug(1, "%s isn't a valid conference\n", confno);
ast_log(LOG_WARNING, "%s isn't a valid conference\n", confno);
}
ast_config_destroy(cfg);
}
@ -5219,7 +5299,7 @@ static int user_chan_cb(void *obj, void *args, int flags)
return 0;
}
/*! \brief The MeetMeadmin application
/*! \brief The MeetMeAdmin application
MeetMeAdmin(confno, command, caller) */
static int admin_exec(struct ast_channel *chan, const char *data) {
@ -5235,7 +5315,9 @@ static int admin_exec(struct ast_channel *chan, const char *data) {
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "MeetMeAdmin requires an argument!\n");
pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOPARSE");
if (chan) {
pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOPARSE");
}
return -1;
}
@ -5244,7 +5326,9 @@ static int admin_exec(struct ast_channel *chan, const char *data) {
if (!args.command) {
ast_log(LOG_WARNING, "MeetmeAdmin requires a command!\n");
pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOPARSE");
if (chan) {
pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOPARSE");
}
return -1;
}
@ -5257,7 +5341,9 @@ static int admin_exec(struct ast_channel *chan, const char *data) {
if (!cnf) {
ast_log(LOG_WARNING, "Conference number '%s' not found!\n", args.confno);
AST_LIST_UNLOCK(&confs);
pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOTFOUND");
if (chan) {
pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", "NOTFOUND");
}
return 0;
}
@ -5380,7 +5466,9 @@ usernotfound:
AST_LIST_UNLOCK(&confs);
dispose_conf(cnf);
pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", res == -2 ? "NOTFOUND" : res ? "FAILED" : "OK");
if (chan) {
pbx_builtin_setvar_helper(chan, "MEETMEADMINSTATUS", res == -2 ? "NOTFOUND" : res ? "FAILED" : "OK");
}
return 0;
}
@ -8076,7 +8164,7 @@ static int reload(void)
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "MeetMe conference bridge",
.support_level = AST_MODULE_SUPPORT_EXTENDED,
.support_level = AST_MODULE_SUPPORT_DEPRECATED,
.load = load_module,
.unload = unload_module,
.reload = reload,

546
apps/app_mf.c Normal file
View File

@ -0,0 +1,546 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2021, Naveen Albert
*
* Naveen Albert <asterisk@phreaknet.org>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief MF sender and receiver applications
*
* \author Naveen Albert <asterisk@phreaknet.org>
*
* \ingroup applications
*/
/*** MODULEINFO
<support_level>extended</support_level>
***/
#include "asterisk.h"
#include "asterisk/file.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/app.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/conversions.h"
/*** DOCUMENTATION
<application name="ReceiveMF" language="en_US">
<since>
<version>16.21.0</version>
<version>18.7.0</version>
<version>19.0.0</version>
</since>
<synopsis>
Detects MF digits on a channel and saves them to a variable.
</synopsis>
<syntax>
<parameter name="variable" required="true">
<para>The input digits will be stored in the given
<replaceable>variable</replaceable> name.</para>
</parameter>
<parameter name="timeout">
<para>The number of seconds to wait for all digits, if greater
than <literal>0</literal>. Can be floating point. Default
is no timeout.</para>
</parameter>
<parameter name="options">
<optionlist>
<option name="d">
<para>Delay audio by a frame to try to extra quelch.</para>
</option>
<option name="l">
<para>Receive digits even if a key pulse (KP) has not yet
been received. By default, this application will ignore
all other digits until a KP has been received.</para>
</option>
<option name="k">
<para>Do not return a character for the KP digit.</para>
</option>
<option name="m">
<para>Mute conference.</para>
</option>
<option name="n">
<para>Maximum number of digits, regardless of the sequence.</para>
</option>
<option name="o">
<para>Enable override. Repeated KPs will clear all previous digits.</para>
</option>
<option name="q">
<para>Quelch MF from in-band.</para>
</option>
<option name="r">
<para>"Radio" mode (relaxed MF).</para>
</option>
<option name="s">
<para>Do not return a character for ST digits.</para>
</option>
</optionlist>
</parameter>
</syntax>
<description>
<para>Reads a ST, STP, ST2P, or ST3P-terminated string of MF digits from
the user in to the given <replaceable>variable</replaceable>.</para>
<para>This application does not automatically answer the channel and
should be preceded with <literal>Answer</literal> or
<literal>Progress</literal> as needed.</para>
<variablelist>
<variable name="RECEIVEMFSTATUS">
<para>This is the status of the read operation.</para>
<value name="START" />
<value name="ERROR" />
<value name="HANGUP" />
<value name="MAXDIGITS" />
<value name="TIMEOUT" />
</variable>
</variablelist>
</description>
<see-also>
<ref type="application">Read</ref>
<ref type="application">SendMF</ref>
<ref type="application">ReceiveSF</ref>
</see-also>
</application>
<application name="SendMF" language="en_US">
<since>
<version>16.21.0</version>
<version>18.7.0</version>
<version>19.0.0</version>
</since>
<synopsis>
Sends arbitrary MF digits on the current or specified channel.
</synopsis>
<syntax>
<parameter name="digits" required="true">
<para>List of digits 0-9,*#ABC to send; w for a half-second pause,
also f or F for a flash-hook if the channel supports flash-hook,
h or H for 250 ms of 2600 Hz,
and W for a wink if the channel supports wink.</para>
<para>Key pulse and start digits are not included automatically.
* is used for KP, # for ST, A for STP, B for ST2P, and C for ST3P.</para>
</parameter>
<parameter name="timeout_ms" required="false">
<para>Amount of time to wait in ms between tones. (defaults to 50ms).</para>
</parameter>
<parameter name="duration_ms" required="false">
<para>Duration of each numeric digit (defaults to 55ms).</para>
</parameter>
<parameter name="duration_ms_kp" required="false">
<para>Duration of KP digits (defaults to 120ms).</para>
</parameter>
<parameter name="duration_ms_st" required="false">
<para>Duration of ST, STP, ST2P, and ST3P digits (defaults to 65ms).</para>
</parameter>
<parameter name="channel" required="false">
<para>Channel where digits will be played</para>
</parameter>
</syntax>
<description>
<para>It will send all digits or terminate if it encounters an error.</para>
</description>
<see-also>
<ref type="application">ReceiveMF</ref>
<ref type="application">SendSF</ref>
<ref type="application">SendDTMF</ref>
</see-also>
</application>
<manager name="PlayMF" language="en_US">
<since>
<version>16.21.0</version>
<version>18.7.0</version>
<version>19.0.0</version>
</since>
<synopsis>
Play MF digit on a specific channel.
</synopsis>
<syntax>
<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
<parameter name="Channel" required="true">
<para>Channel name to send digit to.</para>
</parameter>
<parameter name="Digit" required="true">
<para>The MF digit to play.</para>
</parameter>
<parameter name="Duration" required="false">
<para>The duration, in milliseconds, of the digit to be played.</para>
</parameter>
</syntax>
<description>
<para>Plays an MF digit on the specified channel.</para>
</description>
</manager>
***/
enum read_option_flags {
OPT_DELAY = (1 << 0),
OPT_MUTE = (1 << 1),
OPT_QUELCH = (1 << 2),
OPT_RELAXED = (1 << 3),
OPT_LAX_KP = (1 << 4),
OPT_PROCESS = (1 << 5),
OPT_NO_KP = (1 << 6),
OPT_NO_ST = (1 << 7),
OPT_KP_OVERRIDE = (1 << 8),
OPT_MAXDIGITS = (1 << 9),
};
enum {
OPT_ARG_MAXDIGITS,
/* Must be the last element */
OPT_ARG_ARRAY_SIZE,
};
AST_APP_OPTIONS(read_app_options, {
AST_APP_OPTION('d', OPT_DELAY),
AST_APP_OPTION('l', OPT_LAX_KP),
AST_APP_OPTION('k', OPT_NO_KP),
AST_APP_OPTION('m', OPT_MUTE),
AST_APP_OPTION_ARG('n', OPT_MAXDIGITS, OPT_ARG_MAXDIGITS),
AST_APP_OPTION('o', OPT_KP_OVERRIDE),
AST_APP_OPTION('p', OPT_PROCESS),
AST_APP_OPTION('q', OPT_QUELCH),
AST_APP_OPTION('r', OPT_RELAXED),
AST_APP_OPTION('s', OPT_NO_ST),
});
static const char *readmf_name = "ReceiveMF";
static const char sendmf_name[] = "SendMF";
#define MF_BETWEEN_MS 50
#define MF_DURATION 55
#define MF_KP_DURATION 120
#define MF_ST_DURATION 65
/*!
* \brief Detects MF digits on channel using DSP, terminated by ST, STP, ST2P, or ST3P
*
* \param chan channel on which to read digits
* \param buf Buffer in which to store digits
* \param buflen Size of buffer
* \param timeout ms to wait for all digits before giving up
* \param features Any additional DSP features to use
* \param override Start over if we receive additional KPs
* \param no_kp Don't include KP in the output
* \param no_st Don't include start digits in the output
* \param maxdigits If greater than 0, only read this many digits no matter what
*
* \retval 0 if successful
* \retval -1 if unsuccessful (including hangup).
*/
static int read_mf_digits(struct ast_channel *chan, char *buf, int buflen, int timeout, int features, int laxkp, int override, int no_kp, int no_st, int maxdigits) {
struct ast_dsp *dsp;
struct ast_frame *frame = NULL;
struct timeval start;
int remaining_time = timeout;
int digits_read = 0;
int is_start_digit = 0;
char *str = buf;
int res = 0;
if (!(dsp = ast_dsp_new())) {
ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "ERROR");
return -1;
}
ast_dsp_set_features(dsp, DSP_FEATURE_DIGIT_DETECT);
ast_dsp_set_digitmode(dsp, DSP_DIGITMODE_MF | features);
start = ast_tvnow();
*str = 0; /* start with empty output buffer */
/* based on app_read and generic_fax_exec from res_fax */
while (timeout == 0 || remaining_time > 0) {
if (timeout > 0) {
remaining_time = ast_remaining_ms(start, timeout);
if (remaining_time <= 0) {
pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "TIMEOUT");
break;
}
}
if ((maxdigits && digits_read >= maxdigits) || digits_read >= (buflen - 1)) { /* we don't have room to store any more digits (very unlikely to happen for a legitimate reason) */
/* This result will probably not be usable, so status should not be START */
pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "MAXDIGITS");
break;
}
/* ast_waitfordigit only waits for DTMF frames, we need to do DSP on voice frames */
if (ast_waitfor(chan, 1000) > 0) {
frame = ast_read(chan);
if (!frame) {
ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "HANGUP");
break;
} else if (frame->frametype == AST_FRAME_VOICE) {
frame = ast_dsp_process(chan, dsp, frame);
/* AST_FRAME_DTMF is used all over the DSP code for DTMF, MF, fax, etc.
It's used because we can use the frame to store the digit detected.
All this means is that we received something we care about. */
if (frame->frametype == AST_FRAME_DTMF) {
char result = frame->subclass.integer;
if (digits_read == 0 && !laxkp && result != '*') {
ast_debug(1, "Received MF digit, but no KP yet, ignoring: %c\n", result);
ast_frfree(frame);
continue;
}
ast_debug(1, "Received MF digit: %c\n", result);
if (result == '*') {
/* We received an additional KP, start over? */
if (override && digits_read > 0) {
ast_debug(1, "Received another KP, starting over\n");
str = buf;
*str = 0;
digits_read = 1; /* we just detected a KP */
} else {
digits_read++;
}
/* if we were told not to include the KP digit in the output string, then skip it */
if (no_kp) {
ast_frfree(frame);
continue;
}
} else {
digits_read++;
}
is_start_digit = (strchr("#", result) || strchr("A", result) || strchr("B", result) || strchr("C", result));
/* if we were told not to include the ST digit in the output string, then skip it */
if (!no_st || !is_start_digit) {
*str++ = result; /* won't write past allotted memory, because of buffer check at top of loop */
*str = 0;
}
/* we received a ST digit (ST, STP, ST2P, or ST3P), so we're done */
if (is_start_digit) {
pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "START");
ast_frfree(frame);
break;
}
/* only free frame if it was a DSP match. The MF itself should not be muted. */
ast_frfree(frame);
}
}
} else {
pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "HANGUP");
res = -1;
}
}
ast_dsp_free(dsp);
ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
return res;
}
static int read_mf_exec(struct ast_channel *chan, const char *data)
{
#define BUFFER_SIZE 256
char tmp[BUFFER_SIZE] = "";
int to = 0;
double tosec;
struct ast_flags flags = {0};
char *optargs[OPT_ARG_ARRAY_SIZE];
char *argcopy = NULL;
int res, features = 0, maxdigits = 0;
AST_DECLARE_APP_ARGS(arglist,
AST_APP_ARG(variable);
AST_APP_ARG(timeout);
AST_APP_ARG(options);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "ReceiveMF requires an argument (variable)\n");
return -1;
}
argcopy = ast_strdupa(data);
AST_STANDARD_APP_ARGS(arglist, argcopy);
if (!ast_strlen_zero(arglist.options)) {
ast_app_parse_options(read_app_options, &flags, optargs, arglist.options);
}
if (!ast_strlen_zero(arglist.timeout)) {
tosec = atof(arglist.timeout);
if (tosec <= 0) {
to = 0;
} else {
to = tosec * 1000.0;
}
}
if (ast_strlen_zero(arglist.variable)) {
ast_log(LOG_WARNING, "Invalid! Usage: ReceiveMF(variable[,timeout][,option])\n");
return -1;
}
if (ast_test_flag(&flags, OPT_MAXDIGITS) && !ast_strlen_zero(optargs[OPT_ARG_MAXDIGITS])) {
maxdigits = atoi(optargs[OPT_ARG_MAXDIGITS]);
if (maxdigits <= 0) {
ast_log(LOG_WARNING, "Invalid maximum number of digits, ignoring: '%s'\n", optargs[OPT_ARG_MAXDIGITS]);
maxdigits = 0;
}
}
if (ast_test_flag(&flags, OPT_DELAY)) {
features |= DSP_DIGITMODE_MUTEMAX;
}
if (ast_test_flag(&flags, OPT_MUTE)) {
features |= DSP_DIGITMODE_MUTECONF;
}
if (!ast_test_flag(&flags, OPT_QUELCH)) {
features |= DSP_DIGITMODE_NOQUELCH;
}
if (ast_test_flag(&flags, OPT_RELAXED)) {
features |= DSP_DIGITMODE_RELAXDTMF;
}
res = read_mf_digits(chan, tmp, BUFFER_SIZE, to, features, (ast_test_flag(&flags, OPT_LAX_KP)),
(ast_test_flag(&flags, OPT_KP_OVERRIDE)), (ast_test_flag(&flags, OPT_NO_KP)), (ast_test_flag(&flags, OPT_NO_ST)), maxdigits);
pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
if (!ast_strlen_zero(tmp)) {
ast_verb(3, "MF digits received: '%s'\n", tmp);
} else if (!res) { /* if channel hung up, don't print anything out */
ast_verb(3, "No MF digits received.\n");
}
return res;
}
static int sendmf_exec(struct ast_channel *chan, const char *vdata)
{
int res;
char *data;
int dinterval = 0, duration = 0, durationkp = 0, durationst = 0;
struct ast_channel *chan_found = NULL;
struct ast_channel *chan_dest = chan;
struct ast_channel *chan_autoservice = NULL;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(digits);
AST_APP_ARG(dinterval);
AST_APP_ARG(duration);
AST_APP_ARG(durationkp);
AST_APP_ARG(durationst);
AST_APP_ARG(channel);
);
if (ast_strlen_zero(vdata)) {
ast_log(LOG_WARNING, "SendMF requires an argument\n");
return 0;
}
data = ast_strdupa(vdata);
AST_STANDARD_APP_ARGS(args, data);
if (ast_strlen_zero(args.digits)) {
ast_log(LOG_WARNING, "The digits argument is required (0-9,*#ABC,wf)\n");
return 0;
}
if (!ast_strlen_zero(args.dinterval)) {
ast_app_parse_timelen(args.dinterval, &dinterval, TIMELEN_MILLISECONDS);
}
if (!ast_strlen_zero(args.duration)) {
ast_app_parse_timelen(args.duration, &duration, TIMELEN_MILLISECONDS);
}
if (!ast_strlen_zero(args.durationkp)) {
ast_app_parse_timelen(args.durationkp, &durationkp, TIMELEN_MILLISECONDS);
}
if (!ast_strlen_zero(args.durationst)) {
ast_app_parse_timelen(args.durationst, &durationst, TIMELEN_MILLISECONDS);
}
if (!ast_strlen_zero(args.channel)) {
chan_found = ast_channel_get_by_name(args.channel);
if (!chan_found) {
ast_log(LOG_WARNING, "No such channel: %s\n", args.channel);
return 0;
}
chan_dest = chan_found;
if (chan_found != chan) {
chan_autoservice = chan;
}
}
res = ast_mf_stream(chan_dest, chan_autoservice, NULL, args.digits, dinterval <= 0 ? MF_BETWEEN_MS : dinterval,
duration <= 0 ? MF_DURATION : duration, durationkp <= 0 ? MF_KP_DURATION : durationkp,
durationst <= 0 ? MF_ST_DURATION : durationst, 0);
ast_channel_cleanup(chan_found);
return chan_autoservice ? 0 : res;
}
static int manager_play_mf(struct mansession *s, const struct message *m)
{
const char *channel = astman_get_header(m, "Channel");
const char *digit = astman_get_header(m, "Digit");
const char *duration = astman_get_header(m, "Duration");
struct ast_channel *chan;
unsigned int duration_ms = MF_DURATION;
if (!(chan = ast_channel_get_by_name(channel))) {
astman_send_error(s, m, "Channel not found");
return 0;
}
if (ast_strlen_zero(digit)) {
astman_send_error(s, m, "No digit specified");
chan = ast_channel_unref(chan);
return 0;
}
/* Override default duration with KP or ST-specific default durations */
if (!strcmp(digit, "*"))
duration_ms = MF_KP_DURATION;
if (!strcmp(digit, "#") || !strcmp(digit, "A") || !strcmp(digit, "B") || !strcmp(digit, "C"))
duration_ms = MF_ST_DURATION;
if (!ast_strlen_zero(duration) && (sscanf(duration, "%30u", &duration_ms) != 1)) {
astman_send_error(s, m, "Could not convert Duration parameter");
chan = ast_channel_unref(chan);
return 0;
}
ast_mf_stream(chan, NULL, NULL, digit, 0, duration_ms, duration_ms, duration_ms, 1);
chan = ast_channel_unref(chan);
astman_send_ack(s, m, "MF successfully queued");
return 0;
}
static int unload_module(void)
{
int res;
res = ast_unregister_application(readmf_name);
res |= ast_unregister_application(sendmf_name);
res |= ast_manager_unregister("PlayMF");
return res;
}
static int load_module(void)
{
int res;
res = ast_register_application_xml(readmf_name, read_mf_exec);
res |= ast_register_application_xml(sendmf_name, sendmf_exec);
res |= ast_manager_register_xml("PlayMF", EVENT_FLAG_CALL, manager_play_mf);
return res;
}
AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "MF Sender and Receiver Applications");

View File

@ -40,19 +40,29 @@
/*** DOCUMENTATION
<application name="Milliwatt" language="en_US">
<synopsis>
Generate a Constant 1004Hz tone at 0dbm (mu-law).
Generates a 1004 Hz test tone at 0dbm (mu-law).
</synopsis>
<syntax>
<parameter name="options">
<optionlist>
<option name="m">
<para>Generate a 1004 Hz Milliwatt test tone at 0dbm, with a
1 second silent interval. This option must be specified
if you are using this for a milliwatt test line.</para>
</option>
<option name="o">
<para>Generate the tone at 1000Hz like previous version.</para>
<para>Generate a constant tone at 1000 Hz like previous version.</para>
</option>
</optionlist>
</parameter>
</syntax>
<description>
<para>Previous versions of this application generated the tone at 1000Hz. If for
<para>Generates a 1004 Hz test tone.</para>
<para>By default, this application does not provide a Milliwatt test tone. It simply
plays a 1004 Hz tone, which is not suitable for performing a milliwatt test.
The <literal>m</literal> option should be used so that a real Milliwatt test tone
is provided. This will include a 1 second silent interval every 10 seconds.</para>
<para>Previous versions of this application generated a constant tone at 1000 Hz. If for
some reason you would prefer that behavior, supply the <literal>o</literal> option to get the
old behavior.</para>
</description>
@ -155,8 +165,11 @@ static int milliwatt_exec(struct ast_channel *chan, const char *data)
if (!ast_strlen_zero(options) && strchr(options, 'o')) {
return old_milliwatt_exec(chan);
}
res = ast_playtones_start(chan, 23255, "1004/1000", 0);
if (!ast_strlen_zero(options) && strchr(options, 'm')) {
res = ast_playtones_start(chan, 23255, "1004/9000,0/1000", 0);
} else {
res = ast_playtones_start(chan, 23255, "1004/1000", 0);
}
while (!res) {
res = ast_safe_sleep(chan, 10000);

View File

@ -26,7 +26,7 @@
* based on the Comedian Mail voicemail system (app_voicemail.c).
*
* \par See also
* \arg \ref Config_minivm_examples
* \arg \ref minivm.conf "Config_minivm"
* \arg \ref App_minivm
*
* \ingroup applications
@ -78,16 +78,16 @@
* - English, GB en_gb
*
* \par See also
* \arg \ref Config_minivm
* \arg \ref minivm.conf "Config_minivm"
* \arg \ref Config_minivm_examples
* \arg \ref Minivm_directories
* \arg \ref app_minivm.c
* \arg Comedian mail: app_voicemail.c
* \arg \ref descrip_minivm_accmess
* \arg \ref descrip_minivm_greet
* \arg \ref descrip_minivm_record
* \arg \ref descrip_minivm_delete
* \arg \ref descrip_minivm_notify
* \arg \ref minivm_accmess_exec
* \arg \ref minivm_greet_exec
* \arg \ref minivm_record_exec
* \arg \ref minivm_delete_exec
* \arg \ref minivm_notify_exec
*
* \arg \ref App_minivm_todo
*/
@ -113,6 +113,13 @@
* Back: \ref App_minivm
*/
/*!
* \page minivm.conf minivm.conf
* \verbinclude minivm.conf.sample
*
* Back: \ref App_minivm
*/
/*! \page Config_minivm_examples Example dialplan for Mini-Voicemail
* \section Example dialplan scripts for Mini-Voicemail
* \verbinclude extensions_minivm.conf.sample
@ -154,7 +161,6 @@
#include <dirent.h>
#include <locale.h>
#include "asterisk/paths.h" /* use various paths */
#include "asterisk/lock.h"
#include "asterisk/file.h"
@ -535,8 +541,6 @@
#define SENDMAIL "/usr/sbin/sendmail -t"
#define SOUND_INTRO "vm-intro"
#define B64_BASEMAXINLINE 256 /*!< Buffer size for Base 64 attachment encoding */
#define B64_BASELINELEN 72 /*!< Line length for Base 64 endoded messages */
#define EOL "\r\n"
#define MAX_DATETIME_FORMAT 512
@ -652,15 +656,6 @@ struct leave_vm_options {
signed char record_gain;
};
/*! \brief Structure for base64 encoding */
struct b64_baseio {
int iocp;
int iolen;
int linelength;
int ateof;
unsigned char iobuf[B64_BASEMAXINLINE];
};
/*! \brief Voicemail time zones */
struct minivm_zone {
char name[80]; /*!< Name of this time zone */
@ -846,134 +841,6 @@ static void message_destroy_list(void)
AST_LIST_UNLOCK(&message_templates);
}
/*!\internal
* \brief read buffer from file (base64 conversion) */
static int b64_inbuf(struct b64_baseio *bio, FILE *fi)
{
int l;
if (bio->ateof)
return 0;
if ((l = fread(bio->iobuf, 1, B64_BASEMAXINLINE, fi)) != B64_BASEMAXINLINE) {
bio->ateof = 1;
if (l == 0) {
/* Assume EOF */
return 0;
}
}
bio->iolen = l;
bio->iocp = 0;
return 1;
}
/*!\internal
* \brief read character from file to buffer (base64 conversion) */
static int b64_inchar(struct b64_baseio *bio, FILE *fi)
{
if (bio->iocp >= bio->iolen) {
if (!b64_inbuf(bio, fi))
return EOF;
}
return bio->iobuf[bio->iocp++];
}
/*!\internal
* \brief write buffer to file (base64 conversion) */
static int b64_ochar(struct b64_baseio *bio, int c, FILE *so)
{
if (bio->linelength >= B64_BASELINELEN) {
if (fputs(EOL,so) == EOF)
return -1;
bio->linelength= 0;
}
if (putc(((unsigned char) c), so) == EOF)
return -1;
bio->linelength++;
return 1;
}
/*!\internal
* \brief Encode file to base64 encoding for email attachment (base64 conversion) */
static int base_encode(char *filename, FILE *so)
{
unsigned char dtable[B64_BASEMAXINLINE];
int i,hiteof= 0;
FILE *fi;
struct b64_baseio bio;
memset(&bio, 0, sizeof(bio));
bio.iocp = B64_BASEMAXINLINE;
if (!(fi = fopen(filename, "rb"))) {
ast_log(LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
return -1;
}
for (i= 0; i<9; i++) {
dtable[i]= 'A'+i;
dtable[i+9]= 'J'+i;
dtable[26+i]= 'a'+i;
dtable[26+i+9]= 'j'+i;
}
for (i= 0; i < 8; i++) {
dtable[i+18]= 'S'+i;
dtable[26+i+18]= 's'+i;
}
for (i= 0; i < 10; i++) {
dtable[52+i]= '0'+i;
}
dtable[62]= '+';
dtable[63]= '/';
while (!hiteof){
unsigned char igroup[3], ogroup[4];
int c,n;
igroup[0]= igroup[1]= igroup[2]= 0;
for (n= 0; n < 3; n++) {
if ((c = b64_inchar(&bio, fi)) == EOF) {
hiteof= 1;
break;
}
igroup[n]= (unsigned char)c;
}
if (n> 0) {
ogroup[0]= dtable[igroup[0]>>2];
ogroup[1]= dtable[((igroup[0]&3)<<4) | (igroup[1]>>4)];
ogroup[2]= dtable[((igroup[1]&0xF)<<2) | (igroup[2]>>6)];
ogroup[3]= dtable[igroup[2]&0x3F];
if (n<3) {
ogroup[3]= '=';
if (n<2)
ogroup[2]= '=';
}
for (i= 0;i<4;i++)
b64_ochar(&bio, ogroup[i], so);
}
}
/* Put end of line - line feed */
if (fputs(EOL, so) == EOF)
return 0;
fclose(fi);
return 1;
}
static int get_date(char *s, int len)
{
struct ast_tm tm;
@ -1474,7 +1341,7 @@ static int sendmail(struct minivm_template *template, struct minivm_account *vmu
fprintf(p, "Content-Description: Voicemail sound attachment.\n");
fprintf(p, "Content-Disposition: attachment; filename=\"voicemail%s.%s\"\n\n", counter ? counter : "", format);
base_encode(fname, p);
ast_base64_encode_file_path(fname, p, EOL);
fprintf(p, "\n\n--%s--\n.\n", bound);
}
fclose(p);
@ -1737,7 +1604,7 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
}
return cmd;
default:
/* If the caller is an ouside caller, and the review option is enabled,
/* If the caller is an outside caller, and the review option is enabled,
allow them to review the message, but let the owner of the box review
their OGM's */
if (outsidecaller && !ast_test_flag(vmu, MVM_REVIEW))
@ -2827,7 +2694,7 @@ static int apply_general_options(struct ast_variable *var)
} else if (!strcmp(var->name, "externnotify")) {
/* External voicemail notify application */
ast_copy_string(global_externnotify, var->value, sizeof(global_externnotify));
} else if (!strcmp(var->name, "silencetreshold")) {
} else if (!strcmp(var->name, "silencethreshold") || !strcmp(var->name, "silencetreshold")) {
/* Silence treshold */
global_silencethreshold = atoi(var->value);
} else if (!strcmp(var->name, "maxmessage")) {
@ -2956,6 +2823,8 @@ static int load_config(int reload)
ast_copy_string(template->fromaddress, chanvar, sizeof(template->fromaddress));
if ((chanvar = ast_variable_retrieve(cfg, "general", "emailaaddress")))
ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
if ((chanvar = ast_variable_retrieve(cfg, "general", "emailaddress")))
ast_copy_string(template->serveremail, chanvar, sizeof(template->serveremail));
if ((chanvar = ast_variable_retrieve(cfg, "general", "emailcharset")))
ast_copy_string(template->charset, chanvar, sizeof(template->charset));
if ((chanvar = ast_variable_retrieve(cfg, "general", "emailsubject")))

View File

@ -631,6 +631,7 @@ static void mixmonitor_free(struct mixmonitor *mixmonitor)
* \brief Copies the mixmonitor to all voicemail recipients
* \param mixmonitor The mixmonitor that needs to forward its file to recipients
* \param ext Format of the file that was saved
* \param filename
*/
static void copy_to_voicemail(struct mixmonitor *mixmonitor, const char *ext, const char *filename)
{

View File

@ -3,6 +3,8 @@
*
* Copyright (c) 2006, Tilghman Lesher. All rights reserved.
*
* Updated by Naveen Albert <asterisk@phreaknet.org>
*
* Tilghman Lesher <app_morsecode__v001@the-tilghman.com>
*
* This code is released by the author with no restrictions on usage.
@ -20,6 +22,7 @@
* \brief Morsecode application
*
* \author Tilghman Lesher <app_morsecode__v001@the-tilghman.com>
* \author Naveen Albert <asterisk@phreaknet.org>
*
* \ingroup applications
*/
@ -58,6 +61,14 @@
<variable name="MORSETONE">
<para>The pitch of the tone in (Hz), default is 800</para>
</variable>
<variable name="MORSESPACETONE">
<para>The pitch of the spaces in (Hz), default is 0</para>
</variable>
<variable name="MORSETYPE">
<para>The code type to use (AMERICAN for standard American Morse
or INTERNATIONAL for international code.
Default is INTERNATIONAL).</para>
</variable>
</variablelist>
</description>
<see-also>
@ -68,7 +79,7 @@
***/
static const char app_morsecode[] = "Morsecode";
static const char * const morsecode[] = {
static const char * const internationalcode[] = {
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 0-15 */
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 16-31 */
" ", /* 32 - <space> */
@ -95,16 +106,16 @@ static const char * const morsecode[] = {
"", /* 62 - > */
"..--..", /* 63 - ? */
".--.-.", /* 64 - @ */
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
"-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..",
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", /* A-M */
"-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", /* N-Z */
"-.--.-", /* 91 - [ (really '(') */
"-..-.", /* 92 - \ (really '/') */
"-.--.-", /* 93 - ] (really ')') */
"", /* 94 - ^ */
"..--.-", /* 95 - _ */
".----.", /* 96 - ` */
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
"-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..",
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", /* a-m */
"-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", /* n-z */
"-.--.-", /* 123 - { (really '(') */
"", /* 124 - | */
"-.--.-", /* 125 - } (really ')') */
@ -112,63 +123,159 @@ static const char * const morsecode[] = {
". . .", /* 127 - <del> (error) */
};
static void playtone(struct ast_channel *chan, int tone, int len)
static const char * const americanmorsecode[] = {
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 0-15 */
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 16-31 */
" ", /* 32 - <space> */
"---.", /* 33 - ! */
"..-. -.",/* 34 - " (QN)*/
"", /* 35 - # */
"... .-..",/* 36 - $ (SX) */
"", /* 37 - % */
". ...", /* 38 - & (ES) */
"..-. .-..",/* 39 - ' (QX) */
"..... -.", /* 40 - ( (PN) */
"..... .. ..", /* 41 - ) (PY) */
"", /* 42 - * */
"", /* 43 - + */
".-.-", /* 44 - , */
".... .-..",/* 45 - (HX) */
"..--..", /* 46 - . */
"..- -", /* 47 - / (UT) */
".--.", "..-..", "...-.", "....-", "---", "......", "--..", "-....", "-..-", "0", /* 48-57 - 0-9 */
"-.- . .",/* 58 - : (KO) */
"... ..", /* 59 - ; */
"", /* 60 - < */
"-...-", /* 61 - = (paragraph mark) */
"", /* 62 - > */
"-..-.", /* 63 - ? */
".--.-.", /* 64 - @ */
".-", "-...", ".. .", "-..", ".", ".-.", "--.", "....", "..", ".-.-", "-.-", "L", "--", /* A-M */
"-.", ". .", ".....", "..-.", ". ..", "...", "-", "..-", "...-", ".--", ".-..", ".. ..", "... .", /* N-Z */
"..... -.", /* 91 - [ (really '(') */
"..- -", /* 92 - \ (really '/') */
"..... .. ..", /* 93 - ] (really ')') */
"", /* 94 - ^ */
"..--.-", /* 95 - _ */
".----.", /* 96 - ` */
".-", "-...", ".. .", "-..", ".", ".-.", "--.", "....", "..", ".-.-", "-.-", "L", "--", /* a-m */
"-.", ". .", ".....", "..-.", ". ..", "...", "-", "..-", "...-", ".--", ".-..", ".. ..", "... .", /* n-z */
"..... -.", /* 123 - { (really '(') */
"", /* 124 - | */
"..... .. ..", /* 125 - } (really ')') */
"..- -", /* 126 - ~ (really bar) */
". . .", /* 127 - <del> (error) */
};
static int playtone(struct ast_channel *chan, int tone, int len)
{
int res;
char dtmf[20];
snprintf(dtmf, sizeof(dtmf), "%d/%d", tone, len);
ast_playtones_start(chan, 0, dtmf, 0);
ast_safe_sleep(chan, len);
res = ast_safe_sleep(chan, len);
ast_playtones_stop(chan);
return res;
}
static int morsecode_exec(struct ast_channel *chan, const char *data)
{
int res=0, ditlen, tone;
int res = 0, ditlen, tone, toneoff, digit2;
const char *digit;
const char *ditlenc, *tonec;
const char *ditlenc, *tonec, *toneb, *codetype;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Syntax: Morsecode(<string>) - no argument found\n");
return 0;
}
/* Use variable MORESEDITLEN, if set (else 80) */
ast_channel_lock(chan);
/* Use variable MORESEDITLEN, if set (else 80) */
ditlenc = pbx_builtin_getvar_helper(chan, "MORSEDITLEN");
if (ast_strlen_zero(ditlenc) || (sscanf(ditlenc, "%30d", &ditlen) != 1)) {
ditlen = 80;
}
ast_channel_unlock(chan);
/* Use variable MORSETONE, if set (else 800) */
ast_channel_lock(chan);
tonec = pbx_builtin_getvar_helper(chan, "MORSETONE");
if (ast_strlen_zero(tonec) || (sscanf(tonec, "%30d", &tone) != 1)) {
tone = 800;
}
/* Use variable MORSESPACETONE, if set (else 0) */
toneb = pbx_builtin_getvar_helper(chan, "MORSESPACETONE");
if (ast_strlen_zero(toneb) || (sscanf(toneb, "%30d", &toneoff) != 1)) {
toneoff = 0;
}
/* Use variable MORSETYPE, if set (else INTERNATIONAL) */
codetype = pbx_builtin_getvar_helper(chan, "MORSETYPE");
if (!codetype || strcmp(codetype, "AMERICAN")) {
codetype = "INTERNATIONAL";
}
ast_channel_unlock(chan);
for (digit = data; *digit; digit++) {
int digit2 = *digit;
const char *dahdit;
if (digit2 < 0) {
continue;
}
for (dahdit = morsecode[digit2]; *dahdit; dahdit++) {
if (*dahdit == '-') {
playtone(chan, tone, 3 * ditlen);
} else if (*dahdit == '.') {
playtone(chan, tone, 1 * ditlen);
} else {
/* Account for ditlen of silence immediately following */
playtone(chan, 0, 2 * ditlen);
if (!strcmp(codetype, "AMERICAN")) {
for (digit = data; *digit; digit++) {
const char *dahdit;
digit2 = *digit;
if (digit2 < 0 || digit2 > 127) {
continue;
}
for (dahdit = americanmorsecode[digit2]; *dahdit; dahdit++) {
if (*dahdit == '-') {
res = playtone(chan, tone, 3 * ditlen);
} else if (*dahdit == '.') {
res = playtone(chan, tone, 1 * ditlen);
} else if (*dahdit == 'L' || *dahdit == 'l') {
res = playtone(chan, tone, 6 * ditlen); /* long dash */
} else if (*dahdit == '0') {
res = playtone(chan, tone, 9 * ditlen); /* extra long dash */
} else if (*dahdit == ' ') { /* space char (x20) = 6 dot lengths */
/* Intra-char pauses, specific to American Morse */
res = playtone(chan, toneoff, 3 * ditlen);
} else {
/* Account for ditlen of silence immediately following */
res = playtone(chan, toneoff, 2 * ditlen);
}
/* Pause slightly between each dit and dah */
playtone(chan, 0, 1 * ditlen);
/* Pause slightly between each dit and dah */
res = playtone(chan, toneoff, 1 * ditlen);
if (res)
break;
}
/* Pause between characters */
res = playtone(chan, toneoff, 3 * ditlen);
if (res)
break;
}
} else { /* International */
for (digit = data; *digit; digit++) {
const char *dahdit;
digit2 = *digit;
if (digit2 < 0 || digit2 > 127) {
continue;
}
for (dahdit = internationalcode[digit2]; *dahdit; dahdit++) {
if (*dahdit == '-') {
res = playtone(chan, tone, 3 * ditlen);
} else if (*dahdit == '.') {
res = playtone(chan, tone, 1 * ditlen);
} else {
/* Account for ditlen of silence immediately following */
res = playtone(chan, toneoff, 2 * ditlen);
}
/* Pause slightly between each dit and dah */
res = playtone(chan, toneoff, 1 * ditlen);
if (res)
break;
}
/* Pause between characters */
res = playtone(chan, toneoff, 2 * ditlen);
if (res)
break;
}
/* Pause between characters */
playtone(chan, 0, 2 * ditlen);
}
return res;

View File

@ -64,10 +64,13 @@
</syntax>
<description>
<para>Executes mpg123 to play the given location, which typically would be a mp3 filename
or m3u playlist filename or a URL. Please read http://en.wikipedia.org/wiki/M3U
to see how M3U playlist file format is like, Example usage would be
or m3u playlist filename or a URL. Please read https://en.wikipedia.org/wiki/M3U
to see what the M3U playlist file format is like.</para>
<para>Note that mpg123 does not support HTTPS, so use HTTP for web streams.</para>
<para>User can exit by pressing any key on the dialpad, or by hanging up.</para>
<example title="Play an MP3 playlist">
exten => 1234,1,MP3Player(/var/lib/asterisk/playlist.m3u)
User can exit by pressing any key on the dialpad, or by hanging up.</para>
</example>
<para>This application does not automatically answer and should be preceeded by an
application such as Answer() or Progress().</para>
</description>
@ -98,39 +101,39 @@ static int mp3play(const char *filename, unsigned int sampling_rate, int fd)
/* Execute mpg123, but buffer if it's a net connection */
if (!strncasecmp(filename, "http://", 7) && strstr(filename, ".m3u")) {
char buffer_size_str[8];
snprintf(buffer_size_str, 8, "%u", (int) 0.5*2*sampling_rate/1000); // 0.5 seconds for a live stream
snprintf(buffer_size_str, 8, "%u", (int) 0.5*2*sampling_rate/1000); /* 0.5 seconds for a live stream */
/* Most commonly installed in /usr/local/bin */
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
execl(LOCAL_MPG_123, "mpg123", "-e", "s16", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
/* But many places has it in /usr/bin */
execl(MPG_123, "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
execl(MPG_123, "mpg123", "-e", "s16", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
/* As a last-ditch effort, try to use PATH */
execlp("mpg123", "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
execlp("mpg123", "mpg123", "-e", "s16", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
}
else if (!strncasecmp(filename, "http://", 7)) {
char buffer_size_str[8];
snprintf(buffer_size_str, 8, "%u", 6*2*sampling_rate/1000); // 6 seconds for a remote MP3 file
snprintf(buffer_size_str, 8, "%u", 6*2*sampling_rate/1000); /* 6 seconds for a remote MP3 file */
/* Most commonly installed in /usr/local/bin */
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
execl(LOCAL_MPG_123, "mpg123", "-e", "s16", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
/* But many places has it in /usr/bin */
execl(MPG_123, "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
execl(MPG_123, "mpg123", "-e", "s16", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
/* As a last-ditch effort, try to use PATH */
execlp("mpg123", "mpg123", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
execlp("mpg123", "mpg123", "-e", "s16", "-q", "-s", "-b", buffer_size_str, "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
}
else if (strstr(filename, ".m3u")) {
/* Most commonly installed in /usr/local/bin */
execl(LOCAL_MPG_123, "mpg123", "-q", "-z", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
execl(LOCAL_MPG_123, "mpg123", "-e", "s16", "-q", "-z", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
/* But many places has it in /usr/bin */
execl(MPG_123, "mpg123", "-q", "-z", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
execl(MPG_123, "mpg123", "-e", "s16", "-q", "-z", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
/* As a last-ditch effort, try to use PATH */
execlp("mpg123", "mpg123", "-q", "-z", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
execlp("mpg123", "mpg123", "-e", "s16", "-q", "-z", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, "-@", filename, (char *)NULL);
}
else {
/* Most commonly installed in /usr/local/bin */
execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
execl(MPG_123, "mpg123", "-e", "s16", "-q", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
/* But many places has it in /usr/bin */
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
execl(LOCAL_MPG_123, "mpg123", "-e", "s16", "-q", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
/* As a last-ditch effort, try to use PATH */
execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
execlp("mpg123", "mpg123", "-e", "s16", "-q", "-s", "-f", "8192", "--mono", "-r", sampling_rate_str, filename, (char *)NULL);
}
/* Can't use ast_log since FD's are closed */
fprintf(stderr, "Execute of mpg123 failed\n");
@ -177,6 +180,7 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
int pid = -1;
RAII_VAR(struct ast_format *, owriteformat, NULL, ao2_cleanup);
int timeout = 2;
int startedmp3 = 0;
struct timeval next;
struct ast_frame *f;
struct myframe {
@ -240,12 +244,19 @@ static int mp3_exec(struct ast_channel *chan, const char *data)
if (res > 0) {
myf.f.datalen = res;
myf.f.samples = res / 2;
startedmp3 = 1;
if (ast_write(chan, &myf.f) < 0) {
res = -1;
break;
}
} else {
ast_debug(1, "No more mp3\n");
if (!startedmp3) { /* we couldn't do anything, which means this stream doesn't work */
if (!strncasecmp(data, "https://", 8)) {
ast_log(LOG_WARNING, "%s() does not support HTTPS streams. Use HTTP instead.\n", app);
}
ast_log(LOG_WARNING, "MP3 stream '%s' is broken or nonexistent\n", data);
}
res = 0;
break;
}

View File

@ -1,223 +0,0 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Silly application to play an NBScat file -- uses nbscat8k
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
/*** MODULEINFO
<support_level>deprecated</support_level>
***/
#include "asterisk.h"
#include <fcntl.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <signal.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/frame.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/app.h"
#include "asterisk/format_cache.h"
/*** DOCUMENTATION
<application name="NBScat" language="en_US">
<synopsis>
Play an NBS local stream.
</synopsis>
<syntax />
<description>
<para>Executes nbscat to listen to the local NBS stream.
User can exit by pressing any key.</para>
</description>
</application>
***/
#define LOCAL_NBSCAT "/usr/local/bin/nbscat8k"
#define NBSCAT "/usr/bin/nbscat8k"
#ifndef AF_LOCAL
#define AF_LOCAL AF_UNIX
#endif
static char *app = "NBScat";
static int NBScatplay(int fd)
{
int res;
res = ast_safe_fork(0);
if (res < 0) {
ast_log(LOG_WARNING, "Fork failed\n");
}
if (res) {
return res;
}
if (ast_opt_high_priority)
ast_set_priority(0);
dup2(fd, STDOUT_FILENO);
ast_close_fds_above_n(STDERR_FILENO);
/* Most commonly installed in /usr/local/bin */
execl(NBSCAT, "nbscat8k", "-d", (char *)NULL);
execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL);
fprintf(stderr, "Execute of nbscat8k failed\n");
_exit(0);
}
static int timed_read(int fd, void *data, int datalen)
{
int res;
struct pollfd fds[1];
fds[0].fd = fd;
fds[0].events = POLLIN;
res = ast_poll(fds, 1, 2000);
if (res < 1) {
ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res);
return -1;
}
return read(fd, data, datalen);
}
static int NBScat_exec(struct ast_channel *chan, const char *data)
{
int res=0;
int fds[2];
int ms = -1;
int pid = -1;
struct ast_format *owriteformat;
struct timeval next;
struct ast_frame *f;
struct myframe {
struct ast_frame f;
char offset[AST_FRIENDLY_OFFSET];
short frdata[160];
} myf;
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
ast_log(LOG_WARNING, "Unable to create socketpair\n");
return -1;
}
ast_stopstream(chan);
owriteformat = ao2_bump(ast_channel_writeformat(chan));
res = ast_set_write_format(chan, ast_format_slin);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
ao2_cleanup(owriteformat);
return -1;
}
myf.f.frametype = AST_FRAME_VOICE;
myf.f.subclass.format = ast_format_slin;
myf.f.mallocd = 0;
myf.f.offset = AST_FRIENDLY_OFFSET;
myf.f.src = __PRETTY_FUNCTION__;
myf.f.delivery.tv_sec = 0;
myf.f.delivery.tv_usec = 0;
myf.f.data.ptr = myf.frdata;
res = NBScatplay(fds[1]);
/* Wait 1000 ms first */
next = ast_tvnow();
next.tv_sec += 1;
if (res >= 0) {
pid = res;
/* Order is important -- there's almost always going to be mp3... we want to prioritize the
user */
for (;;) {
ms = ast_tvdiff_ms(next, ast_tvnow());
if (ms <= 0) {
res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
if (res > 0) {
myf.f.datalen = res;
myf.f.samples = res / 2;
if (ast_write(chan, &myf.f) < 0) {
res = -1;
break;
}
} else {
ast_debug(1, "No more mp3\n");
res = 0;
break;
}
next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
} else {
ms = ast_waitfor(chan, ms);
if (ms < 0) {
ast_debug(1, "Hangup detected\n");
res = -1;
break;
}
if (ms) {
f = ast_read(chan);
if (!f) {
ast_debug(1, "Null frame == hangup() detected\n");
res = -1;
break;
}
if (f->frametype == AST_FRAME_DTMF) {
ast_debug(1, "User pressed a key\n");
ast_frfree(f);
res = 0;
break;
}
ast_frfree(f);
}
}
}
}
close(fds[0]);
close(fds[1]);
ast_frfree(&myf.f);
if (pid > -1)
kill(pid, SIGKILL);
if (!res && owriteformat)
ast_set_write_format(chan, owriteformat);
ao2_cleanup(owriteformat);
return res;
}
static int unload_module(void)
{
return ast_unregister_application(app);
}
static int load_module(void)
{
return ast_register_application_xml(app, NBScat_exec);
}
AST_MODULE_INFO_STANDARD_DEPRECATED(ASTERISK_GPL_KEY, "Silly NBS Stream Application");

View File

@ -95,6 +95,10 @@ static const char app_originate[] = "Originate";
<argument name="argN" />
</argument>
</option>
<option name="C">
<para>Comma-separated list of codecs to use for this call.
Default is <literal>slin</literal>.</para>
</option>
<option name="c">
<para>The caller ID number to use for the called channel. Default is
the current channel's Caller ID number.</para>
@ -114,7 +118,7 @@ static const char app_originate[] = "Originate";
</parameter>
</syntax>
<description>
<para>This application originates an outbound call and connects it to a specified extension or application. This application will block until the outgoing call fails or gets answered. At that point, this application will exit with the status variable set and dialplan processing will continue.</para>
<para>This application originates an outbound call and connects it to a specified extension or application. This application will block until the outgoing call fails or gets answered, unless the async option is used. At that point, this application will exit with the status variable set and dialplan processing will continue.</para>
<para>This application sets the following channel variable before exiting:</para>
<variablelist>
<variable name="ORIGINATE_STATUS">
@ -141,7 +145,8 @@ enum {
OPT_ASYNC = (1 << 2),
OPT_CALLER_NUM = (1 << 3),
OPT_CALLER_NAME = (1 << 4),
OPT_VARIABLES = (1 << 5),
OPT_CODECS = (1 << 5),
OPT_VARIABLES = (1 << 6),
};
enum {
@ -149,6 +154,7 @@ enum {
OPT_ARG_PREDIAL_CALLER,
OPT_ARG_CALLER_NUM,
OPT_ARG_CALLER_NAME,
OPT_ARG_CODECS,
OPT_ARG_VARIABLES,
/* note: this entry _MUST_ be the last one in the enum */
OPT_ARG_ARRAY_SIZE,
@ -158,6 +164,7 @@ AST_APP_OPTIONS(originate_exec_options, BEGIN_OPTIONS
AST_APP_OPTION('a', OPT_ASYNC),
AST_APP_OPTION_ARG('b', OPT_PREDIAL_CALLEE, OPT_ARG_PREDIAL_CALLEE),
AST_APP_OPTION_ARG('B', OPT_PREDIAL_CALLER, OPT_ARG_PREDIAL_CALLER),
AST_APP_OPTION_ARG('C', OPT_CODECS, OPT_ARG_CODECS),
AST_APP_OPTION_ARG('c', OPT_CALLER_NUM, OPT_ARG_CALLER_NUM),
AST_APP_OPTION_ARG('n', OPT_CALLER_NAME, OPT_ARG_CALLER_NAME),
AST_APP_OPTION_ARG('v', OPT_VARIABLES, OPT_ARG_VARIABLES),
@ -178,7 +185,7 @@ static int originate_exec(struct ast_channel *chan, const char *data)
char *opt_args[OPT_ARG_ARRAY_SIZE];
char *predial_callee = NULL;
char *parse, *cnum = NULL, *cname = NULL;
struct ast_variable *vars = NULL;
char *chantech, *chandata;
int res = -1;
@ -186,22 +193,15 @@ static int originate_exec(struct ast_channel *chan, const char *data)
int outgoing_status = 0;
unsigned int timeout = 30;
static const char default_exten[] = "s";
struct ast_format_cap *cap_slin = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
struct ast_format_cap *capabilities;
capabilities = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
ast_autoservice_start(chan);
if (!cap_slin) {
if (!capabilities) {
goto return_cleanup;
}
ast_format_cap_append(cap_slin, ast_format_slin, 0);
ast_format_cap_append(cap_slin, ast_format_slin12, 0);
ast_format_cap_append(cap_slin, ast_format_slin16, 0);
ast_format_cap_append(cap_slin, ast_format_slin24, 0);
ast_format_cap_append(cap_slin, ast_format_slin32, 0);
ast_format_cap_append(cap_slin, ast_format_slin44, 0);
ast_format_cap_append(cap_slin, ast_format_slin48, 0);
ast_format_cap_append(cap_slin, ast_format_slin96, 0);
ast_format_cap_append(cap_slin, ast_format_slin192, 0);
ast_format_cap_append(capabilities, ast_format_slin, 0);
if (ast_strlen_zero(data)) {
ast_log(LOG_ERROR, "Originate() requires arguments\n");
@ -257,6 +257,13 @@ static int originate_exec(struct ast_channel *chan, const char *data)
goto return_cleanup;
}
if (ast_test_flag64(&opts, OPT_CODECS)) {
if (!ast_strlen_zero(opt_args[OPT_ARG_CODECS])) {
ast_format_cap_remove_by_type(capabilities, AST_MEDIA_TYPE_UNKNOWN);
ast_format_cap_update_by_allow_disallow(capabilities, opt_args[OPT_ARG_CODECS], 1);
}
}
if (ast_test_flag64(&opts, OPT_CALLER_NUM)) {
if (!ast_strlen_zero(opt_args[OPT_ARG_CALLER_NUM])) {
cnum = opt_args[OPT_ARG_CALLER_NUM];
@ -318,7 +325,7 @@ static int originate_exec(struct ast_channel *chan, const char *data)
ast_debug(1, "Originating call to '%s/%s' and connecting them to extension %s,%s,%d\n",
chantech, chandata, args.arg1, exten, priority);
res = ast_pbx_outgoing_exten_predial(chantech, cap_slin, chandata,
res = ast_pbx_outgoing_exten_predial(chantech, capabilities, chandata,
timeout * 1000, args.arg1, exten, priority, &outgoing_status,
ast_test_flag64(&opts, OPT_ASYNC) ? AST_OUTGOING_NO_WAIT : AST_OUTGOING_WAIT,
cid_num, cid_name, vars, NULL, NULL, 0, NULL,
@ -329,7 +336,7 @@ static int originate_exec(struct ast_channel *chan, const char *data)
ast_debug(1, "Originating call to '%s/%s' and connecting them to %s(%s)\n",
chantech, chandata, args.arg1, S_OR(args.arg2, ""));
res = ast_pbx_outgoing_app_predial(chantech, cap_slin, chandata,
res = ast_pbx_outgoing_app_predial(chantech, capabilities, chandata,
timeout * 1000, args.arg1, args.arg2, &outgoing_status,
ast_test_flag64(&opts, OPT_ASYNC) ? AST_OUTGOING_NO_WAIT : AST_OUTGOING_WAIT,
cid_num, cid_name, vars, NULL, NULL, NULL,
@ -380,7 +387,7 @@ return_cleanup:
if (vars) {
ast_variables_destroy(vars);
}
ao2_cleanup(cap_slin);
ao2_cleanup(capabilities);
ast_autoservice_stop(chan);
return continue_in_dialplan ? 0 : -1;

View File

@ -31,7 +31,10 @@
/*** MODULEINFO
<depend>osptk</depend>
<depend>openssl</depend>
<support_level>extended</support_level>
<defaultenabled>no</defaultenabled>
<support_level>deprecated</support_level>
<deprecated_in>19</deprecated_in>
<removed_in>21</removed_in>
***/
#include "asterisk.h"
@ -3163,7 +3166,7 @@ static int reload(void)
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Open Settlement Protocol Applications",
.support_level = AST_MODULE_SUPPORT_EXTENDED,
.support_level = AST_MODULE_SUPPORT_DEPRECATED,
.load = load_module,
.unload = unload_module,
.reload = reload,

View File

@ -174,8 +174,6 @@ struct page_options {
*
* \param chan Setup bridge profile on this channel.
* \param options Options to setup bridge profile.
*
* \return Nothing
*/
static void setup_profile_bridge(struct ast_channel *chan, struct page_options *options)
{
@ -192,8 +190,6 @@ static void setup_profile_bridge(struct ast_channel *chan, struct page_options *
*
* \param chan Setup user profile on this channel.
* \param options Options to setup paged user profile.
*
* \return Nothing
*/
static void setup_profile_paged(struct ast_channel *chan, struct page_options *options)
{
@ -216,8 +212,6 @@ static void setup_profile_paged(struct ast_channel *chan, struct page_options *o
*
* \param chan Setup user profile on this channel.
* \param options Options to setup caller user profile.
*
* \return Nothing
*/
static void setup_profile_caller(struct ast_channel *chan, struct page_options *options)
{

View File

@ -35,7 +35,7 @@
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
/* This file provides config-file based 'say' functions, and implenents
/* This file provides config-file based 'say' functions, and implements
* some CLI commands.
*/
#include "asterisk/say.h" /*!< provides config-file based 'say' functions */
@ -62,13 +62,19 @@
be answered before the sound is played.</para>
<note><para>Not all channel types support playing messages while still on hook.</para></note>
</option>
<option name="say">
<para>Play using the say.conf file.</para>
</option>
<option name="mix">
<para>Play using a mix of filename and the say.conf file.</para>
</option>
</optionlist>
</parameter>
</syntax>
<description>
<para>Plays back given filenames (do not put extension of wav/alaw etc).
The playback command answer the channel if no options are specified.
If the file is non-existant it will fail</para>
The Playback application answers the channel if no options are specified.
If the file is non-existent it will fail.</para>
<para>This application sets the following channel variable upon completion:</para>
<variablelist>
<variable name="PLAYBACKSTATUS">
@ -446,6 +452,7 @@ static int playback_exec(struct ast_channel *chan, const char *data)
char *tmp;
int option_skip=0;
int option_say=0;
int option_mix=0;
int option_noanswer = 0;
AST_DECLARE_APP_ARGS(args,
@ -466,6 +473,8 @@ static int playback_exec(struct ast_channel *chan, const char *data)
option_skip = 1;
if (strcasestr(args.options, "say"))
option_say = 1;
if (strcasestr(args.options, "mix"))
option_mix = 1;
if (strcasestr(args.options, "noanswer"))
option_noanswer = 1;
}
@ -486,6 +495,13 @@ static int playback_exec(struct ast_channel *chan, const char *data)
while (!res && (front = strsep(&back, "&"))) {
if (option_say)
res = say_full(chan, front, "", ast_channel_language(chan), NULL, -1, -1);
else if (option_mix){
/* Check if it is in say format but not remote audio file */
if (strcasestr(front, ":") && !strcasestr(front, "://"))
res = say_full(chan, front, "", ast_channel_language(chan), NULL, -1, -1);
else
res = ast_streamfile(chan, front, ast_channel_language(chan));
}
else
res = ast_streamfile(chan, front, ast_channel_language(chan));
if (!res) {

File diff suppressed because it is too large Load Diff

View File

@ -75,6 +75,16 @@
<option name="n">
<para>to read digits even if the line is not up.</para>
</option>
<option name="t">
<para>Terminator digit(s) to use for ending input.
Default is <literal>#</literal>. If you need to read
the digit <literal>#</literal> literally, you should
remove or change the terminator character. Multiple
terminator characters may be specified. If no terminator
digit is present, input cannot be ended using digits
and you will need to rely on duration and max digits
for ending input.</para>
</option>
</optionlist>
</parameter>
<parameter name="attempts">
@ -114,12 +124,20 @@ enum read_option_flags {
OPT_SKIP = (1 << 0),
OPT_INDICATION = (1 << 1),
OPT_NOANSWER = (1 << 2),
OPT_TERMINATOR = (1 << 3),
};
enum {
OPT_ARG_TERMINATOR,
/* note: this entry _MUST_ be the last one in the enum */
OPT_ARG_ARRAY_SIZE,
};
AST_APP_OPTIONS(read_app_options, {
AST_APP_OPTION('s', OPT_SKIP),
AST_APP_OPTION('i', OPT_INDICATION),
AST_APP_OPTION('n', OPT_NOANSWER),
AST_APP_OPTION_ARG('t', OPT_TERMINATOR, OPT_ARG_TERMINATOR),
});
static char *app = "Read";
@ -132,9 +150,11 @@ static int read_exec(struct ast_channel *chan, const char *data)
int tries = 1, to = 0, x = 0;
double tosec;
char *argcopy = NULL;
char *opt_args[OPT_ARG_ARRAY_SIZE];
struct ast_tone_zone_sound *ts = NULL;
struct ast_flags flags = {0};
const char *status = "ERROR";
char *terminator = "#"; /* use default terminator # by default */
AST_DECLARE_APP_ARGS(arglist,
AST_APP_ARG(variable);
@ -156,7 +176,7 @@ static int read_exec(struct ast_channel *chan, const char *data)
AST_STANDARD_APP_ARGS(arglist, argcopy);
if (!ast_strlen_zero(arglist.options)) {
ast_app_parse_options(read_app_options, &flags, NULL, arglist.options);
ast_app_parse_options(read_app_options, &flags, opt_args, arglist.options);
}
if (!ast_strlen_zero(arglist.attempts)) {
@ -192,6 +212,13 @@ static int read_exec(struct ast_channel *chan, const char *data)
ts = ast_get_indication_tone(ast_channel_zone(chan), arglist.filename);
}
}
if (ast_test_flag(&flags, OPT_TERMINATOR)) {
if (!ast_strlen_zero(opt_args[OPT_ARG_TERMINATOR])) {
terminator = opt_args[OPT_ARG_TERMINATOR];
} else {
terminator = ""; /* no digit inherently will terminate input */
}
}
if (ast_channel_state(chan) != AST_STATE_UP) {
if (ast_test_flag(&flags, OPT_SKIP)) {
/* At the user's option, skip if the line is not up */
@ -223,7 +250,7 @@ static int read_exec(struct ast_channel *chan, const char *data)
break;
}
tmp[x++] = res;
if (tmp[x-1] == '#') {
if (terminator && strchr(terminator, tmp[x-1])) {
tmp[x-1] = '\0';
status = "OK";
break;
@ -233,7 +260,7 @@ static int read_exec(struct ast_channel *chan, const char *data)
}
}
} else {
res = ast_app_getdata(chan, arglist.filename, tmp, maxdigits, to);
res = ast_app_getdata_terminator(chan, arglist.filename, tmp, maxdigits, to, terminator);
if (res == AST_GETDATA_COMPLETE || res == AST_GETDATA_EMPTY_END_TERMINATED)
status = "OK";
else if (res == AST_GETDATA_TIMEOUT)

View File

@ -39,6 +39,11 @@
/*** DOCUMENTATION
<application name="Reload" language="en_US">
<since>
<version>16.20.0</version>
<version>18.6.0</version>
<version>19.0.0</version>
</since>
<synopsis>
Reloads an Asterisk module, blocking the channel until the reload has completed.
</synopsis>

View File

@ -21,6 +21,7 @@
* \brief App to transmit a text message
*
* \author Mark Spencer <markster@digium.com>
* \author Naveen Albert <asterisk@phreaknet.org>
*
* \note Requires support of sending text messages from channel driver
*
@ -140,11 +141,55 @@
<see-also>
<ref type="application">SendImage</ref>
<ref type="application">SendURL</ref>
<ref type="application">ReceiveText</ref>
</see-also>
</application>
<application name="ReceiveText" language="en_US">
<since>
<version>16.24.0</version>
<version>18.10.0</version>
<version>19.2.0</version>
</since>
<synopsis>
Receive a Text Message on a channel.
</synopsis>
<syntax>
<parameter name="timeout" required="false">
<para>Time in seconds to wait for text. Default is 0 (forever).</para>
</parameter>
</syntax>
<description>
<para>Waits for <replaceable>timeout</replaceable> seconds on the current channel
to receive text.</para>
<para>Result of transmission will be stored in the following variables:</para>
<variablelist>
<variable name="RECEIVETEXTMESSAGE">
<para>The received text message.</para>
</variable>
<variable name="RECEIVETEXTSTATUS">
<value name="SUCCESS">
Transmission succeeded.
</value>
<value name="FAILURE">
Transmission failed or timed out.
</value>
</variable>
</variablelist>
<example title="Receive message on channel">
same => n,ReceiveText()
same => n,NoOp(${RECEIVETEXTMESSAGE})
</example>
</description>
<see-also>
<ref type="application">SendText</ref>
<ref type="application">SendImage</ref>
<ref type="application">SendURL</ref>
</see-also>
</application>
***/
static const char * const app = "SendText";
static const char * const app2 = "ReceiveText";
static int sendtext_exec(struct ast_channel *chan, const char *data)
{
@ -237,14 +282,55 @@ cleanup:
return rc;
}
static int recvtext_exec(struct ast_channel *chan, const char *data)
{
double timeout = 0, timeout_ms = 0;
char *parse, *buf;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(timeout);
);
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
if (!ast_strlen_zero(args.timeout)) {
if (sscanf(args.timeout, "%30lg", &timeout) != 1) {
ast_log(LOG_WARNING, "Invalid timeout provided: %s. No timeout set.\n", args.timeout);
return -1;
}
timeout_ms = timeout * 1000.0;
}
buf = ast_recvtext(chan, timeout_ms);
pbx_builtin_setvar_helper(chan, "RECEIVETEXTSTATUS", buf ? "SUCCESS" : "FAILURE");
if (buf) {
pbx_builtin_setvar_helper(chan, "RECEIVETEXTMESSAGE", buf);
ast_free(buf);
}
return 0;
}
static int unload_module(void)
{
return ast_unregister_application(app);
int res;
res = ast_unregister_application(app);
res |= ast_unregister_application(app2);
return res;
}
static int load_module(void)
{
return ast_register_application_xml(app, sendtext_exec);
int res;
res = ast_register_application_xml(app, sendtext_exec);
res |= ast_register_application_xml(app2, recvtext_exec);
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Send Text Applications");
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Send and Receive Text Applications");

467
apps/app_sf.c Normal file
View File

@ -0,0 +1,467 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2021, Naveen Albert
*
* Naveen Albert <asterisk@phreaknet.org>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief SF sender and receiver applications
*
* \author Naveen Albert <asterisk@phreaknet.org>
*
* \ingroup applications
*/
/*** MODULEINFO
<support_level>extended</support_level>
***/
#include "asterisk.h"
#include "asterisk/file.h"
#include "asterisk/pbx.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/app.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/conversions.h"
/*** DOCUMENTATION
<application name="ReceiveSF" language="en_US">
<since>
<version>16.24.0</version>
<version>18.10.0</version>
<version>19.2.0</version>
</since>
<synopsis>
Detects SF digits on a channel and saves them to a variable.
</synopsis>
<syntax>
<parameter name="variable" required="true">
<para>The input digits will be stored in the given
<replaceable>variable</replaceable> name.</para>
</parameter>
<parameter name="digits" required="false">
<para>Maximum number of digits to read. Default is unlimited.</para>
</parameter>
<parameter name="timeout">
<para>The number of seconds to wait for all digits, if greater
than <literal>0</literal>. Can be floating point. Default
is no timeout.</para>
</parameter>
<parameter name="frequency">
<para>The frequency for which to detect pulsed digits.
Default is 2600 Hz.</para>
</parameter>
<parameter name="options">
<optionlist>
<option name="d">
<para>Delay audio by a frame to try to extra quelch.</para>
</option>
<option name="e">
<para>Allow receiving extra pulses 11 through 16.</para>
</option>
<option name="m">
<para>Mute conference.</para>
</option>
<option name="q">
<para>Quelch SF from in-band.</para>
</option>
<option name="r">
<para>"Radio" mode (relaxed SF).</para>
</option>
</optionlist>
</parameter>
</syntax>
<description>
<para>Reads SF digits from the user in to the given
<replaceable>variable</replaceable>.</para>
<para>This application does not automatically answer the channel and
should be preceded with <literal>Answer</literal> or
<literal>Progress</literal> as needed.</para>
<variablelist>
<variable name="RECEIVESFSTATUS">
<para>This is the status of the read operation.</para>
<value name="START" />
<value name="ERROR" />
<value name="HANGUP" />
<value name="MAXDIGITS" />
<value name="TIMEOUT" />
</variable>
</variablelist>
</description>
<see-also>
<ref type="application">ReceiveMF</ref>
<ref type="application">SendMF</ref>
<ref type="application">SendSF</ref>
<ref type="application">Read</ref>
</see-also>
</application>
<application name="SendSF" language="en_US">
<since>
<version>16.24.0</version>
<version>18.10.0</version>
<version>19.2.0</version>
</since>
<synopsis>
Sends arbitrary SF digits on the current or specified channel.
</synopsis>
<syntax>
<parameter name="digits" required="true">
<para>List of digits 0-9 to send; w for a half-second pause,
also f or F for a flash-hook if the channel supports flash-hook,
h or H for 250 ms of 2600 Hz, and W for a wink if the channel
supports wink.</para>
</parameter>
<parameter name="frequency" required="false">
<para>Frequency to use. (defaults to 2600 Hz).</para>
</parameter>
<parameter name="channel" required="false">
<para>Channel where digits will be played</para>
</parameter>
</syntax>
<description>
<para>It will send all digits or terminate if it encounters an error.</para>
</description>
<see-also>
<ref type="application">SendDTMF</ref>
<ref type="application">SendMF</ref>
<ref type="application">ReceiveMF</ref>
<ref type="application">ReceiveSF</ref>
</see-also>
</application>
***/
enum read_option_flags {
OPT_DELAY = (1 << 0),
OPT_MUTE = (1 << 1),
OPT_QUELCH = (1 << 2),
OPT_RELAXED = (1 << 3),
OPT_EXTRAPULSES = (1 << 4),
};
AST_APP_OPTIONS(read_app_options, {
AST_APP_OPTION('d', OPT_DELAY),
AST_APP_OPTION('e', OPT_EXTRAPULSES),
AST_APP_OPTION('m', OPT_MUTE),
AST_APP_OPTION('q', OPT_QUELCH),
AST_APP_OPTION('r', OPT_RELAXED),
});
static const char *readsf_name = "ReceiveSF";
static const char sendsf_name[] = "SendSF";
/*!
* \brief Detects SF digits on channel using DSP
*
* \param chan channel on which to read digits
* \param buf Buffer in which to store digits
* \param buflen Size of buffer
* \param timeout ms to wait for all digits before giving up
* \param maxdigits Maximum number of digits
* \param freq Frequency to use
* \param features DSP features
* \param extrapulses Whether to recognize extra pulses
*
* \retval 0 if successful
* \retval -1 if unsuccessful (including hangup).
*/
static int read_sf_digits(struct ast_channel *chan, char *buf, int buflen, int timeout, int maxdigits, int freq, int features, int extrapulses) {
/* Bell System Technical Journal 39 (Nov. 1960) */
#define SF_MIN_OFF 25
#define SF_ON 67
#define SF_BETWEEN 600
#define SF_MIN_DETECT 50
struct ast_dsp *dsp = NULL;
struct ast_frame *frame = NULL;
struct timeval start, pulsetimer, digittimer;
int remaining_time = timeout;
char *str = buf;
int hits = 0, digits_read = 0;
unsigned short int sf_on = 0;
int res = 0;
if (!(dsp = ast_dsp_new())) {
ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "ERROR");
return -1;
}
ast_dsp_set_features(dsp, DSP_FEATURE_FREQ_DETECT);
/* tolerance is 46 to 76% make break at 8 to 12 pps */
ast_dsp_set_freqmode(dsp, freq, SF_MIN_DETECT, 16, 0);
start = ast_tvnow();
*str = 0; /* start with empty output buffer */
while (timeout == 0 || remaining_time > 0) {
if (timeout > 0) {
remaining_time = ast_remaining_ms(start, timeout);
if (remaining_time <= 0) {
pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "TIMEOUT");
break;
}
}
if (digits_read >= (buflen - 1)) { /* we don't have room to store any more digits (very unlikely to happen for a legitimate reason) */
/* This result will probably not be usable, so status should not be START */
pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "MAXDIGITS");
break;
}
if (ast_waitfor(chan, 1000) > 0) {
frame = ast_read(chan);
if (!frame) {
ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "HANGUP");
break;
} else if (frame->frametype == AST_FRAME_VOICE) {
frame = ast_dsp_process(chan, dsp, frame);
if (frame->frametype == AST_FRAME_DTMF) {
char result = frame->subclass.integer;
if (result == 'q') {
sf_on = 1;
pulsetimer = ast_tvnow(); /* reset the pulse timer */
/* now, we need at least a 33ms pause to register the pulse */
}
} else {
if (sf_on) {
int timeleft = ast_remaining_ms(pulsetimer, SF_MIN_OFF);
if (timeleft <= 0) {
sf_on = 0;
/* The pulse needs to end no more than 30ms after we detected it */
if (timeleft > -30) {
hits++;
digittimer = ast_tvnow(); /* reset the digit timer */
ast_debug(5, "Detected SF pulse (pulse #%d)\n", hits);
ast_dsp_free(dsp);
if (!(dsp = ast_dsp_new())) {
ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "ERROR");
ast_frfree(frame);
return -1;
}
ast_dsp_set_features(dsp, DSP_FEATURE_FREQ_DETECT);
ast_dsp_set_freqmode(dsp, freq, SF_MIN_DETECT, 16, 0);
} else {
ast_debug(5, "SF noise, ignoring, time elapsed was %d ms\n", timeleft);
}
}
} else if (hits > 0 && ast_remaining_ms(digittimer, SF_BETWEEN) <= 0) {
/* has the digit finished? */
ast_debug(2, "Received SF digit: %d\n", hits);
digits_read++;
if (hits > 10) {
if (extrapulses) {
/* dahdi-base.c translates 11 to * and 12 to # */
if (hits == 11) {
hits = '*';
} else if (hits == 12) {
hits = '#';
} else if (hits == 13) {
hits = 'D';
} else if (hits == 14) {
hits = 'C';
} else if (hits == 15) {
hits = 'B';
} else if (hits == 16) {
hits = 'A';
} else {
ast_debug(3, "Got %d SF pulses, is someone playing with the phone?\n", hits);
hits = 'A';
}
*str++ = hits;
} else {
ast_debug(2, "Got more than 10 pulses, truncating to 10\n");
hits = 0; /* 10 dial pulses = digit 0 */
*str++ = hits + '0';
}
} else {
if (hits == 10) {
hits = 0; /* 10 dial pulses = digit 0 */
}
*str++ = hits + '0';
}
*str = 0;
hits = 0;
if (maxdigits > 0 && digits_read >= maxdigits) {
pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "START");
ast_frfree(frame);
break;
}
}
}
}
ast_frfree(frame);
} else {
pbx_builtin_setvar_helper(chan, "RECEIVESFSTATUS", "HANGUP");
res = -1;
}
}
if (dsp) {
ast_dsp_free(dsp);
}
ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
return res;
}
static int read_sf_exec(struct ast_channel *chan, const char *data)
{
#define BUFFER_SIZE 256
char tmp[BUFFER_SIZE] = "";
double tosec;
struct ast_flags flags = {0};
char *argcopy = NULL;
int res, features = 0, digits = 0, to = 0, freq = 2600;
AST_DECLARE_APP_ARGS(arglist,
AST_APP_ARG(variable);
AST_APP_ARG(digits);
AST_APP_ARG(timeout);
AST_APP_ARG(freq);
AST_APP_ARG(options);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "ReceiveSF requires an argument (variable)\n");
return -1;
}
argcopy = ast_strdupa(data);
AST_STANDARD_APP_ARGS(arglist, argcopy);
if (!ast_strlen_zero(arglist.options)) {
ast_app_parse_options(read_app_options, &flags, NULL, arglist.options);
}
if (!ast_strlen_zero(arglist.timeout)) {
tosec = atof(arglist.timeout);
if (tosec <= 0) {
to = 0;
} else {
to = tosec * 1000.0;
}
}
if (!ast_strlen_zero(arglist.digits) && (ast_str_to_int(arglist.digits, &digits) || digits <= 0)) {
ast_log(LOG_WARNING, "Invalid number of digits: %s\n", arglist.digits);
return -1;
}
if (!ast_strlen_zero(arglist.freq) && (ast_str_to_int(arglist.freq, &freq) || freq <= 0)) {
ast_log(LOG_WARNING, "Invalid freq: %s\n", arglist.freq);
return -1;
}
if (ast_strlen_zero(arglist.variable)) {
ast_log(LOG_WARNING, "Invalid! Usage: ReceiveSF(variable[,timeout][,option])\n");
return -1;
}
if (ast_test_flag(&flags, OPT_DELAY)) {
features |= DSP_DIGITMODE_MUTEMAX;
}
if (ast_test_flag(&flags, OPT_MUTE)) {
features |= DSP_DIGITMODE_MUTECONF;
}
if (!ast_test_flag(&flags, OPT_QUELCH)) {
features |= DSP_DIGITMODE_NOQUELCH;
}
if (ast_test_flag(&flags, OPT_RELAXED)) {
features |= DSP_DIGITMODE_RELAXDTMF;
}
res = read_sf_digits(chan, tmp, BUFFER_SIZE, to, digits, freq, features, ast_test_flag(&flags, OPT_EXTRAPULSES));
pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
if (!ast_strlen_zero(tmp)) {
ast_verb(3, "SF digits received: '%s'\n", tmp);
} else if (!res) { /* if channel hung up, don't print anything out */
ast_verb(3, "No SF digits received.\n");
}
return res;
}
static int sendsf_exec(struct ast_channel *chan, const char *vdata)
{
int res;
char *data;
int frequency = 2600;
struct ast_channel *chan_found = NULL;
struct ast_channel *chan_dest = chan;
struct ast_channel *chan_autoservice = NULL;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(digits);
AST_APP_ARG(frequency);
AST_APP_ARG(channel);
);
if (ast_strlen_zero(vdata)) {
ast_log(LOG_WARNING, "SendSF requires an argument\n");
return 0;
}
data = ast_strdupa(vdata);
AST_STANDARD_APP_ARGS(args, data);
if (ast_strlen_zero(args.digits)) {
ast_log(LOG_WARNING, "The digits argument is required (0-9,wf)\n");
return 0;
}
if (!ast_strlen_zero(args.frequency) && (ast_str_to_int(args.frequency, &frequency) || frequency < 1)) {
ast_log(LOG_WARNING, "Invalid duration: %s\n", args.frequency);
return -1;
}
if (!ast_strlen_zero(args.channel)) {
chan_found = ast_channel_get_by_name(args.channel);
if (!chan_found) {
ast_log(LOG_WARNING, "No such channel: %s\n", args.channel);
return 0;
}
chan_dest = chan_found;
if (chan_found != chan) {
chan_autoservice = chan;
}
}
res = ast_sf_stream(chan_dest, chan_autoservice, NULL, args.digits, frequency, 0);
ast_channel_cleanup(chan_found);
return chan_autoservice ? 0 : res;
}
static int unload_module(void)
{
int res;
res = ast_unregister_application(readsf_name);
res |= ast_unregister_application(sendsf_name);
return res;
}
static int load_module(void)
{
int res;
res = ast_register_application_xml(readsf_name, read_sf_exec);
res |= ast_register_application_xml(sendsf_name, sendsf_exec);
return res;
}
AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "SF Sender and Receiver Applications");

View File

@ -590,8 +590,8 @@ static int gosub_exec(struct ast_channel *chan, const char *data)
ast_channel_unlock(chan);
if (!ast_exists_extension(chan, dest_context, dest_exten, dest_priority, caller_id)) {
ast_log(LOG_ERROR, "Attempt to reach a non-existent destination for %s: (Context:%s, Extension:%s, Priority:%d)\n",
app_gosub, dest_context, dest_exten, dest_priority);
ast_log(LOG_ERROR, "%s attempted to reach non-existent destination '%s,%s,%d' from '%s,%s,%d'",
app_gosub, dest_context, dest_exten, dest_priority, orig_context, orig_exten, orig_priority);
goto error_exit;
}
@ -924,8 +924,6 @@ static struct ast_custom_function stackpeek_function = {
* \param chan Channel to balance stack on.
*
* \note The channel is already locked when called.
*
* \return Nothing
*/
static void balance_stack(struct ast_channel *chan)
{
@ -1078,7 +1076,7 @@ static int gosub_run(struct ast_channel *chan, const char *sub_args, int ignore_
ast_channel_name(chan), app_gosub, sub_args,
S_OR(pbx_builtin_getvar_helper(chan, "GOSUB_RETVAL"), ""));
} else {
ast_log(LOG_NOTICE, "%s Abnormal '%s(%s)' exit. Popping routine return locations.\n",
ast_log(LOG_WARNING, "%s Abnormal '%s(%s)' exit. Popping routine return locations.\n",
ast_channel_name(chan), app_gosub, sub_args);
balance_stack(chan);
pbx_builtin_setvar_helper(chan, "GOSUB_RETVAL", "");

View File

@ -79,7 +79,7 @@
/*! \brief Dialplan application name */
static const char *stasis = "Stasis";
/*! /brief Stasis dialplan application callback */
/*! \brief Stasis dialplan application callback */
static int app_exec(struct ast_channel *chan, const char *data)
{
char *parse = NULL;

View File

@ -78,7 +78,7 @@ static const char app[] = "StatsD";
*
* \param value The value of the statistic to be sent to StatsD.
*
* This function checks to see if the value given to the StatsD daialplan
* This function checks to see if the value given to the StatsD dailplan
* application is within the allowed range of [-2^63, 2^63] as specified by StatsD.
*
* \retval zero on success.
@ -100,7 +100,7 @@ static int value_in_range(const char *value) {
*
* \param value The value of the statistic to be sent to StatsD.
*
* This function checks to see if the value given to the StatsD daialplan
* This function checks to see if the value given to the StatsD dailplan
* application is within the allowed range of [0, 2^64] as specified by StatsD.
*
* \retval zero on success.

View File

@ -352,7 +352,7 @@ static int testserver_exec(struct ast_channel *chan, const char *data)
if (!res)
res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
ast_debug(1, "read test identifier: %s\n", testid);
/* Check for sneakyness */
/* Check for sneakiness */
if (strchr(testid, '/'))
res = -1;
if ((res >=0) && (!ast_strlen_zero(testid))) {

View File

@ -1,180 +0,0 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief App to transmit a URL
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
/*** MODULEINFO
<support_level>deprecated</support_level>
***/
#include "asterisk.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
#include "asterisk/channel.h"
/*** DOCUMENTATION
<application name="SendURL" language="en_US">
<synopsis>
Send a URL.
</synopsis>
<syntax>
<parameter name="URL" required="true" />
<parameter name="option">
<optionlist>
<option name="w">
<para>Execution will wait for an acknowledgement that the
URL has been loaded before continuing.</para>
</option>
</optionlist>
</parameter>
</syntax>
<description>
<para>Requests client go to <replaceable>URL</replaceable> (IAX2) or sends the
URL to the client (other channels).</para>
<para>Result is returned in the <variable>SENDURLSTATUS</variable> channel variable:</para>
<variablelist>
<variable name="SENDURLSTATUS">
<value name="SUCCESS">
URL successfully sent to client.
</value>
<value name="FAILURE">
Failed to send URL.
</value>
<value name="NOLOAD">
Client failed to load URL (wait enabled).
</value>
<value name="UNSUPPORTED">
Channel does not support URL transport.
</value>
</variable>
</variablelist>
<para>SendURL continues normally if the URL was sent correctly or if the channel
does not support HTML transport. Otherwise, the channel is hung up.</para>
</description>
<see-also>
<ref type="application">SendImage</ref>
<ref type="application">SendText</ref>
</see-also>
</application>
***/
static char *app = "SendURL";
enum option_flags {
OPTION_WAIT = (1 << 0),
};
AST_APP_OPTIONS(app_opts,{
AST_APP_OPTION('w', OPTION_WAIT),
});
static int sendurl_exec(struct ast_channel *chan, const char *data)
{
int res = 0;
char *tmp;
struct ast_frame *f;
char *status = "FAILURE";
char *opts[0];
struct ast_flags flags = { 0 };
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(url);
AST_APP_ARG(options);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "SendURL requires an argument (URL)\n");
pbx_builtin_setvar_helper(chan, "SENDURLSTATUS", status);
return -1;
}
tmp = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, tmp);
if (args.argc == 2)
ast_app_parse_options(app_opts, &flags, opts, args.options);
if (!ast_channel_supports_html(chan)) {
/* Does not support transport */
pbx_builtin_setvar_helper(chan, "SENDURLSTATUS", "UNSUPPORTED");
return 0;
}
res = ast_channel_sendurl(chan, args.url);
if (res == -1) {
pbx_builtin_setvar_helper(chan, "SENDURLSTATUS", "FAILURE");
return res;
}
status = "SUCCESS";
if (ast_test_flag(&flags, OPTION_WAIT)) {
for(;;) {
/* Wait for an event */
res = ast_waitfor(chan, -1);
if (res < 0)
break;
f = ast_read(chan);
if (!f) {
res = -1;
status = "FAILURE";
break;
}
if (f->frametype == AST_FRAME_HTML) {
switch (f->subclass.integer) {
case AST_HTML_LDCOMPLETE:
res = 0;
ast_frfree(f);
status = "NOLOAD";
goto out;
break;
case AST_HTML_NOSUPPORT:
/* Does not support transport */
status = "UNSUPPORTED";
res = 0;
ast_frfree(f);
goto out;
break;
default:
ast_log(LOG_WARNING, "Don't know what to do with HTML subclass %d\n", f->subclass.integer);
};
}
ast_frfree(f);
}
}
out:
pbx_builtin_setvar_helper(chan, "SENDURLSTATUS", status);
return res;
}
static int unload_module(void)
{
return ast_unregister_application(app);
}
static int load_module(void)
{
return ast_register_application_xml(app, sendurl_exec);
}
AST_MODULE_INFO_STANDARD_DEPRECATED(ASTERISK_GPL_KEY, "Send URL Applications");

View File

@ -33,6 +33,7 @@
#include "asterisk/module.h"
#include "asterisk/app.h"
#include "asterisk/channel.h"
#include "asterisk/logger.h"
static char *app_verbose = "Verbose";
static char *app_log = "Log";
@ -61,7 +62,8 @@ static char *app_log = "Log";
<syntax>
<parameter name="level" required="true">
<para>Level must be one of <literal>ERROR</literal>, <literal>WARNING</literal>, <literal>NOTICE</literal>,
<literal>DEBUG</literal>, <literal>VERBOSE</literal> or <literal>DTMF</literal>.</para>
<literal>DEBUG</literal>, <literal>VERBOSE</literal>, <literal>DTMF</literal>, or
the name of a custom dynamic logging level.</para>
</parameter>
<parameter name="message" required="true">
<para>Output text message.</para>
@ -135,7 +137,7 @@ static int log_exec(struct ast_channel *chan, const char *data)
} else if (!strcasecmp(args.level, "DTMF")) {
lnum = __LOG_DTMF;
} else {
ast_log(LOG_ERROR, "Unknown log level: '%s'\n", args.level);
lnum = ast_logger_get_dynamic_level(args.level);
}
if (lnum > -1) {
@ -143,6 +145,9 @@ static int log_exec(struct ast_channel *chan, const char *data)
snprintf(extension, sizeof(extension), "Ext. %s", ast_channel_exten(chan));
ast_log(lnum, extension, ast_channel_priority(chan), context, "%s\n", args.msg);
} else {
ast_log(LOG_ERROR, "Unknown log level: '%s'\n", args.level);
return 0;
}
return 0;

View File

@ -26,7 +26,7 @@
* (http://www.washington.edu/imap/)
*
* \par See also
* \arg \ref Config_vm
* \arg \ref voicemail.conf "Config_voicemail"
* \note For information about voicemail IMAP storage, https://wiki.asterisk.org/wiki/display/AST/IMAP+Voicemail+Storage
* \ingroup applications
* \todo This module requires res_adsi to load. This needs to be optional
@ -149,6 +149,11 @@
<para>Skip the playback of instructions for leaving a message to the
calling party.</para>
</option>
<option name="S">
<para>Skip the playback of instructions for leaving a message to the
calling party, but only if a greeting has been recorded by the
mailbox user.</para>
</option>
<option name="t">
<argument name="x" required="false" />
<para>Play a custom beep tone to the caller instead of the default one.
@ -214,6 +219,10 @@
<para>Use the specified amount of gain when recording a voicemail message.
The units are whole-number decibels (dB).</para>
</option>
<option name="r">
<para>"Read only". Prevent user from deleting any messages.</para>
<para>This applies only to specific executions of VoiceMailMain, NOT the mailbox itself.</para>
</option>
<option name="s">
<para>Skip checking the passcode for the mailbox.</para>
</option>
@ -524,7 +533,6 @@ static AST_LIST_HEAD_STATIC(vmstates, vmstate);
/* Default mail command to mail voicemail. Change it with the
* mailcmd= command in voicemail.conf */
#define SENDMAIL "/usr/sbin/sendmail -t"
#define INTRO "vm-intro"
#define MAX_MAIL_BODY_CONTENT_SIZE 134217728L // 128 Mbyte
@ -534,8 +542,6 @@ static AST_LIST_HEAD_STATIC(vmstates, vmstate);
#define MINPASSWORD 0 /*!< Default minimum mailbox password length */
#define BASELINELEN 72
#define BASEMAXINLINE 256
#ifdef IMAP_STORAGE
#define ENDL "\r\n"
#else
@ -555,7 +561,7 @@ static AST_LIST_HEAD_STATIC(vmstates, vmstate);
#define VM_FORCENAME (1 << 7) /*!< Have new users record their name */
#define VM_FORCEGREET (1 << 8) /*!< Have new users record their greetings */
#define VM_PBXSKIP (1 << 9) /*!< Skip the [PBX] preamble in the Subject line of emails */
#define VM_DIRECFORWARD (1 << 10) /*!< Permit caller to use the Directory app for selecting to which mailbox to forward a VM */
#define VM_DIRECTFORWARD (1 << 10) /*!< Permit caller to use the Directory app for selecting to which mailbox to forward a VM */
#define VM_ATTACH (1 << 11) /*!< Attach message to voicemail notifications? */
#define VM_DELETE (1 << 12) /*!< Delete message after sending notification */
#define VM_ALLOCED (1 << 13) /*!< Structure was malloc'ed, instead of placed in a return (usually static) buffer */
@ -588,7 +594,9 @@ enum vm_option_flags {
OPT_MESSAGE_Urgent = (1 << 8),
OPT_MESSAGE_PRIORITY = (1 << 9),
OPT_EARLYM_GREETING = (1 << 10),
OPT_BEEP = (1 << 11)
OPT_BEEP = (1 << 11),
OPT_SILENT_IF_GREET = (1 << 12),
OPT_READONLY = (1 << 13),
};
enum vm_option_args {
@ -608,6 +616,7 @@ enum vm_passwordlocation {
AST_APP_OPTIONS(vm_app_options, {
AST_APP_OPTION('s', OPT_SILENT),
AST_APP_OPTION('S', OPT_SILENT_IF_GREET),
AST_APP_OPTION('b', OPT_BUSY_GREETING),
AST_APP_OPTION('u', OPT_UNAVAIL_GREETING),
AST_APP_OPTION_ARG('g', OPT_RECORDGAIN, OPT_ARG_RECORDGAIN),
@ -617,7 +626,8 @@ AST_APP_OPTIONS(vm_app_options, {
AST_APP_OPTION('U', OPT_MESSAGE_Urgent),
AST_APP_OPTION('P', OPT_MESSAGE_PRIORITY),
AST_APP_OPTION('e', OPT_EARLYM_GREETING),
AST_APP_OPTION_ARG('t', OPT_BEEP, OPT_ARG_BEEP_TONE)
AST_APP_OPTION_ARG('t', OPT_BEEP, OPT_ARG_BEEP_TONE),
AST_APP_OPTION('r', OPT_READONLY),
});
static const char * const mailbox_folders[] = {
@ -737,14 +747,6 @@ and vm-Old are spelled plural, to make them sound more as folder name than an ad
*/
struct baseio {
int iocp;
int iolen;
int linelength;
int ateof;
unsigned char iobuf[BASEMAXINLINE];
};
#define MAX_VM_MBOX_ID_LEN (AST_MAX_EXTENSION)
#define MAX_VM_CONTEXT_LEN (AST_MAX_CONTEXT)
/* MAX_VM_MAILBOX_LEN allows enough room for the '@' and NULL terminator */
@ -1084,7 +1086,7 @@ static int vm_test_create_user(const char *context, const char *mailbox);
* \brief Parse the given mailbox_id into mailbox and context.
* \since 12.0.0
*
* \param mailbox_id The mailbox@context string to separate.
* \param mailbox_id The mailbox\@context string to separate.
* \param mailbox Where the mailbox part will start.
* \param context Where the context part will start. ("default" if not present)
*
@ -1921,22 +1923,6 @@ static int make_file(char *dest, const int len, const char *dir, const int num)
return snprintf(dest, len, "%s/msg%04d", dir, num);
}
/* same as mkstemp, but return a FILE * */
static FILE *vm_mkftemp(char *template)
{
FILE *p = NULL;
int pfd = mkstemp(template);
chmod(template, VOICEMAIL_FILE_MODE & ~my_umask);
if (pfd > -1) {
p = fdopen(pfd, "w+");
if (!p) {
close(pfd);
pfd = -1;
}
}
return p;
}
/*! \brief basically mkdir -p $dest/$context/$ext/$folder
* \param dest String. base directory.
* \param len Length of dest.
@ -2690,7 +2676,7 @@ static int imap_store_file(const char *dir, const char *mailboxuser, const char
/* Make a temporary file instead of piping directly to sendmail, in case the mail
command hangs. */
if (!(p = vm_mkftemp(tmp))) {
if (!(p = ast_file_mkftemp(tmp, VOICEMAIL_FILE_MODE & ~my_umask))) {
ast_log(AST_LOG_WARNING, "Unable to store '%s' (can't create temporary file)\n", fn);
if (tempcopy) {
ast_free(vmu->email);
@ -2843,9 +2829,9 @@ static int inboxcount2(const char *mailbox_context, int *urgentmsgs, int *newmsg
return 0;
}
/**
/*!
* \brief Determines if the given folder has messages.
* \param mailbox The @ delimited string for user@context. If no context is found, uses 'default' for the context.
* \param mailbox The \@ delimited string for user\@context. If no context is found, uses 'default' for the context.
* \param folder the folder to look in
*
* This function is used when the mailbox is stored in an IMAP back end.
@ -2885,6 +2871,7 @@ static int has_voicemail(const char *mailbox, const char *folder)
* \param recip
* \param fmt
* \param dir
* \param flag, dest_folder
*
* This works with IMAP storage based mailboxes.
*
@ -3017,7 +3004,7 @@ static int init_mailstream(struct vm_state *vms, int box)
ast_mutex_lock(&vms->lock);
ast_mutex_lock(&mail_open_lock);
vms->mailstream = mail_open (stream, tmp, debug ? OP_DEBUG : NIL);
/* Create the folder if it dosn't exist */
/* Create the folder if it doesn't exist */
if (vms->mailstream && !mail_status(vms->mailstream, tmp, SA_UIDNEXT)) {
mail_create(vms->mailstream, tmp);
}
@ -4174,8 +4161,6 @@ bail:
*
* This method is used when mailboxes are stored in an ODBC back end.
* The specified message is directly deleted from the database 'voicemessages' table.
*
* \return the value greater than zero on success to indicate the number of messages, less than zero on error.
*/
static void delete_file(const char *sdir, int smsg)
{
@ -4764,134 +4749,6 @@ static int vm_delete(char *file)
return ast_filedelete(file, NULL);
}
/*!
* \brief utility used by inchar(), for base_encode()
*/
static int inbuf(struct baseio *bio, FILE *fi)
{
int l;
if (bio->ateof)
return 0;
if ((l = fread(bio->iobuf, 1, BASEMAXINLINE, fi)) != BASEMAXINLINE) {
bio->ateof = 1;
if (l == 0) {
/* Assume EOF */
return 0;
}
}
bio->iolen = l;
bio->iocp = 0;
return 1;
}
/*!
* \brief utility used by base_encode()
*/
static int inchar(struct baseio *bio, FILE *fi)
{
if (bio->iocp>=bio->iolen) {
if (!inbuf(bio, fi))
return EOF;
}
return bio->iobuf[bio->iocp++];
}
/*!
* \brief utility used by base_encode()
*/
static int ochar(struct baseio *bio, int c, FILE *so)
{
if (bio->linelength >= BASELINELEN) {
if (fputs(ENDL, so) == EOF) {
return -1;
}
bio->linelength = 0;
}
if (putc(((unsigned char) c), so) == EOF) {
return -1;
}
bio->linelength++;
return 1;
}
/*!
* \brief Performs a base 64 encode algorithm on the contents of a File
* \param filename The path to the file to be encoded. Must be readable, file is opened in read mode.
* \param so A FILE handle to the output file to receive the base 64 encoded contents of the input file, identified by filename.
*
* TODO: shouldn't this (and the above 3 support functions) be put into some kind of external utility location, such as funcs/func_base64.c ?
*
* \return zero on success, -1 on error.
*/
static int base_encode(char *filename, FILE *so)
{
static const unsigned char dtable[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
'1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'};
int i, hiteof = 0;
FILE *fi;
struct baseio bio;
memset(&bio, 0, sizeof(bio));
bio.iocp = BASEMAXINLINE;
if (!(fi = fopen(filename, "rb"))) {
ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s\n", filename, strerror(errno));
return -1;
}
while (!hiteof){
unsigned char igroup[3], ogroup[4];
int c, n;
memset(igroup, 0, sizeof(igroup));
for (n = 0; n < 3; n++) {
if ((c = inchar(&bio, fi)) == EOF) {
hiteof = 1;
break;
}
igroup[n] = (unsigned char) c;
}
if (n > 0) {
ogroup[0]= dtable[igroup[0] >> 2];
ogroup[1]= dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
ogroup[2]= dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
ogroup[3]= dtable[igroup[2] & 0x3F];
if (n < 3) {
ogroup[3] = '=';
if (n < 2)
ogroup[2] = '=';
}
for (i = 0; i < 4; i++)
ochar(&bio, ogroup[i], so);
}
}
fclose(fi);
if (fputs(ENDL, so) == EOF) {
return 0;
}
return 1;
}
static void prep_email_sub_vars(struct ast_channel *ast, struct ast_vm_user *vmu, int msgnum, char *context, char *mailbox, const char *fromfolder, char *cidnum, char *cidname, char *dur, char *date, const char *category, const char *flag)
{
char callerid[256];
@ -5080,7 +4937,7 @@ static const char *ast_str_encode_mime(struct ast_str **end, ssize_t maxlen, con
* \param imap if == 1, indicates the target folder for the email notification to be sent to will be an IMAP mailstore. This causes additional mailbox headers to be set, which would facilitate searching for the email in the destination IMAP folder.
* \param flag, msg_id
*
* The email body, and base 64 encoded attachement (if any) are stored to the file identified by *p. This method does not actually send the email. That is done by invoking the configure 'mailcmd' and piping this generated file into it, or with the sendemail() function.
* The email body, and base 64 encoded attachment (if any) are stored to the file identified by *p. This method does not actually send the email. That is done by invoking the configure 'mailcmd' and piping this generated file into it, or with the sendemail() function.
*/
static void make_email_file(FILE *p,
char *srcemail,
@ -5502,7 +5359,7 @@ static int add_email_attachment(FILE *p, struct ast_vm_user *vmu, char *format,
fprintf(p, "Content-Disposition: attachment; filename=\"%s\"" ENDL ENDL, filename);
else
fprintf(p, "Content-Disposition: attachment; filename=\"%s.%s\"" ENDL ENDL, greeting_attachment, format);
base_encode(fname, p);
ast_base64_encode_file_path(fname, p, ENDL);
if (last)
fprintf(p, ENDL ENDL "--%s--" ENDL "." ENDL, bound);
@ -5555,7 +5412,7 @@ static int sendmail(char *srcemail,
ast_debug(3, "Attaching file '%s', format '%s', uservm is '%d', global is %u\n", attach, format, attach_user_voicemail, ast_test_flag((&globalflags), VM_ATTACH));
/* Make a temporary file instead of piping directly to sendmail, in case the mail
command hangs */
if ((p = vm_mkftemp(tmp)) == NULL) {
if ((p = ast_file_mkftemp(tmp, VOICEMAIL_FILE_MODE & ~my_umask)) == NULL) {
ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
return -1;
} else {
@ -5594,7 +5451,7 @@ static int sendpage(char *srcemail, char *pager, int msgnum, char *context, char
strip_control_and_high(cidname, enc_cidname, sizeof(enc_cidname));
}
if ((p = vm_mkftemp(tmp)) == NULL) {
if ((p = ast_file_mkftemp(tmp, VOICEMAIL_FILE_MODE & ~my_umask)) == NULL) {
ast_log(AST_LOG_WARNING, "Unable to launch '%s' (can't create temporary file)\n", mailcmd);
ast_free(str1);
ast_free(str2);
@ -5940,9 +5797,9 @@ bail:
return nummsgs;
}
/**
/*!
* \brief Determines if the given folder has messages.
* \param mailbox The @ delimited string for user@context. If no context is found, uses 'default' for the context.
* \param mailbox The \@ delimited string for user\@context. If no context is found, uses 'default' for the context.
*
* This function is used when the mailbox is stored in an ODBC back end.
* This invokes the messagecount(). Here we are interested in the presence of messages (> 0) only, not the actual count.
@ -6112,7 +5969,7 @@ static int __has_voicemail(const char *context, const char *mailbox, const char
return ret;
}
/**
/*!
* \brief Determines if the given folder has messages.
* \param mailbox The \@ delimited string for user\@context. If no context is found, uses 'default' for the context.
* \param folder the folder to look in
@ -6145,7 +6002,7 @@ static int has_voicemail(const char *mailbox, const char *folder)
/*!
* \brief Check the given mailbox's message count.
* \param mailbox The @ delimited string for user@context. If no context is found, uses 'default' for the context.
* \param mailbox The \@ delimited string for user\@context. If no context is found, uses 'default' for the context.
* \param urgentmsgs urgent message count.
* \param newmsgs new message count.
* \param oldmsgs old message count pointer
@ -6781,8 +6638,14 @@ static int leave_voicemail(struct ast_channel *chan, char *ext, struct leave_vm_
#endif
RETRIEVE(prefile, -1, ext, context);
if (ast_fileexists(prefile, NULL, NULL) > 0) {
if (ast_streamfile(chan, prefile, ast_channel_language(chan)) > -1)
if (ast_streamfile(chan, prefile, ast_channel_language(chan)) > -1) {
/* We know we have a greeting at this point, so squelch the instructions
* if that is what is being asked of us */
if (ast_test_flag(options, OPT_SILENT_IF_GREET)) {
ast_set_flag(options, OPT_SILENT);
}
res = ast_waitstream(chan, ecodes);
}
#ifdef ODBC_STORAGE
if (success == -1) {
/* We couldn't retrieve the file from the database, but we found it on the file system. Let's put it in the database. */
@ -7240,7 +7103,7 @@ static int save_to_folder(struct ast_vm_user *vmu, struct vm_state *vms, int msg
/* get the current mailbox so that we can point the mailstream back to it later */
curr_mbox = get_folder_by_name(vms->curbox);
/* Create the folder if it dosn't exist */
/* Create the folder if it doesn't exist */
imap_mailbox_name(mailbox, sizeof(mailbox), vms, box, 1); /* Get the full mailbox name */
if (vms->mailstream && !mail_status(vms->mailstream, mailbox, SA_UIDNEXT)) {
if (mail_create(vms->mailstream, mailbox) != NIL) {
@ -7359,7 +7222,7 @@ static int adsi_load_vmail(struct ast_channel *chan, int *useadsi)
bytes = 0;
bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advanced", "3", 1);
bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
bytes += ast_adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
@ -8301,7 +8164,7 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
ast_test_suite_event_notify("FORWARD", "Message: entering forward message menu");
while (!res && !valid_extensions) {
int use_directory = 0;
if (ast_test_flag((&globalflags), VM_DIRECFORWARD)) {
if (ast_test_flag((&globalflags), VM_DIRECTFORWARD)) {
int done = 0;
int retries = 0;
cmd = 0;
@ -8370,7 +8233,7 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
ast_channel_priority_set(chan, old_priority);
} else {
ast_log(AST_LOG_WARNING, "Could not find the Directory application, disabling directory_forward\n");
ast_clear_flag((&globalflags), VM_DIRECFORWARD);
ast_clear_flag((&globalflags), VM_DIRECTFORWARD);
}
} else {
/* Ask for an extension */
@ -8694,7 +8557,7 @@ static int play_message_datetime(struct ast_channel *chan, struct ast_vm_user *v
res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q 'digits/at' HM", NULL);
} else if (!strncasecmp(ast_channel_language(chan), "pl", 2)) { /* POLISH syntax */
res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Q HM", NULL);
} else if (!strncasecmp(ast_channel_language(chan), "pt_BR", 5)) { /* Brazillian PORTUGUESE syntax */
} else if (!strncasecmp(ast_channel_language(chan), "pt_BR", 5)) { /* Brazilian PORTUGUESE syntax */
res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' Ad 'digits/pt-de' B 'digits/pt-de' Y 'digits/pt-as' HM ", NULL);
} else if (!strncasecmp(ast_channel_language(chan), "se", 2)) { /* SWEDISH syntax */
res = ast_say_date_with_format(chan, t, AST_DIGIT_ANY, ast_channel_language(chan), "'vm-received' dB 'digits/at' k 'and' M", NULL);
@ -9434,9 +9297,9 @@ static int vm_intro_gr(struct ast_channel *chan, struct vm_state *vms)
* on vm-message.
* 3) Call ast_say_counted_adjective() to put the proper gender and number
* prefix on vm-new and vm-old (none for English).
* 4) Pass the gender of the language's word for "message" as an agument to
* 4) Pass the gender of the language's word for "message" as an argument to
* this function which is can in turn pass on to the functions which
* say numbers and put endings on nounds and adjectives.
* say numbers and put endings on nouns and adjectives.
*
* All languages require these messages:
* vm-youhave "You have..."
@ -9923,6 +9786,51 @@ static int vm_intro_no(struct ast_channel *chan, struct vm_state *vms)
return res;
}
/* Danish syntax */
static int vm_intro_da(struct ast_channel *chan, struct vm_state *vms)
{
/* Introduce messages they have */
int res;
res = ast_play_and_wait(chan, "vm-youhave");
if (res)
return res;
if (!vms->oldmessages && !vms->newmessages && !vms->urgentmessages) {
res = ast_play_and_wait(chan, "vm-no");
res = res ? res : ast_play_and_wait(chan, "vm-messages");
return res;
}
if (vms->newmessages) {
if ((vms->newmessages == 1)) {
res = ast_play_and_wait(chan, "digits/1");
res = res ? res : ast_play_and_wait(chan, "vm-INBOX");
res = res ? res : ast_play_and_wait(chan, "vm-message");
} else {
res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
res = res ? res : ast_play_and_wait(chan, "vm-INBOXs");
res = res ? res : ast_play_and_wait(chan, "vm-messages");
}
if (!res && vms->oldmessages)
res = ast_play_and_wait(chan, "vm-and");
}
if (!res && vms->oldmessages) {
if (vms->oldmessages == 1) {
res = ast_play_and_wait(chan, "digits/1");
res = res ? res : ast_play_and_wait(chan, "vm-Old");
res = res ? res : ast_play_and_wait(chan, "vm-message");
} else {
res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
res = res ? res : ast_play_and_wait(chan, "vm-Olds");
res = res ? res : ast_play_and_wait(chan, "vm-messages");
}
}
return res;
}
/* GERMAN syntax */
static int vm_intro_de(struct ast_channel *chan, struct vm_state *vms)
{
@ -10403,6 +10311,8 @@ static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm
return vm_intro_nl(chan, vms);
} else if (!strncasecmp(ast_channel_language(chan), "no", 2)) { /* NORWEGIAN syntax */
return vm_intro_no(chan, vms);
} else if (!strncasecmp(ast_channel_language(chan), "da", 2)) { /* DANISH syntax */
return vm_intro_da(chan, vms);
} else if (!strncasecmp(ast_channel_language(chan), "pl", 2)) { /* POLISH syntax */
return vm_intro_pl(chan, vms);
} else if (!strncasecmp(ast_channel_language(chan), "pt_BR", 5)) { /* BRAZILIAN PORTUGUESE syntax */
@ -10424,7 +10334,7 @@ static int vm_intro(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm
}
}
static int vm_instructions_en(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_instructions_en(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
{
int res = 0;
/* Play instructions and wait for new command */
@ -10484,10 +10394,12 @@ static int vm_instructions_en(struct ast_channel *chan, struct ast_vm_user *vmu,
#ifdef IMAP_STORAGE
ast_mutex_unlock(&vms->lock);
#endif
if (!curmsg_deleted) {
res = ast_play_and_wait(chan, "vm-delete");
} else {
res = ast_play_and_wait(chan, "vm-undelete");
if (!nodelete) {
if (!curmsg_deleted) {
res = ast_play_and_wait(chan, "vm-delete");
} else {
res = ast_play_and_wait(chan, "vm-undelete");
}
}
if (!res) {
res = ast_play_and_wait(chan, "vm-toforward");
@ -10512,7 +10424,7 @@ static int vm_instructions_en(struct ast_channel *chan, struct ast_vm_user *vmu,
return res;
}
static int vm_instructions_ja(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_instructions_ja(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
{
int res = 0;
/* Play instructions and wait for new command */
@ -10608,7 +10520,7 @@ static int vm_instructions_ja(struct ast_channel *chan, struct ast_vm_user *vmu,
return res;
}
static int vm_instructions_zh(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_instructions_zh(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
{
int res = 0;
/* Play instructions and wait for new command */
@ -10626,20 +10538,20 @@ static int vm_instructions_zh(struct ast_channel *chan, struct ast_vm_user *vmu,
res = ast_play_and_wait(chan, "vm-opts");
if (!res) {
vms->starting = 0;
return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent, nodelete);
}
}
return res;
}
static int vm_instructions(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
static int vm_instructions(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent, int nodelete)
{
if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* Japanese syntax */
return vm_instructions_ja(chan, vmu, vms, skipadvanced, in_urgent);
return vm_instructions_ja(chan, vmu, vms, skipadvanced, in_urgent, nodelete);
} else if (vms->starting && !strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) syntax */
return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent, nodelete);
} else { /* Default to ENGLISH */
return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent, nodelete);
}
}
@ -11285,12 +11197,14 @@ static int vm_authenticate(struct ast_channel *chan, char *mailbox, int mailbox_
password[0] = '\0';
} else {
if (ast_streamfile(chan, vm_password, ast_channel_language(chan))) {
ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
if (!ast_check_hangup(chan)) {
ast_log(AST_LOG_WARNING, "Unable to stream password file\n");
}
free_user(vmu);
return -1;
}
if (ast_readstring(chan, password, sizeof(password) - 1, 2000, 10000, "#") < 0) {
ast_log(AST_LOG_WARNING, "Unable to read password\n");
ast_log(AST_LOG_NOTICE, "Unable to read password\n");
free_user(vmu);
return -1;
} else if (password[0] == '*') {
@ -11522,6 +11436,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data)
int play_auto = 0;
int play_folder = 0;
int in_urgent = 0;
int nodelete = 0;
#ifdef IMAP_STORAGE
int deleted = 0;
#endif
@ -11584,6 +11499,9 @@ static int vm_execmain(struct ast_channel *chan, const char *data)
play_folder = 0;
}
}
if (ast_test_flag(&flags, OPT_READONLY)) {
nodelete = 1;
}
} else {
/* old style options parsing */
while (*(args.argv0)) {
@ -11608,10 +11526,16 @@ static int vm_execmain(struct ast_channel *chan, const char *data)
else
ast_copy_string(vms.username, args.argv0, sizeof(vms.username));
if (!ast_strlen_zero(vms.username) && (vmu = find_user(&vmus, context ,vms.username)))
skipuser++;
else
if (!ast_strlen_zero(vms.username)) {
if ((vmu = find_user(&vmus, context ,vms.username))) {
skipuser++;
} else {
ast_log(LOG_WARNING, "Mailbox '%s%s%s' doesn't exist\n", vms.username, context ? "@": "", context ? context : "");
valid = 0;
}
} else {
valid = 0;
}
}
if (!valid)
@ -11991,7 +11915,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data)
}
break;
case '7': /* Delete the current message */
if (vms.curmsg >= 0 && vms.curmsg <= vms.lastmsg) {
if (!nodelete && vms.curmsg >= 0 && vms.curmsg <= vms.lastmsg) {
vms.deleted[vms.curmsg] = !vms.deleted[vms.curmsg];
if (useadsi)
adsi_delete(chan, &vms);
@ -12180,7 +12104,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data)
if (!cmd)
cmd = ast_play_and_wait(chan, "vm-opts");
if (!cmd)
cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent);
cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent, nodelete);
break;
}
cmd = ast_play_and_wait(chan, "vm-onefor");
@ -12192,7 +12116,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data)
if (!cmd)
cmd = ast_play_and_wait(chan, "vm-opts");
if (!cmd)
cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent);
cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent, nodelete);
} else
cmd = 0;
break;
@ -12209,7 +12133,7 @@ static int vm_execmain(struct ast_channel *chan, const char *data)
break;
default: /* Nothing */
ast_test_suite_event_notify("PLAYBACK", "Message: instructions");
cmd = vm_instructions(chan, vmu, &vms, 0, in_urgent);
cmd = vm_instructions(chan, vmu, &vms, 0, in_urgent, nodelete);
break;
}
}
@ -12295,7 +12219,7 @@ static int vm_exec(struct ast_channel *chan, const char *data)
if (args.argc == 2) {
if (ast_app_parse_options(vm_app_options, &flags, opts, args.argv1))
return -1;
ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
ast_copy_flags(&leave_options, &flags, OPT_SILENT | OPT_SILENT_IF_GREET | OPT_BUSY_GREETING | OPT_UNAVAIL_GREETING | OPT_MESSAGE_Urgent | OPT_MESSAGE_PRIORITY | OPT_DTMFEXIT);
if (ast_test_flag(&flags, OPT_RECORDGAIN)) {
int gain;
@ -12527,7 +12451,7 @@ AST_TEST_DEFINE(test_voicemail_vmuser)
res = 1;
}
if (strcasecmp(vmu->attachfmt, "wav49")) {
ast_test_status_update(test, "Parse failure for attachftm option\n");
ast_test_status_update(test, "Parse failure for attachfmt option\n");
res = 1;
}
if (strcasecmp(vmu->fromstring, "Voicemail System")) {
@ -14199,7 +14123,7 @@ static int actual_load_config(int reload, struct ast_config *cfg, struct ast_con
if (!(val = ast_variable_retrieve(cfg, "general", "usedirectory")))
val = "no";
ast_set2_flag((&globalflags), ast_true(val), VM_DIRECFORWARD);
ast_set2_flag((&globalflags), ast_true(val), VM_DIRECTFORWARD);
if (!(val = ast_variable_retrieve(cfg, "general", "passwordlocation"))) {
val = "voicemail.conf";
@ -15577,6 +15501,12 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
}
cmd = ast_play_and_wait(chan, "beep");
}
if (cmd == -1) {
/* User has hung up, no options to give */
ast_debug(1, "User hung up before message could be rerecorded\n");
ast_filedelete(tempfile, NULL);
return cmd;
}
recorded = 1;
/* After an attempt has been made to record message, we have to take care of INTRO and beep for incoming messages, but not for greetings */
if (record_gain)
@ -15695,7 +15625,7 @@ static int play_record_review(struct ast_channel *chan, char *playfile, char *re
}
return cmd;
default:
/* If the caller is an ouside caller and the review option is enabled or it's forward intro
/* If the caller is an outside caller and the review option is enabled or it's forward intro
allow them to review the message, but let the owner of the box review
their OGM's */
if (outsidecaller && !ast_test_flag(vmu, VM_REVIEW) && !forwardintro)
@ -16071,7 +16001,7 @@ static struct ast_vm_mailbox_snapshot *vm_mailbox_snapshot_destroy(struct ast_vm
* \param vms The voicemail state corresponding to an open mailbox
* \param msg_ids An array of message identifiers
* \param num_msgs The number of identifiers in msg_ids
* \param msg_nums [out] The message indexes corresponding to the given
* \param[out] msg_nums The message indexes corresponding to the given
* \param vmu
* message IDs
* \pre vms must have open_mailbox() called on it prior to this function.

View File

@ -39,6 +39,11 @@
/*** DOCUMENTATION
<application name="WaitForCondition" language="en_US">
<since>
<version>16.20.0</version>
<version>18.6.0</version>
<version>19.0.0</version>
</since>
<synopsis>
Wait (sleep) until the given condition is true.
</synopsis>
@ -66,7 +71,7 @@
<para>Waits until <replaceable>expression</replaceable> evaluates to true, checking every
<replaceable>interval</replaceable> seconds for up to <replaceable>timeout</replaceable>. Default
is evaluate <replaceable>expression</replaceable> every 50 milliseconds with no timeout.</para>
<example title="Wait for ${condition} to become 1 for up to 40 seconds, checking every 500ms">
<example title="Wait for condition dialplan variable/function to become 1 for up to 40 seconds, checking every 500ms">
same => n,WaitForCondition(#,#["#{condition}"="1"],40,0.5)
</example>
<para>Sets <variable>WAITFORCONDITIONSTATUS</variable> to one of the following values:</para>

View File

@ -23,9 +23,6 @@
*
* \brief Wait for Silence
* - Waits for up to 'x' milliseconds of silence, 'y' times \n
* - WaitForSilence(500,2) will wait for 1/2 second of silence, twice \n
* - WaitForSilence(1000,1) will wait for 1 second of silence, once \n
* - WaitForSilence(300,3,10) will wait for 300ms of silence, 3 times, and return after 10sec \n
*
* \author David C. Troy <dave@popvox.com>
*
@ -78,11 +75,15 @@
playing a message.</para>
<para>Typically you will want to include two or more calls to WaitForSilence when dealing with an answering
machine; first waiting for the spiel to finish, then waiting for the beep, etc.</para>
<para>Examples:</para>
<para>WaitForSilence(500,2) will wait for 1/2 second of silence, twice</para>
<para>WaitForSilence(1000) will wait for 1 second of silence, once</para>
<para>WaitForSilence(300,3,10) will wait for 300ms silence, 3 times, and returns after 10 sec, even if silence
is not detected</para>
<example title="Wait for half a second of silence, twice">
same => n,WaitForSilence(500,2)
</example>
<example title="Wait for one second of silence, once">
same => n,WaitForSilence(1000)
</example>
<example title="Wait for 300 ms of silence, 3 times, and returns after 10 seconds, even if no silence detected">
same => n,WaitForSilence(300,3,10)
</example>
<para>Sets the channel variable <variable>WAITSTATUS</variable> to one of these values:</para>
<variablelist>
<variable name="WAITSTATUS">

View File

@ -97,6 +97,9 @@
<configOption name="quiet">
<synopsis>Silence enter/leave prompts and user intros for this user</synopsis>
</configOption>
<configOption name="hear_own_join_sound">
<synopsis>Determines if the user also hears the join sound when they enter a conference</synopsis>
</configOption>
<configOption name="announce_user_count">
<synopsis>Sets if the number of users should be announced to the user</synopsis>
</configOption>
@ -117,6 +120,9 @@
<configOption name="end_marked">
<synopsis>Kick the user from the conference when the last marked user leaves</synopsis>
</configOption>
<configOption name="end_marked_any">
<synopsis>Kick the user from the conference when any marked user leaves</synopsis>
</configOption>
<configOption name="talk_detection_events">
<synopsis>Set whether or not notifications of when a user begins and ends talking should be sent out as events over AMI</synopsis>
</configOption>
@ -384,7 +390,7 @@
specific conference bridge.
You should be aware that there are potential races between testing for the
existence of a bridge, and taking action upon that information, consider
for example two callers executing the check simultaniously, and then taking
for example two callers executing the check simultaneously, and then taking
special action as "first caller" into the bridge. The same for exiting,
directly after the check the bridge can be destroyed before the new caller
enters (creating a new bridge), for example, and the "first member" actions
@ -459,7 +465,7 @@
<enum name="sound_kicked"><para>The sound played to a user who has been kicked from the conference.</para></enum>
<enum name="sound_muted"><para>The sound played when the mute option it toggled on.</para></enum>
<enum name="sound_unmuted"><para>The sound played when the mute option it toggled off.</para></enum>
<enum name="sound_binaural_on"><para>The sound played when binaural auudio is turned on.</para></enum>
<enum name="sound_binaural_on"><para>The sound played when binaural audio is turned on.</para></enum>
<enum name="sound_binaural_off"><para>The sound played when the binaural audio is turned off.</para></enum>
<enum name="sound_only_person"><para>The sound played when the user is the only person in the conference.</para></enum>
<enum name="sound_only_one"><para>The sound played to a user when there is only one other
@ -1353,7 +1359,7 @@ static int add_menu_entry(struct conf_menu *menu, const char *dtmf, const char *
comma = strchr(tmp_action_names, ',');
/* If the next action has brackets with comma delimited arguments in it,
* make the delimeter ')' instead of a comma to preserve the argments */
* make the delimeter ')' instead of a comma to preserve the arguments */
if (startbrace && endbrace && comma && (comma > startbrace && comma < endbrace)) {
delimiter = ")";
} else {
@ -1437,10 +1443,7 @@ static int add_menu_entry(struct conf_menu *menu, const char *dtmf, const char *
/* if adding any of the actions failed, bail */
if (res) {
struct conf_menu_action *menu_action;
while ((menu_action = AST_LIST_REMOVE_HEAD(&menu_entry->actions, action))) {
ast_free(menu_action);
}
conf_menu_entry_destroy(menu_entry);
ast_free(menu_entry);
return -1;
}
@ -1449,6 +1452,7 @@ static int add_menu_entry(struct conf_menu *menu, const char *dtmf, const char *
AST_LIST_TRAVERSE_SAFE_BEGIN(&menu->entries, cur, entry) {
if (!strcasecmp(cur->dtmf, menu_entry->dtmf)) {
AST_LIST_REMOVE_CURRENT(entry);
conf_menu_entry_destroy(cur);
ast_free(cur);
break;
}
@ -1574,12 +1578,18 @@ static char *handle_cli_confbridge_show_user_profile(struct ast_cli_entry *e, in
ast_cli(a->fd,"Quiet: %s\n",
u_profile.flags & USER_OPT_QUIET ?
"enabled" : "disabled");
ast_cli(a->fd,"Hear Join: %s\n",
u_profile.flags & USER_OPT_HEAR_OWN_JOIN_SOUND ?
"enabled" : "disabled");
ast_cli(a->fd,"Wait Marked: %s\n",
u_profile.flags & USER_OPT_WAITMARKED ?
"enabled" : "disabled");
ast_cli(a->fd,"END Marked: %s\n",
ast_cli(a->fd,"END Marked (All): %s\n",
u_profile.flags & USER_OPT_ENDMARKED ?
"enabled" : "disabled");
ast_cli(a->fd,"END Marked (Any): %s\n",
u_profile.flags & USER_OPT_ENDMARKEDANY ?
"enabled" : "disabled");
ast_cli(a->fd,"Drop_silence: %s\n",
u_profile.flags & USER_OPT_DROP_SILENCE ?
"enabled" : "disabled");
@ -2396,12 +2406,14 @@ int conf_load_config(void)
aco_option_register(&cfg_info, "startmuted", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_STARTMUTED);
aco_option_register(&cfg_info, "music_on_hold_when_empty", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_MUSICONHOLD);
aco_option_register(&cfg_info, "quiet", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_QUIET);
aco_option_register(&cfg_info, "hear_own_join_sound", ACO_EXACT, user_types, "yes", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_HEAR_OWN_JOIN_SOUND);
aco_option_register_custom(&cfg_info, "announce_user_count_all", ACO_EXACT, user_types, "no", announce_user_count_all_handler, 0);
aco_option_register(&cfg_info, "announce_user_count", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_ANNOUNCEUSERCOUNT);
/* Negative logic. Defaults to "yes" and evaluates with ast_false(). If !ast_false(), USER_OPT_NOONLYPERSON is cleared */
aco_option_register(&cfg_info, "announce_only_user", ACO_EXACT, user_types, "yes", OPT_BOOLFLAG_T, 0, FLDSET(struct user_profile, flags), USER_OPT_NOONLYPERSON);
aco_option_register(&cfg_info, "wait_marked", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_WAITMARKED);
aco_option_register(&cfg_info, "end_marked", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_ENDMARKED);
aco_option_register(&cfg_info, "end_marked_any", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_ENDMARKEDANY);
aco_option_register(&cfg_info, "talk_detection_events", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_TALKER_DETECT);
aco_option_register(&cfg_info, "dtmf_passthrough", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_DTMF_PASS);
aco_option_register(&cfg_info, "announce_join_leave", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_ANNOUNCE_JOIN_LEAVE);

View File

@ -14,9 +14,6 @@
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*
* Please follow coding guidelines
* http://svn.digium.com/view/asterisk/trunk/doc/CODING-GUIDELINES
*/
/*! \file
@ -52,8 +49,6 @@ void conf_invalid_event_fn(struct confbridge_user *user)
* \brief Mute the user and play MOH if the user requires it.
*
* \param user Conference user to mute and optionally start MOH on.
*
* \return Nothing
*/
static void conf_mute_moh_inactive_waitmarked(struct confbridge_user *user)
{

View File

@ -14,9 +14,6 @@
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*
* Please follow coding guidelines
* http://svn.digium.com/view/asterisk/trunk/doc/CODING-GUIDELINES
*/
/*! \file

View File

@ -14,9 +14,6 @@
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*
* Please follow coding guidelines
* http://svn.digium.com/view/asterisk/trunk/doc/CODING-GUIDELINES
*/
/*! \file

View File

@ -14,9 +14,6 @@
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*
* Please follow coding guidelines
* http://svn.digium.com/view/asterisk/trunk/doc/CODING-GUIDELINES
*/
/*! \file

View File

@ -14,9 +14,6 @@
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*
* Please follow coding guidelines
* http://svn.digium.com/view/asterisk/trunk/doc/CODING-GUIDELINES
*/
/*! \file
@ -85,37 +82,39 @@ static void leave_marked(struct confbridge_user *user)
conf_remove_user_marked(user->conference, user);
if (user->conference->markedusers == 0) {
AST_LIST_TRAVERSE_SAFE_BEGIN(&user->conference->active_list, user_iter, list) {
/* Kick ENDMARKED cbu_iters */
if (ast_test_flag(&user_iter->u_profile, USER_OPT_ENDMARKED) && !user_iter->kicked) {
if (ast_test_flag(&user_iter->u_profile, USER_OPT_WAITMARKED)
&& !ast_test_flag(&user_iter->u_profile, USER_OPT_MARKEDUSER)) {
AST_LIST_REMOVE_CURRENT(list);
user_iter->conference->activeusers--;
AST_LIST_INSERT_TAIL(&user_iter->conference->waiting_list, user_iter, list);
user_iter->conference->waitingusers++;
}
user_iter->kicked = 1;
pbx_builtin_setvar_helper(user_iter->chan, "CONFBRIDGE_RESULT", "ENDMARKED");
ast_bridge_remove(user_iter->conference->bridge, user_iter->chan);
} else if (ast_test_flag(&user_iter->u_profile, USER_OPT_WAITMARKED)
&& !ast_test_flag(&user_iter->u_profile, USER_OPT_MARKEDUSER)) {
need_prompt = 1;
/* If all marked users have left, or we're set to kick if any marked user leaves, then boot everyone */
AST_LIST_TRAVERSE_SAFE_BEGIN(&user->conference->active_list, user_iter, list) {
if (user->conference->markedusers > 0 && !ast_test_flag(&user_iter->u_profile, USER_OPT_ENDMARKEDANY)) {
continue;
}
/* Kick ENDMARKED cbu_iters */
if ((ast_test_flag(&user_iter->u_profile, USER_OPT_ENDMARKED) || ast_test_flag(&user_iter->u_profile, USER_OPT_ENDMARKEDANY)) && !user_iter->kicked) {
if (ast_test_flag(&user_iter->u_profile, USER_OPT_WAITMARKED)
&& (!ast_test_flag(&user_iter->u_profile, USER_OPT_MARKEDUSER) || ast_test_flag(&user_iter->u_profile, USER_OPT_ENDMARKEDANY))) {
AST_LIST_REMOVE_CURRENT(list);
user_iter->conference->activeusers--;
AST_LIST_INSERT_TAIL(&user_iter->conference->waiting_list, user_iter, list);
user_iter->conference->waitingusers++;
} else {
/* User is neither wait_marked nor end_marked; however, they
* should still hear the prompt.
*/
need_prompt = 1;
}
user_iter->kicked = 1;
pbx_builtin_setvar_helper(user_iter->chan, "CONFBRIDGE_RESULT", "ENDMARKED");
ast_bridge_remove(user_iter->conference->bridge, user_iter->chan);
} else if (ast_test_flag(&user_iter->u_profile, USER_OPT_WAITMARKED)
&& !ast_test_flag(&user_iter->u_profile, USER_OPT_MARKEDUSER)) {
need_prompt = 1;
AST_LIST_REMOVE_CURRENT(list);
user_iter->conference->activeusers--;
AST_LIST_INSERT_TAIL(&user_iter->conference->waiting_list, user_iter, list);
user_iter->conference->waitingusers++;
} else {
/* User is neither wait_marked nor end_marked nor end_marked_any; however, they
* should still hear the prompt.
*/
need_prompt = 1;
}
AST_LIST_TRAVERSE_SAFE_END;
}
AST_LIST_TRAVERSE_SAFE_END;
switch (user->conference->activeusers) {
case 0:

View File

@ -14,9 +14,6 @@
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*
* Please follow coding guidelines
* http://svn.digium.com/view/asterisk/trunk/doc/CODING-GUIDELINES
*/
/*! \file

View File

@ -14,9 +14,6 @@
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*
* Please follow coding guidelines
* http://svn.digium.com/view/asterisk/trunk/doc/CODING-GUIDELINES
*/
/*! \file

View File

@ -14,9 +14,6 @@
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*
* Please follow coding guidelines
* http://svn.digium.com/view/asterisk/trunk/doc/CODING-GUIDELINES
*/
/*! \file

View File

@ -70,6 +70,8 @@ enum user_profile_flags {
USER_OPT_ECHO_EVENTS = (1 << 18), /*!< Send events only to the admin(s) */
USER_OPT_TEXT_MESSAGING = (1 << 19), /*!< Send text messages to the user */
USER_OPT_ANSWER_CHANNEL = (1 << 20), /*!< Sets if the channel should be answered if currently unanswered */
USER_OPT_HEAR_OWN_JOIN_SOUND = (1 << 21), /*!< Set if the caller should hear the join sound */
USER_OPT_ENDMARKEDANY = (1 << 22), /*!< Set if the user should be kicked after any marked user exits */
};
enum bridge_profile_flags {
@ -457,8 +459,6 @@ void conf_ended(struct confbridge_conference *conference);
* \brief Update the actual mute status of the user and set it on the bridge.
*
* \param user User to update the mute status.
*
* \return Nothing
*/
void conf_update_user_mute(struct confbridge_user *user);
@ -466,8 +466,6 @@ void conf_update_user_mute(struct confbridge_user *user);
* \brief Stop MOH for the conference user.
*
* \param user Conference user to stop MOH on.
*
* \return Nothing
*/
void conf_moh_stop(struct confbridge_user *user);
@ -475,8 +473,6 @@ void conf_moh_stop(struct confbridge_user *user);
* \brief Start MOH for the conference user.
*
* \param user Conference user to start MOH on.
*
* \return Nothing
*/
void conf_moh_start(struct confbridge_user *user);
@ -487,8 +483,6 @@ void conf_mute_only_active(struct confbridge_conference *conference);
/*! \brief Callback to execute any time we transition from zero to one active users
* \param conference The conference bridge with a single active user joined
* \retval 0 success
* \retval -1 failure
*/
void conf_handle_first_join(struct confbridge_conference *conference);
@ -702,7 +696,7 @@ int conf_announce_channel_push(struct ast_channel *ast);
* \since 13.22.0
* \since 15.5.0
*
* \param confbridge_name The name to search for
* \param conference_name The name to search for
*
* \return ConfBridge (which must be unreffed) or NULL.
*/

Some files were not shown because too many files have changed in this diff Show More