Compare commits

...

460 Commits
master ... 17.4

Author SHA1 Message Date
Asterisk Development Team 4ed3cec580 Update for 17.4.0 2020-04-30 09:28:46 -05:00
Asterisk Development Team 21286195d5 Update for 17.4.0-rc2 2020-04-28 14:20:57 -05:00
Guido Falsi f44bd5c806 res_rtp_asterisk: Protect access to nochecksums with #ifdef
Recently code accessing nochecksums variable has been added without including #ifdef SO_NO_CHECK protection, while the variable is created only when such constant is defined.

ASTERISK-28852 #close

Change-Id: I381718893b80599ab8635f2b594a10c1000d595e
2020-04-28 13:56:05 -05:00
Guido Falsi 2a7a252ba1 core/dns: Add system include required on FreeBSD
While testing the latest RC on FreeBSD I noticed this new file fails to build. On FreeBSD inlcuding resolv.h requires sockaddr_in to be defined, and it's defined in netinet/in.h. So I added this include.

ASTERISK-28853 #close

Change-Id: I6997daf3956e6eb70ab6cb358628d162fad80079
2020-04-28 10:48:53 -05:00
Asterisk Development Team f3eaf2b7d1 Update for 17.4.0-rc1 2020-04-23 11:37:51 -05:00
Asterisk Development Team 3907b81397 Update CHANGES and UPGRADE.txt for 17.4.0 2020-04-23 11:04:29 -05:00
Joshua C. Colp fe11bc7a2a stream: Enforce formats immutability and ensure formats exist.
Some places in Asterisk did not treat the formats on a stream
as immutable when they are.

The ast_stream_get_formats function is now const to enforce this
and parts of Asterisk have been updated to take this into account.
Some violations of this were also fixed along the way.

An additional minor tweak is that streams are now allocated with
an empty format capabilities structure removing the need in various
places to check that one is present on the stream.

ASTERISK-28846

Change-Id: I32f29715330db4ff48edd6f1f359090458a9bfbe
2020-04-23 09:16:38 -05:00
sungtae kim 9a90ab3722 res_ari_channels: Fixed endpoint 80 characters limit
Fixed it to copy the entire string from the requested endpoint body except tech-prefix.

ASTERISK-28847

Change-Id: I91b5f6708a1200363f3267b847dd6a0915222c25
2020-04-22 15:59:08 -05:00
Joshua C. Colp e7b6736ba3 fax: Fix crashes in PJSIP re-negotiation scenarios.
This change fixes a few re-negotiation issues
uncovered with fax.

1. The fax support uses its own mechanism for
re-negotiation by conveying T.38 information in
its own frames. The new support for re-negotiating
when adding/removing/changing streams was also
being triggered for this causing multiple re-INVITEs.
The new support will no longer trigger when
transitioning between fax.

2. In off-nominal re-negotiation cases it was
possible for some state information to be left
over and used by the next re-negotiation. This
is now cleared.

ASTERISK-28811
ASTERISK-28839

Change-Id: I8ed5924b53be9fe06a385c58817e5584b0f25cc2
2020-04-22 10:14:03 -05:00
DanielYK 139cd912af res_pjsip: Fixed format of IPv6 addresses for external media addresses
ASTERISK-28835

Change-Id: I66289afd164c5cdd6c5caa39e79d629a467e7a26
2020-04-21 17:35:44 -05:00
Alexander Traud 2fc7780a3a chan_sip: externhost/externaddr with non-default TCP/TLS ports.
ASTERISK-28372
Reported by: Anton Satskiy

ASTERISK-24428
Reported by: sstream

Change-Id: I2b7432a9bf3b09dc8515297ff955636db7a6224c
2020-04-20 13:44:07 -05:00
Alexander Traud 6d4ddc3151 cdr_odbc: Sync load- and build-time deps.
MODULEINFO is checked while buidling/linking the module.
AST_MODULE_INFO is checked while loading/running the module.

ASTERISK-28838

Change-Id: I55dc05ce19552d0415c9045021b42bd82ef44e52
2020-04-20 12:05:58 -05:00
Alexander Traud 71c70dfbfb res_pjsip: Sync load- and build-time deps.
MODULEINFO is checked while buidling/linking the module.
AST_MODULE_INFO is checked while loading/running the module.

ASTERISK-28838

Change-Id: I4bb868532ca217fec1351885d99eb55c21b58042
2020-04-20 12:03:42 -05:00
Joshua C. Colp 21f0759b2c confbridge: Add support for disabling text messaging.
When in a conference bridge it may be necessary to have
text messages disabled for specific participants or for
all. This change adds a configuration option, "text_messaging",
which can be used to enable or disable this on the
user profile. By default existing behavior is preserved
as it defaults to "yes".

ASTERISK-28841

Change-Id: I30b5d9ae6f4803881d1ed9300590d405e392bc13
2020-04-20 11:32:26 -05:00
Alexander Traud c4c259c3af res_pjsip_refer: Add build-time dependency.
ASTERISK-28838

Change-Id: Ic693c3f464e35ec0db242afdb0a1415806af4e25
2020-04-20 10:55:28 -05:00
Alexander Traud 9fc5654e5a app_getcpeid: Add build-time dependency.
ASTERISK-28838

Change-Id: I68b78e7e4718be82507247433127ce3992a5ba96
2020-04-20 10:05:06 -05:00
Alexander Traud 2cd2852f57 curl: Add build-time dependency.
ASTERISK-28838

Change-Id: I34724e799e1ffaf723eb2c358abe8934dbadcd52
2020-04-20 09:57:29 -05:00
Alexander Traud 12dda5d867 res_pjsip: Add build-time dependency.
ASTERISK-28838

Change-Id: Icb08304744ae3f34dce6ccb76f94379b8382a074
2020-04-20 09:21:10 -05:00
Alexander Traud fccfa256a3 pjproject_bundled: Honor --without-pjproject.
ASTERISK-28837

Change-Id: Id057324912a3cfe6f50af372675626bb515907d9
2020-04-17 06:54:46 -05:00
Pirmin Walthert 7ed8078bdb res_rtp_asterisk: Resolve loop when receive buffer is flushed
When the receive buffer was flushed by a received packet while it
already contained a packet with the same sequence number, Asterisk
never left the while loop which tried to order the packets.

This change makes it so if the packet is in the receive buffer it
is retrieved and freed allowing the buffer to empty.

ASTERISK-28827

Change-Id: Idaa376101bc1ac880047c49feb6faee773e718b3
2020-04-17 06:08:48 -05:00
Alexander Traud 3a5bdc68b2 install_prereq: Add libcap for high bits in DiffServ/ToS.
works automatically; see Mantis 7047 (now ASTERISK-6863)

Change-Id: I27d2c109180bd857b6757fd532de48eddb78aee6
2020-04-16 10:36:40 -05:00
Alexander Traud 3b4be152d5 chan_sip: DiffServ/ToS not only on UDP but also on TCP and TLS sockets.
ASTERISK-27195
Reported by: Joshua Roys

Change-Id: I6e72ecb874200dec7a3865c7babaf5ac0d3101de
2020-04-16 10:35:53 -05:00
Alexander Traud 39f5be81a3 BuildSystem: Only if found LibPRI, check its optional parts.
Change-Id: If8445f899ee4ce0c606c484943d4ce0c8e43b5da
2020-04-16 09:53:18 -05:00
Pirmin Walthert 26dec66598 res_rtp_asterisk: Free payload when error on insertion to data buffer
When the ast_data_buffer_put rejects to add a packet, for example because
the buffer already contains a packet with the same sequence number, the
payload will never be freed, resulting in a memory leak.

The data buffer will now return an error if this situation occurs
allowing the caller to free the payload. The res_rtp_asterisk module
has also been updated to do this.

ASTERISK-28826

Change-Id: Ie6c49495d1c921d5f997651c7d0f79646f095cf1
2020-04-15 14:01:03 -05:00
Alexander Traud 77e2afe8cc BuildSystem: Only if found external PJProject, check its optional parts.
Change-Id: I11d5693d25c166c99d8cebffc16184d58f6362de
2020-04-15 11:26:27 -05:00
bernard merindol 7544e6d095 res_rtp_asterisk.c: Check for first DTMF having timestamp set to 0
When the first DTMF receive in RF2833 codec have TimeStamp at 0
is not processed.

ASTERISK-28812

Change-Id: I3196803a062dd2daee4938c9a778c3810cb7e504
2020-04-14 10:49:59 -05:00
Jean Aunis c23f899254 func_volume: Accept decimal number as argument
Allow voice volume to be multiplied or divided by a floating point number.

ASTERISK-28813

Change-Id: I5b42b890ec4e1f6b0b3400cb44ff16522b021c8c
2020-04-14 09:28:24 -05:00
Jaco Kroon 7a568549ee res_rtp_asterisk: iterate all local addresses looking to populate ICE.
By using pjproject to give us a list of candidates, and then filtering,
if the host has >32 addresses configured, then it is possible that we
end up filtering out all 32 of those, and ending up with no candidates
at all.  Instead, get getifaddrs (which pjsip is using underlying
anyway) to retrieve all local addresses, and iterate those, adding the
first 32 addresses not excluded by the ICE ACL.

In our setup at any point in time We've got between 6 and 328 addresses
on any given system.  The lower limit is the lower limit but the upper
limit is growing on a near daily basis currently.

Change-Id: I109eaffc3e2b432f00bf958e3caa0f38cacb4edb
Signed-off-by: Jaco Kroon <jaco@uls.co.za>
2020-04-13 19:43:23 -05:00
Alexander Traud 84495aae4c pjproject_bundled: Repair ./configure --with-ssl without ARG.
ASTERISK-28758
Reported by: Patrick Wakano
Reported by: Dmitriy Serov

Change-Id: Ifb6b85c559d116739af00bc48d1f547caa85efac
2020-04-13 19:41:26 -05:00
Jaco Kroon c3d49c304b res_pjsip: document legal dtls_verify endpoint options.
Change-Id: I7fa7c5c8a7ddb0bd525982f58bff3264ebbd9a1b
2020-04-13 17:49:50 -05:00
Alexander Traud 8bbc6605c9 BuildSystem: Search for Python/C API when possibly needed only.
The Python/C API is used only if the Test Framework was enabled in Asterisk
'make menuselect'. The Test Framework is available only if the Developer Mode
was enabled in Asterisk './configure --enable-dev-mode'. And that Python/C API
is used only if the PJProject was found and not disabled in Asterisk; the user
did not go for './configure --without-pjproject'.

Furthermore, because version 2 of that Python/C API is required (currently) and
because some platforms do not offer a generic version 2, the script searches
for 2.7 explicitly as well.

To avoid version mismatch between the Python/C API and the Python environment,
the script searches for the latter in the same versions, in the same the order
as well. Because this Python/C API is just for (some) Asterisk contributors,
the script also goes for the Python 3 environment as a last resort for all
other Asterisk users. This allows 'make full' even on minimal installations of
Ubuntu 18.04 LTS and newer.

Because the Python/C API is Asterisk contributor specific, the Python packages
are removed from the script './contrib/scripts/install_prereq' as this script
is intended for Asterisk users. Asterisk contributors have to install much more
packages in any case, like:
sudo apt install autoconf automake git git-review python2.7-dev

ASTERISK-28824
ASTERISK-27717

Change-Id: Id46d357e18869f64dcc217b8fdba821b63eeb876
2020-04-13 16:54:55 -05:00
traud 223da4dfa1 chan_sip: TCP/TLS client without server.
It is possible to configure a TCP/TLS client without having a TCP/TLS
server. In that case, no error or warning was printed but the headers
Contact and Via in SIP REGISTER were "(null)".

ASTERISK-28798

Change-Id: I387ca5cb6a65f1eb675a29c5e41df8ec6c242ab2
2020-04-13 16:39:27 -05:00
Alexander Traud 44f921bb13 res_rtp_asterisk: Build without PJProject.
Change-Id: Ifc5059cd867e77b9c92ed9f4b895a9a91200d3ec
2020-04-13 15:03:03 -05:00
Alexander Traud e832fb6f1c _pjsua: Build even with Clang.
Change-Id: Iebf7687613aa0295ea3c82256460b337f1595be2
2020-04-13 12:06:45 -05:00
Kevin Harwell d38839067b chan_pjsip: digit_begin - constant DTMF tone if RTP is not setup yet
If chan_pjsip is configured for DTMF_RFC_4733, and the core triggers a
digit begin before media, or rtp has been setup then it's possible the
outgoing channel will hear a constant DTMF tone upon answering.

This happens because when there is no media, or rtp chan_pjsip notifies
the core to initiate inband DTMF. However, upon digit end if media, and
rtp become available then chan_pjsip does not notify the core to stop
inband DTMF. Thus the tone continues playing.

This patch makes it so chan_pjsip only notifies the core to start
inband DTMF in only the required cases. Now if there is no media, or
rtp availabe upon digit begin chan_pjsip does nothing, but tells the
core it handled it.

ASTERISK-28817 #close

Change-Id: I0dbea9fff444a2595fb18c64b89653e90d2f6eb5
2020-04-13 11:03:10 -05:00
Alexander Traud 1f7c32f397 bridge_softmix_binaural: Show state in menuselect.
ASTERISK-28819

Change-Id: Iba7ee7bc7936d7a156171c8fc0f1670e864e7600
2020-04-13 10:29:38 -05:00
traud 5aeb31e790 BuildSystem: Remove doc/tex and doc/pdf leftovers.
Furthermore, the nowhere used compress is removed.

ASTERISK-28816

Change-Id: I77daab80cfabb56d51c3ea6b1d14bd9b9fbc577c
2020-04-13 10:24:03 -05:00
Alexander Traud dda530002a BuildSystem: Allow space in path.
ASTERISK-28818

Change-Id: Ib7f246896457d9e3b14d7f5199136d6545ce0b6f
2020-04-09 07:07:51 -05:00
traud c971769db5 res_rtp_asterisk: Avoid absolute value on unsigned subtraction.
ASTERISK-28809

Change-Id: I269731715347c8e5ef7db1b6ffd3f8d15fc04be4
2020-04-08 09:37:59 -05:00
Sebastien Duthil a29fd59340 func_channel: allow reading 4 fields from dialplan
The following fields return an error when read from dialplan:

- exten
- context
- userfield
- channame

ASTERISK-28796 #close

Change-Id: Ieacaac629490f8710fdacc9de80ed5916c5f6ee2
2020-04-08 09:22:12 -05:00
Sean Bright f56e4e73af Revert "res_config_odbc: Preserve empty strings returned by the database"
This reverts commit a3a2fbaec6.

Reason for revert: There is a lot of code that relies on the broken
behavior that this fixes.

Change-Id: I410c395a0168acbdaf89e616e3cb5e1312d190cb
2020-04-08 08:32:58 -05:00
traud a14690fc00 test_stasis: Avoid always true warning with clang.
ASTERISK-28808

Change-Id: I5e76831373532d7b8065d024e66cd1fb75dedd80
2020-04-07 19:00:56 -05:00
traud 45a4cb163c chan_unistim: Avoid tautological warnings with clang.
ASTERISK-28803

Change-Id: I15449621b68d0ad4d57b7c337c1167adb15135af
2020-04-07 18:14:57 -05:00
Jaco Kroon a5119e9600 main/backtrace: binutils-2.34 fix.
My tester missed this one previously, have confirmed a positive build
this time round.

Change-Id: Id06853375954a200f03f9a1b9c97fe0b10d31fbf
2020-04-06 10:28:58 -05:00
Joshua C. Colp 79b453b579 res_pjsip: Don't set endpoint to unavailable in all cases.
When an AOR is modified endpoints are updated that reference
the AOR so they can start receiving updates and reflect the
correct state. If this is the case then we shouldn't change
the endpoint to be offline if it does not reference the AOR
but instead only when the endpoint is completely updated for
all its AORs.

ASTERISK-28056
patches:
  pjsip_options-aor.diff submitted by jhord (license 6978)

Change-Id: I3ee00023be2393113cd4e056599f23f3499ef164
2020-04-06 09:15:37 -05:00
Kevin Harwell a03cb75523 channel: write to a stream on multi-frame writes
If a frame handling routine returns a list of frames (vs. a single frame)
those frames are never passed to a tech's write_stream handler even if one is
available. For instance, if a codec translation occurred and that codec
returned multiple frames then those particular frames were always only sent
to the tech's "write" handler. If that tech (pjsip for example) was stream
capable then those frames were essentially ignored. Thus resulting in bad
audio.

This patch makes it so the "write_stream" handler is appropriately called
for all cases, and for all frames if available.

ASTERISK-28795 #close

Change-Id: I868faea0b73a07ed5a32c2b05bb9cf4b586f739d
2020-03-31 13:05:50 -05:00
traud 96923ec871 test_utils: Avoid incorrect error message on load.
In case of no OpenSSL headers, the module was built but did not load.

ASTERISK-28789

Change-Id: Ie007e84296bcf2bd4237f19d68ba5f932b84cd02
2020-03-31 12:50:00 -05:00
sungtae kim 41c1e0b45d dial.c: Removed dial string 80 character limitation
The dial application had 80 characters of destination length
limitation. But this limitation causes unexpected dial string
cut if the dial string is long.

Removed unnecessary limited buffer to support longer dial
destination.

ASTERISK-27946

Change-Id: I72c8f0319a4b47e8180817a66a7e9bde063cb330
2020-03-31 12:13:40 -05:00
traud bdc0aaca9d func_aes: Avoid incorrect error message on load.
In case of no OpenSSL headers, the module func_aes was built but did not load.

ASTERISK-28788

Change-Id: I0b99b8468cbeb3b0eab23069cbd64062ef885ffc
2020-03-31 11:58:53 -05:00
Torrey Searle 46be4668e3 res_pjsip_session: implement processing of Content-Disposition
RFC5621 requires any content type with a Content-Disposition
with handling=required to be rejected with a 415 response

ASTERISK-28782 #close

Change-Id: Iad969df75936730254b95c1a8bc3b48497070bb4
2020-03-31 11:09:07 -05:00
Jaco Kroon 1b01a6abfd acl: implement a centralized ACL output mechanism for HAs and ACLs.
named_acl.c (which is really a named_ha) now uses ast_ha_output.

I've also updated main/manager.c to output the actual ACL on "manager
show user <username>" if one is set.  If this works then we can add
similar to other modules as required.

Change-Id: I0ec9876a90dddd379c80ec078d48e3ee6991eb0f
2020-03-31 10:59:12 -05:00
Joshua C. Colp 5e24379cf2 chan_sip: Send 403 when ACL fails.
Change-Id: I0910c79196f2b7c7e5ad6f1db95e83800ac737a2
2020-03-31 10:16:11 -05:00
Joshua C. Colp 26c75683bf CHANGES: Change md file extension to txt.
Change-Id: I168e2d3a65d444fb0961bd228257441fe718f6a7
(cherry picked from commit c9cd681261)
2020-03-26 11:54:21 -05:00
Joshua C. Colp e181cbde63 res_pjsip_session: Apply intention behind requested formats.
When an outgoing channel is created a list of formats may
optionally be provided which is used as a request that the
formats be used if possible. If an endpoint is not configured
for any of the formats we ignore this request and use what is
configured. This has the side effect of also including other
stream types (such as video) that were not present in the
requested formats.

This change makes it so that the intention of the request is
preserved - that is if only an audio format is requested then
even if there is no joint audio format between the request and
the configuration we will still only place an audio stream in
the outgoing call.

ASTERISK-28787

Change-Id: Ia54c0c63e94aca176169b9bae4bb8a8380ea245f
2020-03-26 11:54:05 -05:00
Joshua C. Colp 4b2729e89d res_rtp_asterisk: Ensure sufficient space for worst case NACK.
ASTERISK-28790

Change-Id: I10df52f98b19ed62575f25dab36e82d136dccd99
2020-03-26 08:36:58 -05:00
Jaco Kroon ba47752d0d netsock2: compile fixes.
This fixes ast_addressfamily_to_sockaddrsize to reference the
provided argument, and ast_sockaddr_from_sockaddr to not use the name of
a structure as argument.

Change-Id: Ibf5db469c47c3b4214edf8456326086174e8edd7
2020-03-26 07:44:10 -05:00
Kevin Harwell 9255a17410 ast_coredumper: add Asterisk information dump
This patch makes it so ast_coredumper now outputs the following information to
a *-info.txt file when processing a core file:

  asterisk version and "built by" string
  BUILD_OPTS
  system start, and last reloaded date/time
  taskprocessor list
  equivalent of "bridge show all"
  equivalent of "core show channels verbose"

Also a slight modification was made when trying to obtain the pid(s) of a
running Asterisk. If it fails to retrieve any it now reports an error.

Change-Id: I54f35c19ab69b8f8dc78cc933c3fb7c99cef346b
2020-03-26 07:41:18 -05:00
Jaco Kroon 836203a3fd dahdiras: Only set plugin dahdi.so to pppd if we're running as root.
Users of this should set plugin dahdi.so in their options file.

ASTERISK-16676

Change-Id: I6d01ad0a10e9fea477876d0941c3f38aac357e91
2020-03-25 17:24:20 -05:00
Jaco Kroon 122ef44584 dundi: fix NULL dereference.
If a negative (error) return is received from dundi_lookup_internal,
this is not handled correctly when assigning the result to the buffer.
As such, use a signed integer in the assignment and do a proper
comparison.

ASTERISK-21205

Change-Id: I5214ebb6491e2bd14f90c7d3ce229da86888f739
2020-03-25 17:22:05 -05:00
Joshua C. Colp 6c4e181b2f res_pjsip_sdp_rtp: Only do hold/unhold on default audio stream.
When examining a stream to determine hold/unhold information we
only care about the default audio stream. Other streams aren't
used for hold/unhold.

ASTERISK-28784

Change-Id: I7a1f10f07822c4aee1f98a38b9628849b578afe4
2020-03-25 15:21:58 -05:00
Sungtae Kim b58dfbc68a res_pjsip_session: Fixed wrong session termination
When the Asterisk receives 200 OK with invalid SDP,
the Asterisk/PJPROJECT terminating the session.
But if the channel was in the Bridge, Asterisk tries send
the Re-Invite before terminating the session.
And when the Asterisk sending the Re-Invite, it doesn't check
the SDP is NULL or not. This crashes the Asterisk.

Fixed it to close the session correctly if the UAS sends the
200 OK with wrong SDP.

ASTERISK-28743

Change-Id: Ifa864e0e125b1a7ed2f3abd4164187e1dddc56da
2020-03-25 07:55:02 -05:00
Jaco Kroon 6706af0d5b build: enable building with uClibc
This patch has been included in Gentoo distribution for at least since
asterisk 1.8, but there are references in the logs going back as far as
1.0.0 - not sure if this is still required in any way, it does apply,
and it doesn't (as far as we can determine) cause build failures.

Change-Id: I46d8845e30200205e80580680bf060aa3012ba54
2020-03-25 07:30:01 -05:00
Jaco Kroon 9c911b0f9b build: search from newest to oldest for gmime.
We (Gentoo distribution) reckon that in the case of multiple versions of
gmime installed we should prefer the newest one.

Change-Id: Idf7be613230232eb1d573d93c4a5a8297f4ecd2d
2020-03-25 07:05:39 -05:00
Joshua C. Colp f0d6189032 res_pjsip_session: Don't restrict non-audio default streams to sendrecv.
The state of the default audio stream is used for hold/unhold so we
restrict it to sendrecv as the core does not handle when it changes as
a result of hold/unhold.

This restriction does not apply to other media types though so we now
only restrict it to audio. This allows the other default streams to
store their state at all values, and not just sendrecv and removed.

ASTERISK-28783

Change-Id: I139740f38cea7f7d92a876ec2631ef50681f6625
2020-03-25 05:46:39 -05:00
Michael Neuhauser 580e260ff8 chan_psip, res_pjsip_sdp_rtp: ignore rtptimeout if direct-media is active
Do not hang up a PJSIP channel on RTP timeout if that channel is in
a direct-media bridge. Also reset the time of the last received RTP packet when
direct-media ends (wait full rtp_timeout period before checking first time after
audio came back to Asterisk).

ASTERISK-28774
Reported-by: Michael Neuhauser

Change-Id: I8b62012be7685849e8fb2b1c5dd39d35313ca2d1
2020-03-20 10:17:33 -05:00
Jaco Kroon c7c52b8e7a res_rtp_asterisk: implement ACL mechanism for ICE and STUN addresses.
A pure blacklist is not good enough, we need a whitelist mechanism as
well, and the simplest way to do that is to re-use existing ACL
infrastructure.

This makes it simpler to blacklist say an entire block (/24) except a
smaller block (eg, a /29 or even a /32).  Normally you'd need to
recursively split the block, so if you want to blacklist a /24 except
for a /29 you'd end up with a blacklit for a /25, /26, /27 and /28.  I
feel that having an ACL instead of a blacklist only is clearer.

Change-Id: Id57a8df51fcfd3bd85ea67c489c85c6c3ecd7b30
Signed-off-by: Jaco Kroon <jaco@uls.co.za>
2020-03-17 12:26:58 -05:00
Jaco Kroon af414ef015 Update main/backtrace.c to deal with changes in binutils 2.34.
binutils 2.34 merged this commit:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commitdiff;\
	h=fd3619828e94a24a92cddec42cbc0ab33352eeb4

Which effectively does things like:

-#define bfd_section_size(bfd, ptr) ((ptr)->size)
-#define bfd_get_section_size(ptr) ((ptr)->size)

+#define bfd_section_size(sec) ((sec)->size)

So in order to remain backwards compatible we need to detect this API
change, and adjust accordingly.  The simplest is to notice that the
bfd_get_section_size and bfd_get_section_vma MACROs are no longer
defined, and define then onto the new API.  The alternative is to litter
the code with a number of #ifdef #else #endif splatters right through
the code.

Change-Id: I3efe0f8e8f3e338d16fcbc2b26a505367b6e172f
2020-03-17 09:14:16 -05:00
Sean Bright 83981ad783 func_odbc.conf.sample: Clarify sample documentation
ASTERISK-20325 #close

Change-Id: I06cb9b467b0fd06c8af2a5aee049f872c09cc4b6
2020-03-17 08:19:22 -05:00
Sean Bright 31c6a20862 chan_vpb: Fix 'catching polymorphic type ... by value' error
Fixes the following compile error:

    chan_vpb.cc:2688:26: error: catching polymorphic type
        ‘class std::exception’ by value

Change-Id: Ic87bc357d72427d77626735c83200fd278a7a649
2020-03-13 13:44:55 -05:00
Sean Bright 7a38d5f4e2 dns_txt: Add TXT record parsing support
Change-Id: Ie0eca23b8e6f4c7d9846b6013d79099314d90ef5
2020-03-13 10:00:31 -05:00
Joshua C. Colp aa9e4f395b audiohook: Don't allow audiohooks to attach to hung up channels.
Given a scenario where MixMonitor was initiated over AMI it
was possible for the channel and MixMonitor thread to remain
alive past hang up of the channel. This scenario required
the AMI initiated MixMonitor to retrieve the channel, a
hangup to occur on the channel in another thread, and then
for MixMonitor to actually start. If this occurred the
MixMonitor thread would remain alive indefinitely and
the channel reference would remain.

This change ensures that audiohooks are never able to
be attached to channels that have been hung up. An
additional fix has also been done in app_mixmonitor to
properly release the channel reference if this occurs.

ASTERISK-28780

Change-Id: I8044c06daa06f0f16607788c596f55623be26f58
2020-03-13 09:56:50 -05:00
George Joseph 24f32eb138 CI: Create generic jenkinsfile
This is a generic jenkinsfile to build Asterisk and optionally
perform one or more of the following:
 * Publish the API docs to the wiki
 * Run the Unit tests
 * Run Testsuite Tests

This job can be triggered manually from Jenkins or be triggered
automatically on a schedule based on a cron string.

Change-Id: Id9d22a778a1916b666e0e700af2b9f1bacda0852
2020-03-13 08:38:09 -05:00
Torrey Searle b8a67fc15d res_rtp_asterisk: Send correct sender SSRC when p2p bridge in use
bridge_p2p_rtp_write will forward rtp to the bridged rtp instance
without modifying the ssrc.  However, it is not updating the SSRC
in the bridged rtp.  Thus, when SSRC packets are generated, they
have the correct SSRC for the sender.

ASTERISK-28773 #close

Change-Id: I39f923bde28ebb4f0fddc926b92494aed294a478
2020-03-12 10:32:29 -05:00
George Joseph a3599cc01d Merge "res_pjsip_sdp_rtp: Don't wait for ICE if not negotiated" into 17 2020-03-10 13:36:49 -05:00
George Joseph 10149ad712 Merge "chan_pjsip: Check audio frame when remote SSRC changes." into 17 2020-03-10 12:00:09 -05:00
George Joseph c3bb94b1ee Merge "enum.c: Make ast_get_txt() actually do something." into 17 2020-03-09 10:14:48 -05:00
George Joseph 80c7f130a4 Merge "enum.c: Add support for regular expression flag in NAPTR record" into 17 2020-03-09 10:02:27 -05:00
Joshua Colp 73641deedb Merge "res_rtp_asterisk: Add 'rtp show settings' cli command" into 17 2020-03-09 08:57:22 -05:00
Torrey Searle 1c6314627d res_pjsip_sdp_rtp: Don't wait for ICE if not negotiated
If ICE support is enabled but not negotiated, the rtp->ice structure is
not being destroyed. This leads to Asterisk waiting for ICE to complete
instead of immediately starting the DTLS handshake, resulting in the
call leg having no RTP.

ASTERISK-28769 #close

Change-Id: I17c137546dc9ecfb9583c24dcf4c2ced8bbd7a27
2020-03-09 06:32:43 -06:00
Paulo Vicentini 8645a294ca chan_pjsip: Check audio frame when remote SSRC changes.
If the SSRC of a received RTP packet differed from the previous SSRC
an SSRC change control frame would be queued ahead of the media
frame. In the case of audio this would result in the format of the
audio frame not being checked, and if it differed or was not allowed
then it could cause the call to drop due to failure to set up a
translation path.

The chan_pjsip module will now no longer assume the first frame
will be the audio frame and instead goes through the complete list
to find it.

ASTERISK-28759

Change-Id: I6d854cc523f343e299a615636fc65bdbd5f809ec
2020-03-09 04:52:13 -06:00
Sean Bright 7eec090030 enum.c: Add support for regular expression flag in NAPTR record
A regular expression in a NAPTR response record can have a trailing
'i' flag to indicate that the expression should be evaluated in a
case-insensitive way. We were not checking for that flag which caused
the record parsing to fail on otherwise valid input.

Although this change will initially go into Asterisk 13, 16, and 17,
it is my intention to replace the majority of this code in 16 and up -
including this fix - by changing enum.c to consume the new DNS API
which duplicates most of this logic already. Asterisk 13 doesn't have
the DNS API, so this fix will be as good as it gets.

ASTERISK-26711 #close
Reported by: Vitold

Change-Id: I33943a5b3e7539c6dca3a5079982ee15a08186f0
2020-03-06 15:06:31 -06:00
Jared Smith ff48a6cd56 indications.conf.sample: Add indication tones for Indonesia
These tones come from http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf

ASTERISK-23407

Change-Id: I48e2285f1e5bb29b3335f762006f66c423d0fcb8
2020-03-06 08:42:04 -06:00
Rodrigo Ramírez Norambuena 6857ba98d5 res_rtp_asterisk: Add 'rtp show settings' cli command
This change introduce a CLI command for the RTP to display the general
configuration.

In the first step add the follow fields of the configurations:
  - rtpstart
  - rtpend
  - dtmftimeout
  - rtpchecksum
  - strictrtp
  - learning_min_sequential
  - icesupport

Change-Id: Ibe5450898e2c3e1ed68c10993aa1ac6bf09b821f
2020-03-05 14:16:51 -06:00
Asterisk Development Team 1d3256c5e4 Update CHANGES and UPGRADE.txt for 17.3.0 2020-03-05 12:23:58 -05:00
Kevin Harwell 2f75f071d2 Merge "res_pjsip_refer: ensure refer progress is still sent after Proceeding()" into 17 2020-03-05 11:03:18 -06:00
Sean Bright 2c26705a9b enum.c: Make ast_get_txt() actually do something.
The ast_get_txt() API function (and by extension, the TXTCIDNAME
dialplan function) were broken in
65b8381550 such that we would never
actually make a DNS TXT query as described.

This patch restores the documented behavior.

ASTERISK-19460 #close
Reported by: George Joseph

Change-Id: I1b19aea711488cb1ecd63843cddce05010e39376
2020-03-04 17:02:13 -06:00
Joshua Colp c189ad1f7b Merge "check_expr2: fix cross-compile/hardening issues" into 17 2020-03-04 06:57:05 -06:00
Joshua Colp ada97a6724 Merge "message & stasis/messaging: make text message variables work in ARI" into 17 2020-03-04 06:11:11 -06:00
lvl 88393db74d res_pjsip_refer: ensure refer progress is still sent after Proceeding()
ASTERISK-28766 #close

Change-Id: I5ce2210062f9325db762edbf6e46075079bb2cd1
2020-03-04 05:29:30 -06:00
Sebastian Kemper 61f943d405 check_expr2: fix cross-compile/hardening issues
When building check_expr2 with ASLR PIE hardening enabled the linker
fails. This is resolved by adding the regular compiler flags when
building the object files from ast_expr2f.c and ast_expr2.c.

Note: The STANDALONE define is removed because it is already defined in
_ASTCFLAGS. YY_NO_INPUT is defined so that the compile survives
'--enable-dev-mode'.

Also, a Makefile variable "CROSS_COMPILING" is added so that the
build system doesn't try to run check_expr2 when cross-compiling,
because that will fail the build as will.

ASTERISK-28685 #close

Signed-off-by: Sebastian Kemper <sebastian_ml@gmx.net>
Change-Id: If435b7db9f9ad8266245bda51c81c220f9658915
2020-03-03 08:18:06 -06:00
Joshua C. Colp 029c3e49d4 res_rtp_asterisk: Improve video performance in certain networks.
The receive buffer will now grow if we end up flushing the
receive queue after not receiving the expected packet in time.
This is done in hopes that if this is encountered again the
extra buffer size will allow more time to pass and any missing
packets to be received.

The send buffer will now grow if we are asked for packets and
can't find them. This is done in hopes that the packets are
from the past and have simply been expired. If so then in
the future with the extra buffer space the packets should be
available.

Sequence number cycling has been handled so that the
correct sequence number is calculated and used in
various places, including for sorting packets and
for determining if a packet is old or not.

NACK sending is now more aggressive. If a substantial number
of missing sequence numbers are added a NACK will be sent
immediately. Afterwards once the receive buffer reaches 25%
a single NACK is sent. If the buffer continues to grow and
reaches 50% or greater a NACK will be sent for each received
future packet to aggressively ask the remote endpoint to
retransmit.

ASTERISK-28764

Change-Id: I97633dfa8a09a7889cef815b2be369f3f0314b41
2020-03-03 04:53:15 -06:00
Kevin Harwell c07ed4e651 Merge "res/res_pjsip_sdp_rtp: Fix MOH transitions" into 17 2020-03-02 14:17:27 -06:00
Kevin Harwell c47dbf1fbe message & stasis/messaging: make text message variables work in ARI
When a text message was received any associated variable was not written to
the ARI TextMessageReceived event. This occurred because Asterisk only wrote
out "send" variables. However, even those "send" variables would fail ARI
validation due to a TextMessageVariable formatting bug.

Since it seems the TextMessageReceived event has never been able to include
actual variables it was decided to remove the TextMessageVariable object type
from ARI, and simply return a JSON object of key/value pairs for variables.
This aligns more with how the ARI sendMessage handles variables, and other
places in ARI.

That being the case, and since this is technically an API breaking change (no
one should really be affected since things never really worked) the ARI version
was updated to reflect that.

ASTERISK-28755 #close

Change-Id: Ia6051c01a53b30cf7edef84c27df4ed4479b8b6f
2020-03-02 12:12:06 -06:00
Kevin Harwell ac95b79699 Merge "addons/res_config_mysql: silense warnings about printf format errors." into 17 2020-02-27 14:44:43 -06:00
Kevin Harwell d1ad85622b Merge "app_queue: Refactor odd placement of if's around say_position" into 17 2020-02-27 14:42:26 -06:00
Torrey Searle 1c8c560f39 res/res_pjsip_sdp_rtp: Fix MOH transitions
Update the state of remote_hold immediately on receipt of remote
SDP so that the information is available when building the SDP
answer

ASTERISK-28754 #close

Change-Id: I7026032a807e9c95081cb8f060400b05deb4836f
2020-02-27 14:22:18 -06:00
Kevin Harwell d7bb1241ab Merge "say: Remove unused "plural" option from main/say" into 17 2020-02-27 13:43:04 -06:00
Kevin Harwell 38e88f9469 Merge "format_cap: make function parameters 'const'" into 17 2020-02-27 13:16:23 -06:00
Kevin Harwell 31e9c110f5 Merge "pjsip: Update ACLs on named ACL changes." into 17 2020-02-27 12:53:08 -06:00
Walter Doekes a3f5a80a59 say: Remove unused "plural" option from main/say
There are exceptions for plural objects, but they are detected using the
supplied NUMBER, not using an extra option.

Change-Id: I95d1d1b2796b1aba92048a2dbae8a3856ed8a113
2020-02-25 10:00:15 -06:00
Walter Doekes b455d57f7d app_queue: Refactor odd placement of if's around say_position
Change-Id: Icba97905e331812f129e5966e91a59b104c7a748
2020-02-25 09:59:08 -06:00
Kevin Harwell d77a89cb9e format_cap: make function parameters 'const'
There were a couple places where the format cap function parameter was not
'const' when it should have been. This patch makes them 'const'.

Change-Id: Ife753fb16a962d842a6b44f45363a61a66bfdb2e
2020-02-24 13:37:37 -06:00
Jaco Kroon 77d4923307 addons/res_config_mysql: silense warnings about printf format errors.
Warnings without this:

res_config_mysql.c: In function 'update2_mysql':
res_config_mysql.c:741:15: warning: format '%llu' expects argument of type
    'long long unsigned int', but argument 6 has type 'my_ulonglong'
    {aka 'long unsigned int'} [-Wformat=]
ast_debug(1, "MySQL RealTime: Updated %llu rows on table: %s\n",
    numrows, tablename);

(reformatted for readability within line-wrap)

Change-Id: I2af4d419a37c1a7eeee750cf9ae4a9a2b3a37fd3
2020-02-24 08:22:03 -06:00
George Joseph fd31ef67b9 Merge "tcptls.c: Log more informative OpenSSL errors" into 17 2020-02-21 09:01:38 -06:00
George Joseph e4f5142e23 Merge "bridging: Add better support for adding/removing streams." into 17 2020-02-20 13:43:36 -06:00
George Joseph 3e4752165d Merge "ast_tls_cert: Allow private key size to be set on command line" into 17 2020-02-20 10:52:26 -06:00
George Joseph e300d57134 Merge "app_mixmonitor: Set MIXMONITOR_FILENAME to correct value when wav49 is used" into 17 2020-02-20 09:25:20 -06:00
George Joseph f1896e9279 Merge "RTP/ICE: Send on first valid pair." into 17 2020-02-20 09:23:48 -06:00
Joshua C. Colp bc3c095e9f pjsip: Update ACLs on named ACL changes.
This change extends the Sorcery API to allow a wizard to be
told to explicitly reload objects or a specific object type
even if the wizard believes that nothing has changed.

This has been leveraged by res_pjsip and res_pjsip_acl to
reload endpoints and PJSIP ACLs when a named ACL changes.

ASTERISK-28697

Change-Id: Ib8fee9bd9dd490db635132c479127a4114c1ca0b
2020-02-20 04:52:03 -06:00
Sean Bright 9ef514ae98 tcptls.c: Log more informative OpenSSL errors
Dump OpenSSL's error stack to the error log when things fail.

ASTERISK-28750 #close
Reported by: Martin Zeh

Change-Id: Ib63cd0df20275586e68ac4c2ddad222ed7bd9c0a
2020-02-19 13:38:23 -06:00
Sean Bright cf26ce5d4f ast_tls_cert: Allow private key size to be set on command line
The default size in release branches will be 1024 but we'll use 2048 in master.

ASTERISK~28750

Change-Id: I435cea18bdd58824ed2b55259575c7ec7133842a
2020-02-19 08:39:36 -06:00
George Joseph 5f36196384 res_pjsip_outbound_registration: Fix SRV failover on timeout
In order to retry outbound registrations for some situations, we
need access to the tdata from the original request.  For instance,
for 401/407 responses we need it to properly construct the
subsequent request with the authentication.  We also need it if
we're iterating over a DNS SRV response record set so we can skip
entries we've already tried.

We've been getting the tdata from the server response rdata and
transaction but that only works for the failures where there was
actually a response (4XX, 5XX, etc).  For timeouts there's no
response and therefore no rdata or transaction from which to get
the tdata.  When processing a single A/AAAA record for a server,
this wasn't an issue as we just retried that same server after the
retry timer expired.  If we got an SRV record set for the server
though, without the state from the tdata, we just kept trying the
first entry in the set repeatedly instead of skipping to the next
one in the list.

* Added a "last_tdata" member to the client state structure to keep
  track of the sent tdata.

* Updated registration_client_send() to save the tdata it used into
  the client_state.

* Updated sip_outbound_registration_response_cb() to use the tdata
  saved in client_state when we don't get a response from the
  server. We still use the tdata from the transaction when we DO
  get a response from the server so we can properly handle 4XX
  responses where our new request depends on it.

General note on timeouts:

Although res_pjsip_outbound_registration skips to the next record
immediately when a timeout occurs during SRV set traversal, it's
pjproject that determines how long to wait before a timeout is
declared.  As with other SIP message types, pjproject will continue
trying the same server at an interval specified by "timer_t1" until
"timer_b" expires.  Both of those timers are set in the pjsip.conf
"system" section.

ASTERISK-28746

Change-Id: I199b8274392d17661dd3ce3b4d69a3968368fa06
2020-02-18 13:09:39 -06:00
Joshua C. Colp 957681e08b bridging: Add better support for adding/removing streams.
This change adds support to bridge_softmix to allow the addition
and removal of additional video source streams. When such a change
occurs each participant is renegotiated as needed to reflect the
update. If another video source is added then each participant
gets another source. If a video source is removed then it is
removed from each participant. This functionality allows you to
have both your webcam and screenshare providing video if you
desire, or even more streams. Mapping has been changed to use
the topology index on the source channel as a unique identifier
for outgoing participant streams, this will never change and
provides an easy way to establish the mapping.

The bridge_simple and bridge_native_rtp modules have also been
updated to renegotiate when the stream topology of a party changes
allowing the same behavior to occur as added to bridge_softmix.
If a screen share is added then the opposite party is renegotiated.
If that screen share is removed then the opposite party is
renegotiated again.

Some additional fixes are also included in here. Stream state is
now conveyed in SDP so sendonly/recvonly/inactive streams can
be requested. Removed streams now also remove previous state
from themselves so consumers don't get confused.

ASTERISK-28733

Change-Id: I93f41fb41b85646bef71408111c17ccea30cb0c5
2020-02-18 10:26:15 -06:00
George Joseph f93325ce52 Merge "res_pjsip_sdp_rtp: implement hold state handling on moh_passthrough" into 17 2020-02-18 10:08:55 -06:00
Ben Ford 7a921cfe8c RTP/ICE: Send on first valid pair.
When handling ICE negotiations, it's possible that there can be a delay
between STUN binding requests which in turn will cause a delay in ICE
completion, preventing media from flowing. It should be possible to send
media when there is at least one valid pair, preventing this scenario
from occurring.

A change was added to PJPROJECT that adds an optional callback
(on_valid_pair) that will be called when the first valid pair is found
during ICE negotiation. Asterisk uses this to start the DTLS handshake,
allowing media to flow. It will only be called once, either on the first
valid pair, or when ICE negotiation is complete.

ASTERISK-28716

Change-Id: Ia7b68c34f06d2a1d91c5ed51627b66fd0363d867
2020-02-18 09:54:51 -06:00
George Joseph 50704a8f4d Merge "res_rtp_asterisk: bad audio (static) due to incomplete dtls/srtp setup" into 17 2020-02-17 11:28:22 -06:00
Sean Bright 5f28ecc7af app_mixmonitor: Set MIXMONITOR_FILENAME to correct value when wav49 is used
When opening a file for writing, Asterisk silently converts filenames
ending with 'wav49' to 'WAV.' We aren't taking that in to account when
setting the MIXMONITOR_FILENAME variable in MixMonitor.

* If the user wants to write to a wav49 file, make sure that it is
  reflected properly in MIXMONITOR_FILENAME.

* Add a note to the documentation describing this behavior.

* Add a note in main/file.c indicating that app_mixmonitor needs to be
  changed if the logic in build_filename was changed.

ASTERISK-24798 #close
Reported by: xrobau

Change-Id: I384691ce624eb55c80a125b9ca206d2d691c574c
2020-02-17 10:58:32 -06:00
Torrey Searle fb7cff4103 res_pjsip_sdp_rtp: implement hold state handling on moh_passthrough
When moh_passthrough is used, asterisk is only generating invites
of type sendonly and sendrecv instead of taking fully into account
the on hold state of the local and remote parties

ASTERISK-28738 #close

Change-Id: Iaaad9fbc033cb14803d433b8a4071bc337047761
2020-02-17 08:34:50 -06:00
Joshua C. Colp 5a0218a960 stasis: Use format specifier for size_t.
Change-Id: Ic9b4afcc5398e7f46314419fc3c90433d818e35c
2020-02-15 08:04:21 -06:00
Kevin Harwell 08d8035599 res_rtp_asterisk: bad audio (static) due to incomplete dtls/srtp setup
There was a race condition between client initiated DTLS setup, and handling
of server side ice completion that caused the underlying SSL object to get
cleared during DTLS initialization. If this happened Asterisk would be left
in a partial DTLS setup state. RTP packets were sent and received, but were
not being encrypted and decrypted. This resulted in no audio, or static.

Specifically, this occurred when '__rtp_recvfrom' was processing the handshake
sequence from the client to the server, and then 'ast_rtp_on_ice_complete'
gets called from another thread and clears the SSL object when calling the
'dtls_perform_setup' function. The timing had to be just right in the sense
that from the external SSL library perspective SSL initialization completed
(rtp recv), Asterisk clears/resets the SSL object (ice done), and then checks
to see if SSL is intialized (rtp recv). Since it was cleared, Asterisk thinks
it is not finished, thus not completing 'dtls_srtp_setup'.

This patch removes calls to 'dtls_perform_setup', which clears the SSL object,
in 'ast_rtp_on_ice_complete'. When ice completes, there is no reason to clear
the underlying SSL object. If an ice candidate changes a full protocol level
renegotiation occurs. Also, in the case of bundled ICE candidates are reused
when a stream is added. So no real reason to have to clear, and reset in this
instance.

Also, this patch adds a bit of extra logging to aid in diagnosis of any future
problems.

ASTERISK-28742 #close

Change-Id: I34c9e6bad5a39b087164646e2836e3e48fe6892f
2020-02-14 10:52:05 -06:00
Joshua Colp f424562a41 Merge "res_pjsip_session: Fix off-nominal session refreshes." into 17 2020-02-13 19:02:22 -06:00
Joshua Colp b86ef296b3 Merge "res_musiconhold: Avoid spurious warning when 'format' is the empty string" into 17 2020-02-13 19:01:11 -06:00
George Joseph 8914a77f35 Merge "doc: Fix CHANGES entries to have .txt suffix and update READMEs" into 17 2020-02-13 08:29:33 -06:00
Sean Bright d1a96fa9ba res_musiconhold: Avoid spurious warning when 'format' is the empty string
The change to res_config_odbc that allowed empty strings to be
returned to realtime consumers¹ causes a warning to be emitted when
loading MoH classes. So we need to treat an empty 'format' as if it
was not specified to avoid the warning.

ASTERISK-28735 #close
Reported by: Ross Beer

[1] https://gerrit.asterisk.org/c/asterisk/+/13722

Change-Id: I9a271d721e1a0973e80ebe7d75b46a0d8fa0e5a5
2020-02-11 07:56:30 -06:00
Sean Bright 4b897f6fe4 func_odbc: Prevent snprintf() truncation warning
For reasons that are not clear to me - this only appears for me when
_not_ building in dev-mode.

Change-Id: Ib45c54daaea8e0d571cb470cab1daaae2edba968
2020-02-10 15:42:44 -06:00
Joshua C. Colp 3a8da5ece7 res_pjsip_session: Fix off-nominal session refreshes.
Given a scenario where session refreshes occur close to
each other while another is finishing it was possible for
the session refreshes to occur out of order. It was
also possible for session refreshes to be delayed for
quite some time if a session refresh did not result in
a topology change.

For the out of order session refreshes the first session
refresh would be queued due to a transaction in progress.
This transaction would then finish. When finished a
separate task to process the delayed requests queue
would be queued for handling. A second refresh would
be requested internally before this delayed request
queued task was processed. As no transaction was in
progress this session refresh would be immediately
handled before the queued session refresh.

The code will now check if any delayed requests exist
before allowing a session refresh to immediately occur.
If any exist then the session refresh is queued.

For the delayed session refreshes if a session refresh
did not result in a topology change the attempt would
be immediately stopped and no other delayed requests would
be processed.

The code will now go through the entire delayed requests
queue until a delayed request results in a request
actually being sent.

ASTERISK-28730

Change-Id: Ied640280133871f77d3f332be62265e754605088
2020-02-10 06:11:53 -06:00
George Joseph 4d6346dc26 doc: Fix CHANGES entries to have .txt suffix and update READMEs
Although the wiki page for the new CHANGES and UPGRADE scheme
states that the files must have the ".txt" suffix, the READMEs
didn't.

Change-Id: I490306aa2cc24d6f014738e9ebbc78592efe0f05
(cherry picked from commit 7416703f04)
2020-02-07 14:08:29 -06:00
Joshua Colp 47a5e33280 Merge "pjproject_bundled: Allow brackets in via parameters" into 17 2020-02-07 07:05:41 -06:00
Joshua Colp 78732ff08e Merge "install_prereq: Install aptitude non-interactively" into 17 2020-02-06 07:59:10 -06:00
Joshua Colp 5379c065ae Merge "chan_sip: Return 503 if we're out of RTP ports" into 17 2020-02-06 07:23:48 -06:00
Sean Bright eb33b0fb0b pjproject_bundled: Allow brackets in via parameters
ASTERISK-26955 #close
Reported by: Peter Sokolov

Change-Id: Ib2803640905a77b65d0cee2d0ed2c7b310d470ac
2020-02-06 06:35:14 -06:00
Friendly Automation 2f992bf800 Merge "res_rtp_asterisk: Don't produce transport-cc if no packets." into 17 2020-02-05 18:44:48 -06:00
Friendly Automation 3ec3d39676 Merge "chan_sip: Clarify in sample docs how directmediapermit/-acl should be used" into 17 2020-02-05 10:29:03 -06:00
Friendly Automation d9e625519a Merge "res_config_odbc: Preserve empty strings returned by the database" into 17 2020-02-05 09:49:22 -06:00
Friendly Automation 259edcf5c7 Merge "res_stasis_playback: Prevent media_index from going out of bounds" into 17 2020-02-05 09:48:04 -06:00
Sylvain Afchain cf87d63775 install_prereq: Install aptitude non-interactively
Currently aptitude is installed using interactive mode. This patch
changes this to use the non-interactive mode as it can block
automatic dependencies installation, ex: CI, Docker build.

ASTERISK-28726 #close

Change-Id: I271ee00d230513a6f044810351a32d83b2181133
(cherry picked from commit 0c02d0a450)
2020-02-05 14:22:22 +01:00
Walter Doekes a5ec14970d chan_sip: Return 503 if we're out of RTP ports
If you're for some reason out of RTP ports, chan_sip would previously
responde to an INVITE with a 403, which will fail the call.

Now, it returns a 503, allowing the device/proxy to retry the call on a
different machine.

ASTERISK-28718

Change-Id: I968dcf6c1e30ecddcce397dcda36db727c83ca90
2020-02-05 06:33:06 -06:00
Walter Doekes d19dec53b5 chan_sip: Clarify in sample docs how directmediapermit/-acl should be used
It said "restrict [...] which peers should be able to pass [audio]
to each other".

However, these settings are not global (for which you would expect
signaling IPs to be checked). These settings are available per peer
only, and the IPs being checked, are the RTP IPs.

Change-Id: I2a6c6cd7c2f5f30d1df4844e3e0308a077021660
2020-02-05 06:27:15 -06:00
Joshua C. Colp 325e3f8111 res_rtp_asterisk: Don't produce transport-cc if no packets.
The code assumed that when the transport-cc feedback
function was called at least one packet will have been
received. In practice this isn't always true, so now
we just reschedule the sending and do nothing.

Change-Id: Iabe7b358704da446fc3b0596b847bff8b8a0da6a
2020-02-04 08:19:33 -06:00
George Joseph 54cd865946 message.c: Add option to suppress the Message channel AMI and ARI events
In order to reduce the amount of AMI and ARI events generated,
the global "Message/ast_msg_queue" channel can be set to suppress
it's normal channel housekeeping events such as "Newexten",
"VarSet", etc. This can greatly reduce load on the manager
and ARI applications when the Digium Phone Module for Asterisk
is in use.  To enable, set "hide_messaging_ami_events" in
asterisk.conf to "yes"  In Asterisk versions <18, the default
is "no" preserving existing behavior.  Beginning with
Asterisk 18, the option will default to "yes".

NOTE:  This change does not affect UserEvents or the ARI
TextMessageReceived events.

* Added the "hide_messaging_ami_events" option to asterisk.conf.

* Changed message.c to set the AST_CHAN_TP_INTERNAL property on
  the "Message/ast_msg_queue" channel if the option is set in
  asterisk.conf.  This suppresses the reporting of the events.

Change-Id: Ia2e3516d43f4e0df994fc6598565d6bba2d7018b
2020-02-03 13:58:35 -06:00
Joshua Colp 3efeb147bb Merge "res_pjsip_messaging: Allow Content-Type to be overridden" into 17 2020-02-03 06:11:56 -06:00
Friendly Automation e7e65588e4 Merge "res_stasis: trigger cleanup after update" into 17 2020-01-30 10:02:40 -06:00
George Joseph 2c72e26478 Merge "res_pjsip_pubsub: Increment persistence data ref when recreating." into 17 2020-01-30 09:22:21 -06:00
Friendly Automation 82eb8e7097 Merge "stasis/app: don't lock an app before a call to send" into 17 2020-01-30 09:14:56 -06:00
Sean Bright 646789106f res_config_odbc: Preserve empty strings returned by the database
When res_config_odbc (and perhaps other realtime backends) reads a SQL
NULL from the database, it coalesces the value to the empty string
which prevents it from being returned to the realtime core.

However, if it instead reads the empty string from the database, it
needs a way to encode that fact without having the value omitted
entirely. It does this by changing the value to a string with a single
space. The realtime code in main/config.c recognizes this special case
and _turns the string back into the empty string_ before passing it to
realtime API consumers.

For all of this to work, we need to ensure that we actually pass the
single-space-string back to the realtime core, which is currently
failing because we are trimming the value before checking its
content. So instead we now special case the single-space-string case
so that empty values are returned properly.

ASTERISK-28719 #close
Reported by: EDV O-TON

Change-Id: I673ed8c31ad037aa224e80c78c7a1dc4e4a4e3de
2020-01-29 09:15:02 -06:00
Sean Bright 8b8c1dd07f res_stasis_playback: Prevent media_index from going out of bounds
Incrementing stasis_app_playback.media_index directly in our playback
loop means that when we reach the end of our playlist the index into
the vector will be outside of the bounds of the vector.

Instead use a temporary variable and only assign when we're sure that
we are in bounds.

ASTERISK-28713 #close
Reported by: Sébastien Duthil

Change-Id: Ib53f7f156097e0607eb5871d9d78d246ed274928
2020-01-29 07:15:41 -06:00
Friendly Automation e86c32b878 Merge "res_pjsip_messaging: Ensure MESSAGE_SEND_STATUS is set properly" into 17 2020-01-28 10:22:09 -06:00
Joshua C. Colp 35c9332edf res_pjsip_pubsub: Increment persistence data ref when recreating.
Each subscription needs to have a reference to the persisted data
for it, as well as the main JSON contained within the tree. When
recreating a subscription this did not occur and they both shared
the same reference.

ASTERISK-28714

Change-Id: I706abd49ea182ea367a4ac3feca2706460ae9f4a
2020-01-28 09:24:33 -06:00
Sean Bright ef5702cef1 res_pjsip_messaging: Allow Content-Type to be overridden
ASTERISK-26082 #close
Reported by: Alex

Change-Id: I6549e90932016349bc72b0f053432dc25286f4fb
2020-01-28 08:16:40 -06:00
Friendly Automation 5192a045f6 Merge "chan_sip: Always process updated SDP on media source change" into 17 2020-01-27 18:27:52 -06:00
Kevin Harwell 737bd8365e stasis/app: don't lock an app before a call to send
Calling 'app_send' eventually calls the app's message handler. It's possible
for a handler to obtain a lock on another object, and then need/want to lock
the app object. If the caller of 'app_send' locks the app object prior to
calling then there's a potential for a deadlock, if another thread calls
'app_send' without locking.

This patch makes it so 'app_send' is not called with the app object locked in
the section of code doing such.

ASTERISK-28423 #close

Change-Id: I6767c6d0933c7db1b984018966eefca4c0638a27
2020-01-27 12:11:21 -06:00
Kevin Harwell 7031c3b7bd res_stasis: trigger cleanup after update
The cleanup code in stasis shuts down applications if they are in a deactivated
state, and no longer have explicit subscriptions. When registering an app the
cleanup code was running before calling 'update'. When it should be executed
after 'update' since a call to register may re-activate the app. We don't want
it to shutdown before the 'update' otherwise the app won't be re-activated,
or registered.

This patch makes it so the cleanup code is executed post 'update'.

ASTERISK-28679 #close

Change-Id: I8f2c0b17e33bb8128441567b97fd4c7bf74a327b
2020-01-27 11:59:13 -06:00
Sean Bright 69cf67d8c6 res_pjsip_messaging: Ensure MESSAGE_SEND_STATUS is set properly
We need to wait for the message sending callback to finish to know if
we succeeded or failed.

ASTERISK-25421 #close
Reported by:  Dmitriy Serov

Change-Id: I22b954398821d2caf4c6fe58f0607c8cfa378059
2020-01-27 11:07:06 -06:00
Walter Doekes be6eec7b25 chan_sip: Always process updated SDP on media source change
Fixes no-audio issues when the media source is changed and
strictrtp is enabled (default).

If the peer media source changes, the SDP session version also changes.
If it is lower than the one we had stored, chan_sip would ignore it.

This changeset keeps track of the remote media origin identifier,
comparing that as well. If it changes, the session version needn't be
higher for us to accept the SDP.

Common scenario where this would've caused problems: a separate media
gateway that informs the caller about premium rates before handing off
the call to the final destination.

(An alternative fix would be to set ignoresdpversion=yes on the peer.)

ASTERISK-28686

Change-Id: I88fdbc5aeb777b583e7738c084254c482a7776ee
2020-01-24 10:29:09 -06:00
Sean Bright ace97a3786 chan_pjsip: Ignore RTP that we haven't negotiated
If chan_pjsip receives an RTP packet whose payload differs from the
channel's native format, and asymmetric_rtp_codec is disabled (the
default), Asterisk will switch the channel's native format to match
that of the incoming packet without regard to the negotiated payloads.

We now check that the received frame is in a format we have negotiated
before switching payloads which results in these packets being dropped
instead of causing the session to terminate.

ASTERISK-28139 #close
Reported by: Paul Brooks

Change-Id: Icc3b85cee1772026cee5dc1b68459bf9431c14a3
2020-01-23 10:21:52 -06:00
Asterisk Development Team a0f44b1052 Update CHANGES and UPGRADE.txt for 17.2.0 2020-01-23 11:15:46 -05:00
Friendly Automation 6747dd31b4 Merge "http: Add ability to disable /httpstatus URI" into 17 2020-01-23 08:48:37 -06:00
George Joseph f34a4d5a77 cdr.c: Set event time on party b when leaving a parking bridge
When Alice calls Bob and Bob does a blind transfer to Charlie,
Bob's bridge leave event generates a finalize on both the party_a
and party_b CDRs but while the party_a CDR has the correct end time
set from the event time, party_b's leg did not. This caused that
CDR's end time to be equal to the answered time and resulted in a
billsec of 0.

* We now pass the bridge leave message event time to
cdr_object_party_b_left_bridge_cb() and set it on that CDR before
calling cdr_object_finalize() on it.

NOTE:  This issue affected transfers using chan_sip most of the
time but also occasionally affected chan_pjsip probably due to
message timing.

ASTERISK-28677
Reported by: Maciej Michno

Change-Id: I790720f1e7326f9b8ce8293028743b0ef0fb2cca
2020-01-22 12:13:44 -07:00
Sean Bright 1e79bf44fc http: Add ability to disable /httpstatus URI
Add a new configuration option 'enable_status' which allows the
/httpstatus URI handler to be administratively disabled.

We also no longer unconditionally register the /static and /httpstatus
URI handlers, but instead do it based upon configuration.

Behavior change: If enable_static was turned off, the URI handler was
still installed but returned a 403 when it was accessed. Because we
now register/unregister the URI handlers as appropriate, if the
/static URI is disabled we will return a 404 instead.

Additionally:

* Change 'enablestatic' to 'enable_static' but keep the former for
  backwards compatibility.
* Improve some internal variable names

ASTERISK-28710 #close

Change-Id: I647510f796473793b1d3ce1beb32659813be69e1
2020-01-22 10:09:59 -06:00
Friendly Automation f7e0b6baf8 Merge "func_odbc.conf.sample: Add example lookup" into 17 2020-01-22 09:21:57 -06:00
Friendly Automation f556efe0b9 Merge "res_statsd: Document that res_statsd does nothing on its own" into 17 2020-01-22 08:43:01 -06:00
Friendly Automation c8dc9365a4 Merge "translate.c: Fix silk 24kHz truncation in 'core show translation'" into 17 2020-01-22 07:51:05 -06:00
Joshua Colp 73cd259895 Merge "chan_dahdi: Change 999999 to INT_MAX to better reflect "no timeout"" into 17 2020-01-22 07:49:04 -06:00
Friendly Automation d6a4560016 Merge "chan_sip.c: Stop handling continuation lines after reading headers" into 17 2020-01-21 08:25:33 -06:00
Andrew Siplas 1c5116f842 chan_dahdi: Change 999999 to INT_MAX to better reflect "no timeout"
The no-entry timeout set to 999999 == 16⅔ minutes, change to INT_MAX
to match behavior of "no timeout" defined in comment.

ASTERISK-28702 #close

Change-Id: I4ea015986e061374385dba247b272f7aac60bf11
2020-01-21 09:11:40 -05:00
Sean Bright 687890f734 translate.c: Fix silk 24kHz truncation in 'core show translation'
SILK @ 24kHz is not shown in the 'core show translation' output because of an
off-by-one-error. Discovered while looking into ASTERISK~19871.

ASTERISK-28706
Reported by: Sean Bright

Change-Id: Ie1a551a8a484e07b45c8699cc0c90f1061029510
2020-01-20 15:58:16 -06:00
Sean Bright d33cd39260 func_odbc.conf.sample: Add example lookup
Change-Id: Ia05aab1f579597963d2ea23920d2210cfcb97c84
2020-01-20 15:26:34 -06:00
Sean Bright deed0f5706 res_statsd: Document that res_statsd does nothing on its own
ASTERISK-24484 #close
Reported by: Dan Jenkins

Change-Id: I05f298904511d6739aefb1486b6fcbee27efa9ec
2020-01-20 11:59:08 -06:00
Friendly Automation 503cac85ee Merge "queue_log: Add alembic script for generate db table for queue_log" into 17 2020-01-20 11:31:12 -06:00
Joshua Colp 7a9a4575bc Merge "app_voicemail, say: Fix various leading whitespace problems" into 17 2020-01-20 09:33:00 -06:00
Friendly Automation 88e3f5c315 Merge "app_voicemail: Prevent crash when saving message with realtime voicemail" into 17 2020-01-20 09:19:52 -06:00
Rodrigo Ramírez Norambuena 7b32763190 queue_log: Add alembic script for generate db table for queue_log
Change-Id: I35b928a6251f9da9a1742b2cd14c63a00c3d0f0c
2020-01-20 09:16:54 -06:00
Joshua Colp 68b7ef924e Merge "pbx.c: Include filesystem cache in free memory calculation" into 17 2020-01-20 07:10:47 -06:00
Joshua Colp cf37de8a5d Merge "res_realtime: Fix 'realtime update2' argument handling" into 17 2020-01-17 08:53:19 -06:00
Joshua Colp f132679193 Merge "app_voicemail: Set globals to default values when voicemail.conf missing" into 17 2020-01-17 08:37:19 -06:00
Sean Bright cb6f106d76 app_voicemail, say: Fix various leading whitespace problems
In af90afd90c, Japanese language support
was added to app_voicemail and main/say.c, but the leading whitespace
is not consistent with Asterisk coding guidelines. This patch fixes
that.

Whitespace only, no functional change.

ASTERISK~23324
Reported by: Kevin McCoy

Change-Id: I72c725f5930084673749bd7c9cc426a987f08e87
2020-01-16 13:55:25 -06:00
Sean Bright 9ff062f994 pbx.c: Include filesystem cache in free memory calculation
ASTERISK-28695 #close
Reported by: Kevin Flyn

Change-Id: Ief098bb6eb77378daeace8f97ba30701c8de55b8
2020-01-16 12:38:03 -06:00
Sean Bright 7c137ebbd4 chan_sip.c: Stop handling continuation lines after reading headers
lws2sws() does not stop trying to handle header continuation lines
even after all headers have been found. This is problematic if the
first character of a SIP message body is a space or tab character, so
we update to recognize the end of the message header.

ASTERISK-28693 #close
Reported by: Frank Matano

Change-Id: Idec8fa58545cd3fd898cbe0075d76c223f8d33df
2020-01-16 09:17:24 -06:00
Sean Bright d1cd27ba1f app_voicemail: Prevent crash when saving message with realtime voicemail
ast_store_realtime() is not NULL tolerant, so we need to initialize
the field values we pass to it to the empty string to avoid a crash.

ASTERISK-23739 #close
Reported by: Stas Kobzar

Change-Id: I756c5dd0299c77f4274368f7c99eb0464367466c
2020-01-15 15:52:17 -06:00
Joshua Colp 8cad8db7d3 Merge "app_queue: Deprecate the QueueMemberPause.Reason field" into 17 2020-01-15 07:03:49 -06:00
Friendly Automation af4e503005 Merge "res_pjsip_notify: Only allow a single Event header to be added to a NOTIFY" into 17 2020-01-15 06:41:09 -06:00
Sean Bright b60dfac98e app_voicemail: Set globals to default values when voicemail.conf missing
If voicemail.conf exists but is empty, the config parsing process will
default a number of global variables to non-zero values. On the other
hand, if voicemail.conf is missing (arguably semantically equivalent
to an empty file), this process is skipped and the globals are
defaulted to 0.

Set the globals to the same values they would be set to if a
configuration were present. This allows voicemail configuration to be
done completely by Realtime without the need to create an empty
voicemail.conf file.

ASTERISK-27622 #close
Reported by: Jim Van Meggelen

Change-Id: Id907d280f310f12e542ca527e6a025432b9fb409
2020-01-14 16:31:33 -06:00
Sean Bright 62e5fa400e app_queue: Deprecate the QueueMemberPause.Reason field
The QueueMemberPause AMI event includes two fields that return the
reason a member was paused.

* In release branches, deprecate Reason in favor of PausedReason.
* In master, remove the Reason field entirely.

ASTERISK-28349 #close
Reported by: Niksa Baldun

Change-Id: I01da58f2b0ab927baeee754870f62b51b7b3d296
2020-01-14 13:51:41 -06:00
Joshua Colp 0bd7cd562e Merge "res_pjsip_endpoint_identifier_ip: Document support for hostnames" into 17 2020-01-14 12:39:08 -06:00
Friendly Automation acbe620d41 Merge "func_curl: Add 'followlocation' option to CURLOPT()" into 17 2020-01-14 12:31:49 -06:00
Sean Bright 3779e76b68 res_realtime: Fix 'realtime update2' argument handling
The change in 9b99ef50b5 updated the
syntax of the 'realtime update2' CLI command but did not correctly
update the calls to ast_update2_realtime().

The issue this addresses was originally opened because we aren't
allowing a SQL NULL to be set as part of the update, but this is a
limitation of the Realtime API and is not a bug.

Additionally, this patch:

* Corrects the example in the command documentation to reflect
  'update2' instead of 'update.'

* Fixes the leading spacing of the command documentation.

* Checks that the required 'NULL' literal argument is present where we
  expect it to be.

ASTERISK-21794 #close
Reported by: Cédric Bassaget

Change-Id: Idda63a5dc50d5f9bcb34c27ea3238d90f733b2cd
2020-01-14 10:07:12 -06:00
Joshua Colp 65bc8d70e3 Merge "app_record: Do not hang up if beep audio is missing" into 17 2020-01-14 09:10:45 -06:00
Sean Bright a810025782 func_curl: Add 'followlocation' option to CURLOPT()
We allow for 'maxredirs' to be set, but this value is ignored when
followlocation is not enabled which, by default, it is not.

ASTERISK-17491 #close
Reported by: candrews

Change-Id: I96a4ab0142f2fb7d2e96ff976f6cf7b2982c761a
2020-01-13 08:26:48 -06:00
Sean Bright 28275609b3 res_pjsip_endpoint_identifier_ip: Document support for hostnames
ASTERISK-25429 #close
Reported by: Joshua C. Colp

Change-Id: I7cdfc6026821636acc2465094b7fcde8471a3824
2020-01-10 15:15:52 -06:00
Sean Bright 6898c8e0da res_pjsip_notify: Only allow a single Event header to be added to a NOTIFY
ASTERISK-27775 #close
Reported by: AvayaXAsterisk

Change-Id: Iad158e908e34675ad98f74d09c5e73024e50c257
2020-01-10 14:49:47 -06:00
Jaco Kroon 0a9e5febd5 netsock2: ast_addressfamily_to_sockaddrsize and ast_sockaddr_from_sockaddr.
ast_addressfamily_to_sockaddrize will determine the size that's
required, and ast_sockaddr_from_sockaddr then wraps this new function
and ast_sockaddr_copy_sockaddr to copy arbitrary sockaddr's (without
knowing the address family) into the ast_sockaddr structure.

Change-Id: Iee604e96e9096c79b477d6e5ff310cf0b06dae86
Signed-off-by: Jaco Kroon <jaco@uls.co.za>
2020-01-10 01:57:50 -06:00
Kevin Harwell 5dda6d49b0 Merge "res_pjsip_pubsub: Add ability to persist generator state information." into 17 2020-01-09 17:28:34 -06:00
Joshua Colp ec6598b1eb Merge "app_agent_pool: Update XML docs for AgentLogin" into 17 2020-01-09 15:06:49 -06:00
Friendly Automation f4f4519db6 Merge "CI: Update buildAsterisk.sh to do a "make full"" into 17 2020-01-09 14:29:27 -06:00
Friendly Automation e98856b5c7 Merge "res_pjsip_endpoint_identifier_ip.c: Add port matching support" into 17 2020-01-09 09:47:48 -06:00
Corey Farrell 1675ab3ce2 app_record: Do not hang up if beep audio is missing
Additionally alter the warning to mention that it was "beep" which could
not be streamed to give admins a better clue about what the warning
means.

ASTERISK-28682

Change-Id: If5aed21226a173117ed17589f44826dd1ba6576e
2020-01-09 05:32:44 -06:00
Kevin Harwell 21d8d2426d app_agent_pool: Update XML docs for AgentLogin
This patch fixes some wrongly formatted documentation for the AgentLogin
application. A couple of "see also" links should contain only the function
name, and no parameters.

Change-Id: I3f788b47dce3292e311f8a9856938d59a0bd0661
2020-01-08 14:01:57 -06:00
George Joseph 40bfd895a9 CI: Update buildAsterisk.sh to do a "make full"
If you do a "make all" when building Asterisk the xml documentation
produced will be missing certain AMI events where their
documentation is located not at the top of the c source file but
embedded further down next to the event's manager_event()
registration call.  See main/manager_mwi.c for an example.

"make full" does produce the correct documentation so we're changing
it in the build script.  A separate commit/issue will address the
problem with "make all".

ASTERISK-28507
Reported by: David Lee

Change-Id: I4a22635d6eef99eacecc0efb69e28360eebdb86c
2020-01-08 12:17:28 -06:00
Joshua C. Colp e17ba921f3 res_pjsip_pubsub: Add ability to persist generator state information.
Some body generators, such as dialog-info+xml, require storing state
information which is then conveyed in the NOTIFY request itself. Up
until now there was no way for such body generators to persist this
information.

Two new API calls have been added to allow body generators to set and
get persisted data. This data is persisted out alongside the normal
persistence information and allows the body generator to restore
state information or to simply use this for normal storage of state.
State is stored in the form of JSON and it is up to the body
generator to interpret this as needed.

The dialog-info+xml body generator has been updated to take advantage
of this to persist the version number.

ASTERISK-27759

Change-Id: I5fda56c624fd13c17b3c48e0319b77079e9e27de
2020-01-08 09:48:10 -06:00
Joshua Colp 9bbb03f776 Merge "sig_pri: Fix deadlock caused by sig_pri_queue_hangup" into 17 2020-01-08 09:41:52 -06:00
Friendly Automation 21334e00c5 Merge "stasis.c: Use correct topic name in stasis_topic_pool_delete_topic" into 17 2020-01-08 08:57:17 -06:00
Sean Bright eac6eb663d res_pjsip_endpoint_identifier_ip.c: Add port matching support
Adds source port matching support when IP matching is used:

  [example]
  type = identify
  match = 1.2.3.4:5060/32, 1.2.3.4:6000/32, asterisk.org:4444

If the IP matches but the source port does not, we reject and search for
alternatives. SRV lookups are still performed if enabled (srv_lookups = yes),
unless the configured FQDN includes a port number in which case just a host
lookup is performed.

ASTERISK-28639 #close
Reported by: Mitch Claborn

Change-Id: I256d5bd5d478b95f526e2f80ace31b690eebba92
2020-01-08 08:37:45 -06:00
Friendly Automation 0b09aa087c Merge "app_chanisavail.c: Simplify dialplan using ChanIsAvail." into 17 2020-01-07 13:59:10 -06:00
George Joseph 09680cdaa4 Merge "res_pjsip_config_wizard: Fix change detection for wizard settings" into 17 2020-01-07 13:05:23 -06:00
Friendly Automation b2a7d6ccfb Merge "features.c: Make Bridge application tolerate unspecified channel." into 17 2020-01-07 12:22:50 -06:00
Friendly Automation 73131cefaf Merge "app_dial.c: Simplify dialplan using Dial." into 17 2020-01-07 11:48:42 -06:00
Friendly Automation 6406abc834 Merge "app_page.c: Simplify dialplan using Page." into 17 2020-01-07 11:31:20 -06:00
Friendly Automation 87958810d3 Merge "app_softhangup.c: Reduce unnecessary warning to verbose message." into 17 2020-01-07 10:51:40 -06:00
George Joseph 3cc8a1bb84 Merge "websocket: Consider pending SSL data when waiting for socket input" into 17 2020-01-07 10:12:38 -06:00
Friendly Automation 5d6b533005 Merge "app_chanspy.c: Reduce log message level from notice to verbose." into 17 2020-01-07 10:07:12 -06:00
George Joseph beaa14d721 Merge "contrib/valgrind: Fix use of frame-level suppression" into 17 2020-01-07 09:57:41 -06:00
George Joseph 015cdc9f64 sig_pri: Fix deadlock caused by sig_pri_queue_hangup
The change to add setting hangupsource to sig_pri_queue_hangup()
made in https://gerrit.asterisk.org/c/asterisk/+/12857 casued
deadlocks when a hangup request was received from the core at the
same time a hanguprequest was received from the remote end via the
D channel.

Although the PRI's channel private structure was being unlocked
before setting the hangupsource, the PRI's own lock was still being
held during the process.  If channel actions were also coming from
the core, a deadlock on the PRI could result.  This deadlock could
then escalate to the entire DAHDI subsystem via DAHDI's global
interface list lock, especially if someone used the PRI CLI commands.

Fix:

* We now unlock the PRI as well as the PRI's channel private
  structure before setting the hangupsource, then relock both
  afterwards.

ASTERISK-28605
Reported by: Dirk Wendland

Change-Id: Id74aaa5d4e3746063dbe9deed188eb65193cb9c9
2020-01-07 07:20:07 -06:00
Richard Mudgett 62a8750d2d app_chanisavail.c: Simplify dialplan using ChanIsAvail.
Dialplan has to be careful about passing an empty device list or empty
positions in the list.  As a result, dialplan has to check for these
conditions before using ChanIsAvail.  Simplify dialplan by making
ChanIsAvail handle these conditions gracefully.

* Made tolerate empty positions in the device list.

* Simplified the code and eliminated some unnecessary indention.

ASTERISK-28638

Change-Id: I9e4b67e2cbf26b2417c2d03485b8568e898931d3
2020-01-06 19:11:44 -06:00
George Joseph e0449939ec stasis.c: Use correct topic name in stasis_topic_pool_delete_topic
When a topic is created for an object, its name is only
<object>:<uniqueid>
For example:
bridge:cb68b3a8-fce7-4738-8a17-d7847562f020

When a topic is added to a pool, its name has the pool's topic
name prepended.  For example:
bridge:all/bridge:cb68b3a8-fce7-4738-8a17-d7847562f020

The topic_pool_entry's name however, is only what was passed
in to stasis_topic_pool_get_topic which is
bridge:cb68b3a8-fce7-4738-8a17-d7847562f020
That's actually correct because the entry is qualified by the
pool that's in.

When you're ready to delete the entry from the pool, you retrieve
the tropic name from the object but since it now has the pool's
topic name prepended, it won't be found in the pool container.

Fix:

* Modified stasis_topic_pool_delete_topic() to skip past the
pool topic's name, if it was prepended to the topic name,
before searching the container for a pool entry.

ASTERISK-28633
Reported by: Joeran Vinzens

Change-Id: I4396aa69dd83e4ab84c5b91b39293cfdbcf483e6
2020-01-06 09:52:11 -06:00
Richard Mudgett b3d0b0c484 app_dial.c: Simplify dialplan using Dial.
Dialplan has to be careful about passing an empty destination list or
empty positions in the list.  As a result, dialplan has to check for
these conditions before using Dial.  Simplify dialplan by making Dial
handle these conditions gracefully.

* Made tolerate empty positions in the dialed device list.

* Reduced some message log levels from notice to verbose.

ASTERISK-28638

Change-Id: I6edc731aff451f8bdfaee5498078dd18c3a11ab9
2020-01-05 21:24:09 -06:00
Richard Mudgett f7c6a7df9f app_page.c: Simplify dialplan using Page.
Dialplan has to be careful about passing an empty destination list or
empty positions in the list.  As a result, dialplan has to check for
these conditions before using Page.  Simplify dialplan by making Page
handle these conditions gracefully.

* Made tolerate empty positions in the paged device list.

* Reduced some warnings associated with the 's' option to verbose
messages.  The warning level for those messages really serves no purpose
as that is why the 's' option exists.

ASTERISK-28638

Change-Id: I95b64a6d6800cd1a25279c88889314ae60fc21e3
2020-01-05 21:21:03 -06:00
Richard Mudgett 919da21690 features.c: Make Bridge application tolerate unspecified channel.
The Bridge application was inconsistent if the channel to bridge with is
not specified.  If no parameters are given then a warning is issued and
the current channel is hung up.  If options are given but no channel is
specified then a warning is issued and the current channel is not hung up.

* Made the Bridge application give a verbose message instead of a warning
if the channel to bridge with is not specified and made not hang up the
current channel.  As a result dialplan no longer needs to check if a
channel name is passed before calling Bridge and simply needs to check the
BRIDGERESULT channel variable instead.  This is something you likely want
your dialplan to do anyway.

* Fixed up L() option warning message.  It is up to the caller to
determine if the channel is hung up because of the warning.  Dial() hangs
up the current channel while Bridge() does not.

Change-Id: I44349a8dc3912397f28852777de04f19e7bb9c73
2020-01-05 21:17:51 -06:00
Richard Mudgett a82fc35606 app_chanspy.c: Reduce log message level from notice to verbose.
Change-Id: Ica5f38ccd8cdc077aef14d0c50425e0b29ac7e0a
2020-01-05 21:12:50 -06:00
Richard Mudgett 4dfa19eb27 app_softhangup.c: Reduce unnecessary warning to verbose message.
Why log a warning for something your dialplan explicitly asked for?

Change-Id: I167b90daf4c7d75dd4b7ef94849f6cef05aa43a7
2020-01-05 21:08:44 -06:00
Sean Bright a0d1197ab3 res_pjsip_config_wizard: Fix change detection for wizard settings
ast_sorcery_changeset_create() is not commutative and will fail to detect
differences between two variable lists depending on what changed, so switch to
ast_variable_lists_match().

ASTERISK-28492 #close
Reported by: Jean-Denis Girard

Change-Id: I7b3256983ddfaa2138d3de92a444a53b5193a4e1
2020-01-05 10:12:54 -06:00
Sean Bright 7038c8676e res_agi: Improve GET FULL VARIABLE documentation
ASTERISK-28673 #close
Reported by: Jonathan Harris

Change-Id: I591afdec669622bfa19243aabec31b579652c92f
2020-01-03 10:28:56 -06:00
Sean Bright f344356290 websocket: Consider pending SSL data when waiting for socket input
When TLS is in use, checking the readiness of the underlying FD is insufficient
for determining if there is data available to be read. So before polling the
FD, check if there is any buffered data in the TLS layer and use that first.

ASTERISK-28562 #close
Reported by: Robert Sutton

Change-Id: I95fcb3e2004700d5cf8e5ee04943f0115b15e10d
2020-01-02 15:51:28 -06:00
Snuffy c4cd2fa7b9 contrib/valgrind: Fix use of frame-level suppression
Fix use of frame-level wildcard usage in suppression file.

ASTERISK-27243 #close
Reported-by: Richard Kenner

Change-Id: I1c0c64c5f305d2c9aa124e11f1f64a2eec52dc51
2020-01-02 09:44:04 -06:00
Friendly Automation e5446d7ffc Merge "func_odbc: acf_odbc_read() and cli_odbc_read() unicode support" into 17 2020-01-02 09:40:12 -06:00
Friendly Automation b401891036 Merge "res_fax: wrap v21 detected Asterisk initiated negotiation with config option" into 17 2020-01-02 08:38:49 -06:00
Boris P. Korzun 6d2eced3d3 func_odbc: acf_odbc_read() and cli_odbc_read() unicode support
Added ast_odbc_ast_str_SQLGetData() considers SQL_DESC_OCTET_LENGTH
column attribute for correct allocating the buffer.

ASTERISK-28497 #close

Change-Id: I50e86c8a277996f13d4a4b9b318ece0d60b279bf
2020-01-02 08:28:39 -06:00
George Joseph 321b0c5041 Merge "chan_sip: voice frames are no longer transmitted after emitting a COLP" into 17 2019-12-31 08:39:04 -06:00
Jean Aunis 811c7bdabe chan_sip: voice frames are no longer transmitted after emitting a COLP
The SIP transaction state was reset when emitting an UPDATE or a re-INVITE
related to a COLP, preventing RTP packets to be emitted.

ASTERISK-28647

Change-Id: Ie7a30fa7a97f711e7ba6cc17f221a0993d48bd8b
2019-12-30 01:44:58 -06:00
Sean Bright 843d601e2c db: Initialize condition primitive before use
The db_init() function ultimately calls db_sync() which signals the
condition before it is initialized.

Change-Id: Id4a4e025b637bc4ac7d90557fcb71d56598892ab
2019-12-27 17:32:12 -06:00
George Joseph 86550a59f3 Merge "config.c: Skip UTF-8 BOMs if present when reading config files" into 17 2019-12-27 13:12:47 -06:00
Joshua C. Colp 0c36ef530b Merge "app_chanisavail/cdr: ChanIsAvail sometimes fails to deactivate CDR." into 17 2019-12-19 18:39:53 -06:00
Joshua C. Colp 7aa2445264 Merge "confbridge: Add support for specifying maximum sample rate." into 17 2019-12-19 18:38:49 -06:00
Friendly Automation 2dcb96a868 Merge "main/file.c: Limit media cache usage to remote files." into 17 2019-12-19 11:23:36 -06:00
Friendly Automation 7d0757d660 Merge "chan_sip: in case of tcp/tls, be less annoying about tx errors." into 17 2019-12-19 10:28:33 -06:00
Sean Bright 8c8989f205 config.c: Skip UTF-8 BOMs if present when reading config files
ASTERISK-28667 #close

Change-Id: I4767ed365c98f3e1587b7653321048a31d8a53b2
2019-12-19 04:48:34 -06:00
Kevin Reeves 45f7f9bb85 main/file.c: Limit media cache usage to remote files.
When testing for the existance of a file, the media cache is searched even if
the file has no chance of being in it.  This can cause performance issues
as the media cache size increases.

As a result, calls to applications like Read and Playback using local files
must scan through the media cache before playing.  Under load and with a
large cache, this can delay the playback of those files.

This patch updates the function that checks for the existance of a file to
only consult the media cache database if the requested file is a remote path.
It introduces a new is_remote_path() function in main/file.c.

ASTERISK-28625  #close
Reported-by: kevin@phoneburner.com

Change-Id: If91137493732d9034dafa381c081c69274a7dcc9
2019-12-18 18:45:04 -06:00
George Joseph 2634e63f4d Merge "res_rtp_asterisk: Add frame list cleanups to ast_rtp_read" into 17 2019-12-18 08:58:13 -06:00
Friendly Automation 2725c885e8 Merge "sip_to_pjsip.py: Fix trustrpid typo" into 17 2019-12-18 07:26:25 -06:00
Joshua C. Colp 3104c03476 Merge "configure: Add check for MySQL client bool and my_bool type usage." into 17 2019-12-18 06:37:56 -06:00
Joshua C. Colp 58a6d4ecf5 Merge "res_pjsip_session: Set stream state on created streams for incoming SDP." into 17 2019-12-18 05:46:16 -06:00
Pascal Cadotte Michaud 69c9b74836
sip_to_pjsip.py: Fix trustrpid typo
ASTERISK-28664 #close

Change-Id: I6c28b1002fd7075ae0ed36f026f8c1855c9418a6
2019-12-17 13:19:21 -05:00
Frederic LE FOLL a0e31cc14e app_chanisavail/cdr: ChanIsAvail sometimes fails to deactivate CDR.
Temporary channel lifespan is very short and CDR deactivation request
through ast_cdr_set_property() may happen when CDR is not available
yet. Use CDR_PROP() dialplan function instead, it will first wait
for pending CDR insertion requests to be processed.

ASTERISK-28636

Change-Id: I1cbe09e8d2169c0962c1195133ff260d291f2074
2019-12-16 15:02:30 -06:00
Joshua C. Colp 5a80c36d62 configure: Add check for MySQL client bool and my_bool type usage.
Instead of trying to use the defined MySQL client version from the
header use a configure check to determine whether the bool or my_bool
type should be used for defining a boolean.

ASTERISK-28604

Change-Id: Id2225b3785115de074c50c123ff1a68005b4a9c7
2019-12-16 10:36:07 -06:00
Friendly Automation c7966269f5 Merge "res_pjsip_nat: Restore original contact for REGISTER responses" into 17 2019-12-16 10:28:01 -06:00
Joshua C. Colp 41fdcf7a65 confbridge: Add support for specifying maximum sample rate.
ConfBridge has the ability to move between different sample
rates for mixing the conference bridge. Up until now there has
only been the ability to set the conference bridge to mix at
a specific sample rate, or to let it move between sample rates
as necessary. This change adds the ability to configure a
conference bridge with a maximum sample rate so it can move
between sample rates but only up to the configured maximum.

ASTERISK-28658

Change-Id: Idff80896ccfb8a58a816e4ce9ac4ebde785963ee
2019-12-16 09:54:13 -06:00
Friendly Automation a7a5bf0129 Merge "PJSIP_CONTACT: add missing argument documentation" into 17 2019-12-16 06:56:51 -06:00
Joshua Colp 895a66f772 Merge "ACL: ast_apply_acl_nolog - identical to ast_apply_acl but without logging." into 17 2019-12-16 06:04:59 -06:00
Joshua C. Colp c9147a759e res_pjsip_session: Set stream state on created streams for incoming SDP.
A previous review, 13174, made a change whereby on an incoming offer SDP
the pending topology was initialized to the configured. This caused a problem
for bundle with WebRTC where bundle could reference a stream that did not
actually exist if the configuration had both audio and video but the
offer SDP only contained audio.

This change undoes that review and instead fixes the original problem it
sought to solve by setting the state of created streams based on the
contents of the offer SDP. This way the stream state is not inactive
until negotiation later completes.

ASTERISK-28659

Change-Id: Ic5ae5a86437d3e686ac5afd91d133cc916198355
2019-12-16 05:23:42 -06:00
Kevin Harwell 68724425e4 res_fax: wrap v21 detected Asterisk initiated negotiation with config option
A previous patch:

Gerrit Change-Id: I73bb24799bfe1a48adae9c034a2edbae54cc2a39

made it so a T.38 Gateway tries to negotiate with both sides by sending T.38
negotiation request to both endpoints supported T.38 versus the previous
behavior of forwarding negotiation to the "other" channel once a preamble
was detected.

This had the unfortunate side effect of breaking some setups. Specifically
ones that set the max datagram option on an endpoint configuration (configured
max datagram was not propagated since Asterisk now initiates negotiations).

This patch adds a configuration option, "negotiate_both", that when enabled
makes it so Asterisk initiates the negotiation requests to both endpoints vs.
the previous behavior of waiting, and forwarding the request.

The default is disabled keeping with the old behavior.

ASTERISK-28660

Change-Id: I5deb875f3485e20bc75119ec743090655d864a1a
2019-12-13 14:24:02 -06:00
Asterisk Development Team 08a6e8c553 Update CHANGES and UPGRADE.txt for 17.1.0 2019-12-12 06:04:48 -05:00
Jaco Kroon 6041fc8b9c ACL: ast_apply_acl_nolog - identical to ast_apply_acl but without logging.
Due to use in res_rtp_asterisk there is a need to be able to apply an
ACL without logging any invalid/denies.  It's probably sensible to at
least validate the ACL once directly after load and report invalid ACLs.

Change-Id: I256169229d945ca7c1bbf228fc492d91df345843
Signed-off-by: Jaco Kroon <jaco@uls.co.za>
2019-12-12 01:45:42 -06:00
Pascal Cadotte Michaud 39aff53cff PJSIP_CONTACT: add missing argument documentation
add missing argument "rtt" and "status" to the documentation

The change to the dtd file allow an enumlist to contain one or many
configOptionToEnum or enum.

This is different from the previous patch I submitted when you could have a
configOptionToEnum or (a configOptionToEnum followed by one or manu enums) or
(one or many enums)

ASTERISK-28626

Change-Id: Ia71743ee7ec813f40297b0ddefeee7909db63b6d
2019-12-11 11:15:45 -06:00
George Joseph 87d5fb1196 Merge "Revert "PJSIP_CONTACT: add missing argument documentation"" into 17 2019-12-11 10:36:42 -06:00
Joshua Colp 6a89784b78 Revert "PJSIP_CONTACT: add missing argument documentation"
This reverts commit 450173a0ae.

Reason for revert: Regression in XML validation.

validity error : Content model of enumlist is not determinist:
(configOptionToEnum | (configOptionToEnum , enum+) | enum+)

As we are preparing to do releases and this is not critical
I am reverting this for now until resolved.

Change-Id: I47a6714bb555b35a371861d434daf5b97c0cdcbd
2019-12-11 07:01:23 -06:00
George Joseph 86822722b6 res_rtp_asterisk: Add frame list cleanups to ast_rtp_read
In Asterisk 16+, there are a few places in ast_rtp_read where we've
allocated a frame list but return a null frame instead of the list.
In these cases, any frames left in the list won't be freed.  In the
vast majority of the cases, the list is empty when we return so
there's nothing to free but there have been leaks reported in the
wild that can be traced back to frames left in the list before
returning.

The escape paths now all have logic to free frames left in the
list.

ASTERISK-28609
Reported by: Ted G

Change-Id: Ia1d7075857ebd26b47183c44b1aebb0d8f985f7a
2019-12-10 12:48:20 -06:00
Friendly Automation 5fb0d1d562 Merge "res_pjsip_registrar.c: Prevent potential double free if AOR is not found" into 17 2019-12-09 10:34:41 -06:00
Jaco Kroon 32ce8fa046 chan_sip: in case of tcp/tls, be less annoying about tx errors.
chan_sip.c:3782 __sip_xmit: sip_xmit of 0x7f1478069230 (len 600) to
213.150.203.60:1492 returned -2: Interrupted system call

returned -2 implies this wasn't actually an OS error, so errno makes no
sense either.  Internal error was already logged higher up, and -2
generally means that either there isn't a valid connection available, or
the pipe notification failed, and that is already correctly logged.

ASTERISK-28651 #close

Change-Id: I46eb82924beeff9dfd86fa6c7eb87d2651b950f2
Signed-off-by: Jaco Kroon <jaco@uls.co.za>
2019-12-07 06:08:22 -06:00
Friendly Automation ffbfc09fc1 Merge "app_queue: Fix old confusing comment about when the members are called" into 17 2019-12-06 13:27:59 -06:00
George Joseph fd14d7302f res_pjsip_nat: Restore original contact for REGISTER responses
RFC3261 Section 10 "Registrations", specifically paragraph
"10.2.4: Refreshing Bindings", states that a user agent compares
each contact address (in a 200 REGISTER response) to see if it
created the contact.  If the Asterisk endpoint has the
rewrite_contact option set however, the contact host and port sent
back in the 200 response will be the rewritten one and not the
one sent by the user agent.  This prevents the user agent from
matching its own contact.  Some user agents get very upset when
this happens and will not consider the registration successful.
While this is rare, it is acceptable behavior especially if more
than 1 user agent is allowed to register to a single endpoint/aor.

This commit updates res_pjsip_nat (where rewrite_contact is
implemented) to store the original incoming Contact header in
a new "x-ast-orig-host" URI parameter before rewriting it, and to
restore the original host and port to the Contact headers in the
outgoing response.

This is only done if the request is a REGISTER and rewrite_contact
is enabled.

pjsip_message_filter was also updated to ensure that if a request
comes in with any existing x-ast-* URI parameters, we remove them
so they don't conflict.  Asterisk will never send a request
with those headers in it but someone might just decide to add them
to a request they craft and send to Asterisk.

NOTE: If a device changes its contact address and registers again,
it's a NEW registration.  If the device didn't unregister the
original registration then all existing behavior based
on aor/remove_existing and aor/max_contacts apply.

ASTERISK-28502
Reported-by: Ross Beer

Change-Id: Idc263ad2d2d7bd8faa047e5804d96a5fe1cd282e
2019-12-06 12:47:54 -06:00
George Joseph 2526c8e562 Merge "channel.c: Resolve issue with receiving SIP INFO packets for DTMF" into 17 2019-12-06 12:41:09 -06:00
Friendly Automation af079f5085 Merge "res_pjsip_outbound_registration: add support for SRV failover" into 17 2019-12-06 09:35:43 -06:00
Friendly Automation 6685a1862c Merge "res_pjsip_registrar.c: Prevent possible buffer overflow with domain aliases" into 17 2019-12-06 09:09:02 -06:00
Friendly Automation e17bde758b Merge "PJSIP_CONTACT: add missing argument documentation" into 17 2019-12-04 18:45:22 -06:00
Friendly Automation aa2765d366 Merge "chan_sip+native_bridge_rtp: no directmedia for ptime other than default ptime." into 17 2019-12-04 18:02:33 -06:00
Friendly Automation 478a602e70 Merge "res_pjsip_session.c: Prevent use-after-free with TEST_FRAMEWORK enabled" into 17 2019-12-04 17:45:05 -06:00
Friendly Automation 77b5ec3e7a Merge "parking: Fall back to parker channel name even if it matches parkee." into 17 2019-12-04 17:07:48 -06:00
Sean Bright 4e057eb9d2 res_pjsip_registrar.c: Prevent potential double free if AOR is not found
The simple fix here is simply to NULL out username and password after we call
ast_free on them. Unfortunately, I noticed that we weren't checking for
allocation failures for username and password, and adding those checks made
things noisy and cumbersome.

So instead we partially rollback the recent LGTM patch, and move the alloca
calls into find_aor_name().

ASTERISK-28641 #close
Reported by: Ross Beer

Change-Id: Ic9d01624e717a020be0b0aee31f0814e7f1ffbe2
2019-12-04 16:18:53 -06:00
Sean Bright f26e5bacc0 res_pjsip_registrar.c: Prevent possible buffer overflow with domain aliases
We're appropriately sizing the id_domain_alias buffer, but then copying the data
into the id_domain one. We were then using the uninitialized id_domain_alias
buffer we just allocated.

This is ASTERISK~28641 adjacent, but significant enough to warrant its own
patch.

Change-Id: I81c38724d18deab8c6573153e2b99dbb6e2f33d9
2019-12-04 16:15:19 -06:00
Walter Doekes e1eb5e8dc2 app_queue: Fix old confusing comment about when the members are called
ASTERISK-28644

Change-Id: I2771a931d00a8fc2b9f9a4d1a33ea8f1ad24e06b
2019-12-04 11:38:56 -06:00
Frederic LE FOLL 3e73893e53 chan_sip+native_bridge_rtp: no directmedia for ptime other than default ptime.
During capabilities selection (joint capabilities of us and peer,
configured capability for this peer, or general configured
capabilities), if sip_new() does not keep framing information,
then directmedia activation will fail for any framing different
from default framing.

ASTERISK-28637

Change-Id: I99257502788653c2816fc991cac7946453082466
2019-12-04 05:01:29 -06:00
Sean Bright 4d56adf8fb res_pjsip_session.c: Prevent use-after-free with TEST_FRAMEWORK enabled
We need to copy the endpoint name before we call ao2_cleanup() on it,
otherwise we might try to access memory that has been reclaimed.

ASTERISK-28445 #close
Reported by: Bernhard Schmidt

Change-Id: I404b952608aa606e0babd3c4108346721fb726b3
2019-12-03 15:44:43 -06:00
George Joseph c0ab241cc0 Merge "media_cache.c: Various CLI improvements" into 17 2019-12-02 16:01:42 -06:00
George Joseph 88150323a2 channel.c: Resolve issue with receiving SIP INFO packets for DTMF
The problem is essentially the same as in ASTERISK~28245. Besides
the direct media scenario we have an additional scenario where a
special client is involved. This device mutes audio by default in
transmit direction (no rtp frames) and activates audio only by a
foot switch. In this situation dtmf input (pin for conferences,
transfer features codes , etc) using SIP INFO mode is not
understood properly especially when SIP INFO messages are sent
quickly.

This patch ensures that SIP INFO frames are properly queued and
processed in the above scenario. The patch also corrects situations
where successive dtmf events are received quicker than the
signalled event duration (plus minimum gap/pause) allows, i.e. DTMF
events have to be buffered in the ast channel read queue and
emulation has to be processed asynchronously at slower speed.

Reported by: Thomas Arimont
patches:
  trigger_dtmf_emulation.patch submitted by Thomas Arimont (license 5525)

Change-Id: I309bf61dd065c9978c8e48f5b9a936ab47de64c2
2019-12-02 08:39:36 -06:00
George Joseph 5b15a1c639 CI: Turn off shallow cloning altogether
Change-Id: I73ed4aef33a92f20080128aafc34e19fd4457196
2019-12-02 07:54:25 -05:00
Joshua Colp 41d58a4ce2 parking: Fall back to parker channel name even if it matches parkee.
ASTERISK-28631

Change-Id: Ia74d084799fbb9bee3403e30d2391aacd46243cc
2019-11-25 12:56:51 +00:00
Sean Bright cc59e21409 media_cache.c: Various CLI improvements
* Use ast_cli_completion_add() to improve performance when large number of
  cached items are present.

* Only complete one URI for commands that only accept a single URI.

* Change command documentation to wrap at 80 characters to improve
  readability.

Change-Id: Iedb0a2c3541e49561bc231dca2dcc0ebd8612902
2019-11-22 16:38:17 -05:00
Salah Ahmed 4ac0299bfb res_pjsip_t38: T.38 error correction mode selection at 200 ok received
if asterisk offer T38 SDP with none error correction scheme and
the endpoint respond with redundancy EC scheme, asterisk switch
to that mode. Since we configure the endpoint as none EC mode
we should not switch to any other mode except none.
following logic implemented in code.

1. If asterisk offer none, and anything except none in answer
   will be ignored.
2. If asterisk offer fec, answer with fec, redundancy and none will
   be accepted.
3. If asterisk offer redundancy, answer with redundancy and none
   will be accepted.

ASTERISK-28621

Change-Id: I343c62253ea4c8b7ee17abbfb377a4d484a14b19
2019-11-21 16:10:17 -05:00
Friendly Automation e9b9141d09 Merge "manager.c: Prevent the Originate action from running the Originate app" into 17 2019-11-21 14:03:02 -06:00
Ben Ford 665a94cb76 chan_sip.c: Prevent address change on unauthenticated SIP request.
If the name of a peer is known and a SIP request is sent using that
peer's name, the address of the peer will change even if the request
fails the authentication challenge. This means that an endpoint can
be altered and even rendered unusuable, even if it was in a working
state previously. This can only occur when the nat option is set to the
default, or auto_force_rport.

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

ASTERISK-28589 #close

Change-Id: I581c5ed1da60ca89f590bd70872de2b660de02df
2019-11-21 09:46:26 -06:00
George Joseph 6b1ba58967 manager.c: Prevent the Originate action from running the Originate app
If an AMI user without the "system" authorization calls the
Originate AMI command with the Originate application,
the second Originate could run the "System" command.

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

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

ASTERISK-28580
Reported by: Eliel Sardañons

Change-Id: Ic4c9dedc34c426f03c8c14fce334a71386d8a5fa
2019-11-21 09:40:52 -06:00
George Joseph 6aa9ee1661 Merge "chan_dahdi: PRI span status may stay "Down, Active" after a short alarm" into 17 2019-11-21 09:23:42 -06:00
Friendly Automation 715e4d0e72 Merge "app_senddtmf: Add receive mode to AMI Action PlayDTMF" into 17 2019-11-21 08:38:53 -06:00
Pascal Cadotte Michaud 450173a0ae PJSIP_CONTACT: add missing argument documentation
add missing argument "rtt" and "status" to the documentation

ASTERISK-28626
Change-Id: I8419e4c8203e411b87d93dc395acdbcf7526dedf
2019-11-21 09:23:29 -05:00
Kevin Harwell b1c9176b3f Merge "app_amd: Fixed timeout issue" into 17 2019-11-20 16:14:47 -06:00
Kevin Harwell 8c99930375 res_pjsip_outbound_registration: add support for SRV failover
ASTERISK-28624

Change-Id: I8da7c300dd985ab7b10dbd5194aff2f737808561
2019-11-20 13:56:49 -05:00
Friendly Automation ecdc5405f9 Merge "func_curl.c: Support custom http headers" into 17 2019-11-20 09:49:42 -06:00
George Joseph 8a02454ec6 Merge "res_pjsip_registrar: Fix uninitlized variable warning" into 17 2019-11-20 08:59:38 -06:00
George Joseph 2a92e6b576 CI: Fix missing script block in jenkinsfiles
Change-Id: I9f44a3d5085ea7880fad1a3883a4820907e29ea3
(cherry picked from commit 95213b01d2)
2019-11-19 13:13:22 -05:00
George Joseph f0d1ce50af CI: Fix missing script block in jenkinsfiles
Change-Id: Ib4b6e4887695f230ea7a5b0c879b29fc5a13be4f
(cherry picked from commit d60f23ecbd)
(cherry picked from commit ce8a23fdf9)
2019-11-19 13:03:58 -05:00
George Joseph 46dceab33f CI: Increase clone depth and do better cleanup
The original clone depth of 10 was causing the need to rebase
changes whose parent was older than the 10 commits.  The clone
depth has been increased to 100.

Workspace cleanup was only happening for successful builds which
wasn't enough to keep the 8G workspace in-memory drives on the
docker slaves from filling up.  Now the workspaces are cleaned up
after every build regardless of success/failure.  If you need to
preserve builds temporarily, you can log into Jenkins/Manage
Jenkins/Configure System and change the CLEANUP_WS_* environment
variable for the job type you're troubleshooting to "FALSE".

Change-Id: I0d7366e87cea714e5dbc9488caf718802fce75ca
2019-11-19 11:58:58 -05:00
Friendly Automation 43a7e44fbe Merge "serializer: set high/low alert levels on whole pool" into 17 2019-11-19 10:13:55 -06:00
Sean Bright 76ef36fafc res_pjsip_registrar: Fix uninitlized variable warning
Fixes: error: ‘domain_name’ may be used uninitialized in this function

Found with gcc (Ubuntu 9.2.1-9ubuntu2) 9.2.1 20191008

Change-Id: I44413b49ea1205aa25538142161deb73883c79e8
2019-11-19 10:32:56 -05:00
Michael Cargile e23b2856d0 app_amd: Fixed timeout issue
ASTERISK_28143 attempted to fix an issue where calls with no audio would never
timeout. It did so by adding AST_FRAME_NULL as a frame type to process in its
calculations. Unfortunately these frames seem to show up at irregular time
intervals. This resulted in app_amd returning prematurely most of the time.

* Removed AST_FRAME_NULL from the calculations
* Added a check to see how much time has actually passed since app_amd began

ASTERISK-28608

Change-Id: I642a21b02d389b17e40ccd5357754b034c3daa42
2019-11-19 10:07:19 -05:00
Frederic LE FOLL d3dd4c5459 chan_dahdi: PRI span status may stay "Down, Active" after a short alarm
Upon a short PRI disconnection, libpri may maintain Q.921 layer 'up' and
may thus not send PRI_EVENT_DCHAN_DOWN / PRI_EVENT_DCHAN_UP events.
If pri_event_alarm() clears DCHAN_UP status bit upon alarm detection
and no Q.921 reconnection sequence occurs, chan_dahdi will keep
seeing span status "Down" at the end of alarm.

This patch modifies pri_event_alarm() in order to keep DCHAN_UP bit
unchanged. libpri will send a PRI_EVENT_DCHAN_DOWN event if it detects
a disconnection of Q.921 layer and this will clear DCHAN_UP if required.

ASTERISK-28615

Change-Id: Ibe27df4971fd4c82cc6850020bce4a8b2692c996
2019-11-19 02:20:14 -05:00
lvl 6345a00228 app_senddtmf: Add receive mode to AMI Action PlayDTMF
ASTERISK-28614

Change-Id: I183501297ae1dc294ae56b34acac9b0343eb2664
2019-11-18 18:10:13 -05:00
Friendly Automation f1f28aa9e3 Merge "parking: Fix case where we can't get the parker." into 17 2019-11-18 15:19:49 -06:00
George Joseph 16066ce5fc Merge "various files - fix some alerts raised by lgtm code analysis" into 17 2019-11-18 11:42:03 -06:00
Friendly Automation d75099b845 Merge "func_env: Prevent FILE() from reading garbage at end-of-file" into 17 2019-11-18 10:40:21 -06:00
Friendly Automation cb58d4cc2d Merge "res_rtp_asterisk: Always return provided DTLS packet length." into 17 2019-11-18 10:37:09 -06:00
Alexei Gradinari 649733612d serializer: set high/low alert levels on whole pool
The current code sets alert levels starting from index 1.
Need to set on whole pool starting from index 0.

Change-Id: I5decbb43160954fb9a512f04302637fc666b6f5d
2019-11-18 11:03:29 -05:00
Joshua Colp 0c486e7edf res_rtp_asterisk: Always return provided DTLS packet length.
OpenSSL can not tolerate if the packet sent out does not
match the length that it provided to the sender. This change
lies and says that each time the full packet was sent. If
a problem does occur then a retransmission will occur as
appropriate.

ASTERISK-28576

Change-Id: Id42455b15c9dc4eb987c8c023ece6fbf3c22a449
2019-11-18 08:34:15 -06:00
Sean Bright 92bb381d5d func_env: Prevent FILE() from reading garbage at end-of-file
If the last line of a file does not have a terminating EOL sequence, we
potentially add garbage to the value returned from the FILE() function.

There is no overflow potential here as we are reading from a buffer of a
known size, we are just reading too much of it.

ASTERISK-26481 #close

Change-Id: I50dd4fcf416fb3c83150040a1a79a59d9eb1ae01
2019-11-18 08:32:41 -06:00
Kevin Harwell 8b4610acfe bridge_softmix: clear hold when joining a softmix bridge
MOH continues to play to a channel if that channel was on hold prior to
entering a softmix bridge. MOH will not stop even if the original "holder"
attempts an unhold.

For the most part a softmix bridge ignores holds, so a participating channel
shouldn't join while on hold. This patch checks to see if the channel joining
the softmix bridge is currently on hold. If so then it indicates an unhold.

ASTERISK-28618

Change-Id: I66ccd4efc80f5b4c3dd68186b379eb442916392b
2019-11-18 08:31:56 -06:00
Kevin Harwell 8bc6fa0fbd various files - fix some alerts raised by lgtm code analysis
This patch fixes several issues reported by the lgtm code analysis tool:

https://lgtm.com/projects/g/asterisk/asterisk

Not all reported issues were addressed in this patch. This patch mostly fixes
confirmed reported errors, potential problematic code points, and a few other
"low hanging" warnings or recommendations found in core supported modules.
These include, but are not limited to the following:

* innapropriate stack allocation in loops
* buffer overflows
* variable declaration "hiding" another variable declaration
* comparisons results that are always the same
* ambiguously signed bit-field members
* missing header guards

Change-Id: Id4a881686605d26c94ab5409bc70fcc21efacc25
2019-11-18 08:30:25 -06:00
Martin Tomec d579ec9cdf func_curl.c: Support custom http headers
When user wants to send json data, the default Content-Type header
is incorect (application/x-www-form-urlencoded). This patch allows
to set any custom headers so the Content-Type header can be
overriden. User can set multiple headers by multiple calls of
curlopt(). This approach is not consistent with other parameters,
but is more readable in dialplan than one call with multiple
headers.

ASTERISK-28613

Change-Id: I4dd68c3f4e25362ef941d73a3861f58348dcfbf9
2019-11-15 09:13:11 -05:00
Joshua Colp de433cdcaf parking: Fix case where we can't get the parker.
ASTERISK-28616

Change-Id: Iabe31ae38d01604284fcc5c2438d44e29a32ea4d
2019-11-15 06:49:19 -04:00
Joshua Colp d638d9c6c6 parking: Use channel snapshot instead of channel.
There exists a scenario where a thread can hold a lock on the
channels container while trying to lock a bridge. At the same
time another thread can hold the lock for said bridge while
attempting to retrieve a channel. This causes a deadlock.

This change fixes this scenario by retrieving a channel snapshot
instead of a channel, as information present in the snapshot
is all that is needed.

ASTERISK-28616

Change-Id: I68ceb1d62c7378addcd286e21be08a660a7cecf2
2019-11-14 17:20:22 -06:00
Kevin Harwell 3084a6c617 Merge "res_pjsip_session: initialize pending's topology to endpoint's" into 17 2019-11-14 13:12:20 -06:00
Kevin Harwell ea3daa94c8 res_pjsip_session: initialize pending's topology to endpoint's
Found during some testing, there is a race condition between selecting an
appropriate bridge type for a call versus the applying of media on the callee's
session. In some instances a native bridge type would have been chosen, but
due to the callee's media not yet being established at bridge compatibility
check time the simple bridge type is picked instead.

When using chan_pjsip this initiates a topology change event. The topologies
are then compared for the two sessions. However, when the topology was created
for the caller its streams are initialized to "inactive". This topology is then
used as a base when creating the callee's topology, and streams. Soon after
the caller's topology's stream(s) get updated based on the sdp (get set to
sendrecv in the failing scenario).

Now when the topology change event is raised, and the two topologies are
compared, the comparison fails due to a stream state mismatch (sendrecv vs
inactive). And since they differ a reinvite is sent out (to the caller in
this case).

This patch makes it such that when the caller's topology is initially created
it gets created based on its configured endpoint's media topology. When the
endpoint's topology is created its stream's state(s) are initialized to
sendrecv instead of inactive. Subsequently, now when the callee's topology is
created its topology streams are now initialized to sendrecv. Thus when the
topology change event occurs due to the mentioned scenario the stream states
match for the given sessions, and the reinvite is not sent unless due to some
other valid mismatch.

Note, this patch only changes one pending media state's creation point. It's
possible other places *could* be changed, however for now it was deemed best
to only alter what's here.

Change-Id: I6ba3a6a75f64824a1b963044c37acbe951c389c7
2019-11-12 15:41:19 -05:00
George Joseph 7202624b3b stasis: Don't hold app_registry and session locks unnecessarily
resource_events:stasis_app_message_handler() was locking the session,
then attempting to determine if the app had debug enabled which
locked the app_registry container.  res_stasis:__stasis_app_register
was locking the app_registry container then calling app_update
which caused app_handler (which locks the session) to run.
The result was a deadlock.

* Updated resource_events:stasis_app_message_handler() to determine
  if debug was set (which locks the app_registry) before obtaining the
  session lock.

* Updated res_stasis:__stasis_app_register to release the app_registry
  container lock before calling app_update (which locks the sesison).

ASTERISK-28423
Reported by Ross Beer

Change-Id: I58c69d08cb372852a63933608e4d6c3e456247b4
2019-11-10 19:45:25 -05:00
George Joseph 36b28c98dd Build: Fix compile issues with seldom used modules
The following modules needed tweaks for API changes.

addons/cdr_mysql.c
addons/chan_ooh323.c
apps/app_meetme.c

ASTERISK-28604

Change-Id: Ib40e513ae55b5114be035cdc929abb6a8ce2d06d
2019-11-07 07:31:20 -06:00
Joshua Colp eea2d499f4 res_pjsip_outbound_registration: Extend documentation for "max_retries".
If the "max_retries" option is set to 0 then upon failure no
further attemps are made, so explicitly document the behavior.

ASTERISK-28602

Change-Id: I1e30daae9dd6c49ce18744164214d3def505acbf
2019-10-31 11:54:56 -05:00
Joshua Colp 43ea6e21db Merge "res_calendar: Resolve memory leak on calendar destruction" into 17 2019-10-29 10:24:49 -05:00
Sean Bright b3792e1288 res_calendar: Resolve memory leak on calendar destruction
Calling ne_uri_parse allocates memory that needs to be freed with a
corresponding call to ne_uri_free.

ASTERISK-28572 #close

Change-Id: I8a6834da27000a6807d89cb7a157b2a88fcb5e61
2019-10-24 09:18:28 -05:00
Joshua Colp e37d546109 res_ari_events: Add module reference when a WebSocket is open.
This change ensures that the module isn't unloaded when a
WebSocket is open. Previously it was possible to unload the
module manually or during shutdown which could cause a crash
when any active WebSockets were terminated.

ASTERISK-28585

Change-Id: I85c71ab112f99875b586419a34c08c8b34c14c5c
2019-10-24 05:26:46 -05:00
George Joseph 1b4502ec5d Merge "ExternalMedia: Change return object from ExternalMedia to Channel" into 17 2019-10-21 13:53:10 -05:00
Friendly Automation 8b0661df75 Merge "utils.h: Set lower bound for thread stack size to PTHREAD_STACK_MIN" into 17 2019-10-21 13:31:34 -05:00
Joshua Colp 0cfe9186b0 Merge "app_voicemail.c: Support multiple file formats for forwarded messages." into 17 2019-10-21 10:31:47 -05:00
Friendly Automation 500e5f488f Merge "Crash during "pjsip show channelstats" execution" into 17 2019-10-21 07:26:19 -05:00
Sean Bright b3c56c7fa5 utils.h: Set lower bound for thread stack size to PTHREAD_STACK_MIN
ASTERISK-28590 #close

Change-Id: I51abce00c04d0a06550bda5205580705185b9c1c
2019-10-18 13:53:32 -05:00
Joshua Colp 4d67cd10ba Merge "res_rtp_asterisk: Remove a log message that slipped in." into 17 2019-10-18 09:37:45 -05:00
George Joseph 2d665091a3 ExternalMedia: Change return object from ExternalMedia to Channel
When we created the External Media addition to ARI we created an
ExternalMedia object to be returned from the channels/externalMedia
REST endpoint.  This object contained the channel object that was
created plus local_address and local_port attributes (which are
also in the Channel variables).  At the time, we thought that
creating an ExternalMedia object would give us more flexibility
in the future but as we created the sample speech to text
application, we discovered that it doesn't work so well with ARI
client libraries that a) don't have the ExternalMedia object
defined and/or b) can't promote the embedded channel structure
to a first-class Channel object.

This change causes the channels/externalMedia REST endpoint to
return a Channel object (like channels/create and channels/originate)
instead of the ExternalMedia object.

Change-Id: If280094debd35102cf21e0a31a5e0846fec14af9
2019-10-18 08:09:01 -05:00
Salah Ahmed 40acd7d198 Crash during "pjsip show channelstats" execution
During execution "pjsip show channelstats" cli command by an
external module asterisk crashed. It seems this is a separate
thread running to fetch and print rtp stats. The crash happened on
the ao2_lock method, just before it going to read the rtp stats on
a rtp instance. According to gdb backtrace log, it seems the
session media was already cleaned up at that moment.

ASTERISK-28578

Change-Id: I3e05980dd4694577be6d39be2c21a5736bae3c6f
2019-10-18 11:30:48 +02:00
Joshua Colp b8ae799ca9 res_rtp_asterisk: Remove a log message that slipped in.
This was only supposed to be for testing, so now it can be
removed.

Change-Id: I3dfc2e776e70b3196aeed5688372ea80c0214b59
2019-10-17 05:50:38 -05:00
Sean Bright 4bc1c170cd README-SERIOUSLY.bestpractices.md: Speling correetions.
ASTERISK-28586 #close

Change-Id: I43dc4e8bd9dc685b17695b215a5360314074734f
2019-10-16 16:07:30 -05:00
Joshua Colp b590e8f23e Merge "test_res_rtp: Enable FIR and REMB nominal tests." into 17 2019-10-16 07:43:55 -05:00
cmaj aa0973f868 app_voicemail.c: Support multiple file formats for forwarded messages.
If you specify multiple formats in voicemail.conf, eg. "format = gsm|wav"
and are using realtime ODBC backend, only the first format gets stored
in the database. So when you forward a message later on, there is a bug
generating the email, related to the stored format (GSM) being different
than the desired email format (WAV) specified for the user. Sox can
handle this, but Asterisk needs to tell sox exactly what to do.

ASTERISK-22192

Change-Id: I7321e7f7e7c58adbf41dd4fd7191c887b9b2eafd
2019-10-14 17:24:59 -05:00
George Joseph 3c712391c6 Merge "res_pjsip_mwi: potential double unref, and potential unwanted double link" into 17 2019-10-14 12:00:51 -05:00
Joshua Colp ba688e6891 test_res_rtp: Enable FIR and REMB nominal tests.
Now that both FIR and REMB are being sent in compound packets
these tests can be enabled.

This also extends the REMB nominal test to cover the REMB
contents itself.

Change-Id: Ibfee526ad780eefcce5dd787f53785382210024a
2019-10-14 11:49:05 -05:00
Friendly Automation bbf995320e Merge "pbx: deadlock when outgoing dialed channel hangs up too quickly" into 17 2019-10-14 06:56:25 -05:00
Friendly Automation 236ff0af7a Merge "cdr_pgsql cel_pgsql res_config_pgsql: compatibility with PostgreSQL 12" into 17 2019-10-14 06:29:35 -05:00
Christoph Moench-Tegeder 79cc8ae3b8 cdr_pgsql cel_pgsql res_config_pgsql: compatibility with PostgreSQL 12
PostgreSQL 12 finally removed column adsrc from table pg_catalog.pg_attrdef
(column default values), which has been deprecated since version 8.0.
Since then, the official/correct/supported way to retrieve the column
default value from the catalog is function pg_catalog.pg_get_expr().

This change breaks compatibility with pre-8.0 PostgreSQL servers,
but has reached end-of-support more than a decade ago.
cdr_pgsql and res_config_pgsql still have support for pre-7.3
servers, but cleaning that up is perhaps a topic for a major release,
not this bugfix.

ASTERISK-28571

Change-Id: I834cb3addf1937e19e87ede140bdd16cea531ebe
2019-10-14 05:07:46 -05:00
George Joseph 5b77f572e3 Merge "pjproject_bundled: Replace earlier reverts with official fixes." into 17 2019-10-11 09:32:36 -05:00
Kevin Harwell 45c0d99185 res_pjsip_mwi: potential double unref, and potential unwanted double link
When creating an unsolicited MWI aggregate subscription it was possible for
the subscription object to be double unref'ed. This patch removes the explicit
unref as it is not needed since the RAII_VAR will handle it at function end.

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

ASTERISK-28575

Change-Id: I9ccfdb5ea788bc0c3618db183aae235e53c12763
2019-10-10 15:30:15 -05:00
csavinovich c84135d2a3 test_taskprocessor.c: Fix test failure on Ubuntu
Fixes a failure in /main/taskprocesor unit test, only occurring in Ubuntu.
Newer versions of GCC require variable initialization.

Change-Id: I2994d8aab9307a8c2c7330584f287a27144a580c
2019-10-10 15:23:05 -05:00
Friendly Automation b25e529ad8 Merge "Revert "app_voicemail: Cleanup stale lock files on module load"" into 17 2019-10-10 10:05:37 -05:00
George Joseph d869882697 Merge changes from topic "pjsip_shutdown" into 17
* changes:
  res_pjsip_mwi: use an ao2_global object for mwi containers
  res_pjsip/res_pjsip_mwi: use centralized serializer pools
2019-10-10 09:13:48 -05:00
George Joseph 82372fa816 Merge "serializer: move/add asterisk serializer pool functionality" into 17 2019-10-10 09:09:22 -05:00
Friendly Automation 804f5ddfeb Merge "chan_pjsip: Prevent segfault when running PlayDTMF on hungup channel" into 17 2019-10-10 08:43:57 -05:00
George Joseph 2652bda3a0 pjproject_bundled: Replace earlier reverts with official fixes.
Issues in pjproject 2.9 caused us to revert some of their changes
as a work around.  This introduced another issue where pjproject
wouldn't build with older gcc versions such as that found on
CentOS 6.  This commit replaces the reverts with the official
fixes for the original issues and allows pjproject to be built
on CentOS 6 again.

ASTERISK-28574
Reported-by: Niklas Larsson

Change-Id: I06f8507bea553d1a01b0b8874197d35b9d47ec4c
2019-10-10 06:43:14 -05:00
Kevin Harwell ae761c7473 pbx: deadlock when outgoing dialed channel hangs up too quickly
Here's the basic scenario that occurred when executing an AMI fast originate
while at the same time something else locks the channels container, and also
wants a lock on the dialed channel:

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

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

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

Change-Id: I51b42b92dde8f2215b69bb509e28667ee3a3853a
2019-10-09 16:07:08 -05:00
Friendly Automation 6bedd43b98 Merge "cdr_mysql: Don't clean up on unload unless we can unregister from CDRs" into 17 2019-10-08 07:27:22 -05:00
Sean Bright b903994987 Revert "app_voicemail: Cleanup stale lock files on module load"
This reverts commit fd2e8d0da7.

Reason for revert: Problematic for users who store their voicemail
on network storage devices, or share voicemail storage between
multiple Asterisk instances.

ASTERISK-28567 #close

Change-Id: I3ff4ca983d8e753fe2971f3439bd154705693c41
2019-10-08 06:34:55 -05:00
lvl 71f86e78b6 chan_pjsip: Prevent segfault when running PlayDTMF on hungup channel
ASTERISK-28086 #close

Change-Id: Ib3baadc89b9f0477a6f25a63861433812368c5ea
2019-10-08 02:31:11 -05:00
Kevin Harwell 996fc40e2b res_pjsip_mwi: use an ao2_global object for mwi containers
On shutdown it's possible for the unsolicited mwi container to be freed before
other dependent threads are done using it. This patch ensures this can no
longer happen by wrapping the container in an ao2_global object. The solicited
container was also changed too.

ASTERISK-28552

Change-Id: I8f812286dc19a34916acacd71ce2ec26e1042047
2019-10-07 16:53:17 -05:00
Kevin Harwell 37ec88c4c8 serializer: move/add asterisk serializer pool functionality
Serializer pools have previously existed in Asterisk. However, for the most
part the code has been duplicated across modules. This patch abstracts the
code into an 'ast_serializer_pool' object. As well the code is now centralized
in serializer.c/h.

In addition serializer pools can now optionally be monitored by a shutdown
group. This will prevent the pool from being destroyed until all serializers
have completed.

Change-Id: Ib1e906144b90ffd4d5ed9826f0b719ca9c6d2971
2019-10-07 16:53:17 -05:00
Kevin Harwell 299ba78b09 res_pjsip/res_pjsip_mwi: use centralized serializer pools
Both res_pjsip and res_pjsip_mwi made use of serializer pools. However, they
both implemented their own serializer pool functionality that was pretty much
identical in each of the source files. This patch removes the duplicated code,
and uses the new 'ast_serializer_pool' object instead.

Additionally res_pjsip_mwi enables a shutdown group on the pool since if the
timing was right the module could be unloaded while taskprocessor threads still
needed to execute, thus causing a crash.

Change-Id: I959b0805ad024585bbb6276593118be34fbf6e1d
2019-10-07 16:53:17 -05:00
Friendly Automation 119a18ef08 Merge "channel/chan_pjsip: add dialplan function for music on hold" into 17 2019-10-07 08:01:36 -05:00
Sean Bright 1dc3451a34 cdr_mysql: Don't clean up on unload unless we can unregister from CDRs
ASTERISK-28566 #close

Change-Id: I6daa4e5128e9406d04d3aed670c3bae98d38d40c
2019-10-04 16:00:46 -05:00
Corey Farrell 25fbe79793 stasis_state: Create internal stasis_state_proxy object.
This improves the way which stasis_state reference counting works.
Since manager->states holds onto the proxy object instead of the real
object this allows stasis_state objects to be freed when appropriate
without use of a special state_remove function.  Additionally each
distinct eid associated with the state holds a reference to the state to
prevent early release and potentially allow easier debug of leaks.

Change-Id: I400e0db4b9afa3d5cb4ac7dad60907897e73f9a9
2019-10-04 07:08:00 -05:00
Joshua Colp 57fa604571 stasis: Pass bumped topic_all reference to proxy_dtor.
This avoids use of the global variable and ensures topic_all remains
active until all topics are freed.

ASTERISK-28553
patches:
  ASTERISK-28553.patch by coreyfarrell (license 5909)

Change-Id: I9a8cd8977f3c3a6aa00783f8336d2cfb9c2820f1
2019-10-01 09:05:49 -05:00
Friendly Automation f7ed688ae8 Merge "res_pjsip_pubsub: add endpoint to some warning" into 17 2019-10-01 06:28:54 -05:00
Torrey Searle 55b760d762 channel/chan_pjsip: add dialplan function for music on hold
Add a new dialplan function PJSIP_MOH_PASSTHROUGH that allows
the on-hold behavior to be controlled on a per-call basis

ASTERISK-28542 #close

Change-Id: Iebe905b2ad6dbaa87ab330267147180b05a3c3a8
2019-10-01 02:06:28 -05:00
Alexei Gradinari 4b47d4774d res_pjsip_pubsub: add endpoint to some warning
There are some warning messages which are not informative without endpoint:
"No registered subscribe handler for event presence.winfo"
"No registered publish handler for event presence"

This patch adds an endpoint name to these messages.

Change-Id: Ia2811ec226d8a12659b4f9d4d224b48289650827
2019-09-27 17:12:52 -05:00
Sean Bright 6527eb8213 res_pjsip_transport_websocket: Don't put brackets around local_name if IPv6
ASTERISK-28544 #close

Change-Id: I8e62c444d107674c298f472e3545661de8a80dce
2019-09-27 13:07:57 -05:00
George Joseph 0257a039e4 Merge "basic-pbx: Bring forward queue configuration from 13" into 17 2019-09-27 08:59:17 -05:00
George Joseph 23858b7ef4 Merge "pbx: Prevent Realtime switch crash on invalid priority" into 17 2019-09-27 08:58:30 -05:00
George Joseph a398196fd0 Merge "res_musiconhold: Add new 'playlist' mode" into 17 2019-09-27 08:57:23 -05:00
George Joseph cc82a0c66c Merge "taskprocessor.c: Added "like" support to 'core show taskprocessors'" into 17 2019-09-27 08:56:28 -05:00
Jonathan Rose d223419bcd basic-pbx: Bring forward queue configuration from 13
Original commit: cfbf5fbe91

Change-Id: I34a841d73c429ca8d944481f8dccb756ee231c9c
2019-09-26 08:21:47 -05:00
George Joseph 2fcf9c7e49 Merge "res_pjsip_registrar: Validate Contact URI before adding to responses" into 17 2019-09-26 07:08:12 -05:00
Sean Bright 8d0edf2b37 pbx: Prevent Realtime switch crash on invalid priority
pbx_extension_helper takes two 'context' arguments. One (con) is a
pointer directly to a 'struct ast_context' and the other (context) is
the name of the context. In all cases, one of these arguments is NULL
and the other is non-NULL.

Functions that are ultimately called by pbx_extension_helper expect that
'context' will be non-NULL, so we set it unconditionally on entry into
this function.

ASTERISK-28534 #close

Change-Id: Ifbbc5e71440afd80efd441f7a9d72e8b10b6f47d
2019-09-26 04:48:08 -05:00
Ben Ford 8269fcbf03 taskprocessor.c: Added "like" support to 'core show taskprocessors'
Added "like" support for 'core show taskprocessors'. Now you
can specify a specific set of taskprocessors (or just one) by
adding the keyword "like" to the above command, followed by
your search criteria.

Change-Id: I021e740201e9ba487204b5451e46feb0e3222464
2019-09-25 14:01:41 -05:00
Asterisk Development Team 37139e16a5 Update CHANGES and UPGRADE.txt for 17.0.0-rc2 2019-09-25 12:21:13 -05:00
George Joseph 048c0f3a04 Merge "core: Fix ABI mismatch of ao2_global_obj." into 17 2019-09-25 08:10:40 -05:00
George Joseph 93973eb90f Merge "res_pjsip_pubsub: change warning to debug" into 17 2019-09-25 07:04:28 -05:00
Friendly Automation d8523dccb7 Merge "taskprocessor.c: Add CLI commands to reset taskprocessor stats." into 17 2019-09-25 06:43:05 -05:00
Sean Bright 7550a82fe0 res_musiconhold: Add new 'playlist' mode
Allow the list of files to be played to be provided explicitly in the
music class's configuration. The primary driver for this change is to
allow URLs to be used for MoH.

Change-Id: I9f43b80b43880980b18b2bee26ec09429d0b92fa
2019-09-25 06:23:58 -05:00
Sean Bright 51cf060c6c res_pjsip_registrar: Validate Contact URI before adding to responses
If a permanent contact URI associated with an AOR is invalid, we add a
Contact header to REGISTER responses with a NULL URI, causing a crash.

ASTERISK-28463 #close

Change-Id: Id2b643e58b975bc560aab1c111e6669d54db9102
2019-09-25 06:21:06 -05:00
Friendly Automation 5b8e0fef34 Merge "core: Add AO2_ALLOC_OPT_NO_REF_DEBUG option." into 17 2019-09-25 06:02:19 -05:00
George Joseph ad4a358595 Merge "pjproject_bundled: Revert pjproject 2.9 commits causing leaks" into 17 2019-09-24 15:37:27 -05:00
Kevin Harwell 175a7ccac7 res_pjsip_pubsub: change warning to debug
The following message:

"Subscription request from endpoint <blah> rejected. Expiration of 0 is invalid"

Would sometimes spam the log with warnings if Asterisk restarted and a bunch
of clients sent unsubscribes. This patch changes it from a warning to a debug
message.

Change-Id: I841ec42f65559f3135e037df0e55f89b6447a467
2019-09-24 11:24:30 -05:00
Corey Farrell 5bedd4a9b4 core: Fix ABI mismatch of ao2_global_obj.
astobj2.c declares DEBUG_THREADS_LOOSE_ABI to avoid overhead of debug
threads tracking information in the internal structures of astobj2.
Unfortunately this means that ao2_global_obj contains the statically
allocated debug threads tracking fields which are used by initialization
and cleanup but main/astobj2.c believed those fields and associated
space did not exist.

Change-Id: Icef41ad97d88a8c1d1515e034ec8133cab3b1527
2019-09-24 11:20:12 -05:00
Ben Ford f181dfc065 taskprocessor.c: Add CLI commands to reset taskprocessor stats.
Added two new CLI commands to reset stats for taskprocessors. You can
reset stats for a single, specific taskprocessor ('core reset
taskprocessor <taskprocessor>'), or you can reset all taskprocessors
('core reset taskprocessors'). These commands will reset the counter for
the number of tasks processed as well as the max queue size.

Change-Id: Iaf17fc4ae29396ab0c6ac92408fc7bdc2f12362d
2019-09-24 10:42:16 -05:00
George Joseph d95a76edd3 Merge "astmm.c: Display backtrace with memory show allocations" into 17 2019-09-24 08:27:49 -05:00
George Joseph 7c0435f854 pjproject_bundled: Revert pjproject 2.9 commits causing leaks
We've found a connection re-use regression in pjproject 2.9
introduced by commit
"Close #1019: Support for multiple listeners."
https://trac.pjsip.org/repos/changeset/6002
https://trac.pjsip.org/repos/ticket/1019

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

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

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

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

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

Both of these issues have been acknowledged by Teluu.

ASTERISK-28521

Change-Id: I8ae7233c3ac4ec29a3b991f738e655dabcaba9f1
2019-09-24 08:16:22 -05:00
Friendly Automation 3b485b3e5a Merge "res_sorcery_memory_cache: stale item update leak" into 17 2019-09-24 08:14:10 -05:00
Kevin Harwell 1d322dc071 Merge "stasis: refcounter.py can incorrectly report skewed objects." into 17 2019-09-23 15:45:50 -05:00
Friendly Automation 09d211b611 Merge "app_voicemail: Fix module unload leak." into 17 2019-09-23 13:27:01 -05:00
Corey Farrell ec712cfab2
core: Add AO2_ALLOC_OPT_NO_REF_DEBUG option.
Previous to this patch passing a NULL tag to ao2_alloc or ao2_ref based
functions would result in the reference not being logged under
REF_DEBUG.  This could sometimes cause inaccurate logging if NULL was
accidentally passed to a reference action.  Now reference logging is
only disabled by option passed to the allocation method.

Change-Id: I3c17d867d901d53f9fcd512bef4d52e342637b54
2019-09-23 13:34:33 -04:00
Kevin Harwell f821e81071 res_sorcery_memory_cache: stale item update leak
When a stale item was being updated the object was being retrieved, but its
reference was not being decremented after the update. This patch makes it so
the object is now appropriately de-referenced.

ASTERISK-28523

Change-Id: I9d8173d3a0416a242f4eba92fa0853279c500ec7
2019-09-23 11:05:34 -05:00
George Joseph b1c5753b78 astmm.c: Display backtrace with memory show allocations
You can currently capture backtraces of memory allocations but they
only get displayed when you stop asterisk and the atexit hooks
are enabled.  Now, if memory backtrace is on and you issue a
"memory show allocations" CLI command for a specific file, then
a backtrace will show for each allocation that occurred after
you turned "memory backtrace on".  The backtrace display is shown
only when a specific file's allocations are displayed to prevent
a massive CLI dump of every file's allocations.

Change-Id: Ic657afc1fc6ec7205e16eb36a97a611d235a2b4f
2019-09-23 07:25:15 -05:00
Corey Farrell af0ccbc45e stasis: refcounter.py can incorrectly report skewed objects.
It is possible for topic->name to be NULL, this causes the allocation
reference to not be logged.  Use the name variable instead which has
been verified to be a non-empty.

Change-Id: I3d0031d03c8356e4808f00cdf2d5428712575883
2019-09-20 08:31:25 -05:00
Corey Farrell fd7fc3d7a5
stasis: Fix leaks
* Release reference returned by cache_remove
* state_alloc unconditionally bumped state_topic even when it was
  locally allocated.

Change-Id: I51101bf7d07b8dc8ce8fc46b6cb31fbbd213fbc7
2019-09-19 18:36:47 -04:00
Corey Farrell 78f329dad9 app_voicemail: Fix module unload leak.
Change-Id: Ib9a06565b9a178822d3bbb67eccf51432e12d84a
2019-09-19 11:16:05 -05:00
Joshua Colp 6e75e2565d Merge "func_jitterbuffer: Add audio/video sync support." into 17 2019-09-19 08:22:58 -05:00
Joshua Colp d2087607b6 Merge "core: Add H.265/HEVC passthrough support" into 17 2019-09-19 06:34:21 -05:00
Joshua Colp 926053d7bd func_jitterbuffer: Add audio/video sync support.
This change adds support to the JITTERBUFFER dialplan function
for audio and video synchronization. When enabled the RTCP SR
report is used to produce an NTP timestamp for both the audio and
video streams. Using this information the video frames are queued
until their NTP timestamp is equal to or behind the NTP timestamp
of the audio. The audio jitterbuffer acts as the leader deciding
when to shrink/grow the jitterbuffer when adaptive is in use. For
both adaptive and fixed the video buffer follows the size of the
audio jitterbuffer.

ASTERISK-28533

Change-Id: I3fd75160426465e6d46bb2e198c07b9d314a4492
2019-09-18 15:24:49 -05:00
Joshua Colp 69e8a44039 Merge "chan_pjsip: Relock correct channel during "fax" redirect." into 17 2019-09-18 15:13:52 -05:00
George Joseph b7e9c8437e Merge "chan_dahdi: Fix build with clang/llvm" into 17 2019-09-17 09:30:11 -05:00
Florian Floimair d7a3e4f5cf core: Add H.265/HEVC passthrough support
This change adds H.265/HEVC as a known codec and creates a cached
"h265" media format for use.

Note that RFC 7798 section 7.2 also describes additional SDP
parameters. Handling of these is not yet supported.

ASTERISK-28512

Change-Id: I26d262cc4110b4f7e99348a3ddc53bad0d2cd1f2
2019-09-17 13:41:51 +02:00
Joshua Colp 4d1baa3ae8 chan_pjsip: Relock correct channel during "fax" redirect.
When fax detection occurs on an outbound PJSIP channel the
redirect operation will result in a masquerade occurring and
the underlying channel on the session changing. The code
incorrectly relocked the new channel instead of the old
channel when returning. This resulted in the new channel
being locked indefinitely. The code now always acts on the
expected channel.

ASTERISK-28538

Change-Id: I2b2e60d07e74383ae7e90d752c036c4b02d6b3a3
2019-09-16 08:42:29 -05:00
Guido Falsi 5ff2f7a016 chan_dahdi: Fix build with clang/llvm
On FreeBSD using the clang/llvm compiler build fails to build due
to the switch statement argument being a non integer type expression.
Switch to an if/else if/else construct to sidestep the issue.

ASTERISK-28536 #close

Change-Id: Idf4a82cc1e94580a2d017fe9e351c226f23e20c8
2019-09-14 10:10:50 -05:00
Ben Ford 1d960195c2 res_rtp_asterisk.c: Send RTCP as compound packets.
According to RFC3550, ALL RTCP packets must be sent in a compond packet
of at least two individual packets, including SR/RR and SDES. REMB,
FIR, and NACK were not following this format, and as a result, would
fail the packet check in ast_rtcp_interpret. This was found from writing
unit tests for RTCP. The browser would accept the way we were
constructing these RTCP packets, but when sending directly from one
Asterisk instance to another, the above mentioned problem would occur.

Change-Id: Ieb140e9c22568a251a564cd953dd22cd33244605
2019-09-13 09:48:21 -05:00
Sean Bright 2fa296e7d4 channels: Allow updating variable value
When modifying an already defined variable in some channel drivers they
add a new variable with the same name to the list, but that value is
never used, only the first one found.

Introduce ast_variable_list_replace() and use it where appropriate.

ASTERISK-23756 #close
Patches:
  setvar-multiplie.patch submitted by Michael Goryainov

Change-Id: Ie1897a96c82b8945e752733612ee963686f32839
2019-09-12 15:59:51 -05:00
Friendly Automation cb9fdc21d1 Merge "res_rtp: Add unit tests for RTCP stats." into 17 2019-09-12 15:16:36 -05:00
George Joseph 492da93771 Merge "ChanIsAvail() generates a CDR when unanswered=yes in cdr.conf." into 17 2019-09-11 09:04:06 -05:00
Friendly Automation db1da38649 Merge "res_musiconhold: Added unregister realtime moh class" into 17 2019-09-11 09:02:35 -05:00
Joshua Colp 377f56bdc0 Merge "chan_sip: Update links referenced in deprecation notice" into 17 2019-09-11 07:12:33 -05:00
Joshua Colp 9f5a027aa3 Merge "chan_dahdi: set CHANNEL(hangupsource) when a PRI channel hangs up" into 17 2019-09-11 07:09:19 -05:00
Joshua Colp e82a765169 Merge "codec_resample: Ensure OUTSIDE_SPEEX is defined when necessary" into 17 2019-09-11 06:19:38 -05:00
sungtae kim 9e26136ee6 res_musiconhold: Added unregister realtime moh class
This fix allows a realtime moh class to be unregistered from the command
line. This is useful when the contents of a directory referenced by a
realtime moh class have changed.
The realtime moh class is then reloaded on the next request and uses the
new directory contents.

ASTERISK-17808

Change-Id: Ibc4c6834592257c4bb90601ee299682d15befbce
2019-09-11 02:31:48 -05:00
Ben Ford 5dad4f4ea1 res_rtp: Add unit tests for RTCP stats.
Added unit tests for RTCP video stats. These tests include NACK, REMB,
FIR/FUR/PLI, SR/RR/SDES, and packet loss statistics. The REMB and FIR
tests are currently disabled due to a bug. We expect to receive a
compound packet, but the code sends this out as a single packet, which
the browser accepts, but makes Asterisk upset.

While writing these tests, I noticed an issue with NACK as well. Where
it is handling a received NACK request, it was reading in only the first
8 bits of following packets that were also lost. This has been changed
to the correct value of 16 bits.

Also made a minor fix to the data buffer unit test.

Change-Id: I56107c7411003a247589bbb6086d25c54719901b
2019-09-10 13:10:59 -05:00
Frederic LE FOLL 50997de887 ChanIsAvail() generates a CDR when unanswered=yes in cdr.conf.
ChanIsAvail() creates a temporary channel with ast_request() to test
resource availability. It should not generate a CDR when it hangs up
this temporary channel.

This patch disables CDR generation for the temporary channel with
ast_cdr_set_property().

ASTERISK-28527

Change-Id: I7b0555c6909c7d322e452dde97c9ea5b111552d1
2019-09-10 11:45:14 -05:00
Frederic LE FOLL 9e67c92502 chan_dahdi: set CHANNEL(hangupsource) when a PRI channel hangs up
When the remote ISDN party ends an ISDN call on a PRI link
(DISCONNECT), CHANNEL(hangupsource) information is not available.

chan_dahdi already contains an ast_set_hangupsource() in
__dahdi_exception() function but it seems that ISDN message processing
does not use this part of code.

Two other channel modules associate ast_queue_hangup() and
ast_set_hangupsource() functions calls:
- chan_pjsip in chan_pjsip_session_end() function,
- chan_sip in sip_queue_hangup_cause() function.
chan_iax2 separates them, in iax2_queue_hangup()/iax2_destroy() and
set_hangup_source_and_cause().

Thus, I propose to add ast_set_hangupsource() beside
ast_queue_hangup() in sig_pri_queue_hangup(), like chan_pjsip and
chan_sip already do.

ASTERISK-28525

Change-Id: I0f588a4bcf15ccd0648fd69830d1b801c3f21b7c
2019-09-10 10:59:02 -05:00
George Joseph 44068cc6bf ARI: External Media
The Channel resource has a new sub-resource "externalMedia".
This allows an application to create a channel for the sole purpose
of exchanging media with an external server.  Once created, this
channel could be placed into a bridge with existing channels to
allow the external server to inject audio into the bridge or
receive audio from the bridge.
See https://wiki.asterisk.org/wiki/display/AST/External+Media+and+ARI
for more information.

Change-Id: I9618899198880b4c650354581b50c0401b58bc46
2019-09-10 10:44:00 -05:00
Friendly Automation 03625b4bc6 Merge "test_utils.c: Skip test adsi_loaded_test if module not loaded." into 17 2019-09-10 08:32:57 -05:00
Friendly Automation 70ebcf26c0 Merge "chan_unistim: Fix clang warning: variable sized type not at end of a struct" into 17 2019-09-10 08:32:22 -05:00
George Joseph c060ef7dee chan_sip: Update links referenced in deprecation notice
The links in the deprecation notice were the shortened
variety but it makes better sense to show the unshortened
links as they're more descriptive.

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

Change-Id: If2da5d5243e2d4a6f193b15691d23e7e5a7c57a9
2019-09-10 06:34:55 -06:00
Sean Bright 75d6418d8e codec_resample: Ensure OUTSIDE_SPEEX is defined when necessary
ASTERISK-28511

Change-Id: If0d58598ce14aad3c786a1c0127b5f7b200b737d
2019-09-08 10:54:02 -05:00
George Joseph e35918235e Merge "AST-2019-005 - translate: Don't assume all frames will have a src." into 17 2019-09-05 07:52:30 -05:00
Joshua Colp 61c01df560 AST-2019-005 - translate: Don't assume all frames will have a src.
This change removes the assumption that a frame will always have
a src set on it. This assumption is incorrect.

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

ASTERISK-28499

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

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

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

Change-Id: I168f45f4da29cfe739acf87e597baa2aae7aa572
2019-09-05 05:25:19 -05:00
Chris-Savinovich 7d99710fa6 test_utils.c: Skip test adsi_loaded_test if module not loaded.
Module res_adsi.so is deprecated, therefore it does not load by default.
Module not loaded causes it to yield a FAIL when tested by tests/test_utils.c.
This fix checks if the corresponding module is loaded at the start of the test,
and if not, it passes the test and exits with a message.

This fix is applied to all versions where the module is marked deprecated.

Change-Id: I52be64c8f6af222e15148a856d1f10cb113e1e94
2019-09-04 16:51:57 -05:00
Igor Goncharovsky 056ddf76ce chan_unistim: Fix clang warning: variable sized type not at end of a struct
On reading information about initial client packet unistim use dirty
implementation of destination ip address retrieval. This fix uses
CMSG_*(..) to get ip address and make clang compile without warning.

ASTERISK-25592 #close
Reported-by: Alexander Traud

Change-Id: Ic1fd34c2c2bcc951da65bf62e3f7a8adff8351b1
2019-09-03 22:59:52 -05:00
George Joseph 16ae4cd2db Merge "res_pjsip_mwi: add better handling of solicited vs unsolicited subscriptions" into 17 2019-09-03 05:34:51 -05:00
George Joseph 2cd5b84af8 Merge "chan_unistim: Fix code, causing all incoming DTMF sent back to asterisk" into 17 2019-09-03 05:31:54 -05:00
George Joseph 0aae0499da Merge "codec_resample: Upgrade speex_resample to fix up-sampling bug" into 17 2019-08-30 07:45:31 -05:00
Kevin Harwell a36fb473fe res_pjsip_mwi: add better handling of solicited vs unsolicited subscriptions
res_pjsip_mwi allows both solicited and unsolicited MWI subscription types.
While both can be set in the configuration for a given endpoint/aor, only
one is allowed. Precedence is given to unsolicited. Meaning if an endpoint/aor
is configured to allow both types then the solicited subscription is rejected
when it comes in. However, there is a configuration option to override that
behavior:

mwi_subscribe_replaces_unsolicited

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

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

ASTERISK-28488

Change-Id: Iec2ec12d9431097e97ed5f37119963aee41af7b1
2019-08-28 18:21:33 -05:00
Igor Goncharovsky 95b3c9839d chan_unistim: Fix code, causing all incoming DTMF sent back to asterisk
Current implementation of ast_channel_tech send_digit_begin hook uses
same function for tone playback as key press handler. This cause every
incoming dtmf send back to asterisk. In case of two unistim phones
connected to each other, it'll cause indefinite DTMF loop. Fix add
separate function for dtmf tone phone play.

Change-Id: I5795db468df552f0c89c7576b6b3858b26c4eab4
2019-08-27 02:53:08 -05:00
Igor Goncharovsky e7f1f7eefd chan_unistim: Fix RTP port byte order for big-endian arch
This patch fixes one-way oudio that users expirienced on
big-endian architechtires. RTP port number bytes was stored
in improper order and phone sent RTP to wrong RTP port.

Reported-by: Andrey Ionov
Change-Id: I9a9ca7f26e31a67bbbceff12923baa10dfb8a3be
2019-08-26 04:49:14 -05:00
Sean Bright 34ab9964f5 codec_resample: Upgrade speex_resample to fix up-sampling bug
ASTERISK-28511 #close

Change-Id: Idd07bf341e89ac999c7f5701d9b72b8a9cb11e82
2019-08-23 16:39:50 -05:00
Friendly Automation 7f64921a37 Merge "Fix misname 'res_external_mwi' to 'res_mwi_external' in comments." into 17 2019-08-23 07:51:54 -05:00
Friendly Automation e33ab894bf Merge "pjproject: Configurable setting for cnonce to include hyphens or not" into 17 2019-08-22 19:49:58 -05:00
Alexei Gradinari a0b0c7540c Fix misname 'res_external_mwi' to 'res_mwi_external' in comments.
Change-Id: Ic784be8500e5cb75dcb34bae9f03cfd93b6b34fb
2019-08-22 19:04:42 -05:00
George Joseph 581ffdf6a9 chan_rtp: Accept hostname as well as ip address as destination
The UnicastRTP channel driver provided by chan_rtp now accepts
"<hostname>:<port>" as an alternative to "<ip_address>:<port>"
in the destination. The first AAAA (preferred) or A record resolved
will be used as the destination. The lookup is synchronous so beware
of possible dialplan delays if you specify a hostname.

Change-Id: Ie6f95b983a8792bf0dacc64c7953a41032dba677
2019-08-22 07:39:12 -05:00
George Joseph b3d9f6ef6c dns_core: Create new API ast_dns_resolve_ipv6_and_ipv4
The new function takes in a pointer to an ast_sockaddr structure,
a hostname and an optional port and then dispatches parallel
"AAAA" and "A" record queries.  If an "AAAA" record is returned,
it's parsed into the ast_sockaddr structure along with the port
if it was supplied.  If no "AAAA" record was returned, the
first "A" record returned (if any) is parsed instead.

This is a synchronous call.  If you need asynchronous lookups,
use ast_dns_query_set_resolve_async and roll your own.

Change-Id: I194b0b0e73da94b35cc35263a868ffac3a8d0a95
2019-08-22 07:33:33 -05:00
Dan Cropp a1d38e19a2 pjproject: Configurable setting for cnonce to include hyphens or not
NEC SIP Station interface with authenticated registration only supports cnonce
up to 32 characters.  In Linux, PJSIP would generate 36 character cnonce
which included hyphens.  Teluu developed this patch adding a compile time
setting to default to not include the hyphens.  They felt it best to still
generate the UUID and strip the hyphens.
They have indicated it will be part of PJSIP 2.10.

ASTERISK-28509
Reported-by: Dan Cropp

Change-Id: Ibdfcf845d4f8c0a14df09fd983b11f2d72c5f470
2019-08-21 18:44:17 -05:00
Friendly Automation 61edef60a1 Merge "res_pjsip: Channel variable SIPFROMDOMAIN" into 17 2019-08-21 09:03:44 -05:00
Friendly Automation 8f7052f8dc Merge "res_ari.c: Prefer exact handler match over wildcard" into 17 2019-08-21 07:48:56 -05:00
Stas Kobzar 3a246c2a69 res_pjsip: Channel variable SIPFROMDOMAIN
In chan_sip, there was variable SIPFROMDOMAIN that allows to set
From header URI domain per channel. This patch introduces res_pjsip
variable SIPFROMDOMAIN for backward compatibility with chan_sip.

ASTERISK-28489

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

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

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

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

Change-Id: I574aa3cbe4249c92c30f74b9b40e750e9002f925
2019-08-20 13:19:16 -05:00
Sean Bright e123d1ccc5 audiohook.c: Substitute silence for unavailable audio frames
There are 4 scenarios to consider when capturing audio from a channel
with an audiohook:

 1. There is no rx and no tx audio, so return nothing.
 2. There is rx but no tx audio, so return rx.
 3. There is tx but no rx audio, so return tx.
 4. There is rx and tx audio, so mix them and return.

The file passed as the primary argument to MixMonitor will be written to
in scenarios 2, 3, and 4. However, if you pass the r() and t() options
to MixMonitor, a frame will only be written to the r() file if there was
rx audio and a frame will only be written to the t() file if there was
tx audio.

If you subsequently take the r() and t() files and try to mix them, the
sides of the conversation will 'drift' and be non-representative of the
user experience.

This patch adds a new 'S' option to MixMonitor that injects a frame of
silence on either the r() side or the t() side of the channel so that
when later mixed, there is no such drift.

Change-Id: Ibf5ed73a811087727bd561a89a59f4447b4ee20e
2019-08-20 08:43:48 -05:00
Alexei Gradinari 052ab9d966 app_voicemail/IMAP: check mailstream not NULL in leave_voicemail
The function leave_voicemail checks if expungeonhangup is set,
but does not check if IMAP stream is closed,
so it could call imap function with NULL stream.
This leads to segfault.

ASTERISK-28505 #close

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

ASTERISK-28487 #close

Change-Id: I6c2ad5b95f422c263d078b5c0e84c111807dffc6
2019-08-09 10:08:41 -05:00
George Joseph 5c9ae25090 Merge "srtp: Fix possible race condition, and add NULL checks" into 17 2019-08-09 07:51:44 -05:00
George Joseph 71f89ce175 Merge "cdr / cel: Use event time at event creation instead of processing." into 17 2019-08-08 13:26:06 -05:00
George Joseph 5489ad5574 CI: Escape backslashes in printenv/sort/tr
Change-Id: I52be64c8f6af2bbe15148a856d1f10cb113e1e94
(cherry picked from commit c6558e09af)
2019-08-08 12:15:26 -05:00
Kevin Harwell 5daa9bbaee srtp: Fix possible race condition, and add NULL checks
Somehow it's possible for the srtp session object to be NULL even though the
Asterisk srtp object itself is valid. When this happened it would cause a
crash down in the srtp code when attempting to protect or unprotect data.

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

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

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

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

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

ASTERISK-28472

Change-Id: I240e11cbb1e9ea8083d59d50db069891228fe5cc
2019-08-08 11:31:00 -05:00
George Joseph aa44e723c5 CI: Add "throttle" label and "skip_gate" capability
To make throttling by label fully active, the "throttle" option
has to be specified with a specific label.

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

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

Change-Id: I4c0b1085acec4805f2ca207eebac50aad81f27e2
2019-08-08 09:49:06 -05:00
Friendly Automation 90a14a0a90 Merge "app_voicemail: Remove extra menuselect build options" into 17 2019-08-08 06:44:14 -05:00
Friendly Automation b4ab3dab90 Merge "CI: Make node labels job-specific" into 17 2019-08-07 11:19:18 -05:00
Joshua Colp 108b1abbd9 cdr / cel: Use event time at event creation instead of processing.
When updating times on CDR or CEL records using the time at which
it is done can result in times being incorrect if the system is
heavily loaded and stasis message processing is delayed.

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

ASTERISK-28498

Change-Id: I6829227e67aefa318efe5e183a94d4a1b4e8500a
2019-08-07 04:48:34 -06:00
George Joseph ec7cd3b0a5 Merge "res_musiconhold: Use a vector instead of custom array allocation" into 17 2019-08-06 11:05:39 -05:00
George Joseph 8652140794 CI: Make node labels job-specific
Originally, the eligible nodes for a job were labelled only by
"swdev-docker".  So basically any node could run any job.  We had
found that allowing a node to run more than 1 gate at a time was
problematic so we limited the nodes to processing 1 job at a time.
With the creation of the Asterisk 17 branches however, we now have
so many active branches that getting checks and gates through in
a timely manner is problematic when a node can run only 1 job
at a time.

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

Change-Id: I2032bf6afbcec5c341d9b852214c0c812d3d6db5
2019-08-06 09:51:34 -06:00
Friendly Automation 261cb42ccb Merge "various modules: json integer overflow" into 17 2019-08-06 10:08:07 -05:00
Friendly Automation a2a4e9c717 Merge "main/udptl.c: correctly handle udptl sequence wrap around" into 17 2019-08-06 09:34:08 -05:00
Sean Bright 87f8ca2812 app_voicemail: Remove extra menuselect build options
You now select voicemail backends like normal dialplan applications, so
there is no longer a need for their own menuselect category.

Reported by snuff-work in #asterisk-dev

Change-Id: Idfa4c9c8349726074318a9e6b68d24c374521005
2019-08-06 09:21:18 -04:00
Kevin Harwell a305f2fdcb various modules: json integer overflow
There were still a few places in the code that could overflow when "packing"
a json object with a value outside the base type integer's range. For instance:

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

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

ASTERISK-28480

Change-Id: Ied530780d83e6f1772adba0e28d8938ef30c49a1
2019-08-01 15:31:34 -06:00
Sean Bright 1976db6ffd res_musiconhold: Use a vector instead of custom array allocation
Change-Id: Ic476a56608b1820ca93dcf68d10cd76fc0b94141
2019-08-01 13:44:16 -06:00
Joshua Colp 20459d4cac res_pjsip: Fix multiple of the same contact in "pjsip show contacts".
The code for gathering contacts could result in the same contact
being retrieved and added to the list multiple times. The container
which stores the contacts to display will now only allow a contact
to be added to it once instead of multiple times.

ASTERISK-28228

Change-Id: I805185cfcec03340f57d2b9e6cc43c49401812df
2019-08-01 04:11:49 -06:00
George Joseph 7300bdd382 Merge "loader.c: Fix possible SEGV when a module fails to register" into 17 2019-07-31 08:56:52 -05:00
George Joseph cccad75517 Merge "res_musiconhold: Use ast_pipe_nonblock() wrapper" into 17 2019-07-31 08:56:14 -05:00
Torrey Searle 44af3e9018 main/udptl.c: correctly handle udptl sequence wrap around
incorrect handling of UDPTL squence number wrap arounds causes
loss of packets every time the wrap around occurs

ASTERISK-28483 #close

Change-Id: I33caeb2bf13c574a1ebb81714b58907091d64234
2019-07-30 06:48:59 -06:00
Sean Bright c748187bbf manager: Send fewer packets
The functions that build manager message headers do so in a way that
results in a single messages being split across multiple packets. While
this doesn't matter to the remote end, it makes network captures noisier
and harder to follow, and also means additional system calls.

With this patch, we build up more of the message content into the TLS
buffer before flushing to the network. This change is completely
internal to the manager code and does not affect any of the existing
API's consumers.

Change-Id: I50128b0769060ca5272dbbb5e60242d131eaddf9
2019-07-29 12:09:49 -06:00
Asterisk Development Team f1e0c9d1b8 Update CHANGES and UPGRADE.txt for 17.0.0 2019-07-29 11:46:38 -05:00
George Joseph 4f2ad5a55d doc: Add "master-only" flag back to the CHANGES and UPGRADE files
In order to run the documentation scripts the flags needs to be
added back to the staging files.

Change-Id: Ia10a153c50c970cfa1e85815208dfaddb3f2ccd4
2019-07-29 10:10:28 -06:00
Sean Bright a66ccb90ac res_musiconhold: Use ast_pipe_nonblock() wrapper
Change-Id: Ib0a4b41e5ececbe633079e2d8c2b66c031d2d1f2
2019-07-29 09:04:38 -06:00
George Joseph e821a637a8 loader.c: Fix possible SEGV when a module fails to register
When a module fails to register itself (usually a coding error
in the module), dlerror() can return NULL.  We weren't checking
for that in load_dlopen() before trying to strdup the error message
so a SEGV was thrown.  dlerror() is now surrounded with an S_OR
so we don't SEGV.

Change-Id: Ie0fb9316f08a321434f3f85aecf3c7d2ede8b956
2019-07-29 07:39:08 -06:00
George Joseph 80d8dce6af Prepare Asterisk 17 Branch
Change-Id: Idb79a69646d2511e7bf1573b9b0322cc22ea54e8
2019-07-26 12:06:57 -06:00
333 changed files with 106245 additions and 4229 deletions

View File

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

1
.lastclean Normal file
View File

@ -0,0 +1 @@
40

1
.version Normal file
View File

@ -0,0 +1 @@
17.4.0

355
CHANGES
View File

@ -12,6 +12,361 @@
===
==============================================================================
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 17.3.0 to Asterisk 17.4.0 ------------
------------------------------------------------------------------------------
app_confbridge
------------------
* A new option, "text_messaging", has been added to the user profile
which allows control over whether text messaging is enabled or
disabled for a user. If enabled (the default) text messages
will be sent to the user. If disabled no text messages will be
sent to the user.
func_volume
------------------
* Accept decimal number as argument.
res_pjsip_session
------------------
* When placing an outgoing call to a PJSIP endpoint the intent
of any requested formats will now be respected. If only an audio
format is requested (such as ulaw) but the underlying endpoint
does not support the format the resulting SDP will still only
contain an audio stream, and not any additional streams such as
video.
res_rtp_asterisk
------------------
* This change include a new cli command 'rtp show settings'
The command display by general settings of rtp configuration. For this
point is added the fields: rtpstart, rtpend, dtmftimeout, rtpchecksum,
strictrtp, learning_min_sequential and icesupport.
* The blacklist mechanism in res_rtp_asterisk for ICE and STUN was converted to
an ACL mechanism.
As such six now options are now available:
ice_deny
ice_permit
ice_acl
stun_deny
stun_permit
stun_acl
These options have their obvious meanings as used elsewhere.
Backwards compatibility was maintained by adding {stun,ice}_blacklist as
aliases for {stun,ice}_deny.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 17.2.0 to Asterisk 17.3.0 ------------
------------------------------------------------------------------------------
Messaging
------------------
* In order to reduce the amount of AMI and ARI events generated,
the global "Message/ast_msg_queue" channel can be set to suppress
it's normal channel housekeeping events such as "Newexten",
"VarSet", etc. This can greatly reduce load on the manager
and ARI applications when the Digium Phone Module for Asterisk
is in use. To enable, set "hide_messaging_ami_events" in
asterisk.conf to "yes" In Asterisk versions <18, the default
is "no" preserving existing behavior. Beginning with
Asterisk 18, the option will default to "yes".
app_mixmonitor
------------------
* If the 'filename' argument to MixMonitor() ended with '.wav49,'
Asterisk would silently convert the extension to '.WAV' when opening
the file for writing. This caused the MIXMONITOR_FILENAME variable to
reference the wrong file. The MIXMONITOR_FILENAME variable will now
reflect the name of the file that Asterisk actually used instead of
the filename that was passed to the application.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 17.1.0 to Asterisk 17.2.0 ------------
------------------------------------------------------------------------------
app_chanisavail
------------------
* The ChanIsAvail application now tolerates empty positions in the supplied
device list. Dialplan can now be simplified by not having to check for
empty positions in the device list.
app_confbridge
------------------
* A new bridge profile option, maximum_sample_rate, has been added which sets
a maximum sample rate that the bridge will be mixed at. This allows the bridge
to move below the maximum sample rate as needed but caps it at the maximum.
app_dial
------------------
* The Dial application now tolerates empty positions in the supplied
destination list. Dialplan can now be simplified by not having to check
for empty positions in the destination list. If there are no endpoints to
dial then DIALSTATUS is set to CHANUNAVAIL.
app_page
------------------
* The Page application now tolerates empty positions in the supplied
destination list. Dialplan can now be simplified by not having to check
for empty positions in the destination list.
func_curl
------------------
* A new option, followlocation, can now be enabled with the CURLOPT()
dialplan function. Setting this will instruct cURL to follow 3xx
redirects, which it does not by default.
http
------------------
* You can now disable the /httpstatus page served by Asterisk's built-in
HTTP server by setting 'enable_status' to 'no' in http.conf.
minmemfree
------------------
* The 'minmemfree' configuration option now counts memory allocated to
the filesystem cache as "free" because it is memory that is available
to the process.
res_pjsip_endpoint_identifier_ip
------------------
* In 'type = identify' sections, the addresses specified for the 'match'
clause can now include a port number. For IP addresses, the port is
provided by including a colon after the address, followed by the
desired port number. If supplied, the netmask should follow the port
number. To specify a port for IPv6 addresses, the address itself must
be enclosed in brackets to be parsed correctly.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 17.0.0 to Asterisk 17.1.0 ------------
------------------------------------------------------------------------------
ARI Channels
------------------
* The Channel resource has a new sub-resource "externalMedia".
This allows an application to create a channel for the sole purpose
of exchanging media with an external server. Once created, this
channel could be placed into a bridge with existing channels to
allow the external server to inject audio into the bridge or
receive audio from the bridge.
See https://wiki.asterisk.org/wiki/display/AST/External+Media+and+ARI
for more information.
Core
------------------
* H.265/HEVC is now a supported video codec and it can be used by
specifying "h265" in the allow line.
Please note however, that handling of the additional SDP parameters
described in RFC 7798 section 7.2 is not yet supported.
app_mixmonitor
------------------
* An option 'S' has been added to MixMonitor. If used in combination with
the r() and/or t() options, if a frame is available to write to one of
those files but not the other, a frame of silence if written to the file
that does not have an audio frame. This should prevent the two files
from "drifting" when mixed after the fact.
app_voicemail
------------------
* A feature was added in Asterisk 13.27.0 and 16.4.0 that removed lock files from
the Asterisk voicemail directory on startup. Some users that store their
voicemails on network storage devices experienced slow startup times due to the
relative expense of traversing the voicemail directory structure looking for
orphaned lock files. This feature has now been removed.
Users who require the lock files to be removed at startup should modify their
startup scripts to do so before starting the asterisk process.
chan_pjsip
------------------
* A new dialplan function, PJSIP_MOH_PASSTRHOUGH, has been added to chan_pjsip. This
allows the behaviour of the moh_passthrough endpoint option to be read or changed
in the dialplan. This allows control on a per-call basis.
chan_rtp
------------------
* The UnicastRTP channel driver provided by chan_rtp now accepts
"<hostname>:<port>" as an alternative to "<ip_address>:<port>" in the destination.
The first AAAA (preferred) or A record resolved will be used as the destination.
The lookup is synchronous so beware of possible dialplan delays if you specify a
hostname.
func_curl
------------------
* A new parameter, httpheader, has been added to CURLOPT function. This parameter
allows to set custom http headers for subsequent calls off CURL function.
Any setting of headers will replace the default curl headers
(e.g. "Content-type: application/x-www-form-urlencoded")
func_jitterbuffer
------------------
* The JITTERBUFFER dialplan function now has an option to enable video synchronization
support. When enabled and used with a compatible channel driver (chan_sip, chan_pjsip)
the video is buffered according to the size of the audio jitterbuffer and is
synchronized to the audio.
res_musiconhold
------------------
* This fix allows a realtime moh class to be unregistered from the command
line. This is useful when the contents of a directory referenced by a
realtime moh class have changed.
The realtime moh class is then reloaded on the next request and uses the
new directory contents.
* A new mode - playlist - has been added to res_musiconhold. This mode allows the
user to specify the files (or URLs) to play explicitly by putting them directly
in musiconhold.conf.
taskprocessor.c
------------------
* Added two new CLI commands to reset stats for taskprocessors. You can
reset stats for a single, specific taskprocessor ('core reset
taskprocessor <taskprocessor>'), or you can reset all taskprocessors
('core reset taskprocessors'). These commands will reset the counter for
the number of tasks processed as well as the max queue size.
* Added "like" support for 'core show taskprocessors'. Now you
can specify a specific set of taskprocessors (or just one) by
adding the keyword "like" to the above command, followed by
your search criteria.
------------------------------------------------------------------------------
--- New functionality introduced in Asterisk 17.0.0 --------------------------
------------------------------------------------------------------------------
Bridging
------------------
* The bridging core no longer uses the stasis cache for bridge
snapshots. The latest bridge snapshot is now stored on the
ast_bridge structure itself.
The following APIs are no longer available since the stasis cache
is no longer used:
ast_bridge_topic_cached()
ast_bridge_topic_all_cached()
A topic pool is now used for individual bridge topics.
The ast_bridge_cache() function was removed since there's no
longer a separate container of snapshots.
A new function "ast_bridges()" was created to retrieve the
container of all bridges. Users formerly calling
ast_bridge_cache() can use the new function to iterate over
bridges and retrieve the latest snapshot directly from the
bridge.
The ast_bridge_snapshot_get_latest() function was renamed to
ast_bridge_get_snapshot_by_uniqueid().
A new function "ast_bridge_get_snapshot()" was created to retrieve
the bridge snapshot directly from the bridge structure.
The ast_bridge_topic_all() function now returns a normal topic
not a cached one so you can't use stasis cache functions on it
either.
The ast_bridge_snapshot_type() stasis message now has the
ast_bridge_snapshot_update structure as it's data. It contains
the last snapshot and the new one.
Channels
------------------
* The core no longer uses the stasis cache for channels snapshots.
The following APIs are no longer available:
ast_channel_topic_cached()
ast_channel_topic_all_cached()
The ast_channel_cache_all() and ast_channel_cache_by_name() functions
now returns an ao2_container of ast_channel_snapshots rather than a
container of stasis_messages therefore you can't call stasis_cache
functions on it.
The ast_channel_topic_all() function now returns a normal topic,
not a cached one so you can't use stasis cache functions on it either.
The ast_channel_snapshot_type() stasis message now has the
ast_channel_snapshot_update structure as it's data.
ast_channel_snapshot_get_latest() still returns the latest snapshot.
chan_sip
------------------
* The chan_sip module is now deprecated, users should migrate to the
replacement module chan_pjsip. See guides at the Asterisk Wiki:
https://wiki.asterisk.org/wiki/x/tAHOAQ
https://wiki.asterisk.org/wiki/x/hYCLAQ
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 16.0.0 to Asterisk 17.0.0 ------------
------------------------------------------------------------------------------
AttendedTransfer
------------------
* A new application, this will queue up attended transfer to the given extension.
BlindTransfer
------------------
* A new application, this will redirect all channels currently
bridged to the caller channel to the specified destination.
ConfBridge
------------------
* Add "average_all", "highest_all", and "lowest_all" values for
the remb_behavior option. These values operate on a bridge
level instead of a per-source level. This means that a single
REMB value is calculated and sent to every sender, instead of
a REMB value that is unique for the specific sender..
Dial
------------------
* Add RINGTIME and RINGTIME_MS variables containing respectively seconds and
milliseconds between creation of the dialing channel and receiving the first
RINGING signal
Add PROGRESSTIME and PROGRESSTIME_MS variables analogous to the above with respect to
the PROGRESS signal. Shorter of these two times should be equivalent to
the PDD (Post Dial Delay) value
Add DIALEDTIME_MS and ANSWEREDTIME_MS variables to get millisecond resolution
versions of DIALEDTIME and ANSWEREDTIME
RTP/ICE
------------------
* You can now indicate that you'd like an ice_host_candidate's local address
to be published as well as the mapped address. See the sample rtp.conf
for more information.
ReadExten
------------------
* Add 'p' option to stop reading extension if user presses '#' key.
pbx_dundi
------------------
* The DUNDi PBX module now supports IPv4/IPv6 dual binding.
res_pjsip
------------------
* Added a new PJSIP global setting called norefersub.
Default is true to keep support working as before.
res_pjsip_refer configures PJSIP norefersub capability accordingly.
Checks the PJSIP global setting value.
If it is true (default) it adds the norefersub capability to PJSIP.
If it is false (disabled) it does not add the norefersub capability
to PJSIP.
This is useful for Cisco switches that do not follow RFC4488.
res_rtp_asterisk
------------------
* DTLS packets will now be fragmented according to the MTU as set in rtp.conf. This
allows larger certificates to be used for the DTLS negotiation. By default this value
is 1200.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 16.2.0 to Asterisk 16.3.0 ----------
------------------------------------------------------------------------------

90042
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

View File

@ -234,6 +234,10 @@ ifeq ($(OSARCH),OpenBSD)
_ASTCFLAGS+=-pthread -ftrampolines
endif
ifeq ($(OSARCH),linux-uclibc)
AST_LIBS+=-lpthread -ldl
endif
ifeq ($(OSARCH),SunOS)
_ASTCFLAGS+=-Wcast-align -DSOLARIS -I../include/solaris-compat -I/opt/ssl/include -I/usr/local/ssl/include -D_XPG4_2 -D__EXTENSIONS__
endif

View File

@ -332,7 +332,7 @@ Data: echo hello world!
```
This manager command will attempt to execute an Asterisk application, System,
which is normally associated with the "system" class authorication. While some
which is normally associated with the "system" class authorization. While some
checks have been put into Asterisk to take this into account, certain dialplan
configurations and/or clever manipulation of the Originate manager action can
circumvent these checks. For example, take the following dialplan:
@ -365,7 +365,7 @@ set channel variables; which allows the execution of dialplan functions.
Dialplan functions within Asterisk are incredibly powerful, which is wonderful
for building applications using Asterisk. But during the read or write
execution, certain diaplan functions do much more. For example, reading the
execution, certain dialplan functions do much more. For example, reading the
SHELL() function can execute arbitrary commands on the system Asterisk is
running on. Writing to the FILE() function can change any file that Asterisk has
write access to.

View File

@ -18,6 +18,198 @@
===
===========================================================
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 17.3.0 to Asterisk 17.4.0 ------------
------------------------------------------------------------------------------
Core
------------------
* The streams API function ast_stream_get_formats is
now defined as returning the format capabilities const.
This has always been the case but was never enforced
through the API itself. Any consumer of this API that
is not treating the formats as immutable should update
their code to create a new format capabilities and set
it on the stream instead.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 17.2.0 to Asterisk 17.3.0 ------------
------------------------------------------------------------------------------
ARI
------------------
* The "TextMessageReceived" event used to include a list of "TextMessageVariable"
objects as part of its output. Due to a couple of bugs in Asterisk a list of
received variables was never included even if ones were available. However,
variables set to send would be (which they should have not been), but would
fail validation due to the bad formatting.
So basically there was no way to get a "TextMessageReceived" event with
variables. Due to this the API has changed. The "TextMessageVariable" object
no longer exists. "TextMessageReceived" now returns a JSON object of key/value
pairs. So for instance instead of a list of "TextMessageVariable" objects:
[ TextMessageVariable, TextMessageVariable, TextMessageVariable]
where a TextMessageVariable was supposed to be:
{ "key": "<var name>", "value":, "<var value>" }
The output is now just:
{ "<var name>": "<var value>" }
This aligns more with how variables are specified when sending a message, as
well as other variable lists in ARI.
res_stasis
------------------
* The "TextMessageReceived" event used to include a list of "TextMessageVariable"
objects as part of its output. Due to a couple of bugs in Asterisk a list of
received variables was never included even if ones were available. However,
variables set to send would be (which they should have not been), but would
fail validation due to the bad formatting.
So basically there was no way to get a "TextMessageReceived" event with
variables. Due to this the API has changed. The "TextMessageVariable" object
no longer exists. "TextMessageReceived" now returns a JSON object of key/value
pairs. So for instance instead of a list of "TextMessageVariable" objects:
[ TextMessageVariable, TextMessageVariable, TextMessageVariable]
where a TextMessageVariable was supposed to be:
{ "key": "<var name>", "value":, "<var value>" }
The output is now just:
{ "<var name>": "<var value>" }
This aligns more with how variables are specified when sending a message, as
well as other variable lists in ARI.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 17.0.0 to Asterisk 17.1.0 ------------
------------------------------------------------------------------------------
AMI
------------------
* The AMI Originate action, which optionally takes a dialplan application as
an argument, no longer accepts "Originate" as the application due to
security concerns.
------------------------------------------------------------------------------
--- New functionality introduced in Asterisk 17.0.0 --------------------------
------------------------------------------------------------------------------
Applications
------------------
* The JabberStatus application, deprecated in Asterisk 12, has been removed.
Bridging
------------------
* The bridging core no longer uses the stasis cache for bridge
snapshots. The latest bridge snapshot is now stored on the
ast_bridge structure itself.
The following APIs are no longer available since the stasis cache
is no longer used:
ast_bridge_topic_cached()
ast_bridge_topic_all_cached()
A topic pool is now used for individual bridge topics.
The ast_bridge_cache() function was removed since there's no
longer a separate container of snapshots.
A new function "ast_bridges()" was created to retrieve the
container of all bridges. Users formerly calling
ast_bridge_cache() can use the new function to iterate over
bridges and retrieve the latest snapshot directly from the
bridge.
The ast_bridge_snapshot_get_latest() function was renamed to
ast_bridge_get_snapshot_by_uniqueid().
A new function "ast_bridge_get_snapshot()" was created to retrieve
the bridge snapshot directly from the bridge structure.
The ast_bridge_topic_all() function now returns a normal topic
not a cached one so you can't use stasis cache functions on it
either.
The ast_bridge_snapshot_type() stasis message now has the
ast_bridge_snapshot_update structure as it's data. It contains
the last snapshot and the new one.
Build
------------------
* Asterisk headers are no longer installed and uninstalled automatically when
performing a "make install" or a "make uninstall". To install/uninstall the
headers, use "make install-headers" and "make uninstall-headers". The headers
also continue to be uninstalled when performing a "make uninstall-all".
Channels
------------------
* The core no longer uses the stasis cache for channels snapshots.
The following APIs are no longer available:
ast_channel_topic_cached()
ast_channel_topic_all_cached()
The ast_channel_cache_all() and ast_channel_cache_by_name() functions
now returns an ao2_container of ast_channel_snapshots rather than a
container of stasis_messages therefore you can't call stasis_cache
functions on it.
The ast_channel_topic_all() function now returns a normal topic,
not a cached one so you can't use stasis cache functions on it either.
The ast_channel_snapshot_type() stasis message now has the
ast_channel_snapshot_update structure as it's data.
ast_channel_snapshot_get_latest() still returns the latest snapshot.
chan_sip
------------------
* The chan_sip module is now deprecated, users should migrate to the
replacement module chan_pjsip. See guides at the Asterisk Wiki:
https://wiki.asterisk.org/wiki/x/tAHOAQ
https://wiki.asterisk.org/wiki/x/hYCLAQ
func_callerid
------------------
* The CALLERPRES() dialplan function, deprecated in Asterisk 1.8, has been
removed.
res_parking
------------------
* The PARKINGSLOT channel variable, deprecated in Asterisk 12 in favor of the
PARKING_SPACE channel variable, will no longer be set.
res_xmpp
------------------
* The JabberStatus application, deprecated in Asterisk 12, has been removed.
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 16.0.0 to Asterisk 17.0.0 ------------
------------------------------------------------------------------------------
Core
------------------
* res_pjsip_pubsub is now required so call transfer progress can be monitored
and reported in the channel variable TRANSFERSTATUS.
app_voicemail.c
------------------
* The "Voicemail Build Options" section of menuselect has been removed along with
the FILE_STORAGE, ODBC_STORAGE and IMAP_STORAGE menuselect options. All 3 variants
of the voicemail app can now be built at the same by enabling app_voicemail,
app_voicemail_imap, and app_voicemail_odbc under the "Applications" section.
By default, only app_voicemail is enabled. Also, the modules.conf sample has
been updated to "noload" app_voicemail_imap and app_voicemail_odbc should they
all be built. Packagers must update their build scripts appropriately.
chan_pjsip
------------------
* res_pjsip_pubsub is now required so call transfer progress can be monitored
and reported in the channel variable TRANSFERSTATUS.
New in 16.0.0:
app_fax:

View File

@ -173,7 +173,9 @@ 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;
#if MYSQL_VERSION_ID >= 50013
#ifdef HAVE_MYSQLCLIENT_BOOL
bool my_bool_true = 1;
#elif HAVE_MYSQLCLIENT_MY_BOOL
my_bool my_bool_true = 1;
#endif
@ -382,6 +384,13 @@ 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) {
@ -406,7 +415,8 @@ static int my_unload_module(int reload)
if (reload) {
return ast_cdr_backend_suspend(name);
} else {
return ast_cdr_unregister(name);
/* We unregistered earlier */
return 0;
}
}
@ -460,7 +470,9 @@ static int my_connect_db(struct ast_config *cfg)
MYSQL_ROW row;
MYSQL_RES *result;
char sqldesc[128];
#if MYSQL_VERSION_ID >= 50013
#ifdef HAVE_MYSQLCLIENT_BOOL
bool my_bool_true = 1;
#elif HAVE_MYSQLCLIENT_MY_BOOL
my_bool my_bool_true = 1;
#endif

View File

@ -536,11 +536,6 @@ static struct ast_channel *ooh323_new(struct ooh323_pvt *i, int state,
ch = NULL;
}
}
if (ch) {
ast_publish_channel_state(ch);
}
} else {
ao2_cleanup(caps);
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
@ -2225,7 +2220,7 @@ int onCallEstablished(ooCallData *call)
}
ast_queue_control(c, AST_CONTROL_ANSWER);
ast_publish_channel_state(c);
ast_channel_publish_snapshot(c);
ast_channel_unlock(p->owner);
}
ast_mutex_unlock(&p->lock);

View File

@ -554,7 +554,7 @@ static struct ast_config *realtime_multi_mysql(const char *database, const char
static int update_mysql(const char *database, const char *tablename, const char *keyfield, const char *lookup, const struct ast_variable *rt_fields)
{
struct mysql_conn *dbh;
my_ulonglong numrows;
uint64_t numrows;
const struct ast_variable *field = rt_fields;
struct ast_str *sql = ast_str_thread_get(&sql_buf, 100), *buf = ast_str_thread_get(&scratch_buf, 100);
struct tables *table;
@ -641,7 +641,7 @@ static int update_mysql(const char *database, const char *tablename, const char
release_table(table);
release_database(dbh);
ast_debug(1, "MySQL RealTime: Updated %llu rows on table: %s\n", numrows, tablename);
ast_debug(1, "MySQL RealTime: Updated %" PRIu64 " rows on table: %s\n", numrows, tablename);
/* From http://dev.mysql.com/doc/mysql/en/mysql-affected-rows.html
* An integer greater than zero indicates the number of rows affected
@ -655,7 +655,7 @@ static int update_mysql(const char *database, const char *tablename, const char
static int update2_mysql(const char *database, const char *tablename, const struct ast_variable *lookup_fields, const struct ast_variable *update_fields)
{
struct mysql_conn *dbh;
my_ulonglong numrows;
uint64_t numrows;
int first;
const struct ast_variable *field;
struct ast_str *sql = ast_str_thread_get(&sql_buf, 100), *buf = ast_str_thread_get(&scratch_buf, 100);
@ -738,7 +738,7 @@ static int update2_mysql(const char *database, const char *tablename, const stru
numrows = mysql_affected_rows(&dbh->handle);
release_database(dbh);
ast_debug(1, "MySQL RealTime: Updated %llu rows on table: %s\n", numrows, tablename);
ast_debug(1, "MySQL RealTime: Updated %" PRIu64 " rows on table: %s\n", numrows, tablename);
/* From http://dev.mysql.com/doc/mysql/en/mysql-affected-rows.html
* An integer greater than zero indicates the number of rows affected
@ -810,7 +810,7 @@ static int store_mysql(const char *database, const char *table, const struct ast
static int destroy_mysql(const char *database, const char *table, const char *keyfield, const char *lookup, const struct ast_variable *rt_fields)
{
struct mysql_conn *dbh;
my_ulonglong numrows;
uint64_t numrows;
struct ast_str *sql = ast_str_thread_get(&sql_buf, 16);
struct ast_str *buf = ast_str_thread_get(&scratch_buf, 16);
const struct ast_variable *field;
@ -862,7 +862,7 @@ static int destroy_mysql(const char *database, const char *table, const char *ke
numrows = mysql_affected_rows(&dbh->handle);
release_database(dbh);
ast_debug(1, "MySQL RealTime: Deleted %llu rows on table: %s\n", numrows, table);
ast_debug(1, "MySQL RealTime: Deleted %" PRIu64 " rows on table: %s\n", numrows, table);
/* From http://dev.mysql.com/doc/mysql/en/mysql-affected-rows.html
* An integer greater than zero indicates the number of rows affected
@ -878,7 +878,7 @@ static struct ast_config *config_mysql(const char *database, const char *table,
struct mysql_conn *dbh;
MYSQL_RES *result;
MYSQL_ROW row;
my_ulonglong num_rows;
uint64_t num_rows;
struct ast_variable *new_v;
struct ast_category *cur_cat = NULL;
struct ast_str *sql = ast_str_thread_get(&sql_buf, 200);
@ -916,7 +916,7 @@ static struct ast_config *config_mysql(const char *database, const char *table,
if ((result = mysql_store_result(&dbh->handle))) {
num_rows = mysql_num_rows(result);
ast_debug(1, "MySQL RealTime: Found %llu rows.\n", num_rows);
ast_debug(1, "MySQL RealTime: Found %" PRIu64 " rows.\n", num_rows);
/* There might exist a better way to access the column names other than counting,
* but I believe that would require another loop that we don't need. */

View File

@ -92,8 +92,8 @@
<ref type="application">PauseQueueMember</ref>
<ref type="application">UnpauseQueueMember</ref>
<ref type="function">AGENT</ref>
<ref type="function">CHANNEL(dtmf_features)</ref>
<ref type="function">CONNECTEDLINE()</ref>
<ref type="function">CHANNEL</ref>
<ref type="function">CONNECTEDLINE</ref>
<ref type="filename">agents.conf</ref>
<ref type="filename">queues.conf</ref>
</see-also>
@ -1457,9 +1457,9 @@ static void send_agent_logoff(struct ast_channel *chan, const char *agent, long
ast_assert(agent != NULL);
blob = ast_json_pack("{s: s, s: i}",
blob = ast_json_pack("{s: s, s: I}",
"agent", agent,
"logintime", logintime);
"logintime", (ast_json_int_t)logintime);
if (!blob) {
return;
}

View File

@ -162,8 +162,10 @@ static int dfltMaxWaitTimeForFrame = 50;
static void isAnsweringMachine(struct ast_channel *chan, const char *data)
{
int res = 0;
int audioFrameCount = 0;
struct ast_frame *f = NULL;
struct ast_dsp *silenceDetector = NULL;
struct timeval amd_tvstart;
int dspsilence = 0, framelength = 0;
RAII_VAR(struct ast_format *, readFormat, NULL, ao2_cleanup);
int inInitialSilence = 1;
@ -275,6 +277,9 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
/* Set silence threshold to specified value */
ast_dsp_set_threshold(silenceDetector, silenceThreshold);
/* Set our start time so we can tie the loop to real world time and not RTP updates */
amd_tvstart = ast_tvnow();
/* Now we go into a loop waiting for frames from the channel */
while ((res = ast_waitfor(chan, 2 * maxWaitTimeForFrame)) > -1) {
int ms = 0;
@ -293,7 +298,24 @@ static void isAnsweringMachine(struct ast_channel *chan, const char *data)
break;
}
if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_NULL || f->frametype == AST_FRAME_CNG) {
/* Check to make sure we haven't gone over our real-world timeout in case frames get stalled for whatever reason */
if ( (ast_tvdiff_ms(ast_tvnow(), amd_tvstart)) > totalAnalysisTime ) {
ast_frfree(f);
strcpy(amdStatus , "NOTSURE");
if ( audioFrameCount == 0 ) {
ast_verb(3, "AMD: Channel [%s]. No audio data received in [%d] seconds.\n", ast_channel_name(chan), totalAnalysisTime);
sprintf(amdCause , "NOAUDIODATA-%d", iTotalTime);
break;
}
ast_verb(3, "AMD: Channel [%s]. Timeout...\n", ast_channel_name(chan));
sprintf(amdCause , "TOOLONG-%d", iTotalTime);
break;
}
if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_CNG) {
/* keep track of the number of audio frames we get */
audioFrameCount++;
/* Figure out how long the frame is in milliseconds */
if (f->frametype == AST_FRAME_VOICE) {
framelength = (ast_codec_samples_count(f) / DEFAULT_SAMPLES_PER_MS);

View File

@ -119,13 +119,13 @@ struct app_cdr_message_payload {
/*! The name of the channel to be manipulated */
const char *channel_name;
/*! Disable the CDR for this channel */
int disable:1;
unsigned int disable:1;
/*! Re-enable the CDR for this channel */
int reenable:1;
unsigned int reenable:1;
/*! Reset the CDR */
int reset:1;
unsigned int reset:1;
/*! If reseting the CDR, keep the variables */
int keep_variables:1;
unsigned int keep_variables:1;
};
static void appcdr_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)

View File

@ -51,16 +51,18 @@ static const char app[] = "ChanIsAvail";
Check channel availability
</synopsis>
<syntax>
<parameter name="Technology/Resource" required="true" argsep="&amp;">
<parameter name="Technology/Resource" required="false" argsep="&amp;">
<argument name="Technology/Resource" required="true">
<para>Specification of the device(s) to check. These must be in the format of
<literal>Technology/Resource</literal>, where <replaceable>Technology</replaceable>
represents a particular channel driver, and <replaceable>Resource</replaceable>
represents a resource available to that particular channel driver.</para>
</argument>
<argument name="Technology2/Resource2" multiple="true">
<para>Optional extra devices to check</para>
<para>If you need more than one enter them as
Technology2/Resource2&amp;Technology3/Resource3&amp;.....</para>
</argument>
<para>Specification of the device(s) to check. These must be in the format of
<literal>Technology/Resource</literal>, where <replaceable>Technology</replaceable>
represents a particular channel driver, and <replaceable>Resource</replaceable>
represents a resource available to that particular channel driver.</para>
</parameter>
<parameter name="options" required="false">
<optionlist>
@ -99,25 +101,28 @@ static const char app[] = "ChanIsAvail";
static int chanavail_exec(struct ast_channel *chan, const char *data)
{
int inuse=-1, option_state=0, string_compare=0, option_all_avail=0;
int inuse = -1;
int option_state = 0;
int string_compare = 0;
int option_all_avail = 0;
int status;
char *info, tmp[512], trychan[512], *peers, *tech, *number, *rest, *cur;
char *info;
char trychan[512];
char *rest;
char *tech;
char *number;
struct ast_str *tmp_availchan = ast_str_alloca(2048);
struct ast_str *tmp_availorig = ast_str_alloca(2048);
struct ast_str *tmp_availstat = ast_str_alloca(2048);
struct ast_str *tmp_availcause = ast_str_alloca(2048);
struct ast_channel *tempchan;
struct ast_custom_function *cdr_prop_func = ast_custom_function_find("CDR_PROP");
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(reqchans);
AST_APP_ARG(options);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "ChanIsAvail requires an argument (DAHDI/1&DAHDI/2)\n");
return -1;
}
info = ast_strdupa(data);
info = ast_strdupa(data ?: "");
AST_STANDARD_APP_ARGS(args, info);
@ -132,61 +137,68 @@ static int chanavail_exec(struct ast_channel *chan, const char *data)
string_compare = 1;
}
}
peers = args.reqchans;
if (peers) {
cur = peers;
do {
/* remember where to start next time */
rest = strchr(cur, '&');
if (rest) {
*rest = 0;
rest++;
rest = args.reqchans;
if (!rest) {
rest = "";
}
while ((tech = strsep(&rest, "&"))) {
tech = ast_strip(tech);
number = strchr(tech, '/');
if (!number) {
if (!ast_strlen_zero(tech)) {
ast_log(LOG_WARNING, "Invalid ChanIsAvail technology/resource argument: '%s'\n",
tech);
}
tech = cur;
number = strchr(tech, '/');
if (!number) {
ast_log(LOG_WARNING, "ChanIsAvail argument takes format ([technology]/[device])\n");
return -1;
ast_str_append(&tmp_availstat, 0, "%s%d",
ast_str_strlen(tmp_availstat) ? "&" : "", AST_DEVICE_INVALID);
continue;
}
*number++ = '\0';
status = AST_DEVICE_UNKNOWN;
if (string_compare) {
/* ast_parse_device_state checks for "SIP/1234" as a channel name.
ast_device_state will ask the SIP driver for the channel state. */
snprintf(trychan, sizeof(trychan), "%s/%s", tech, number);
status = inuse = ast_parse_device_state(trychan);
} else if (option_state) {
/* If the pbx says in use then don't bother trying further.
This is to permit testing if someone's on a call, even if the
channel can permit more calls (ie callwaiting, sip calls, etc). */
snprintf(trychan, sizeof(trychan), "%s/%s", tech, number);
status = inuse = ast_device_state(trychan);
}
ast_str_append(&tmp_availstat, 0, "%s%d",
ast_str_strlen(tmp_availstat) ? "&" : "", status);
if ((inuse <= (int) AST_DEVICE_NOT_INUSE)
&& (tempchan = ast_request(tech, ast_channel_nativeformats(chan), NULL, chan, number, &status))) {
ast_str_append(&tmp_availchan, 0, "%s%s",
ast_str_strlen(tmp_availchan) ? "&" : "", ast_channel_name(tempchan));
ast_str_append(&tmp_availorig, 0, "%s%s/%s",
ast_str_strlen(tmp_availorig) ? "&" : "", tech, number);
ast_str_append(&tmp_availcause, 0, "%s%d",
ast_str_strlen(tmp_availcause) ? "&" : "", status);
/* Disable CDR for this temporary channel. */
if (cdr_prop_func) {
ast_func_write(tempchan, "CDR_PROP(disable)", "1");
}
*number = '\0';
number++;
status = AST_DEVICE_UNKNOWN;
ast_hangup(tempchan);
tempchan = NULL;
if (string_compare) {
/* ast_parse_device_state checks for "SIP/1234" as a channel name.
ast_device_state will ask the SIP driver for the channel state. */
snprintf(trychan, sizeof(trychan), "%s/%s",cur,number);
status = inuse = ast_parse_device_state(trychan);
} else if (option_state) {
/* If the pbx says in use then don't bother trying further.
This is to permit testing if someone's on a call, even if the
channel can permit more calls (ie callwaiting, sip calls, etc). */
snprintf(trychan, sizeof(trychan), "%s/%s",cur,number);
status = inuse = ast_device_state(trychan);
if (!option_all_avail) {
break;
}
snprintf(tmp, sizeof(tmp), "%d", status);
ast_str_append(&tmp_availstat, 0, "%s%s", ast_str_strlen(tmp_availstat) ? "&" : "", tmp);
if ((inuse <= 1) && (tempchan = ast_request(tech, ast_channel_nativeformats(chan), NULL, chan, number, &status))) {
ast_str_append(&tmp_availchan, 0, "%s%s", ast_str_strlen(tmp_availchan) ? "&" : "", ast_channel_name(tempchan));
snprintf(tmp, sizeof(tmp), "%s/%s", tech, number);
ast_str_append(&tmp_availorig, 0, "%s%s", ast_str_strlen(tmp_availorig) ? "&" : "", tmp);
snprintf(tmp, sizeof(tmp), "%d", status);
ast_str_append(&tmp_availcause, 0, "%s%s", ast_str_strlen(tmp_availcause) ? "&" : "", tmp);
ast_hangup(tempchan);
tempchan = NULL;
if (!option_all_avail) {
break;
}
}
cur = rest;
} while (cur);
}
}
pbx_builtin_setvar_helper(chan, "AVAILCHAN", ast_str_buffer(tmp_availchan));
@ -209,4 +221,9 @@ static int load_module(void)
AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "Check channel availability");
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Check channel availability",
.support_level = AST_MODULE_SUPPORT_EXTENDED,
.load = load_module,
.unload = unload_module,
.optional_modules = "func_cdr"
);

View File

@ -509,7 +509,8 @@ static int start_spying(struct ast_autochan *autochan, const char *spychan_name,
int res;
ast_autochan_channel_lock(autochan);
ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan_name, ast_channel_name(autochan->chan));
ast_verb(3, "Attaching spy channel %s to %s\n",
spychan_name, ast_channel_name(autochan->chan));
if (ast_test_flag(flags, OPTION_READONLY)) {
ast_set_flag(audiohook, AST_AUDIOHOOK_MUTE_WRITE);

View File

@ -1706,6 +1706,8 @@ static struct confbridge_conference *join_conference_bridge(const char *conferen
/* Set the internal sample rate on the bridge from the bridge profile */
ast_bridge_set_internal_sample_rate(conference->bridge, conference->b_profile.internal_sample_rate);
/* Set the maximum sample rate on the bridge from the bridge profile */
ast_bridge_set_maximum_sample_rate(conference->bridge, conference->b_profile.maximum_sample_rate);
/* Set the internal mixing interval on the bridge from the bridge profile */
ast_bridge_set_mixing_interval(conference->bridge, conference->b_profile.mix_interval);
ast_bridge_set_binaural_active(conference->bridge, ast_test_flag(&conference->b_profile, BRIDGE_OPT_BINAURAL_ACTIVE));
@ -2626,6 +2628,13 @@ static int confbridge_exec(struct ast_channel *chan, const char *data)
user.features.dtmf_passthrough = 0;
}
/* Set if text messaging is enabled for this user or not */
if (ast_test_flag(&user.u_profile, USER_OPT_TEXT_MESSAGING)) {
user.features.text_messaging = 1;
} else {
user.features.text_messaging = 0;
}
/* Set dsp threshold values if present */
if (user.u_profile.talking_threshold) {
user.tech_args.talking_threshold = user.u_profile.talking_threshold;

View File

@ -113,8 +113,10 @@ static pid_t spawn_ras(struct ast_channel *chan, char *args)
c = strsep(&stringp, ",");
}
argv[argc++] = "plugin";
argv[argc++] = "dahdi.so";
if (geteuid() == 0) {
argv[argc++] = "plugin";
argv[argc++] = "dahdi.so";
}
argv[argc++] = "stdin";
/* Finally launch PPP */

View File

@ -74,7 +74,7 @@
Attempt to connect to another device or endpoint and bridge the call.
</synopsis>
<syntax>
<parameter name="Technology/Resource" required="true" argsep="&amp;">
<parameter name="Technology/Resource" required="false" argsep="&amp;">
<argument name="Technology/Resource" required="true">
<para>Specification of the device(s) to dial. These must be in the format of
<literal>Technology/Resource</literal>, where <replaceable>Technology</replaceable>
@ -1003,7 +1003,8 @@ static void do_forward(struct chanlist *o, struct cause_args *num,
* any Dial operations that happen later won't record CC interfaces.
*/
ast_ignore_cc(o->chan);
ast_log(LOG_NOTICE, "Not accepting call completion offers from call-forward recipient %s\n", ast_channel_name(o->chan));
ast_verb(3, "Not accepting call completion offers from call-forward recipient %s\n",
ast_channel_name(o->chan));
} else
ast_log(LOG_NOTICE,
"Forwarding failed to create channel to dial '%s/%s' (cause = %d)\n",
@ -2003,7 +2004,7 @@ static int do_privacy(struct ast_channel *chan, struct ast_channel *peer,
/* well, there seems basically two choices. Just patch the caller thru immediately,
or,... put 'em thru to voicemail. */
/* since the callee may have hung up, let's do the voicemail thing, no database decision */
ast_log(LOG_NOTICE, "privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding\n");
ast_verb(3, "privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding\n");
/* XXX should we set status to DENY ? */
/* XXX what about the privacy flags ? */
break;
@ -2294,12 +2295,6 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
return -1;
}
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Dial requires an argument (technology/resource)\n");
pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
return -1;
}
if (ast_check_hangup_locked(chan)) {
/*
* Caller hung up before we could dial. If dial is executed
@ -2318,7 +2313,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
return -1;
}
parse = ast_strdupa(data);
parse = ast_strdupa(data ?: "");
AST_STANDARD_APP_ARGS(args, parse);
@ -2328,12 +2323,6 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
goto done;
}
if (ast_strlen_zero(args.peers)) {
ast_log(LOG_WARNING, "Dial requires an argument (technology/resource)\n");
pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
goto done;
}
if (ast_cc_call_init(chan, &ignore_cc)) {
goto done;
}
@ -2359,7 +2348,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
if (ast_test_flag64(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) {
calldurationlimit.tv_sec = atoi(opt_args[OPT_ARG_DURATION_STOP]);
if (!calldurationlimit.tv_sec) {
ast_log(LOG_WARNING, "Dial does not accept S(%s), hanging up.\n", opt_args[OPT_ARG_DURATION_STOP]);
ast_log(LOG_WARNING, "Dial does not accept S(%s)\n", opt_args[OPT_ARG_DURATION_STOP]);
pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
goto done;
}
@ -2506,15 +2495,24 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
/* loop through the list of dial destinations */
rest = args.peers;
while ((cur = strsep(&rest, "&")) ) {
while ((cur = strsep(&rest, "&"))) {
struct ast_channel *tc; /* channel for this destination */
/* Get a technology/resource pair */
char *number = cur;
char *tech = strsep(&number, "/");
char *number;
char *tech;
size_t tech_len;
size_t number_len;
struct ast_stream_topology *topology;
cur = ast_strip(cur);
if (ast_strlen_zero(cur)) {
/* No tech/resource in this position. */
continue;
}
/* Get a technology/resource pair */
number = cur;
tech = strsep(&number, "/");
num_dialed++;
if (ast_strlen_zero(number)) {
ast_log(LOG_WARNING, "Dial argument takes format (technology/resource)\n");
@ -2713,6 +2711,17 @@ 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)) {
ast_verb(3, "No devices or endpoints to dial (technology/resource)\n");
if (continue_exec) {
/* There is no point in having RetryDial try again */
*continue_exec = 1;
}
strcpy(pa.status, "CHANUNAVAIL");
res = 0;
goto out;
}
/*
* PREDIAL: Run gosub on all of the callee channels
*

View File

@ -149,7 +149,8 @@ static int dictate_exec(struct ast_channel *chan, const char *data)
ast_mkdir(base, 0755);
len = strlen(base) + strlen(filein) + 2;
if (!path || len > maxlen) {
path = ast_alloca(len);
ast_free(path);
path = ast_malloc(len);
memset(path, 0, len);
maxlen = len;
} else {
@ -334,6 +335,7 @@ static int dictate_exec(struct ast_channel *chan, const char *data)
ast_frfree(f);
}
}
ast_free(path);
if (oldr) {
ast_set_read_format(chan, oldr);
ao2_ref(oldr, -1);

View File

@ -408,7 +408,6 @@ static int reload_followme(int reload)
char *cat = NULL, *tmp;
struct ast_variable *var;
struct number *cur, *nm;
char *numberstr;
int timeout;
int numorder;
const char* enable_callee_prompt_str;
@ -536,9 +535,12 @@ static int reload_followme(int reload)
while (var) {
if (!strcasecmp(var->name, "number")) {
int idx = 0;
char copy[strlen(var->value) + 1];
char *numberstr;
/* Add a new number */
numberstr = ast_strdupa(var->value);
strcpy(copy, var->value); /* safe */
numberstr = copy;
if ((tmp = strchr(numberstr, ','))) {
*tmp++ = '\0';
timeout = atoi(tmp);
@ -762,10 +764,6 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
}
tmpto = to;
if (to < 0) {
to = 1000;
tmpto = 1000;
}
towas = to;
winner = ast_waitfor_n(watchers, pos, &to);
tmpto -= to;

View File

@ -26,6 +26,7 @@
*/
/*** MODULEINFO
<depend>res_adsi</depend>
<support_level>deprecated</support_level>
***/

View File

@ -1165,7 +1165,7 @@ static int meetme_stasis_init(void)
STASIS_MESSAGE_TYPE_INIT(meetme_talk_request_type);
meetme_event_message_router = stasis_message_router_create(
ast_channel_topic_all_cached());
ast_channel_topic_all());
if (!meetme_event_message_router) {
meetme_stasis_cleanup();

View File

@ -2652,9 +2652,10 @@ static int create_vmaccount(char *name, struct ast_variable *var, int realtime)
ast_copy_string(vmu->fullname, var->value, sizeof(vmu->fullname));
} else if (!strcasecmp(var->name, "setvar")) {
char *varval;
char *varname = ast_strdupa(var->value);
char varname[strlen(var->value) + 1];
struct ast_variable *tmpvar;
strcpy(varname, var->value); /* safe */
if ((varval = strchr(varname, '='))) {
*varval = '\0';
varval++;

View File

@ -115,6 +115,11 @@
Like with the basic filename argument, if an absolute path isn't given, it will create
the file in the configured monitoring directory.</para>
</option>
<option name="S">
<para>When combined with the <replaceable>r</replaceable> or <replaceable>t</replaceable>
option, inserts silence when necessary to maintain synchronization between the receive
and transmit audio streams.</para>
</option>
<option name="i">
<argument name="chanvar" required="true" />
<para>Stores the MixMonitor's ID on this channel variable.</para>
@ -149,6 +154,11 @@
<para>This application does not automatically answer and should be preceeded by
an application such as Answer or Progress().</para>
<note><para>MixMonitor runs as an audiohook.</para></note>
<note><para>If a filename passed to MixMonitor ends with
<literal>.wav49</literal>, Asterisk will silently convert the extension to
<literal>.WAV</literal> for legacy reasons. <variable>MIXMONITOR_FILENAME</variable>
will contain the actual filename that Asterisk is writing to, not necessarily the
value that was passed in.</para></note>
<variablelist>
<variable name="MIXMONITOR_FILENAME">
<para>Will contain the filename used to record.</para>
@ -347,7 +357,8 @@ enum mixmonitor_flags {
MUXFLAG_VMRECIPIENTS = (1 << 10),
MUXFLAG_BEEP = (1 << 11),
MUXFLAG_BEEP_START = (1 << 12),
MUXFLAG_BEEP_STOP = (1 << 13)
MUXFLAG_BEEP_STOP = (1 << 13),
MUXFLAG_RWSYNC = (1 << 14),
};
enum mixmonitor_args {
@ -359,6 +370,7 @@ enum mixmonitor_args {
OPT_ARG_UID,
OPT_ARG_VMRECIPIENTS,
OPT_ARG_BEEP_INTERVAL,
OPT_ARG_RWSYNC,
OPT_ARG_ARRAY_SIZE, /* Always last element of the enum */
};
@ -375,6 +387,7 @@ AST_APP_OPTIONS(mixmonitor_opts, {
AST_APP_OPTION_ARG('t', MUXFLAG_WRITE, OPT_ARG_WRITENAME),
AST_APP_OPTION_ARG('i', MUXFLAG_UID, OPT_ARG_UID),
AST_APP_OPTION_ARG('m', MUXFLAG_VMRECIPIENTS, OPT_ARG_VMRECIPIENTS),
AST_APP_OPTION_ARG('S', MUXFLAG_RWSYNC, OPT_ARG_RWSYNC),
});
struct mixmonitor_ds {
@ -962,6 +975,9 @@ static int launch_monitor_thread(struct ast_channel *chan, const char *filename,
}
ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_SYNC);
if ((ast_test_flag(mixmonitor, MUXFLAG_RWSYNC))) {
ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_SUBSTITUTE_SILENCE);
}
if (readvol)
mixmonitor->audiohook.options.read_volume = readvol;
@ -971,6 +987,7 @@ static int launch_monitor_thread(struct ast_channel *chan, const char *filename,
if (startmon(chan, &mixmonitor->audiohook)) {
ast_log(LOG_WARNING, "Unable to add '%s' spy to channel '%s'\n",
mixmonitor_spy_type, ast_channel_name(chan));
ast_autochan_destroy(mixmonitor->autochan);
ast_audiohook_destroy(&mixmonitor->audiohook);
mixmonitor_free(mixmonitor);
return -1;
@ -987,17 +1004,35 @@ static int launch_monitor_thread(struct ast_channel *chan, const char *filename,
static char *filename_parse(char *filename, char *buffer, size_t len)
{
char *slash;
char *ext;
ast_assert(len > 0);
if (ast_strlen_zero(filename)) {
ast_log(LOG_WARNING, "No file name was provided for a file save option.\n");
} else if (filename[0] != '/') {
char *build;
build = ast_alloca(strlen(ast_config_AST_MONITOR_DIR) + strlen(filename) + 3);
buffer[0] = 0;
return buffer;
}
/* If we don't have an absolute path, make one */
if (*filename != '/') {
char *build = ast_alloca(strlen(ast_config_AST_MONITOR_DIR) + strlen(filename) + 3);
sprintf(build, "%s/%s", ast_config_AST_MONITOR_DIR, filename);
filename = build;
}
ast_copy_string(buffer, filename, len);
/* If the provided filename has a .wav49 extension, we need to convert it to .WAV to
match the behavior of build_filename in main/file.c. Otherwise MIXMONITOR_FILENAME
ends up referring to a file that does not/will not exist */
ext = strrchr(buffer, '.');
if (ext && !strcmp(ext, ".wav49")) {
/* Change to WAV - we know we have at least 6 writeable bytes where 'ext' points,
* so this is safe */
memcpy(ext, ".WAV", sizeof(".WAV"));
}
if ((slash = strrchr(filename, '/'))) {
*slash = '\0';
}

View File

@ -48,7 +48,7 @@
Page series of phones
</synopsis>
<syntax>
<parameter name="Technology/Resource" required="true" argsep="&amp;">
<parameter name="Technology/Resource" required="false" argsep="&amp;">
<argument name="Technology/Resource" required="true">
<para>Specification of the device(s) to dial. These must be in the format of
<literal>Technology/Resource</literal>, where <replaceable>Technology</replaceable>
@ -270,17 +270,12 @@ static int page_exec(struct ast_channel *chan, const char *data)
AST_APP_ARG(timeout);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "This application requires at least one argument (destination(s) to page)\n");
return -1;
}
if (!(app = pbx_findapp("ConfBridge"))) {
ast_log(LOG_WARNING, "There is no ConfBridge application available!\n");
return -1;
};
parse = ast_strdupa(data);
parse = ast_strdupa(data ?: "");
AST_STANDARD_APP_ARGS(args, parse);
@ -301,7 +296,7 @@ static int page_exec(struct ast_channel *chan, const char *data)
/* Count number of extensions in list by number of ampersands + 1 */
num_dials = 1;
tmp = args.devices;
tmp = args.devices ?: "";
while (*tmp) {
if (*tmp == '&') {
num_dials++;
@ -334,13 +329,20 @@ static int page_exec(struct ast_channel *chan, const char *data)
int state = 0;
struct ast_dial *dial = NULL;
/* don't call the originating device */
if (!strcasecmp(tech, originator))
tech = ast_strip(tech);
if (ast_strlen_zero(tech)) {
/* No tech/resource in this position. */
continue;
}
/* don't call the originating device */
if (!strcasecmp(tech, originator)) {
continue;
}
/* If no resource is available, continue on */
if (!(resource = strchr(tech, '/'))) {
ast_log(LOG_WARNING, "Incomplete destination '%s' supplied.\n", tech);
ast_log(LOG_WARNING, "Incomplete destination: '%s' supplied.\n", tech);
continue;
}
@ -348,9 +350,11 @@ static int page_exec(struct ast_channel *chan, const char *data)
if (ast_test_flag(&options.flags, PAGE_SKIP)) {
state = ast_device_state(tech);
if (state == AST_DEVICE_UNKNOWN) {
ast_log(LOG_WARNING, "Destination '%s' has device state '%s'. Paging anyway.\n", tech, ast_devstate2str(state));
ast_verb(3, "Destination '%s' has device state '%s'. Paging anyway.\n",
tech, ast_devstate2str(state));
} else if (state != AST_DEVICE_NOT_INUSE) {
ast_log(LOG_WARNING, "Destination '%s' has device state '%s'.\n", tech, ast_devstate2str(state));
ast_verb(3, "Destination '%s' has device state '%s'.\n",
tech, ast_devstate2str(state));
continue;
}
}
@ -365,7 +369,7 @@ static int page_exec(struct ast_channel *chan, const char *data)
/* Append technology and resource */
if (ast_dial_append(dial, tech, resource, NULL) == -1) {
ast_log(LOG_ERROR, "Failed to add %s to outbound dial\n", tech);
ast_log(LOG_ERROR, "Failed to add %s/%s to outbound dial\n", tech, resource);
ast_dial_destroy(dial);
continue;
}

View File

@ -173,7 +173,10 @@ static int s_streamwait3(const say_args_t *a, const char *fn)
static int do_say(say_args_t *a, const char *s, const char *options, int depth)
{
struct ast_variable *v;
char *lang, *x, *rule = NULL;
char *lang;
char *x;
char *rule = NULL;
char *rule_head = NULL;
int ret = 0;
struct varshead head = { .first = NULL, .last = NULL };
struct ast_var_t *n;
@ -195,7 +198,7 @@ static int do_say(say_args_t *a, const char *s, const char *options, int depth)
for (;;) {
for (v = ast_variable_browse(say_cfg, lang); v ; v = v->next) {
if (ast_extension_match(v->name, s)) {
rule = ast_strdupa(v->value);
rule_head = rule = ast_strdup(v->value);
break;
}
}
@ -220,6 +223,7 @@ static int do_say(say_args_t *a, const char *s, const char *options, int depth)
n = ast_var_assign("SAY", s);
if (!n) {
ast_log(LOG_ERROR, "Memory allocation error in do_say\n");
ast_free(rule_head);
return -1;
}
AST_LIST_INSERT_HEAD(&head, n, entries);
@ -281,6 +285,7 @@ static int do_say(say_args_t *a, const char *s, const char *options, int depth)
}
}
ast_var_delete(n);
ast_free(rule_head);
return ret;
}

View File

@ -1146,7 +1146,7 @@
<syntax>
<xi:include xpointer="xpointer(/docs/managerEvent[@name='QueueMemberStatus']/managerEventInstance/syntax/parameter)" />
<parameter name="Reason">
<para>The reason a member was paused.</para>
<para>This has been deprecated in favor of the <literal>PausedReason</literal> field.</para>
</parameter>
</syntax>
<see-also>
@ -1617,7 +1617,7 @@ struct member {
time_t starttime; /*!< The time at which the member answered the current caller. */
time_t lastcall; /*!< When last successful call was hungup */
time_t lastpause; /*!< When started the last pause */
struct call_queue *lastqueue; /*!< Last queue we received a call */
struct call_queue *lastqueue; /*!< Last queue we received a call */
unsigned int dead:1; /*!< Used to detect members deleted in realtime */
unsigned int delme:1; /*!< Flag to delete entry on reload */
char rt_uniqueid[80]; /*!< Unique id of realtime member entry */
@ -4020,44 +4020,26 @@ static int say_position(struct queue_ent *qe, int ringing)
/* Say we're next, if we are */
if (qe->pos == 1) {
res = play_file(qe->chan, qe->parent->sound_next);
if (res) {
goto playout;
if (!res) {
goto posout;
}
goto posout;
/* Say there are more than N callers */
} else if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit) {
res = (
play_file(qe->chan, qe->parent->queue_quantity1) ||
ast_say_number(qe->chan, qe->parent->announcepositionlimit, AST_DIGIT_ANY,
ast_channel_language(qe->chan), NULL) || /* Needs gender */
play_file(qe->chan, qe->parent->queue_quantity2));
/* Say there are currently N callers waiting */
} else {
if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
/* More than Case*/
res = play_file(qe->chan, qe->parent->queue_quantity1);
if (res) {
goto playout;
}
res = ast_say_number(qe->chan, qe->parent->announcepositionlimit, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL); /* Needs gender */
if (res) {
goto playout;
}
} else {
/* Normal Case */
res = play_file(qe->chan, qe->parent->sound_thereare);
if (res) {
goto playout;
}
res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL); /* Needs gender */
if (res) {
goto playout;
}
}
if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
/* More than Case*/
res = play_file(qe->chan, qe->parent->queue_quantity2);
if (res) {
goto playout;
}
} else {
res = play_file(qe->chan, qe->parent->sound_calls);
if (res) {
goto playout;
}
}
res = (
play_file(qe->chan, qe->parent->sound_thereare) ||
ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY,
ast_channel_language(qe->chan), NULL) || /* Needs gender */
play_file(qe->chan, qe->parent->sound_calls));
}
if (res) {
goto playout;
}
}
/* Round hold time to nearest minute */
@ -4904,7 +4886,7 @@ static void rna(int rnatime, struct queue_ent *qe, struct ast_channel *peer, cha
ast_verb(3, "Auto-Pausing Queue Member %s in all queues since they failed to answer on queue %s.\n",
interface, qe->parent->name);
} else {
ast_verb(3, "Failed to pause Queue Member %s in all queues!\n", interface);
ast_verb(3, "Failed to pause Queue Member %s in all queues!\n", interface);
}
}
}
@ -5898,12 +5880,12 @@ static void send_agent_complete(const char *queuename, struct ast_channel_snapsh
break;
}
blob = ast_json_pack("{s: s, s: s, s: s, s: i, s: i, s: s}",
blob = ast_json_pack("{s: s, s: s, s: s, s: I, s: I, s: s}",
"Queue", queuename,
"Interface", member->interface,
"MemberName", member->membername,
"HoldTime", (long)(callstart - holdstart),
"TalkTime", (long)(time(NULL) - callstart),
"HoldTime", (ast_json_int_t)(callstart - holdstart),
"TalkTime", (ast_json_int_t)(time(NULL) - callstart),
"Reason", reason ?: "");
queue_publish_multi_channel_snapshot_blob(ast_queue_topic(queuename), caller, peer,
@ -6850,8 +6832,7 @@ static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_a
tmp->lastcall = cur->lastcall;
tmp->lastqueue = cur->lastqueue;
ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
/* Special case: If we ring everyone, go ahead and ring them, otherwise
just calculate their metric for the appropriate strategy */
/* Calculate the metric for the appropriate strategy. */
if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
/* Put them in the list of outgoing thingies... We're ready now.
XXX If we're forcibly removed, these outgoing calls won't get
@ -6887,6 +6868,7 @@ static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_a
orig = to;
++qe->pending;
ao2_unlock(qe->parent);
/* Call the queue members with the best metric now. */
ring_one(qe, outgoing, &numbusies);
lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies,
ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT),
@ -7174,12 +7156,12 @@ static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_a
ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "CONNECT", "%ld|%s|%ld", (long) (time(NULL) - qe->start), ast_channel_uniqueid(peer),
(long)(orig - to > 0 ? (orig - to) / 1000 : 0));
blob = ast_json_pack("{s: s, s: s, s: s, s: i, s: i}",
blob = ast_json_pack("{s: s, s: s, s: s, s: I, s: I}",
"Queue", queuename,
"Interface", member->interface,
"MemberName", member->membername,
"HoldTime", (long) (time(NULL) - qe->start),
"RingTime", (long)(orig - to > 0 ? (orig - to) / 1000 : 0));
"HoldTime", (ast_json_int_t)(time(NULL) - qe->start),
"RingTime", (ast_json_int_t)(orig - to > 0 ? (orig - to) / 1000 : 0));
queue_publish_multi_channel_blob(qe->chan, peer, queue_agent_connect_type(), blob);
ast_copy_string(oldcontext, ast_channel_context(qe->chan), sizeof(oldcontext));

View File

@ -170,8 +170,7 @@ static int readexten_exec(struct ast_channel *chan, const char *data)
if (timeout <= 0)
timeout = ast_channel_pbx(chan) ? ast_channel_pbx(chan)->rtimeoutms : 10000;
if (digit_timeout <= 0)
digit_timeout = ast_channel_pbx(chan) ? ast_channel_pbx(chan)->dtimeoutms : 5000;
digit_timeout = ast_channel_pbx(chan) ? ast_channel_pbx(chan)->dtimeoutms : 5000;
if (ast_test_flag(&flags, OPT_INDICATION) && !ast_strlen_zero(arglist.filename)) {
ts = ast_get_indication_tone(ast_channel_zone(chan), arglist.filename);

View File

@ -358,7 +358,8 @@ static int record_exec(struct ast_channel *chan, const char *data)
if (!res) {
res = ast_waitstream(chan, "");
} else {
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", ast_channel_name(chan));
ast_log(LOG_WARNING, "ast_streamfile(beep) failed on %s\n", ast_channel_name(chan));
res = 0;
}
ast_stopstream(chan);
}

View File

@ -80,6 +80,9 @@
<parameter name="Duration" required="false">
<para>The duration, in milliseconds, of the digit to be played.</para>
</parameter>
<parameter name="Receive" required="false">
<para>Emulate receiving DTMF on this channel instead of sending it out.</para>
</parameter>
</syntax>
<description>
<para>Plays a dtmf digit on the specified channel.</para>
@ -147,6 +150,7 @@ static int manager_play_dtmf(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");
const char *receive_s = astman_get_header(m, "Receive");
struct ast_channel *chan;
unsigned int duration_ms = 0;
@ -167,7 +171,14 @@ static int manager_play_dtmf(struct mansession *s, const struct message *m)
return 0;
}
ast_senddigit_external(chan, *digit, duration_ms);
if (ast_true(receive_s)) {
struct ast_frame f = { AST_FRAME_DTMF, };
f.len = duration_ms;
f.subclass.integer = *digit;
ast_queue_frame(chan, &f);
} else {
ast_senddigit_external(chan, *digit, duration_ms);
}
chan = ast_channel_unref(chan);

View File

@ -117,7 +117,7 @@ static int softhangup_exec(struct ast_channel *chan, const char *data)
*cut = 0;
}
if (!strcasecmp(name, args.channel)) {
ast_log(LOG_WARNING, "Soft hanging %s up.\n", ast_channel_name(c));
ast_verb(4, "Soft hanging %s up.\n", ast_channel_name(c));
ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
if (!ast_test_flag(&flags, OPTION_ALL)) {
ast_channel_unlock(c);

View File

@ -46,39 +46,6 @@
* \verbinclude voicemail.conf.sample
*/
/*** MODULEINFO
<defaultenabled>yes</defaultenabled>
<use type="module">res_adsi</use>
<use type="module">res_smdi</use>
<support_level>core</support_level>
***/
/*** MAKEOPTS
<category name="MENUSELECT_OPTS_app_voicemail" displayname="Voicemail Build Options" positive_output="yes" touch_on_change="apps/app_voicemail.c apps/app_directory.c">
<member name="FILE_STORAGE" displayname="Storage of Voicemail using filesystem">
<conflict>ODBC_STORAGE</conflict>
<conflict>IMAP_STORAGE</conflict>
<defaultenabled>yes</defaultenabled>
<support_level>core</support_level>
</member>
<member name="ODBC_STORAGE" displayname="Storage of Voicemail using ODBC">
<depend>generic_odbc</depend>
<conflict>IMAP_STORAGE</conflict>
<conflict>FILE_STORAGE</conflict>
<defaultenabled>no</defaultenabled>
<support_level>core</support_level>
</member>
<member name="IMAP_STORAGE" displayname="Storage of Voicemail using IMAP4">
<depend>imap_tk</depend>
<conflict>ODBC_STORAGE</conflict>
<conflict>FILE_STORAGE</conflict>
<use type="external">openssl</use>
<defaultenabled>no</defaultenabled>
<support_level>core</support_level>
</member>
</category>
***/
#include "asterisk.h"
#ifdef IMAP_STORAGE
@ -510,20 +477,20 @@
***/
#ifdef IMAP_STORAGE
static char imapserver[48];
static char imapport[8];
static char imapserver[48] = "localhost";
static char imapport[8] = "143";
static char imapflags[128];
static char imapfolder[64];
static char imapparentfolder[64] = "\0";
static char greetingfolder[64];
static char imapfolder[64] = "INBOX";
static char imapparentfolder[64];
static char greetingfolder[64] = "INBOX";
static char authuser[32];
static char authpassword[42];
static int imapversion = 1;
static int expungeonhangup = 1;
static int imapgreetings = 0;
static int imap_poll_logout = 0;
static char delimiter = '\0';
static int imapgreetings;
static int imap_poll_logout;
static char delimiter;
/* mail_open cannot be protected on a stream basis */
ast_mutex_t mail_open_lock;
@ -909,8 +876,8 @@ struct vm_state {
};
#ifdef ODBC_STORAGE
static char odbc_database[80];
static char odbc_table[80];
static char odbc_database[80] = "asterisk";
static char odbc_table[80] = "voicemessages";
#define RETRIEVE(a,b,c,d) retrieve_file(a,b)
#define DISPOSE(a,b) remove_file(a,b)
#define STORE(a,b,c,d,e,f,g,h,i,j,k) store_file(a,b,c,d)
@ -984,21 +951,21 @@ static AST_LIST_HEAD_STATIC(zones, vm_zone);
static char zonetag[80];
static char locale[20];
static int maxsilence;
static int maxmsg;
static int maxmsg = MAXMSG;
static int maxdeletedmsg;
static int silencethreshold = 128;
static char serveremail[80];
static char mailcmd[160]; /* Configurable mail cmd */
static char serveremail[80] = ASTERISK_USERNAME;
static char mailcmd[160] = SENDMAIL; /* Configurable mail cmd */
static char externnotify[160];
static struct ast_smdi_interface *smdi_iface = NULL;
static char vmfmts[80];
static char vmfmts[80] = "wav";
static double volgain;
static int vmminsecs;
static int vmmaxsecs;
static int maxgreet;
static int skipms;
static int maxlogins;
static int minpassword;
static int skipms = 3000;
static int maxlogins = 3;
static int minpassword = MINPASSWORD;
static int passwordlocation;
static char aliasescontext[MAX_VM_CONTEXT_LEN];
@ -1006,10 +973,10 @@ static char aliasescontext[MAX_VM_CONTEXT_LEN];
* app_voicemail that may change them. */
static unsigned int poll_mailboxes;
/*! Polling frequency */
static unsigned int poll_freq;
/*! By default, poll every 30 seconds */
#define DEFAULT_POLL_FREQ 30
/*! Polling frequency */
static unsigned int poll_freq = DEFAULT_POLL_FREQ;
AST_MUTEX_DEFINE_STATIC(poll_lock);
static ast_cond_t poll_cond = PTHREAD_COND_INITIALIZER;
@ -1071,7 +1038,7 @@ static char vm_prepend_timeout[80] = "vm-then-pound";
static struct ast_flags globalflags = {0};
static int saydurationminfo;
static int saydurationminfo = 2;
static char dialcontext[AST_MAX_CONTEXT] = "";
static char callcontext[AST_MAX_CONTEXT] = "";
@ -1080,10 +1047,10 @@ static char exitcontext[AST_MAX_CONTEXT] = "";
static char cidinternalcontexts[MAX_NUM_CID_CONTEXTS][64];
static char *emailbody = NULL;
static char *emailsubject = NULL;
static char *pagerbody = NULL;
static char *pagersubject = NULL;
static char *emailbody;
static char *emailsubject;
static char *pagerbody;
static char *pagersubject;
static char fromstring[100];
static char pagerfromstring[100];
static char charset[32] = "ISO-8859-1";
@ -1830,7 +1797,7 @@ static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword)
struct ast_config *cfg = NULL;
struct ast_variable *var = NULL;
struct ast_category *cat = NULL;
char *category = NULL, *value = NULL, *new = NULL;
char *category = NULL;
const char *tmp = NULL;
struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
char secretfn[PATH_MAX] = "";
@ -1857,24 +1824,28 @@ static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword)
if ((cfg = ast_config_load(VOICEMAIL_CONFIG, config_flags)) && valid_config(cfg)) {
while ((category = ast_category_browse(cfg, category))) {
if (!strcasecmp(category, vmu->context)) {
char *value = NULL;
char *new = NULL;
if (!(tmp = ast_variable_retrieve(cfg, category, vmu->mailbox))) {
ast_log(AST_LOG_WARNING, "We could not find the mailbox.\n");
break;
}
value = strstr(tmp, ",");
if (!value) {
new = ast_alloca(strlen(newpassword)+1);
new = ast_malloc(strlen(newpassword) + 1);
sprintf(new, "%s", newpassword);
} else {
new = ast_alloca((strlen(value) + strlen(newpassword) + 1));
new = ast_malloc((strlen(value) + strlen(newpassword) + 1));
sprintf(new, "%s%s", newpassword, value);
}
if (!(cat = ast_category_get(cfg, category, NULL))) {
ast_log(AST_LOG_WARNING, "Failed to get category structure.\n");
ast_free(new);
break;
}
ast_variable_update(cat, vmu->mailbox, new, NULL, 0);
found = 1;
ast_free(new);
}
}
/* save the results */
@ -1898,13 +1869,14 @@ static void vm_change_password(struct ast_vm_user *vmu, const char *newpassword)
for (category = ast_category_browse(cfg, NULL); category; category = ast_category_browse(cfg, category)) {
ast_debug(4, "users.conf: %s\n", category);
if (!strcasecmp(category, vmu->mailbox)) {
char new[strlen(newpassword) + 1];
if (!ast_variable_retrieve(cfg, category, "vmsecret")) {
ast_debug(3, "looks like we need to make vmsecret!\n");
var = ast_variable_new("vmsecret", newpassword, "");
} else {
var = NULL;
}
new = ast_alloca(strlen(newpassword) + 1);
sprintf(new, "%s", newpassword);
if (!(cat = ast_category_get(cfg, category, NULL))) {
ast_debug(4, "failed to get category!\n");
@ -2227,7 +2199,6 @@ static int imap_retrieve_greeting(const char *dir, const int msgnum, struct ast_
struct vm_state *vms_p;
char *file, *filename;
char dest[PATH_MAX];
char *attachment;
int i;
BODY *body;
int ret = 0;
@ -2280,21 +2251,26 @@ static int imap_retrieve_greeting(const char *dir, const int msgnum, struct ast_
mail_fetchstructure(vms_p->mailstream, i + 1, &body);
/* We have the body, now we extract the file name of the first attachment. */
if (body->nested.part && body->nested.part->next && body->nested.part->next->body.parameter->value) {
attachment = ast_strdupa(body->nested.part->next->body.parameter->value);
char *attachment = body->nested.part->next->body.parameter->value;
char copy[strlen(attachment) + 1];
strcpy(copy, attachment); /* safe */
attachment = copy;
filename = strsep(&attachment, ".");
if (!strcmp(filename, file)) {
ast_copy_string(vms_p->fn, dir, sizeof(vms_p->fn));
vms_p->msgArray[vms_p->curmsg] = i + 1;
create_dirpath(dest, sizeof(dest), vmu->context, vms_p->username, "");
save_body(body, vms_p, "2", attachment, 0);
ret = 0;
break;
}
} else {
ast_log(AST_LOG_ERROR, "There is no file attached to this IMAP message.\n");
ret = -1;
break;
}
filename = strsep(&attachment, ".");
if (!strcmp(filename, file)) {
ast_copy_string(vms_p->fn, dir, sizeof(vms_p->fn));
vms_p->msgArray[vms_p->curmsg] = i + 1;
create_dirpath(dest, sizeof(dest), vmu->context, vms_p->username, "");
save_body(body, vms_p, "2", attachment, 0);
ret = 0;
break;
}
}
if (curr_mbox != -1) {
@ -3778,54 +3754,6 @@ static void check_quota(struct vm_state *vms, char *mailbox) {
#endif /* IMAP_STORAGE */
static void cleanup_orphaned_lock_files(const char *base)
{
DIR *dir;
struct dirent *e;
dir = opendir(base);
if (!dir) {
/* Don't complain about this too loudly */
ast_debug(2, "Unable to open `%s': %s\n", base, strerror(errno));
return;
}
while ((e = readdir(dir))) {
char *fullpath;
struct stat s;
/* Always skip . and .. */
if (!strcmp(e->d_name, ".") || !strcmp(e->d_name, "..")) {
continue;
}
/* Build up the full path (using dynamic memory because PATH_MAX is crap) */
if (ast_asprintf(&fullpath, "%s/%s", base, e->d_name) == -1) {
break;
}
if (lstat(fullpath, &s) < 0) {
ast_free(fullpath);
continue;
}
/* This is exposing an implementation detail of ast_lock_path, but it makes
* our life a bit easier */
if (!strcmp(e->d_name, ".lock") && S_ISLNK(s.st_mode)) {
if (!ast_unlock_path(base)) {
ast_log(AST_LOG_NOTICE, "Cleaned up orphaned lock file: %s/.lock\n", base);
}
} else if (S_ISDIR(s.st_mode)) {
/* If it is a directory, let's dive down */
cleanup_orphaned_lock_files(fullpath);
}
ast_free(fullpath);
}
closedir(dir);
}
/*! \brief Lock file path
* only return failure if ast_lock_path returns 'timeout',
* not if the path does not exist or any other reason
@ -4790,11 +4718,15 @@ static int copy(char *infile, char *outfile)
static void copy_plain_file(char *frompath, char *topath)
{
char frompath2[PATH_MAX], topath2[PATH_MAX];
struct ast_variable *tmp,*var = NULL;
const char *origmailbox = NULL, *context = NULL, *macrocontext = NULL, *exten = NULL, *priority = NULL, *callerchan = NULL, *callerid = NULL, *origdate = NULL, *origtime = NULL, *category = NULL, *duration = NULL;
struct ast_variable *tmp, *var = NULL;
const char *origmailbox = "", *context = "", *macrocontext = "", *exten = "";
const char *priority = "", *callerchan = "", *callerid = "", *origdate = "";
const char *origtime = "", *category = "", *duration = "";
ast_filecopy(frompath, topath, NULL);
snprintf(frompath2, sizeof(frompath2), "%s.txt", frompath);
snprintf(topath2, sizeof(topath2), "%s.txt", topath);
if (ast_check_realtime("voicemail_data")) {
var = ast_load_realtime("voicemail_data", "filename", frompath, SENTINEL);
/* This cycle converts ast_variable linked list, to va_list list of arguments, may be there is a better way to do it? */
@ -5479,12 +5411,33 @@ static int add_email_attachment(FILE *p, struct ast_vm_user *vmu, char *format,
char sox_gain_tmpdir[PATH_MAX];
char *file_to_delete = NULL, *dir_to_delete = NULL;
int res;
char altfname[PATH_MAX] = "";
int altused = 0;
char altformat[80] = "";
char *c = NULL;
/* Eww. We want formats to tell us their own MIME type */
char *mime_type = (!strcasecmp(format, "ogg")) ? "application/" : "audio/x-";
/* Users of multiple file formats need special attention. */
snprintf(fname, sizeof(fname), "%s.%s", attach, format);
if (!ast_file_is_readable(fname)) {
ast_copy_string(altformat, vmfmts, sizeof(altformat));
c = strchr(altformat, '|');
if (c) {
*c = '\0';
}
ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s - trying first/alternate format %s\n", fname, strerror(errno), altformat);
snprintf(altfname, sizeof(altfname), "%s.%s", attach, altformat);
if (!ast_file_is_readable(altfname)) {
ast_log(AST_LOG_WARNING, "Failed to open file: %s: %s - alternate format %s failure\n", altfname, strerror(errno), altformat);
} else {
altused = 1;
}
}
/* This 'while' loop will only execute once. We use it so that we can 'break' */
while (vmu->volgain < -.001 || vmu->volgain > .001) {
while (vmu->volgain < -.001 || vmu->volgain > .001 || altused) {
char tmpdir[PATH_MAX];
create_dirpath(tmpdir, sizeof(tmpdir), vmu->context, vmu->mailbox, "tmp");
@ -5510,8 +5463,29 @@ static int add_email_attachment(FILE *p, struct ast_vm_user *vmu, char *format,
break;
}
res = snprintf(sox_gain_cmd, sizeof(sox_gain_cmd), "sox -v %.4f %s.%s %s",
vmu->volgain, attach, format, fname);
if (!altused) {
res = snprintf(sox_gain_cmd, sizeof(sox_gain_cmd), "sox -v %.4f %s.%s %s",
vmu->volgain, attach, format, fname);
} else {
if (!strcasecmp(format, "wav")) {
if (vmu->volgain < -.001 || vmu->volgain > .001) {
res = snprintf(sox_gain_cmd, sizeof(sox_gain_cmd), "sox -v %.4f %s.%s -e signed-integer -b 16 %s",
vmu->volgain, attach, altformat, fname);
} else {
res = snprintf(sox_gain_cmd, sizeof(sox_gain_cmd), "sox %s.%s -e signed-integer -b 16 %s",
attach, altformat, fname);
}
} else {
if (vmu->volgain < -.001 || vmu->volgain > .001) {
res = snprintf(sox_gain_cmd, sizeof(sox_gain_cmd), "sox -v %.4f %s.%s %s",
vmu->volgain, attach, altformat, fname);
} else {
res = snprintf(sox_gain_cmd, sizeof(sox_gain_cmd), "sox %s.%s %s",
attach, altformat, fname);
}
}
}
if (res >= sizeof(sox_gain_cmd)) {
ast_log(LOG_ERROR, "Failed to generate sox command, out of buffer space\n");
break;
@ -7212,7 +7186,7 @@ leave_vm_out:
#ifdef IMAP_STORAGE
/* expunge message - use UID Expunge if supported on IMAP server*/
ast_debug(3, "*** Checking if we can expunge, expungeonhangup set to %d\n", expungeonhangup);
if (expungeonhangup == 1) {
if (expungeonhangup == 1 && vms->mailstream != NULL) {
ast_mutex_lock(&vms->lock);
#ifdef HAVE_IMAP_TK2006
if (LEVELUIDPLUS (vms->mailstream)) {
@ -7919,29 +7893,29 @@ static int get_folder(struct ast_channel *chan, int start)
/* Japanese Syntax */
static int get_folder_ja(struct ast_channel *chan, int start)
{
int x;
int d;
char fn[256];
for (x = start; x< 5; x++) { /* For all folders */
if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, ast_channel_language(chan), (char *) NULL))) {
return d;
int x;
int d;
char fn[256];
for (x = start; x < 5; x++) { /* For all folders */
if ((d = ast_say_number(chan, x, AST_DIGIT_ANY, ast_channel_language(chan), (char *) NULL))) {
return d;
}
snprintf(fn, sizeof(fn), "vm-%s", mbox(NULL, x)); /* Folder name */
d = vm_play_folder_name(chan, fn);
if (d) {
return d;
return d;
}
d = ast_waitfordigit(chan, 500);
if (d) {
return d;
d = ast_waitfordigit(chan, 500);
if (d) {
return d;
}
}
d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
if (d) {
return d;
}
d = ast_waitfordigit(chan, 4000);
return d;
d = ast_play_and_wait(chan, "vm-tocancel"); /* "or pound to cancel" */
if (d) {
return d;
}
d = ast_waitfordigit(chan, 4000);
return d;
}
/*!
@ -7963,13 +7937,13 @@ static int get_folder2(struct ast_channel *chan, char *fn, int start)
res = ast_play_and_wait(chan, fn); /* Folder name */
while (((res < '0') || (res > '9')) &&
(res != '#') && (res >= 0) &&
loops < 4) {
/* res = get_folder(chan, 0); */
if (!strcasecmp(ast_channel_language(chan),"ja")) { /* Japanese syntax */
res = get_folder_ja(chan, 0);
} else { /* Default syntax */
res = get_folder(chan, 0);
(res != '#') && (res >= 0) &&
loops < 4) {
/* res = get_folder(chan, 0); */
if (!strcasecmp(ast_channel_language(chan), "ja")) { /* Japanese syntax */
res = get_folder_ja(chan, 0);
} else { /* Default syntax */
res = get_folder(chan, 0);
}
loops++;
}
@ -8180,10 +8154,12 @@ static void queue_mwi_event(const char *channel_id, const char *box, int urgent,
aliases = ao2_find(mailbox_alias_mappings, box, OBJ_SEARCH_KEY | OBJ_MULTIPLE);
while ((mapping = ao2_iterator_next(aliases))) {
char alias[strlen(mapping->alias) + 1];
strcpy(alias, mapping->alias); /* safe */
mailbox = NULL;
context = NULL;
ast_debug(3, "Found alias mapping: %s -> %s\n", mapping->alias, box);
separate_mailbox(ast_strdupa(mapping->alias), &mailbox, &context);
separate_mailbox(alias, &mailbox, &context);
ast_publish_mwi_state_channel(mailbox, context, new + urgent, old, channel_id);
ao2_ref(mapping, -1);
}
@ -8403,12 +8379,12 @@ static int forward_message(struct ast_channel *chan, char *context, struct vm_st
directory_app = pbx_findapp("Directory");
if (directory_app) {
char vmcontext[256];
char *old_context;
char *old_exten;
char old_context[strlen(ast_channel_context(chan)) + 1];
char old_exten[strlen(ast_channel_exten(chan)) + 1];
int old_priority;
/* make backup copies */
old_context = ast_strdupa(ast_channel_context(chan));
old_exten = ast_strdupa(ast_channel_exten(chan));
strcpy(old_context, ast_channel_context(chan)); /* safe */
strcpy(old_exten, ast_channel_exten(chan)); /* safe */
old_priority = ast_channel_priority(chan);
/* call the Directory, changes the channel */
@ -9089,7 +9065,6 @@ static int imap_remove_file(char *dir, int msgnum)
static int imap_delete_old_greeting (char *dir, struct vm_state *vms)
{
char *file, *filename;
char *attachment;
char arg[11];
int i;
BODY* body;
@ -9118,17 +9093,22 @@ static int imap_delete_old_greeting (char *dir, struct vm_state *vms)
mail_fetchstructure(vms->mailstream, i + 1, &body);
/* We have the body, now we extract the file name of the first attachment. */
if (body->nested.part->next && body->nested.part->next->body.parameter->value) {
attachment = ast_strdupa(body->nested.part->next->body.parameter->value);
char *attachment = body->nested.part->next->body.parameter->value;
char copy[strlen(attachment) + 1];
strcpy(copy, attachment); /* safe */
attachment = copy;
filename = strsep(&attachment, ".");
if (!strcmp(filename, file)) {
snprintf(arg, sizeof(arg), "%d", i + 1);
mail_setflag(vms->mailstream, arg, "\\DELETED");
}
} else {
ast_log(AST_LOG_ERROR, "There is no file attached to this IMAP message.\n");
ast_mutex_unlock(&vms->lock);
return -1;
}
filename = strsep(&attachment, ".");
if (!strcmp(filename, file)) {
snprintf(arg, sizeof(arg), "%d", i + 1);
mail_setflag(vms->mailstream, arg, "\\DELETED");
}
}
mail_expunge(vms->mailstream);
@ -9333,15 +9313,15 @@ static int vm_play_folder_name_gr(struct ast_channel *chan, char *box)
static int vm_play_folder_name_ja(struct ast_channel *chan, char *box)
{
int cmd;
int cmd;
if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
cmd = ast_play_and_wait(chan, box);
return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
} else {
cmd = ast_play_and_wait(chan, box);
return cmd;
}
if (!strcasecmp(box, "vm-INBOX") || !strcasecmp(box, "vm-Old")) {
cmd = ast_play_and_wait(chan, box);
return cmd ? cmd : ast_play_and_wait(chan, "vm-messages");
} else {
cmd = ast_play_and_wait(chan, box);
return cmd;
}
}
static int vm_play_folder_name_pl(struct ast_channel *chan, char *box)
@ -9386,8 +9366,8 @@ static int vm_play_folder_name(struct ast_channel *chan, char *box)
return vm_play_folder_name_gr(chan, box);
} else if (!strncasecmp(ast_channel_language(chan), "he", 2)) { /* Hebrew syntax */
return ast_play_and_wait(chan, box);
} else if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* Japanese syntax */
return vm_play_folder_name_ja(chan, box);
} else if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* Japanese syntax */
return vm_play_folder_name_ja(chan, box);
} else if (!strncasecmp(ast_channel_language(chan), "pl", 2)) {
return vm_play_folder_name_pl(chan, box);
} else if (!strncasecmp(ast_channel_language(chan), "ua", 2)) { /* Ukrainian syntax */
@ -9615,40 +9595,40 @@ static int vm_intro_he(struct ast_channel *chan, struct vm_state *vms)
/* Japanese syntax */
static int vm_intro_ja(struct ast_channel *chan,struct vm_state *vms)
{
/* Introduce messages they have */
int res;
if (vms->newmessages) {
res = ast_play_and_wait(chan, "vm-INBOX");
if (!res)
res = ast_play_and_wait(chan, "vm-message");
if (!res)
res = ast_play_and_wait(chan, "jp-ga");
if (!res)
res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
if (vms->oldmessages && !res)
res = ast_play_and_wait(chan, "silence/1");
/* Introduce messages they have */
int res;
if (vms->newmessages) {
res = ast_play_and_wait(chan, "vm-INBOX");
if (!res)
res = ast_play_and_wait(chan, "vm-message");
if (!res)
res = ast_play_and_wait(chan, "jp-ga");
if (!res)
res = say_and_wait(chan, vms->newmessages, ast_channel_language(chan));
if (vms->oldmessages && !res)
res = ast_play_and_wait(chan, "silence/1");
}
if (vms->oldmessages) {
res = ast_play_and_wait(chan, "vm-Old");
if (!res)
res = ast_play_and_wait(chan, "vm-message");
if (!res)
res = ast_play_and_wait(chan, "jp-ga");
if (!res)
res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
}
if (!vms->oldmessages && !vms->newmessages) {
res = ast_play_and_wait(chan, "vm-messages");
if (!res)
res = ast_play_and_wait(chan, "jp-wa");
if (!res)
res = ast_play_and_wait(chan, "jp-arimasen");
}
else {
res = ast_play_and_wait(chan, "jp-arimasu");
}
return res;
}
if (vms->oldmessages) {
res = ast_play_and_wait(chan, "vm-Old");
if (!res)
res = ast_play_and_wait(chan, "vm-message");
if (!res)
res = ast_play_and_wait(chan, "jp-ga");
if (!res)
res = say_and_wait(chan, vms->oldmessages, ast_channel_language(chan));
}
if (!vms->oldmessages && !vms->newmessages) {
res = ast_play_and_wait(chan, "vm-messages");
if (!res)
res = ast_play_and_wait(chan, "jp-wa");
if (!res)
res = ast_play_and_wait(chan, "jp-arimasen");
}
else {
res = ast_play_and_wait(chan, "jp-arimasu");
}
return res;
} /* Japanese */
/* Default English syntax */
@ -10562,82 +10542,82 @@ static int vm_instructions_en(struct ast_channel *chan, struct ast_vm_user *vmu,
static int vm_instructions_ja(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
{
int res = 0;
/* Play instructions and wait for new command */
while (!res) {
if (vms->starting) {
if (vms->lastmsg > -1) {
res = vm_play_folder_name(chan, vms->vmbox);
if (!res)
res = ast_play_and_wait(chan, "jp-wa");
if (!res)
res = ast_play_and_wait(chan, "digits/1");
if (!res)
res = ast_play_and_wait(chan, "jp-wo");
if (!res)
res = ast_play_and_wait(chan, "silence/1");
}
if (!res)
res = ast_play_and_wait(chan, "vm-opts");
} else {
/* Added for additional help */
if (skipadvanced) {
res = vm_play_folder_name(chan, vms->vmbox);
if (!res)
res = ast_play_and_wait(chan, "jp-wa");
if (!res)
res = ast_play_and_wait(chan, "digits/1");
if (!res)
res = ast_play_and_wait(chan, "jp-wo");
if (!res)
res = ast_play_and_wait(chan, "silence/1");
res = ast_play_and_wait(chan, "vm-opts-full");
}
/* Logic:
* If the current message is not the first OR
* if we're listening to the first new message and there are
* also urgent messages, then prompt for navigation to the
* previous message
*/
if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
res = ast_play_and_wait(chan, "vm-prev");
}
if (!res && !skipadvanced)
res = ast_play_and_wait(chan, "vm-advopts");
if (!res)
res = ast_play_and_wait(chan, "vm-repeat");
/* Logic:
* If we're not listening to the last message OR
* we're listening to the last urgent message and there are
* also new non-urgent messages, then prompt for navigation
* to the next message
*/
if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
(ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
res = ast_play_and_wait(chan, "vm-next");
}
if (!res) {
int curmsg_deleted;
int res = 0;
/* Play instructions and wait for new command */
while (!res) {
if (vms->starting) {
if (vms->lastmsg > -1) {
res = vm_play_folder_name(chan, vms->vmbox);
if (!res)
res = ast_play_and_wait(chan, "jp-wa");
if (!res)
res = ast_play_and_wait(chan, "digits/1");
if (!res)
res = ast_play_and_wait(chan, "jp-wo");
if (!res)
res = ast_play_and_wait(chan, "silence/1");
}
if (!res)
res = ast_play_and_wait(chan, "vm-opts");
} else {
/* Added for additional help */
if (skipadvanced) {
res = vm_play_folder_name(chan, vms->vmbox);
if (!res)
res = ast_play_and_wait(chan, "jp-wa");
if (!res)
res = ast_play_and_wait(chan, "digits/1");
if (!res)
res = ast_play_and_wait(chan, "jp-wo");
if (!res)
res = ast_play_and_wait(chan, "silence/1");
res = ast_play_and_wait(chan, "vm-opts-full");
}
/* Logic:
* If the current message is not the first OR
* if we're listening to the first new message and there are
* also urgent messages, then prompt for navigation to the
* previous message
*/
if (vms->curmsg || (!in_urgent && vms->urgentmessages > 0) || (ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0)) {
res = ast_play_and_wait(chan, "vm-prev");
}
if (!res && !skipadvanced)
res = ast_play_and_wait(chan, "vm-advopts");
if (!res)
res = ast_play_and_wait(chan, "vm-repeat");
/* Logic:
* If we're not listening to the last message OR
* we're listening to the last urgent message and there are
* also new non-urgent messages, then prompt for navigation
* to the next message
*/
if (!res && ((vms->curmsg != vms->lastmsg) || (in_urgent && vms->newmessages > 0) ||
(ast_test_flag(vmu, VM_MESSAGEWRAP) && vms->lastmsg > 0) )) {
res = ast_play_and_wait(chan, "vm-next");
}
if (!res) {
int curmsg_deleted;
#ifdef IMAP_STORAGE
ast_mutex_lock(&vms->lock);
ast_mutex_lock(&vms->lock);
#endif
curmsg_deleted = vms->deleted[vms->curmsg];
curmsg_deleted = vms->deleted[vms->curmsg];
#ifdef IMAP_STORAGE
ast_mutex_unlock(&vms->lock);
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 (!res) {
res = ast_play_and_wait(chan, "vm-toforward");
}
if (!res) {
res = ast_play_and_wait(chan, "vm-savemessage");
}
}
}
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");
}
if (!res) {
res = ast_play_and_wait(chan, "vm-savemessage");
}
}
}
if (!res) {
res = ast_play_and_wait(chan, "vm-helpexit");
@ -10653,7 +10633,7 @@ static int vm_instructions_ja(struct ast_channel *chan, struct ast_vm_user *vmu,
}
return res;
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)
@ -10682,16 +10662,15 @@ static int vm_instructions_zh(struct ast_channel *chan, struct ast_vm_user *vmu,
static int vm_instructions(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, int skipadvanced, int in_urgent)
{
if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* Japanese syntax */
return vm_instructions_ja(chan, vmu, vms, skipadvanced, in_urgent);
} else if (vms->starting && !strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) syntax */
if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* Japanese syntax */
return vm_instructions_ja(chan, vmu, vms, skipadvanced, in_urgent);
} else if (vms->starting && !strncasecmp(ast_channel_language(chan), "zh", 2)) { /* CHINESE (Taiwan) syntax */
return vm_instructions_zh(chan, vmu, vms, skipadvanced, in_urgent);
} else { /* Default to ENGLISH */
return vm_instructions_en(chan, vmu, vms, skipadvanced, in_urgent);
}
}
static int vm_newuser_setup(struct ast_channel *chan, struct ast_vm_user *vmu, struct vm_state *vms, char *fmtc, signed char record_gain)
{
int cmd = 0;
@ -11117,21 +11096,21 @@ static int vm_browse_messages_it(struct ast_channel *chan, struct vm_state *vms,
*/
static int vm_browse_messages_ja(struct ast_channel *chan, struct vm_state *vms, struct ast_vm_user *vmu)
{
int cmd = 0;
int cmd = 0;
if (vms->lastmsg > -1) {
cmd = play_message(chan, vmu, vms);
} else {
snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
cmd = ast_play_and_wait(chan, vms->fn);
if (!cmd)
cmd = ast_play_and_wait(chan, "vm-messages");
if (!cmd)
cmd = ast_play_and_wait(chan, "jp-wa");
if (!cmd)
cmd = ast_play_and_wait(chan, "jp-arimasen");
}
return cmd;
if (vms->lastmsg > -1) {
cmd = play_message(chan, vmu, vms);
} else {
snprintf(vms->fn, sizeof(vms->fn), "vm-%s", vms->curbox);
cmd = ast_play_and_wait(chan, vms->fn);
if (!cmd)
cmd = ast_play_and_wait(chan, "vm-messages");
if (!cmd)
cmd = ast_play_and_wait(chan, "jp-wa");
if (!cmd)
cmd = ast_play_and_wait(chan, "jp-arimasen");
}
return cmd;
}
/*!
@ -11259,8 +11238,8 @@ static int vm_browse_messages(struct ast_channel *chan, struct vm_state *vms, st
return vm_browse_messages_he(chan, vms, vmu);
} else if (!strncasecmp(ast_channel_language(chan), "it", 2)) { /* ITALIAN */
return vm_browse_messages_it(chan, vms, vmu);
} else if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* JAPANESE */
return vm_browse_messages_ja(chan, vms, vmu);
} else if (!strncasecmp(ast_channel_language(chan), "ja", 2)) { /* JAPANESE */
return vm_browse_messages_ja(chan, vms, vmu);
} else if (!strncasecmp(ast_channel_language(chan), "pt", 2)) { /* PORTUGUESE */
return vm_browse_messages_pt(chan, vms, vmu);
} else if (!strncasecmp(ast_channel_language(chan), "vi", 2)) { /* VIETNAMESE */
@ -12216,22 +12195,22 @@ static int vm_execmain(struct ast_channel *chan, const char *data)
break;
case '*': /* Help */
if (!vms.starting) {
if (!strncasecmp(ast_channel_language(chan), "ja", 2)) {
cmd = vm_play_folder_name(chan, vms.vmbox);
if (!cmd)
cmd = ast_play_and_wait(chan, "jp-wa");
if (!cmd)
cmd = ast_play_and_wait(chan, "digits/1");
if (!cmd)
cmd = ast_play_and_wait(chan, "jp-wo");
if (!cmd)
cmd = ast_play_and_wait(chan, "silence/1");
if (!cmd)
cmd = ast_play_and_wait(chan, "vm-opts");
if (!cmd)
cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent);
break;
}
if (!strncasecmp(ast_channel_language(chan), "ja", 2)) {
cmd = vm_play_folder_name(chan, vms.vmbox);
if (!cmd)
cmd = ast_play_and_wait(chan, "jp-wa");
if (!cmd)
cmd = ast_play_and_wait(chan, "digits/1");
if (!cmd)
cmd = ast_play_and_wait(chan, "jp-wo");
if (!cmd)
cmd = ast_play_and_wait(chan, "silence/1");
if (!cmd)
cmd = ast_play_and_wait(chan, "vm-opts");
if (!cmd)
cmd = vm_instructions(chan, vmu, &vms, 1, in_urgent);
break;
}
cmd = ast_play_and_wait(chan, "vm-onefor");
if (!strncasecmp(ast_channel_language(chan), "he", 2)) {
cmd = ast_play_and_wait(chan, "vm-for");
@ -13744,26 +13723,30 @@ static void load_zonemessages(struct ast_config *cfg)
var = ast_variable_browse(cfg, "zonemessages");
while (var) {
struct vm_zone *z;
char *msg_format, *tzone;
if (var->value) {
struct vm_zone *z;
char *msg_format, *tzone;
char storage[strlen(var->value) + 1];
z = ast_malloc(sizeof(*z));
if (!z) {
return;
}
z = ast_malloc(sizeof(*z));
if (!z) {
return;
}
msg_format = ast_strdupa(var->value);
tzone = strsep(&msg_format, "|,");
if (msg_format) {
ast_copy_string(z->name, var->name, sizeof(z->name));
ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
AST_LIST_LOCK(&zones);
AST_LIST_INSERT_HEAD(&zones, z, list);
AST_LIST_UNLOCK(&zones);
} else {
ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
ast_free(z);
strcpy(storage, var->value); /* safe */
msg_format = storage;
tzone = strsep(&msg_format, "|,");
if (msg_format) {
ast_copy_string(z->name, var->name, sizeof(z->name));
ast_copy_string(z->timezone, tzone, sizeof(z->timezone));
ast_copy_string(z->msg_format, msg_format, sizeof(z->msg_format));
AST_LIST_LOCK(&zones);
AST_LIST_INSERT_HEAD(&zones, z, list);
AST_LIST_UNLOCK(&zones);
} else {
ast_log(AST_LOG_WARNING, "Invalid timezone definition at line %d\n", var->lineno);
ast_free(z);
}
}
var = var->next;
}
@ -15187,6 +15170,11 @@ static int unload_module(void)
#endif
ao2_ref(inprocess_container, -1);
ao2_container_unregister("voicemail_alias_mailbox_mappings");
ao2_cleanup(alias_mailbox_mappings);
ao2_container_unregister("voicemail_mailbox_alias_mappings");
ao2_cleanup(mailbox_alias_mappings);
if (poll_thread != AST_PTHREADT_NULL)
stop_poll_thread();
@ -15258,6 +15246,7 @@ static int load_module(void)
if (!mailbox_alias_mappings) {
ast_log(LOG_ERROR, "Unable to create mailbox_alias_mappings container\n");
ao2_cleanup(inprocess_container);
ao2_container_unregister("voicemail_alias_mailbox_mappings");
ao2_cleanup(alias_mailbox_mappings);
return AST_MODULE_LOAD_DECLINE;
}
@ -15265,6 +15254,7 @@ static int load_module(void)
if (res) {
ast_log(LOG_ERROR, "Unable to register mailbox_alias_mappings container\n");
ao2_cleanup(inprocess_container);
ao2_container_unregister("voicemail_alias_mailbox_mappings");
ao2_cleanup(alias_mailbox_mappings);
ao2_cleanup(mailbox_alias_mappings);
return AST_MODULE_LOAD_DECLINE;
@ -15273,9 +15263,6 @@ static int load_module(void)
/* compute the location of the voicemail spool directory */
snprintf(VM_SPOOL_DIR, sizeof(VM_SPOOL_DIR), "%s/voicemail/", ast_config_AST_SPOOL_DIR);
/* Now that we have a spool directory, clean up old lock files */
cleanup_orphaned_lock_files(VM_SPOOL_DIR);
if (!(mwi_subscription_tps = ast_taskprocessor_get("app_voicemail", 0))) {
ast_log(AST_LOG_WARNING, "failed to reference mwi subscription taskprocessor. MWI will not work\n");
}

View File

@ -240,6 +240,13 @@
<configOption name="timeout">
<synopsis>Kick the user out of the conference after this many seconds. 0 means there is no timeout for the user.</synopsis>
</configOption>
<configOption name="text_messaging" default="yes">
<synopsis>Sets if text messages are sent to the user.</synopsis>
<description><para>If text messaging is enabled for this user then
text messages will be sent to it. These may be events or from other
participants in the conference bridge. If disabled then no text
messages are sent to the user.</para></description>
</configOption>
</configObject>
<configObject name="bridge_profile">
<synopsis>A named profile to apply to specific bridges.</synopsis>
@ -274,6 +281,15 @@
will be used.
</para></description>
</configOption>
<configOption name="maximum_sample_rate">
<synopsis>Set the maximum native sample rate for mixing the conference</synopsis>
<description><para>
Sets the maximum native sample rate the
conference is mixed at. This is set to not have a
maximum by default. If a sample rate is specified,
though, the native sample rate will never exceed it.
</para></description>
</configOption>
<configOption name="language" default="en">
<synopsis>The language used for announcements to the conference.</synopsis>
<description><para>
@ -1579,7 +1595,10 @@ static char *handle_cli_confbridge_show_user_profile(struct ast_cli_entry *e, in
ast_cli(a->fd,"Announce User Count all: %s\n",
u_profile.flags & USER_OPT_ANNOUNCEUSERCOUNTALL ?
"enabled" : "disabled");
ast_cli(a->fd,"\n");
ast_cli(a->fd,"Text Messaging: %s\n",
u_profile.flags & USER_OPT_TEXT_MESSAGING ?
"enabled" : "disabled");
ast_cli(a->fd, "\n");
return CLI_SUCCESS;
}
@ -1682,6 +1701,13 @@ static char *handle_cli_confbridge_show_bridge_profile(struct ast_cli_entry *e,
}
ast_cli(a->fd,"Internal Sample Rate: %s\n", tmp);
if (b_profile.maximum_sample_rate) {
snprintf(tmp, sizeof(tmp), "%u", b_profile.maximum_sample_rate);
} else {
ast_copy_string(tmp, "none", sizeof(tmp));
}
ast_cli(a->fd,"Maximum Sample Rate: %s\n", tmp);
if (b_profile.mix_interval) {
ast_cli(a->fd,"Mixing Interval: %u\n", b_profile.mix_interval);
} else {
@ -2365,6 +2391,7 @@ int conf_load_config(void)
aco_option_register(&cfg_info, "dsp_talking_threshold", ACO_EXACT, user_types, __stringify(DEFAULT_TALKING_THRESHOLD), OPT_UINT_T, 0, FLDSET(struct user_profile, talking_threshold));
aco_option_register(&cfg_info, "jitterbuffer", ACO_EXACT, user_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_JITTERBUFFER);
aco_option_register(&cfg_info, "timeout", ACO_EXACT, user_types, "0", OPT_UINT_T, 0, FLDSET(struct user_profile, timeout));
aco_option_register(&cfg_info, "text_messaging", ACO_EXACT, user_types, "yes", OPT_BOOLFLAG_T, 1, FLDSET(struct user_profile, flags), USER_OPT_TEXT_MESSAGING);
/* This option should only be used with the CONFBRIDGE dialplan function */
aco_option_register_custom(&cfg_info, "template", ACO_EXACT, user_types, NULL, user_template_handler, 0);
@ -2376,6 +2403,7 @@ int conf_load_config(void)
/* "auto" will fail to parse as a uint, but we use PARSE_DEFAULT to set the value to 0 in that case, which is the value that auto resolves to */
aco_option_register(&cfg_info, "internal_sample_rate", ACO_EXACT, bridge_types, "0", OPT_UINT_T, PARSE_DEFAULT, FLDSET(struct bridge_profile, internal_sample_rate), 0);
aco_option_register(&cfg_info, "binaural_active", ACO_EXACT, bridge_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct bridge_profile, flags), BRIDGE_OPT_BINAURAL_ACTIVE);
aco_option_register(&cfg_info, "maximum_sample_rate", ACO_EXACT, bridge_types, "0", OPT_UINT_T, PARSE_DEFAULT, FLDSET(struct bridge_profile, maximum_sample_rate), 0);
aco_option_register_custom(&cfg_info, "mixing_interval", ACO_EXACT, bridge_types, "20", mix_interval_handler, 0);
aco_option_register(&cfg_info, "record_conference", ACO_EXACT, bridge_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct bridge_profile, flags), BRIDGE_OPT_RECORD_CONFERENCE);
aco_option_register_custom(&cfg_info, "video_mode", ACO_EXACT, bridge_types, NULL, video_mode_handler, 0);

View File

@ -68,6 +68,7 @@ enum user_profile_flags {
USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW = (1 << 16), /*!< modifies ANNOUNCE_JOIN_LEAVE - user reviews the recording before continuing */
USER_OPT_SEND_EVENTS = (1 << 17), /*!< Send text message events to users */
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 */
};
enum bridge_profile_flags {
@ -228,6 +229,7 @@ struct bridge_profile {
unsigned int flags;
unsigned int max_members; /*!< The maximum number of participants allowed in the conference */
unsigned int internal_sample_rate; /*!< The internal sample rate of the bridge. 0 when set to auto adjust mode. */
unsigned int maximum_sample_rate; /*!< The maximum sample rate of the bridge. 0 when set to no maximum. */
unsigned int mix_interval; /*!< The internal mixing interval used by the bridge. When set to 0 the bridgewill use a default interval. */
struct bridge_profile_sounds *sounds;
char regcontext[AST_MAX_CONTEXT];

View File

@ -0,0 +1,250 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><title>Release Summary - asterisk-17.4.0</title><h1 align="center"><a name="top">Release Summary</a></h1><h3 align="center">asterisk-17.4.0</h3><h3 align="center">Date: 2020-04-30</h3><h3 align="center">&lt;asteriskteam@digium.com&gt;</h3><hr><h2 align="center">Table of Contents</h2><ol>
<li><a href="#summary">Summary</a></li>
<li><a href="#contributors">Contributors</a></li>
<li><a href="#closed_issues">Closed Issues</a></li>
<li><a href="#commits">Other Changes</a></li>
<li><a href="#diffstat">Diffstat</a></li>
</ol><hr><a name="summary"><h2 align="center">Summary</h2></a><center><a href="#top">[Back to Top]</a></center><p>This release is a point release of an existing major version. The changes included were made to address problems that have been identified in this release series, or are minor, backwards compatible new features or improvements. Users should be able to safely upgrade to this version if this release series is already in use. Users considering upgrading from a previous version are strongly encouraged to review the UPGRADE.txt document as well as the CHANGES document for information about upgrading to this release series.</p><p>The data in this summary reflects changes that have been made since the previous release, asterisk-17.3.0.</p><hr><a name="contributors"><h2 align="center">Contributors</h2></a><center><a href="#top">[Back to Top]</a></center><p>This table lists the people who have submitted code, those that have tested patches, as well as those that reported issues on the issue tracker that were resolved in this release. For coders, the number is how many of their patches (of any size) were committed into this release. For testers, the number is the number of times their name was listed as assisting with testing a patch. Finally, for reporters, the number is the number of issues that they reported that were affected by commits that went into this release.</p><table width="100%" border="0">
<tr><th width="33%">Coders</th><th width="33%">Testers</th><th width="33%">Reporters</th></tr>
<tr valign="top"><td width="33%">18 Alexander Traud <pabstraud@compuserve.com><br/>11 Jaco Kroon <jaco@uls.co.za><br/>10 Joshua C. Colp <jcolp@sangoma.com><br/>7 Alexander Traud <pabstraud@compuserve.com><br/>6 Sean Bright <sean.bright@gmail.com><br/>3 Torrey Searle <torrey@voxbone.com><br/>3 Kevin Harwell <kharwell@digium.com><br/>3 Asterisk Development Team <asteriskteam@digium.com><br/>2 Pirmin Walthert <infos@nappsoft.ch><br/>2 sungtae kim <sungtae@messagebird.com><br/>2 Guido Falsi <madpilot@FreeBSD.org><br/>1 George Joseph <gjoseph@digium.com><br/>1 Rodrigo Ramírez Norambuena <a@rodrigoramirez.com><br/>1 Jared Smith <jsmith@fedoraproject.org><br/>1 Daniel Heckl <daniel.heckl@gmail.com><br/>1 Bernard Merindol <bernard.merindol@telnowedge.com><br/>1 Jean Aunis <jean.aunis@prescom.fr><br/>1 Paulo Vicentini <paulo.vicentini@gmail.com><br/>1 Sungtae Kim <sungtae@messagebird.com><br/>1 Michael Neuhauser <mike@firmix.at><br/>1 Sebastien Duthil <sduthil@wazo.community><br/>1 Jason Hord <jhord@fluentstream.com> (license 6978)<br/></td><td width="33%"><td width="33%">17 Alexander Traud <pabstraud@compuserve.com><br/>6 Joshua C. Colp <jcolp@digium.com><br/>3 Torrey Searle <tsearle@gmail.com><br/>2 sungtae kim <pchero21@gmail.com><br/>2 Kevin Harwell <kharwell@digium.com><br/>2 Guido Falsi <madpilot@freebsd.org><br/>2 nappsoft <infos@nappsoft.ch><br/>2 Jaco Kroon <jaco@uls.co.za><br/>1 Paulo Vicentini <paulo.vicentini@gmail.com><br/>1 Patrick Wakano<br/>1 Sébastien Duthil <sduthil@wazo.community><br/>1 Jean Aunis - Prescom <jean.aunis@prescom.fr><br/>1 Jared Smith <jaredsmith@jaredsmith.net><br/>1 Patrick Wakano <pwakano@gmail.com><br/>1 Daniel Heckl <daniel.heckl@gmail.com><br/>1 Pascal Cadotte Michaud <pascal.cadotte@gmail.com><br/>1 Bernard Merindol <bernard.merindol@telnowedge.com><br/>1 Matt Addison <maddison@iquest.net><br/>1 Michael Neuhauser <mike@firmix.at><br/>1 George Joseph<br/>1 Vitold <vit1251@gmail.com><br/>1 Anton Satskiy <satskiy.a@gmail.com><br/>1 Joeran Vinzens <vinzens@sipgate.de><br/>1 Alexey Vasilyev <alexei.vasilyev@gmail.com><br/>1 Anton Satskiy<br/>1 Vitold<br/>1 Joshua Elson <joshelson@gmail.com><br/>1 Michael Neuhauser<br/>1 George Joseph <gjoseph@digium.com><br/>1 sstream <sstream00@yahoo.co.jp><br/>1 Joshua Roys<br/>1 Joshua Roys <roysjosh@gmail.com><br/>1 Olivier Krief <olivier.krief@gmail.com><br/>1 Jason Hord <jhord@fluentstream.com><br/></td></tr>
</table><hr><a name="closed_issues"><h2 align="center">Closed Issues</h2></a><center><a href="#top">[Back to Top]</a></center><p>This is a list of all issues from the issue tracker that were closed by changes that went into this release.</p><h3>New Feature</h3><h4>Category: Core/General</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-6863">ASTERISK-6863</a>: [patch] allow Asterisk to set high ToS bits as non-root on Linux<br/>Reported by: Matt Addison<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=3a5bdc68b226e29a612fd5a972b1052b6978e933">[3a5bdc68b2]</a> Alexander Traud -- install_prereq: Add libcap for high bits in DiffServ/ToS.</li>
</ul><br><h3>Bug</h3><h4>Category: Applications/General</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-16676">ASTERISK-16676</a>: DAHDIRAS fails to properly initiate pppd unless asterisk is running as root<br/>Reported by: Jaco Kroon<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=836203a3fdb3008075b1142ec86985823fd9d9b0">[836203a3fd]</a> Jaco Kroon -- dahdiras: Only set plugin dahdi.so to pppd if we're running as root.</li>
</ul><br><h4>Category: Applications/app_confbridge</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28841">ASTERISK-28841</a>: app_confbridge: Add support for disabling text messaging for a user<br/>Reported by: Joshua C. Colp<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=21f0759b2c890d692e965853ae59857da51755b8">[21f0759b2c]</a> Joshua C. Colp -- confbridge: Add support for disabling text messaging.</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28790">ASTERISK-28790</a>: Crash during conference call using confbridge and video<br/>Reported by: Pascal Cadotte Michaud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=4b2729e89dece563d24168d401f5ab022fecdfc3">[4b2729e89d]</a> Joshua C. Colp -- res_rtp_asterisk: Ensure sufficient space for worst case NACK.</li>
</ul><br><h4>Category: Applications/app_mixmonitor</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28780">ASTERISK-28780</a>: app_mixmonitor: Memory leak due to race condition between AMI MixMonitor and hangup<br/>Reported by: Joshua C. Colp<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=aa9e4f395b381e95098c864e53f84144a3909464">[aa9e4f395b]</a> Joshua C. Colp -- audiohook: Don't allow audiohooks to attach to hung up channels.</li>
</ul><br><h4>Category: Bridges/bridge_softmix</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28819">ASTERISK-28819</a>: [patch] bridge_softmix_binaural: Show state in menuselect.<br/>Reported by: Alexander Traud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=1f7c32f397b046a0165f5459f750fe7b87560eab">[1f7c32f397]</a> Alexander Traud -- bridge_softmix_binaural: Show state in menuselect.</li>
</ul><br><h4>Category: Channels/chan_pjsip</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28835">ASTERISK-28835</a>: IPv6 addresses in SDP incorrectly formatted<br/>Reported by: Daniel Heckl<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=139cd912af9793e47986004937faca3f0c58a3d8">[139cd912af]</a> Daniel Heckl -- res_pjsip: Fixed format of IPv6 addresses for external media addresses</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28817">ASTERISK-28817</a>: chan_pjsip: constant DTMF tone if RTP is not setup yet<br/>Reported by: Kevin Harwell<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=d38839067b2fc90f51359528b0e9d084024ca240">[d38839067b]</a> Kevin Harwell -- chan_pjsip: digit_begin - constant DTMF tone if RTP is not setup yet</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28774">ASTERISK-28774</a>: chan_pjsip's rtptimeout is erroneously triggered during direct-media (native_rtp) bridge<br/>Reported by: Michael Neuhauser<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=580e260ff841e966b7eb2f1609186b4db5bfe741">[580e260ff8]</a> Michael Neuhauser -- chan_psip, res_pjsip_sdp_rtp: ignore rtptimeout if direct-media is active</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28759">ASTERISK-28759</a>: A non negotiated rtp frame causes call disconnection when there is a SSRC change<br/>Reported by: Paulo Vicentini<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=8645a294caa582b4e437a7dae2b62b8e1bca15bd">[8645a294ca]</a> Paulo Vicentini -- chan_pjsip: Check audio frame when remote SSRC changes.</li>
</ul><br><h4>Category: Channels/chan_sip/TCP-TLS</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28372">ASTERISK-28372</a>: Asterisk REPLY Wrong Contact header port (TCP)<br/>Reported by: Anton Satskiy<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=2fc7780a3a233a3577a181614f89bfe2352f449a">[2fc7780a3a]</a> Alexander Traud -- chan_sip: externhost/externaddr with non-default TCP/TLS ports.</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-24428">ASTERISK-24428</a>: Document that Asterisk will use the default SIP ports (5060 for TCP, 5061 for TLS) if the extern option variants aren't used<br/>Reported by: sstream<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=2fc7780a3a233a3577a181614f89bfe2352f449a">[2fc7780a3a]</a> Alexander Traud -- chan_sip: externhost/externaddr with non-default TCP/TLS ports.</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-27195">ASTERISK-27195</a>: chan_sip: only sets ToS bits on UDP socket, ignoring TCP and TLS sockets<br/>Reported by: Joshua Roys<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=3b4be152d5b229deff3fb3f2b5f46ac2e2eb17c1">[3b4be152d5]</a> Alexander Traud -- chan_sip: DiffServ/ToS not only on UDP but also on TCP and TLS sockets.</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28798">ASTERISK-28798</a>: [patch] chan_sip: TCP/TLS client without server.<br/>Reported by: Alexander Traud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=223da4dfa1a760f408b1ab436e1d10205a3f0487">[223da4dfa1]</a> Alexander Traud -- chan_sip: TCP/TLS client without server.</li>
</ul><br><h4>Category: Channels/chan_unistim</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28803">ASTERISK-28803</a>: [patch] chan_unistim: Avoid tautological warnings with clang.<br/>Reported by: Alexander Traud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=45a4cb163c8e486d7b4500e15f80cf9534cecfdd">[45a4cb163c]</a> Alexander Traud -- chan_unistim: Avoid tautological warnings with clang.</li>
</ul><br><h4>Category: Core/Bridging</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28841">ASTERISK-28841</a>: app_confbridge: Add support for disabling text messaging for a user<br/>Reported by: Joshua C. Colp<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=21f0759b2c890d692e965853ae59857da51755b8">[21f0759b2c]</a> Joshua C. Colp -- confbridge: Add support for disabling text messaging.</li>
</ul><br><h4>Category: Core/BuildSystem</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28837">ASTERISK-28837</a>: pjproject_bundled: Honor --without-pjproject.<br/>Reported by: Alexander Traud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=fccfa256a3d4230d5ebbd32fe176ed006cbe69e0">[fccfa256a3]</a> Alexander Traud -- pjproject_bundled: Honor --without-pjproject.</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28824">ASTERISK-28824</a>: BuildSystem: Search for Python/C API when possibly needed only.<br/>Reported by: Alexander Traud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=8bbc6605c9df0ae8f2f682217d56885a1bbf09e8">[8bbc6605c9]</a> Alexander Traud -- BuildSystem: Search for Python/C API when possibly needed only.</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-27717">ASTERISK-27717</a>: [patch] BuildSystem: In NetBSD, the Python Programming Language is python-2.7.<br/>Reported by: Alexander Traud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=8bbc6605c9df0ae8f2f682217d56885a1bbf09e8">[8bbc6605c9]</a> Alexander Traud -- BuildSystem: Search for Python/C API when possibly needed only.</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28816">ASTERISK-28816</a>: [patch] BuildSystem: Remove doc/tex and doc/pdf leftovers.<br/>Reported by: Alexander Traud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=5aeb31e79078eeaa088a271dc6427b1472ef23ed">[5aeb31e790]</a> Alexander Traud -- BuildSystem: Remove doc/tex and doc/pdf leftovers.</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28818">ASTERISK-28818</a>: [patch] BuildSystem: Allow space in path.<br/>Reported by: Alexander Traud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=dda530002aa2cbce2c8efb1332a6ad28c9f48e53">[dda530002a]</a> Alexander Traud -- BuildSystem: Allow space in path.</li>
</ul><br><h4>Category: Core/Channels</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28795">ASTERISK-28795</a>: channel: write to a stream on multi-frame writes<br/>Reported by: Kevin Harwell<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=a03cb7552309f4539acff78e66f5126def2e533c">[a03cb75523]</a> Kevin Harwell -- channel: write to a stream on multi-frame writes</li>
</ul><br><h4>Category: Core/General</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28839">ASTERISK-28839</a>: Sporadic crashes with Segmentation fault<br/>Reported by: Joeran Vinzens<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=e7b6736ba33e74a0d3a5c7807e36b35ba0a77d45">[e7b6736ba3]</a> Joshua C. Colp -- fax: Fix crashes in PJSIP re-negotiation scenarios.</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28780">ASTERISK-28780</a>: app_mixmonitor: Memory leak due to race condition between AMI MixMonitor and hangup<br/>Reported by: Joshua C. Colp<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=aa9e4f395b381e95098c864e53f84144a3909464">[aa9e4f395b]</a> Joshua C. Colp -- audiohook: Don't allow audiohooks to attach to hung up channels.</li>
</ul><br><h4>Category: Core/Streams</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28846">ASTERISK-28846</a>: stream: Enforce formats immutability<br/>Reported by: Joshua C. Colp<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=fe11bc7a2a101f992bc348bde081bbe60ecd205d">[fe11bc7a2a]</a> Joshua C. Colp -- stream: Enforce formats immutability and ensure formats exist.</li>
</ul><br><h4>Category: Documentation</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28816">ASTERISK-28816</a>: [patch] BuildSystem: Remove doc/tex and doc/pdf leftovers.<br/>Reported by: Alexander Traud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=5aeb31e79078eeaa088a271dc6427b1472ef23ed">[5aeb31e790]</a> Alexander Traud -- BuildSystem: Remove doc/tex and doc/pdf leftovers.</li>
</ul><br><h4>Category: Functions/func_aes</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28788">ASTERISK-28788</a>: func_aes: incorrectly printing error 'declined to load'<br/>Reported by: Alexander Traud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=bdc0aaca9d3837be5ea3da6ee59581cbe40f1a28">[bdc0aaca9d]</a> Alexander Traud -- func_aes: Avoid incorrect error message on load.</li>
</ul><br><h4>Category: Functions/func_channel</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28796">ASTERISK-28796</a>: func_channel: cannot read fields exten, context, userfield, channame from dialplan<br/>Reported by: Sébastien Duthil<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=a29fd59340c557345484d69a9951c9f8874ddb47">[a29fd59340]</a> Sebastien Duthil -- func_channel: allow reading 4 fields from dialplan</li>
</ul><br><h4>Category: Functions/func_enum</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-26711">ASTERISK-26711</a>: func_enum: ENUM code wrong case<br/>Reported by: Vitold<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=7eec0900300f51fe882eb32ed82be6075fd15072">[7eec090030]</a> Sean Bright -- enum.c: Add support for regular expression flag in NAPTR record</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-19460">ASTERISK-19460</a>: [patch] Function TXTCIDNAME never actually makes DNS calls and always returns an empty string<br/>Reported by: George Joseph<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=2c26705a9b478a328c0e0b84a190c6be9a772fac">[2c26705a9b]</a> Sean Bright -- enum.c: Make ast_get_txt() actually do something.</li>
</ul><br><h4>Category: Functions/func_odbc</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-20325">ASTERISK-20325</a>: Comments in configs/func_odbc.conf.sample are not consistent with examples. Missing examples.<br/>Reported by: Olivier Krief<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=83981ad7833908736e9d494019a4ffeb1c2ce8ff">[83981ad783]</a> Sean Bright -- func_odbc.conf.sample: Clarify sample documentation</li>
</ul><br><h4>Category: General</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28838">ASTERISK-28838</a>: AST_MODULE_INFO requires, MODULEINFO does not mention<br/>Reported by: Alexander Traud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=6d4ddc3151639f771ee184c03303647f0ef4e50f">[6d4ddc3151]</a> Alexander Traud -- cdr_odbc: Sync load- and build-time deps.</li>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=71c70dfbfbc19a569ef3cf464fd96311dcd7f773">[71c70dfbfb]</a> Alexander Traud -- res_pjsip: Sync load- and build-time deps.</li>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=c4c259c3af0c1edb25324ec759ae003c3a63aba1">[c4c259c3af]</a> Alexander Traud -- res_pjsip_refer: Add build-time dependency.</li>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=9fc5654e5a9e8c441eb2a4696241e58c914fbb34">[9fc5654e5a]</a> Alexander Traud -- app_getcpeid: Add build-time dependency.</li>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=2cd2852f57e628eb88564d73a52eed29898668b6">[2cd2852f57]</a> Alexander Traud -- curl: Add build-time dependency.</li>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=12dda5d8677f96f43696abb2a39e9dcffc54cc43">[12dda5d867]</a> Alexander Traud -- res_pjsip: Add build-time dependency.</li>
</ul><br><h4>Category: PBX/pbx_dundi</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-21205">ASTERISK-21205</a>: [patch] dundi_read_result crash due to negative number<br/>Reported by: Jaco Kroon<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=122ef44584d7d83482bb4226ff11fbf986f1730c">[122ef44584]</a> Jaco Kroon -- dundi: fix NULL dereference.</li>
</ul><br><h4>Category: Resources/res_ari_channels</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28847">ASTERISK-28847</a>: ARI channels cuts the endpoint string over 80 characters<br/>Reported by: sungtae kim<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=9a90ab372223afebf1570b1007275b204e33abcc">[9a90ab3722]</a> sungtae kim -- res_ari_channels: Fixed endpoint 80 characters limit</li>
</ul><br><h4>Category: Resources/res_pjsip</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28056">ASTERISK-28056</a>: res_pjsip: Incorrect endpoint status after endpoint synchronization for a specific AOR<br/>Reported by: Jason Hord<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=79b453b5797e70ebd38ec4fe0ad1b502e2e148d0">[79b453b579]</a> Jason Hord -- res_pjsip: Don't set endpoint to unavailable in all cases.</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28790">ASTERISK-28790</a>: Crash during conference call using confbridge and video<br/>Reported by: Pascal Cadotte Michaud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=4b2729e89dece563d24168d401f5ab022fecdfc3">[4b2729e89d]</a> Joshua C. Colp -- res_rtp_asterisk: Ensure sufficient space for worst case NACK.</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28743">ASTERISK-28743</a>: Asterisk is crashing if the 200 OK with SDP<br/>Reported by: sungtae kim<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=b58dfbc68ac18786b68a29fb6aa730b2dc475d7e">[b58dfbc68a]</a> Sungtae Kim -- res_pjsip_session: Fixed wrong session termination</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-23407">ASTERISK-23407</a>: Fix the FSF address in the headers of lots of pjproject files<br/>Reported by: Jared Smith<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=ff48a6cd56f3702a99a6ff6e7ca2cc4d8b1ed41b">[ff48a6cd56]</a> Jared Smith -- indications.conf.sample: Add indication tones for Indonesia</li>
</ul><br><h4>Category: Resources/res_pjsip_sdp_rtp</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28784">ASTERISK-28784</a>: res_pjsip_sdp_rtp: Only do hold/unhold on first audio stream<br/>Reported by: Joshua C. Colp<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=6c4e181b2ff69355c18108efbe7f2810d32e3036">[6c4e181b2f]</a> Joshua C. Colp -- res_pjsip_sdp_rtp: Only do hold/unhold on default audio stream.</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28774">ASTERISK-28774</a>: chan_pjsip's rtptimeout is erroneously triggered during direct-media (native_rtp) bridge<br/>Reported by: Michael Neuhauser<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=580e260ff841e966b7eb2f1609186b4db5bfe741">[580e260ff8]</a> Michael Neuhauser -- chan_psip, res_pjsip_sdp_rtp: ignore rtptimeout if direct-media is active</li>
</ul><br><h4>Category: Resources/res_pjsip_session</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28783">ASTERISK-28783</a>: res_pjsip_session: Allow default non-audio streams to have reflected state<br/>Reported by: Joshua C. Colp<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=f0d61890324f4757984846c3104cb8fb175c37bb">[f0d6189032]</a> Joshua C. Colp -- res_pjsip_session: Don't restrict non-audio default streams to sendrecv.</li>
</ul><br><h4>Category: Resources/res_rtp_asterisk</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28852">ASTERISK-28852</a>: Unprotected access to nochecksums variable, causes build failures<br/>Reported by: Guido Falsi<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=f44bd5c80679bdc4e48431cccadee1a1d35b79c0">[f44bd5c806]</a> Guido Falsi -- res_rtp_asterisk: Protect access to nochecksums with #ifdef</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28827">ASTERISK-28827</a>: res_rtp_asterisk: Loop when receive buffer is flushed by a received packet that is also in receive buffer with NACK<br/>Reported by: nappsoft<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=7ed8078bdbee11620e042aefccb08e7bbcb15804">[7ed8078bdb]</a> Pirmin Walthert -- res_rtp_asterisk: Resolve loop when receive buffer is flushed</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28826">ASTERISK-28826</a>: res_rtp_asterisk: Duplicate seqnos being added to send buffer with NACK<br/>Reported by: nappsoft<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=26dec6659883d5145a13e09465dbf0504f06cefe">[26dec66598]</a> Pirmin Walthert -- res_rtp_asterisk: Free payload when error on insertion to data buffer</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28812">ASTERISK-28812</a>: First DTMF is not get<br/>Reported by: Bernard Merindol<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=7544e6d095c975e2b780e63ca6c3016bf95c9cca">[7544e6d095]</a> Bernard Merindol -- res_rtp_asterisk.c: Check for first DTMF having timestamp set to 0</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28809">ASTERISK-28809</a>: [patch] res_rtp_asterisk: Avoid absolute value on unsigned subtraction.<br/>Reported by: Alexander Traud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=c971769db58a38e685c2b7e41d57d6a862322c94">[c971769db5]</a> Alexander Traud -- res_rtp_asterisk: Avoid absolute value on unsigned subtraction.</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28773">ASTERISK-28773</a>: Incorrect Sender SSRC in RTCP when p2p rtp bridge is active<br/>Reported by: Torrey Searle<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=b8a67fc15dfa83dc6efc403e13d63c64662446f9">[b8a67fc15d]</a> Torrey Searle -- res_rtp_asterisk: Send correct sender SSRC when p2p bridge in use</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28769">ASTERISK-28769</a>: DTLS Handshake Fails to Occur if ice_support is enabled but not used<br/>Reported by: Torrey Searle<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=1c6314627d0a2fc34c2e94c3eee5ac107a3aa06f">[1c6314627d]</a> Torrey Searle -- res_pjsip_sdp_rtp: Don't wait for ICE if not negotiated</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28759">ASTERISK-28759</a>: A non negotiated rtp frame causes call disconnection when there is a SSRC change<br/>Reported by: Paulo Vicentini<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=8645a294caa582b4e437a7dae2b62b8e1bca15bd">[8645a294ca]</a> Paulo Vicentini -- chan_pjsip: Check audio frame when remote SSRC changes.</li>
</ul><br><h4>Category: Tests/General</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28808">ASTERISK-28808</a>: [patch] test_stasis: Avoid always true warning with clang.<br/>Reported by: Alexander Traud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=a14690fc00dfe9e66c50cdcd6958de6b5cc1b7ee">[a14690fc00]</a> Alexander Traud -- test_stasis: Avoid always true warning with clang.</li>
</ul><br><h4>Category: Tests/testsuite</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-27717">ASTERISK-27717</a>: [patch] BuildSystem: In NetBSD, the Python Programming Language is python-2.7.<br/>Reported by: Alexander Traud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=8bbc6605c9df0ae8f2f682217d56885a1bbf09e8">[8bbc6605c9]</a> Alexander Traud -- BuildSystem: Search for Python/C API when possibly needed only.</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28789">ASTERISK-28789</a>: test_utils: incorrectly printing error 'declined to load'<br/>Reported by: Alexander Traud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=96923ec8713028ad8d236a0314af600724356cfd">[96923ec871]</a> Alexander Traud -- test_utils: Avoid incorrect error message on load.</li>
</ul><br><h4>Category: pjproject/pjsip</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28811">ASTERISK-28811</a>: Crash occurs when fax session switches from T.38 to audio<br/>Reported by: Alexey Vasilyev<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=e7b6736ba33e74a0d3a5c7807e36b35ba0a77d45">[e7b6736ba3]</a> Joshua C. Colp -- fax: Fix crashes in PJSIP re-negotiation scenarios.</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28837">ASTERISK-28837</a>: pjproject_bundled: Honor --without-pjproject.<br/>Reported by: Alexander Traud<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=fccfa256a3d4230d5ebbd32fe176ed006cbe69e0">[fccfa256a3]</a> Alexander Traud -- pjproject_bundled: Honor --without-pjproject.</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28758">ASTERISK-28758</a>: pjsip startup errors when using "with-ssl" configure option<br/>Reported by: Patrick Wakano<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=84495aae4ca0084a691e7d8d873396922d69cb81">[84495aae4c]</a> Alexander Traud -- pjproject_bundled: Repair ./configure --with-ssl without ARG.</li>
</ul><br><h3>Improvement</h3><h4>Category: Applications/app_page</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-27946">ASTERISK-27946</a>: dial (API): Storage of dialed target uses AST_MAX_EXTENSION when it shouldn't<br/>Reported by: Joshua Elson<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=41c1e0b45d9ef75c66beb570ab97c46bbb1d14b3">[41c1e0b45d]</a> sungtae kim -- dial.c: Removed dial string 80 character limitation</li>
</ul><br><h4>Category: Core/DNS</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28853">ASTERISK-28853</a>: Missing include on FreeBSD<br/>Reported by: Guido Falsi<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=2a7a252ba136e556201bdd97432123c12c8ab135">[2a7a252ba1]</a> Guido Falsi -- core/dns: Add system include required on FreeBSD</li>
</ul><br><h4>Category: Core/Dial</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-27946">ASTERISK-27946</a>: dial (API): Storage of dialed target uses AST_MAX_EXTENSION when it shouldn't<br/>Reported by: Joshua Elson<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=41c1e0b45d9ef75c66beb570ab97c46bbb1d14b3">[41c1e0b45d]</a> sungtae kim -- dial.c: Removed dial string 80 character limitation</li>
</ul><br><h4>Category: Functions/func_volume</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28813">ASTERISK-28813</a>: func_volume: Allow decimal numbers as parameter to improve granularity<br/>Reported by: Jean Aunis - Prescom<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=c23f899254d6a001e2c4c822b03dbddccfd184c7">[c23f899254]</a> Jean Aunis -- func_volume: Accept decimal number as argument</li>
</ul><br><h4>Category: Resources/res_pjsip_session</h4><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28782">ASTERISK-28782</a>: Add support for Content-Disposition header in multi-part INVITES<br/>Reported by: Torrey Searle<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=46be4668e34ff05894e65926a2ed5b7cdbe891b2">[46be4668e3]</a> Torrey Searle -- res_pjsip_session: implement processing of Content-Disposition</li>
</ul><a href="https://issues.asterisk.org/jira/browse/ASTERISK-28787">ASTERISK-28787</a>: res_pjsip_session: Decide more intelligently when to add video<br/>Reported by: Joshua C. Colp<ul>
<li><a href="https://code.asterisk.org/code/changelog/asterisk?cs=e181cbde6314dab4561bed7d54a7f35369e38ef8">[e181cbde63]</a> Joshua C. Colp -- res_pjsip_session: Apply intention behind requested formats.</li>
</ul><br><hr><a name="commits"><h2 align="center">Commits Not Associated with an Issue</h2></a><center><a href="#top">[Back to Top]</a></center><p>This is a list of all changes that went into this release that did not reference a JIRA issue.</p><table width="100%" border="1">
<tr><th>Revision</th><th>Author</th><th>Summary</th></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=21286195d532d6275b00d2eddb4ca9e73540eaa5">21286195d5</a></td><td>Asterisk Development Team</td><td>Update for 17.4.0-rc2</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=f3eaf2b7d1c08ca9fe2ea7b2bb5319000cc0fcb4">f3eaf2b7d1</a></td><td>Asterisk Development Team</td><td>Update for 17.4.0-rc1</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=3907b8139741f884e1b629dd0291f98ba3251d46">3907b81397</a></td><td>Asterisk Development Team</td><td>Update CHANGES and UPGRADE.txt for 17.4.0</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=39f5be81a348abdeda26b54e199a4d89cdc0ef2c">39f5be81a3</a></td><td>Alexander Traud</td><td>BuildSystem: Only if found LibPRI, check its optional parts.</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=77e2afe8cc9ca04753455d5fe4928ce176ab4978">77e2afe8cc</a></td><td>Alexander Traud</td><td>BuildSystem: Only if found external PJProject, check its optional parts.</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=7a568549ee3fc827c4e9ba57ef79f64669d43c7e">7a568549ee</a></td><td>Jaco Kroon</td><td>res_rtp_asterisk: iterate all local addresses looking to populate ICE.</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=c3d49c304beecfcdc22901ef7ce1b2a2c21ba7d7">c3d49c304b</a></td><td>Jaco Kroon</td><td>res_pjsip: document legal dtls_verify endpoint options.</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=44f921bb138a8c9ebf7f4223871d638b164dca54">44f921bb13</a></td><td>Alexander Traud</td><td>res_rtp_asterisk: Build without PJProject.</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=e832fb6f1ccc09d28e594958ac564c76a2a983d2">e832fb6f1c</a></td><td>Alexander Traud</td><td>_pjsua: Build even with Clang.</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=f56e4e73af74a997beaa9a36a8062aa751fc559b">f56e4e73af</a></td><td>Sean Bright</td><td>Revert "res_config_odbc: Preserve empty strings returned by the database"</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=a5119e960086f9e8a73173c604522f7351b18e80">a5119e9600</a></td><td>Jaco Kroon</td><td>main/backtrace: binutils-2.34 fix.</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=1b01a6abfd1f323c9043fc9c65f4ab038296f77c">1b01a6abfd</a></td><td>Jaco Kroon</td><td>acl: implement a centralized ACL output mechanism for HAs and ACLs.</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=5e24379cf2cdb06149e92a32e4d6c7497f3653c7">5e24379cf2</a></td><td>Joshua C. Colp</td><td>chan_sip: Send 403 when ACL fails.</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=26c75683bfb1a8412574ef5654eb2cce25e1727c">26c75683bf</a></td><td>Joshua C. Colp</td><td>CHANGES: Change md file extension to txt.</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=ba47752d0d54bfaac9515c587faf86a35d0b88f4">ba47752d0d</a></td><td>Jaco Kroon</td><td>netsock2: compile fixes.</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=9255a17410799a5f82427de1faab251e69302dd2">9255a17410</a></td><td>Kevin Harwell</td><td>ast_coredumper: add Asterisk information dump</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=6706af0d5be43dc4d382e082d9ef6b695512f64d">6706af0d5b</a></td><td>Jaco Kroon</td><td>build: enable building with uClibc</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=9c911b0f9b934f365b227749b4a9ef5cd6171263">9c911b0f9b</a></td><td>Jaco Kroon</td><td>build: search from newest to oldest for gmime.</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=c7c52b8e7ab2c4e1e27bd06b7c35a9ba96711bf2">c7c52b8e7a</a></td><td>Jaco Kroon</td><td>res_rtp_asterisk: implement ACL mechanism for ICE and STUN addresses.</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=af414ef015a6427b34c8f942f8e525dcda277347">af414ef015</a></td><td>Jaco Kroon</td><td>Update main/backtrace.c to deal with changes in binutils 2.34.</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=31c6a208623f06d6f93f4e74eac59b9a7de5972c">31c6a20862</a></td><td>Sean Bright</td><td>chan_vpb: Fix 'catching polymorphic type ... by value' error</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=7a38d5f4e2726d3164f4f1d425d1e04134a4f53a">7a38d5f4e2</a></td><td>Sean Bright</td><td>dns_txt: Add TXT record parsing support</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=24f32eb138d5ac109b0d4efc9cd6a762ce75fc1d">24f32eb138</a></td><td>George Joseph</td><td>CI: Create generic jenkinsfile</td></tr>
<tr><td><a href="https://code.asterisk.org/code/changelog/asterisk?cs=6857ba98d514731c93f4db299cff3effea0805e0">6857ba98d5</a></td><td>Rodrigo Ramírez Norambuena</td><td>res_rtp_asterisk: Add 'rtp show settings' cli command</td></tr>
</table><hr><a name="diffstat"><h2 align="center">Diffstat Results</h2></a><center><a href="#top">[Back to Top]</a></center><p>This is a summary of the changes to the source code that went into this release that was generated using the diffstat utility.</p><pre>asterisk-17.3.0-summary.html | 160 ---
asterisk-17.3.0-summary.txt | 459 ---------
b/.version | 2
b/CHANGES | 50 +
b/ChangeLog | 942 +++++++++++++++++++-
b/Makefile | 4
b/UPGRADE.txt | 14
b/apps/app_confbridge.c | 7
b/apps/app_dahdiras.c | 6
b/apps/app_getcpeid.c | 1
b/apps/app_mixmonitor.c | 1
b/apps/confbridge/conf_config_parser.c | 13
b/apps/confbridge/include/confbridge.h | 1
b/asterisk-17.4.0-rc2-summary.html | 13
b/asterisk-17.4.0-rc2-summary.txt | 91 +
b/bridges/bridge_native_rtp.c | 14
b/bridges/bridge_simple.c | 14
b/bridges/bridge_softmix.c | 2
b/cdr/cdr_odbc.c | 2
b/channels/chan_pjsip.c | 71 -
b/channels/chan_sip.c | 71 +
b/channels/chan_unistim.c | 4
b/channels/chan_vpb.cc | 2
b/channels/pjsip/dialplan_functions.c | 13
b/configs/samples/confbridge.conf.sample | 3
b/configs/samples/func_odbc.conf.sample | 11
b/configs/samples/indications.conf.sample | 11
b/configs/samples/rtp.conf.sample | 30
b/configure | 661 +++++++-------
b/configure.ac | 190 ++--
b/contrib/scripts/ast_coredumper | 417 ++++++++
b/contrib/scripts/install_prereq | 28
b/funcs/func_aes.c | 4
b/funcs/func_channel.c | 8
b/funcs/func_curl.c | 1
b/funcs/func_volume.c | 12
b/include/asterisk/acl.h | 32
b/include/asterisk/bridge_features.h | 2
b/include/asterisk/dns_internal.h | 26
b/include/asterisk/dns_txt.h | 64 +
b/include/asterisk/frame.h | 8
b/include/asterisk/netsock2.h | 6
b/include/asterisk/stream.h | 2
b/include/asterisk/utils.h | 24
b/main/acl.c | 29
b/main/audiohook.c | 9
b/main/backtrace.c | 9
b/main/bridge.c | 1
b/main/bridge_channel.c | 8
b/main/channel.c | 39
b/main/data_buffer.c | 2
b/main/dial.c | 14
b/main/dns_core.c | 3
b/main/dns_txt.c | 127 ++
b/main/enum.c | 104 +-
b/main/frame.c | 27
b/main/manager.c | 3
b/main/named_acl.c | 9
b/main/stream.c | 8
b/makeopts.in | 4
b/menuselect/configure | 8
b/menuselect/menuselect.c | 2
b/pbx/pbx_dundi.c | 6
b/res/ari/resource_channels.c | 15
b/res/res_config_curl.c | 2
b/res/res_config_odbc.c | 2
b/res/res_pjsip.c | 18
b/res/res_pjsip/pjsip_options.c | 7
b/res/res_pjsip_caller_id.c | 3
b/res/res_pjsip_diversion.c | 1
b/res/res_pjsip_dlg_options.c | 3
b/res/res_pjsip_dtmf_info.c | 1
b/res/res_pjsip_empty_info.c | 1
b/res/res_pjsip_messaging.c | 1
b/res/res_pjsip_nat.c | 1
b/res/res_pjsip_one_touch_record_info.c | 1
b/res/res_pjsip_path.c | 1
b/res/res_pjsip_refer.c | 1
b/res/res_pjsip_rfc3326.c | 1
b/res/res_pjsip_sdp_rtp.c | 70 +
b/res/res_pjsip_session.c | 168 ++-
b/res/res_rtp_asterisk.c | 469 ++++++---
b/tests/CI/universal-asterisk-nongerrit.jenkinsfile | 452 +++++++++
b/tests/test_stasis.c | 2
b/tests/test_utils.c | 6
b/third-party/pjproject/Makefile | 2
b/third-party/pjproject/configure.m4 | 198 ++--
87 files changed, 3766 insertions(+), 1569 deletions(-)</pre><br></html>

667
asterisk-17.4.0-summary.txt Normal file
View File

@ -0,0 +1,667 @@
Release Summary
asterisk-17.4.0
Date: 2020-04-30
<asteriskteam@digium.com>
----------------------------------------------------------------------
Table of Contents
1. Summary
2. Contributors
3. Closed Issues
4. Other Changes
5. Diffstat
----------------------------------------------------------------------
Summary
[Back to Top]
This release is a point release of an existing major version. The changes
included were made to address problems that have been identified in this
release series, or are minor, backwards compatible new features or
improvements. Users should be able to safely upgrade to this version if
this release series is already in use. Users considering upgrading from a
previous version are strongly encouraged to review the UPGRADE.txt
document as well as the CHANGES document for information about upgrading
to this release series.
The data in this summary reflects changes that have been made since the
previous release, asterisk-17.3.0.
----------------------------------------------------------------------
Contributors
[Back to Top]
This table lists the people who have submitted code, those that have
tested patches, as well as those that reported issues on the issue tracker
that were resolved in this release. For coders, the number is how many of
their patches (of any size) were committed into this release. For testers,
the number is the number of times their name was listed as assisting with
testing a patch. Finally, for reporters, the number is the number of
issues that they reported that were affected by commits that went into
this release.
Coders Testers Reporters
18 Alexander Traud 17 Alexander Traud
11 Jaco Kroon 6 Joshua C. Colp
10 Joshua C. Colp 3 Torrey Searle
7 Alexander Traud 2 sungtae kim
6 Sean Bright 2 Kevin Harwell
3 Torrey Searle 2 Guido Falsi
3 Kevin Harwell 2 nappsoft
3 Asterisk Development Team 2 Jaco Kroon
2 Pirmin Walthert 1 Paulo Vicentini
2 sungtae kim 1 Patrick Wakano
2 Guido Falsi 1 Sébastien Duthil
1 George Joseph 1 Jean Aunis - Prescom
1 Rodrigo RamÃrez Norambuena 1 Jared Smith
1 Jared Smith 1 Patrick Wakano
1 Daniel Heckl 1 Daniel Heckl
1 Bernard Merindol 1 Pascal Cadotte Michaud
1 Jean Aunis 1 Bernard Merindol
1 Paulo Vicentini 1 Matt Addison
1 Sungtae Kim 1 Michael Neuhauser
1 Michael Neuhauser 1 George Joseph
1 Sebastien Duthil 1 Vitold
1 Jason Hord (license 6978) 1 Anton Satskiy
1 Joeran Vinzens
1 Alexey Vasilyev
1 Anton Satskiy
1 Vitold
1 Joshua Elson
1 Michael Neuhauser
1 George Joseph
1 sstream
1 Joshua Roys
1 Joshua Roys
1 Olivier Krief
1 Jason Hord
----------------------------------------------------------------------
Closed Issues
[Back to Top]
This is a list of all issues from the issue tracker that were closed by
changes that went into this release.
New Feature
Category: Core/General
ASTERISK-6863: [patch] allow Asterisk to set high ToS bits as non-root on
Linux
Reported by: Matt Addison
* [3a5bdc68b2] Alexander Traud -- install_prereq: Add libcap for high
bits in DiffServ/ToS.
Bug
Category: Applications/General
ASTERISK-16676: DAHDIRAS fails to properly initiate pppd unless asterisk
is running as root
Reported by: Jaco Kroon
* [836203a3fd] Jaco Kroon -- dahdiras: Only set plugin dahdi.so to pppd
if we're running as root.
Category: Applications/app_confbridge
ASTERISK-28841: app_confbridge: Add support for disabling text messaging
for a user
Reported by: Joshua C. Colp
* [21f0759b2c] Joshua C. Colp -- confbridge: Add support for disabling
text messaging.
ASTERISK-28790: Crash during conference call using confbridge and video
Reported by: Pascal Cadotte Michaud
* [4b2729e89d] Joshua C. Colp -- res_rtp_asterisk: Ensure sufficient
space for worst case NACK.
Category: Applications/app_mixmonitor
ASTERISK-28780: app_mixmonitor: Memory leak due to race condition between
AMI MixMonitor and hangup
Reported by: Joshua C. Colp
* [aa9e4f395b] Joshua C. Colp -- audiohook: Don't allow audiohooks to
attach to hung up channels.
Category: Bridges/bridge_softmix
ASTERISK-28819: [patch] bridge_softmix_binaural: Show state in menuselect.
Reported by: Alexander Traud
* [1f7c32f397] Alexander Traud -- bridge_softmix_binaural: Show state in
menuselect.
Category: Channels/chan_pjsip
ASTERISK-28835: IPv6 addresses in SDP incorrectly formatted
Reported by: Daniel Heckl
* [139cd912af] Daniel Heckl -- res_pjsip: Fixed format of IPv6 addresses
for external media addresses
ASTERISK-28817: chan_pjsip: constant DTMF tone if RTP is not setup yet
Reported by: Kevin Harwell
* [d38839067b] Kevin Harwell -- chan_pjsip: digit_begin - constant DTMF
tone if RTP is not setup yet
ASTERISK-28774: chan_pjsip's rtptimeout is erroneously triggered during
direct-media (native_rtp) bridge
Reported by: Michael Neuhauser
* [580e260ff8] Michael Neuhauser -- chan_psip, res_pjsip_sdp_rtp: ignore
rtptimeout if direct-media is active
ASTERISK-28759: A non negotiated rtp frame causes call disconnection when
there is a SSRC change
Reported by: Paulo Vicentini
* [8645a294ca] Paulo Vicentini -- chan_pjsip: Check audio frame when
remote SSRC changes.
Category: Channels/chan_sip/TCP-TLS
ASTERISK-28372: Asterisk REPLY Wrong Contact header port (TCP)
Reported by: Anton Satskiy
* [2fc7780a3a] Alexander Traud -- chan_sip: externhost/externaddr with
non-default TCP/TLS ports.
ASTERISK-24428: Document that Asterisk will use the default SIP ports
(5060 for TCP, 5061 for TLS) if the extern option variants aren't used
Reported by: sstream
* [2fc7780a3a] Alexander Traud -- chan_sip: externhost/externaddr with
non-default TCP/TLS ports.
ASTERISK-27195: chan_sip: only sets ToS bits on UDP socket, ignoring TCP
and TLS sockets
Reported by: Joshua Roys
* [3b4be152d5] Alexander Traud -- chan_sip: DiffServ/ToS not only on UDP
but also on TCP and TLS sockets.
ASTERISK-28798: [patch] chan_sip: TCP/TLS client without server.
Reported by: Alexander Traud
* [223da4dfa1] Alexander Traud -- chan_sip: TCP/TLS client without
server.
Category: Channels/chan_unistim
ASTERISK-28803: [patch] chan_unistim: Avoid tautological warnings with
clang.
Reported by: Alexander Traud
* [45a4cb163c] Alexander Traud -- chan_unistim: Avoid tautological
warnings with clang.
Category: Core/Bridging
ASTERISK-28841: app_confbridge: Add support for disabling text messaging
for a user
Reported by: Joshua C. Colp
* [21f0759b2c] Joshua C. Colp -- confbridge: Add support for disabling
text messaging.
Category: Core/BuildSystem
ASTERISK-28837: pjproject_bundled: Honor --without-pjproject.
Reported by: Alexander Traud
* [fccfa256a3] Alexander Traud -- pjproject_bundled: Honor
--without-pjproject.
ASTERISK-28824: BuildSystem: Search for Python/C API when possibly needed
only.
Reported by: Alexander Traud
* [8bbc6605c9] Alexander Traud -- BuildSystem: Search for Python/C API
when possibly needed only.
ASTERISK-27717: [patch] BuildSystem: In NetBSD, the Python Programming
Language is python-2.7.
Reported by: Alexander Traud
* [8bbc6605c9] Alexander Traud -- BuildSystem: Search for Python/C API
when possibly needed only.
ASTERISK-28816: [patch] BuildSystem: Remove doc/tex and doc/pdf leftovers.
Reported by: Alexander Traud
* [5aeb31e790] Alexander Traud -- BuildSystem: Remove doc/tex and
doc/pdf leftovers.
ASTERISK-28818: [patch] BuildSystem: Allow space in path.
Reported by: Alexander Traud
* [dda530002a] Alexander Traud -- BuildSystem: Allow space in path.
Category: Core/Channels
ASTERISK-28795: channel: write to a stream on multi-frame writes
Reported by: Kevin Harwell
* [a03cb75523] Kevin Harwell -- channel: write to a stream on
multi-frame writes
Category: Core/General
ASTERISK-28839: Sporadic crashes with Segmentation fault
Reported by: Joeran Vinzens
* [e7b6736ba3] Joshua C. Colp -- fax: Fix crashes in PJSIP
re-negotiation scenarios.
ASTERISK-28780: app_mixmonitor: Memory leak due to race condition between
AMI MixMonitor and hangup
Reported by: Joshua C. Colp
* [aa9e4f395b] Joshua C. Colp -- audiohook: Don't allow audiohooks to
attach to hung up channels.
Category: Core/Streams
ASTERISK-28846: stream: Enforce formats immutability
Reported by: Joshua C. Colp
* [fe11bc7a2a] Joshua C. Colp -- stream: Enforce formats immutability
and ensure formats exist.
Category: Documentation
ASTERISK-28816: [patch] BuildSystem: Remove doc/tex and doc/pdf leftovers.
Reported by: Alexander Traud
* [5aeb31e790] Alexander Traud -- BuildSystem: Remove doc/tex and
doc/pdf leftovers.
Category: Functions/func_aes
ASTERISK-28788: func_aes: incorrectly printing error 'declined to load'
Reported by: Alexander Traud
* [bdc0aaca9d] Alexander Traud -- func_aes: Avoid incorrect error
message on load.
Category: Functions/func_channel
ASTERISK-28796: func_channel: cannot read fields exten, context,
userfield, channame from dialplan
Reported by: Sébastien Duthil
* [a29fd59340] Sebastien Duthil -- func_channel: allow reading 4 fields
from dialplan
Category: Functions/func_enum
ASTERISK-26711: func_enum: ENUM code wrong case
Reported by: Vitold
* [7eec090030] Sean Bright -- enum.c: Add support for regular expression
flag in NAPTR record
ASTERISK-19460: [patch] Function TXTCIDNAME never actually makes DNS calls
and always returns an empty string
Reported by: George Joseph
* [2c26705a9b] Sean Bright -- enum.c: Make ast_get_txt() actually do
something.
Category: Functions/func_odbc
ASTERISK-20325: Comments in configs/func_odbc.conf.sample are not
consistent with examples. Missing examples.
Reported by: Olivier Krief
* [83981ad783] Sean Bright -- func_odbc.conf.sample: Clarify sample
documentation
Category: General
ASTERISK-28838: AST_MODULE_INFO requires, MODULEINFO does not mention
Reported by: Alexander Traud
* [6d4ddc3151] Alexander Traud -- cdr_odbc: Sync load- and build-time
deps.
* [71c70dfbfb] Alexander Traud -- res_pjsip: Sync load- and build-time
deps.
* [c4c259c3af] Alexander Traud -- res_pjsip_refer: Add build-time
dependency.
* [9fc5654e5a] Alexander Traud -- app_getcpeid: Add build-time
dependency.
* [2cd2852f57] Alexander Traud -- curl: Add build-time dependency.
* [12dda5d867] Alexander Traud -- res_pjsip: Add build-time dependency.
Category: PBX/pbx_dundi
ASTERISK-21205: [patch] dundi_read_result crash due to negative number
Reported by: Jaco Kroon
* [122ef44584] Jaco Kroon -- dundi: fix NULL dereference.
Category: Resources/res_ari_channels
ASTERISK-28847: ARI channels cuts the endpoint string over 80 characters
Reported by: sungtae kim
* [9a90ab3722] sungtae kim -- res_ari_channels: Fixed endpoint 80
characters limit
Category: Resources/res_pjsip
ASTERISK-28056: res_pjsip: Incorrect endpoint status after endpoint
synchronization for a specific AOR
Reported by: Jason Hord
* [79b453b579] Jason Hord -- res_pjsip: Don't set endpoint to
unavailable in all cases.
ASTERISK-28790: Crash during conference call using confbridge and video
Reported by: Pascal Cadotte Michaud
* [4b2729e89d] Joshua C. Colp -- res_rtp_asterisk: Ensure sufficient
space for worst case NACK.
ASTERISK-28743: Asterisk is crashing if the 200 OK with SDP
Reported by: sungtae kim
* [b58dfbc68a] Sungtae Kim -- res_pjsip_session: Fixed wrong session
termination
ASTERISK-23407: Fix the FSF address in the headers of lots of pjproject
files
Reported by: Jared Smith
* [ff48a6cd56] Jared Smith -- indications.conf.sample: Add indication
tones for Indonesia
Category: Resources/res_pjsip_sdp_rtp
ASTERISK-28784: res_pjsip_sdp_rtp: Only do hold/unhold on first audio
stream
Reported by: Joshua C. Colp
* [6c4e181b2f] Joshua C. Colp -- res_pjsip_sdp_rtp: Only do hold/unhold
on default audio stream.
ASTERISK-28774: chan_pjsip's rtptimeout is erroneously triggered during
direct-media (native_rtp) bridge
Reported by: Michael Neuhauser
* [580e260ff8] Michael Neuhauser -- chan_psip, res_pjsip_sdp_rtp: ignore
rtptimeout if direct-media is active
Category: Resources/res_pjsip_session
ASTERISK-28783: res_pjsip_session: Allow default non-audio streams to have
reflected state
Reported by: Joshua C. Colp
* [f0d6189032] Joshua C. Colp -- res_pjsip_session: Don't restrict
non-audio default streams to sendrecv.
Category: Resources/res_rtp_asterisk
ASTERISK-28852: Unprotected access to nochecksums variable, causes build
failures
Reported by: Guido Falsi
* [f44bd5c806] Guido Falsi -- res_rtp_asterisk: Protect access to
nochecksums with #ifdef
ASTERISK-28827: res_rtp_asterisk: Loop when receive buffer is flushed by a
received packet that is also in receive buffer with NACK
Reported by: nappsoft
* [7ed8078bdb] Pirmin Walthert -- res_rtp_asterisk: Resolve loop when
receive buffer is flushed
ASTERISK-28826: res_rtp_asterisk: Duplicate seqnos being added to send
buffer with NACK
Reported by: nappsoft
* [26dec66598] Pirmin Walthert -- res_rtp_asterisk: Free payload when
error on insertion to data buffer
ASTERISK-28812: First DTMF is not get
Reported by: Bernard Merindol
* [7544e6d095] Bernard Merindol -- res_rtp_asterisk.c: Check for first
DTMF having timestamp set to 0
ASTERISK-28809: [patch] res_rtp_asterisk: Avoid absolute value on unsigned
subtraction.
Reported by: Alexander Traud
* [c971769db5] Alexander Traud -- res_rtp_asterisk: Avoid absolute value
on unsigned subtraction.
ASTERISK-28773: Incorrect Sender SSRC in RTCP when p2p rtp bridge is
active
Reported by: Torrey Searle
* [b8a67fc15d] Torrey Searle -- res_rtp_asterisk: Send correct sender
SSRC when p2p bridge in use
ASTERISK-28769: DTLS Handshake Fails to Occur if ice_support is enabled
but not used
Reported by: Torrey Searle
* [1c6314627d] Torrey Searle -- res_pjsip_sdp_rtp: Don't wait for ICE if
not negotiated
ASTERISK-28759: A non negotiated rtp frame causes call disconnection when
there is a SSRC change
Reported by: Paulo Vicentini
* [8645a294ca] Paulo Vicentini -- chan_pjsip: Check audio frame when
remote SSRC changes.
Category: Tests/General
ASTERISK-28808: [patch] test_stasis: Avoid always true warning with clang.
Reported by: Alexander Traud
* [a14690fc00] Alexander Traud -- test_stasis: Avoid always true warning
with clang.
Category: Tests/testsuite
ASTERISK-27717: [patch] BuildSystem: In NetBSD, the Python Programming
Language is python-2.7.
Reported by: Alexander Traud
* [8bbc6605c9] Alexander Traud -- BuildSystem: Search for Python/C API
when possibly needed only.
ASTERISK-28789: test_utils: incorrectly printing error 'declined to load'
Reported by: Alexander Traud
* [96923ec871] Alexander Traud -- test_utils: Avoid incorrect error
message on load.
Category: pjproject/pjsip
ASTERISK-28811: Crash occurs when fax session switches from T.38 to audio
Reported by: Alexey Vasilyev
* [e7b6736ba3] Joshua C. Colp -- fax: Fix crashes in PJSIP
re-negotiation scenarios.
ASTERISK-28837: pjproject_bundled: Honor --without-pjproject.
Reported by: Alexander Traud
* [fccfa256a3] Alexander Traud -- pjproject_bundled: Honor
--without-pjproject.
ASTERISK-28758: pjsip startup errors when using "with-ssl" configure
option
Reported by: Patrick Wakano
* [84495aae4c] Alexander Traud -- pjproject_bundled: Repair ./configure
--with-ssl without ARG.
Improvement
Category: Applications/app_page
ASTERISK-27946: dial (API): Storage of dialed target uses
AST_MAX_EXTENSION when it shouldn't
Reported by: Joshua Elson
* [41c1e0b45d] sungtae kim -- dial.c: Removed dial string 80 character
limitation
Category: Core/DNS
ASTERISK-28853: Missing include on FreeBSD
Reported by: Guido Falsi
* [2a7a252ba1] Guido Falsi -- core/dns: Add system include required on
FreeBSD
Category: Core/Dial
ASTERISK-27946: dial (API): Storage of dialed target uses
AST_MAX_EXTENSION when it shouldn't
Reported by: Joshua Elson
* [41c1e0b45d] sungtae kim -- dial.c: Removed dial string 80 character
limitation
Category: Functions/func_volume
ASTERISK-28813: func_volume: Allow decimal numbers as parameter to improve
granularity
Reported by: Jean Aunis - Prescom
* [c23f899254] Jean Aunis -- func_volume: Accept decimal number as
argument
Category: Resources/res_pjsip_session
ASTERISK-28782: Add support for Content-Disposition header in multi-part
INVITES
Reported by: Torrey Searle
* [46be4668e3] Torrey Searle -- res_pjsip_session: implement processing
of Content-Disposition
ASTERISK-28787: res_pjsip_session: Decide more intelligently when to add
video
Reported by: Joshua C. Colp
* [e181cbde63] Joshua C. Colp -- res_pjsip_session: Apply intention
behind requested formats.
----------------------------------------------------------------------
Commits Not Associated with an Issue
[Back to Top]
This is a list of all changes that went into this release that did not
reference a JIRA issue.
+------------------------------------------------------------------------+
| Revision | Author | Summary |
|------------+----------------------+------------------------------------|
| 21286195d5 | Asterisk Development | Update for 17.4.0-rc2 |
| | Team | |
|------------+----------------------+------------------------------------|
| f3eaf2b7d1 | Asterisk Development | Update for 17.4.0-rc1 |
| | Team | |
|------------+----------------------+------------------------------------|
| 3907b81397 | Asterisk Development | Update CHANGES and UPGRADE.txt for |
| | Team | 17.4.0 |
|------------+----------------------+------------------------------------|
| 39f5be81a3 | Alexander Traud | BuildSystem: Only if found LibPRI, |
| | | check its optional parts. |
|------------+----------------------+------------------------------------|
| | | BuildSystem: Only if found |
| 77e2afe8cc | Alexander Traud | external PJProject, check its |
| | | optional parts. |
|------------+----------------------+------------------------------------|
| | | res_rtp_asterisk: iterate all |
| 7a568549ee | Jaco Kroon | local addresses looking to |
| | | populate ICE. |
|------------+----------------------+------------------------------------|
| c3d49c304b | Jaco Kroon | res_pjsip: document legal |
| | | dtls_verify endpoint options. |
|------------+----------------------+------------------------------------|
| 44f921bb13 | Alexander Traud | res_rtp_asterisk: Build without |
| | | PJProject. |
|------------+----------------------+------------------------------------|
| e832fb6f1c | Alexander Traud | _pjsua: Build even with Clang. |
|------------+----------------------+------------------------------------|
| | | Revert "res_config_odbc: Preserve |
| f56e4e73af | Sean Bright | empty strings returned by the |
| | | database" |
|------------+----------------------+------------------------------------|
| a5119e9600 | Jaco Kroon | main/backtrace: binutils-2.34 fix. |
|------------+----------------------+------------------------------------|
| 1b01a6abfd | Jaco Kroon | acl: implement a centralized ACL |
| | | output mechanism for HAs and ACLs. |
|------------+----------------------+------------------------------------|
| 5e24379cf2 | Joshua C. Colp | chan_sip: Send 403 when ACL fails. |
|------------+----------------------+------------------------------------|
| 26c75683bf | Joshua C. Colp | CHANGES: Change md file extension |
| | | to txt. |
|------------+----------------------+------------------------------------|
| ba47752d0d | Jaco Kroon | netsock2: compile fixes. |
|------------+----------------------+------------------------------------|
| 9255a17410 | Kevin Harwell | ast_coredumper: add Asterisk |
| | | information dump |
|------------+----------------------+------------------------------------|
| 6706af0d5b | Jaco Kroon | build: enable building with uClibc |
|------------+----------------------+------------------------------------|
| 9c911b0f9b | Jaco Kroon | build: search from newest to |
| | | oldest for gmime. |
|------------+----------------------+------------------------------------|
| | | res_rtp_asterisk: implement ACL |
| c7c52b8e7a | Jaco Kroon | mechanism for ICE and STUN |
| | | addresses. |
|------------+----------------------+------------------------------------|
| af414ef015 | Jaco Kroon | Update main/backtrace.c to deal |
| | | with changes in binutils 2.34. |
|------------+----------------------+------------------------------------|
| | | chan_vpb: Fix 'catching |
| 31c6a20862 | Sean Bright | polymorphic type ... by value' |
| | | error |
|------------+----------------------+------------------------------------|
| 7a38d5f4e2 | Sean Bright | dns_txt: Add TXT record parsing |
| | | support |
|------------+----------------------+------------------------------------|
| 24f32eb138 | George Joseph | CI: Create generic jenkinsfile |
|------------+----------------------+------------------------------------|
| 6857ba98d5 | Rodrigo RamÃrez | res_rtp_asterisk: Add 'rtp show |
| | Norambuena | settings' cli command |
+------------------------------------------------------------------------+
----------------------------------------------------------------------
Diffstat Results
[Back to Top]
This is a summary of the changes to the source code that went into this
release that was generated using the diffstat utility.
asterisk-17.3.0-summary.html | 160 ---
asterisk-17.3.0-summary.txt | 459 ---------
b/.version | 2
b/CHANGES | 50 +
b/ChangeLog | 942 +++++++++++++++++++-
b/Makefile | 4
b/UPGRADE.txt | 14
b/apps/app_confbridge.c | 7
b/apps/app_dahdiras.c | 6
b/apps/app_getcpeid.c | 1
b/apps/app_mixmonitor.c | 1
b/apps/confbridge/conf_config_parser.c | 13
b/apps/confbridge/include/confbridge.h | 1
b/asterisk-17.4.0-rc2-summary.html | 13
b/asterisk-17.4.0-rc2-summary.txt | 91 +
b/bridges/bridge_native_rtp.c | 14
b/bridges/bridge_simple.c | 14
b/bridges/bridge_softmix.c | 2
b/cdr/cdr_odbc.c | 2
b/channels/chan_pjsip.c | 71 -
b/channels/chan_sip.c | 71 +
b/channels/chan_unistim.c | 4
b/channels/chan_vpb.cc | 2
b/channels/pjsip/dialplan_functions.c | 13
b/configs/samples/confbridge.conf.sample | 3
b/configs/samples/func_odbc.conf.sample | 11
b/configs/samples/indications.conf.sample | 11
b/configs/samples/rtp.conf.sample | 30
b/configure | 661 +++++++-------
b/configure.ac | 190 ++--
b/contrib/scripts/ast_coredumper | 417 ++++++++
b/contrib/scripts/install_prereq | 28
b/funcs/func_aes.c | 4
b/funcs/func_channel.c | 8
b/funcs/func_curl.c | 1
b/funcs/func_volume.c | 12
b/include/asterisk/acl.h | 32
b/include/asterisk/bridge_features.h | 2
b/include/asterisk/dns_internal.h | 26
b/include/asterisk/dns_txt.h | 64 +
b/include/asterisk/frame.h | 8
b/include/asterisk/netsock2.h | 6
b/include/asterisk/stream.h | 2
b/include/asterisk/utils.h | 24
b/main/acl.c | 29
b/main/audiohook.c | 9
b/main/backtrace.c | 9
b/main/bridge.c | 1
b/main/bridge_channel.c | 8
b/main/channel.c | 39
b/main/data_buffer.c | 2
b/main/dial.c | 14
b/main/dns_core.c | 3
b/main/dns_txt.c | 127 ++
b/main/enum.c | 104 +-
b/main/frame.c | 27
b/main/manager.c | 3
b/main/named_acl.c | 9
b/main/stream.c | 8
b/makeopts.in | 4
b/menuselect/configure | 8
b/menuselect/menuselect.c | 2
b/pbx/pbx_dundi.c | 6
b/res/ari/resource_channels.c | 15
b/res/res_config_curl.c | 2
b/res/res_config_odbc.c | 2
b/res/res_pjsip.c | 18
b/res/res_pjsip/pjsip_options.c | 7
b/res/res_pjsip_caller_id.c | 3
b/res/res_pjsip_diversion.c | 1
b/res/res_pjsip_dlg_options.c | 3
b/res/res_pjsip_dtmf_info.c | 1
b/res/res_pjsip_empty_info.c | 1
b/res/res_pjsip_messaging.c | 1
b/res/res_pjsip_nat.c | 1
b/res/res_pjsip_one_touch_record_info.c | 1
b/res/res_pjsip_path.c | 1
b/res/res_pjsip_refer.c | 1
b/res/res_pjsip_rfc3326.c | 1
b/res/res_pjsip_sdp_rtp.c | 70 +
b/res/res_pjsip_session.c | 168 ++-
b/res/res_rtp_asterisk.c | 469 ++++++---
b/tests/CI/universal-asterisk-nongerrit.jenkinsfile | 452 +++++++++
b/tests/test_stasis.c | 2
b/tests/test_utils.c | 6
b/third-party/pjproject/Makefile | 2
b/third-party/pjproject/configure.m4 | 198 ++--
87 files changed, 3766 insertions(+), 1569 deletions(-)

View File

@ -43,6 +43,7 @@
#include "asterisk/bridge_technology.h"
#include "asterisk/frame.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/stream.h"
/*! \brief Internal structure which contains bridged RTP channel hook data */
struct native_rtp_framehook_data {
@ -85,6 +86,28 @@ struct native_rtp_bridge_channel_data {
struct rtp_glue_data glue;
};
/*! \brief Forward declarations */
static int native_rtp_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel);
static void native_rtp_bridge_unsuspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel);
static void native_rtp_bridge_leave(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel);
static void native_rtp_bridge_suspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel);
static int native_rtp_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame);
static int native_rtp_bridge_compatible(struct ast_bridge *bridge);
static void native_rtp_stream_topology_changed(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel);
static struct ast_bridge_technology native_rtp_bridge = {
.name = "native_rtp",
.capabilities = AST_BRIDGE_CAPABILITY_NATIVE,
.preference = AST_BRIDGE_PREFERENCE_BASE_NATIVE,
.join = native_rtp_bridge_join,
.unsuspend = native_rtp_bridge_unsuspend,
.leave = native_rtp_bridge_leave,
.suspend = native_rtp_bridge_suspend,
.write = native_rtp_bridge_write,
.compatible = native_rtp_bridge_compatible,
.stream_topology_changed = native_rtp_stream_topology_changed,
};
static void rtp_glue_data_init(struct rtp_glue_data *glue)
{
glue->cb = NULL;
@ -713,6 +736,8 @@ static int native_rtp_bridge_compatible_check(struct ast_bridge *bridge, struct
framing_inst0, framing_inst1);
return 0;
}
ast_debug(3, "Symmetric ptimes on the two call legs (%u). May be able to native bridge in RTP\n",
framing_inst0);
}
read_ptime0 = ast_format_cap_get_format_framing(cap0, ast_channel_rawreadformat(bc0->chan));
@ -726,6 +751,9 @@ static int native_rtp_bridge_compatible_check(struct ast_bridge *bridge, struct
read_ptime0, write_ptime1, read_ptime1, write_ptime0);
return 0;
}
ast_debug(3, "Bridge '%s': Packetization comparison success between RTP streams (read_ptime0:%d == write_ptime1:%d and read_ptime1:%d == write_ptime0:%d).\n",
bridge->uniqueid,
read_ptime0, write_ptime1, read_ptime1, write_ptime0);
return 1;
}
@ -826,12 +854,134 @@ static void native_rtp_bridge_framehook_detach(struct ast_bridge_channel *bridge
data->hook_data = NULL;
}
static struct ast_stream_topology *native_rtp_request_stream_topology_update(
struct ast_stream_topology *existing_topology,
struct ast_stream_topology *requested_topology)
{
struct ast_stream *stream;
const struct ast_format_cap *audio_formats = NULL;
struct ast_stream_topology *new_topology;
int i;
new_topology = ast_stream_topology_clone(requested_topology);
if (!new_topology) {
return NULL;
}
/* We find an existing stream with negotiated audio formats that we can place into
* any audio streams in the new topology to ensure that negotiation succeeds. Some
* endpoints incorrectly terminate the call if SDP negotiation fails.
*/
for (i = 0; i < ast_stream_topology_get_count(existing_topology); ++i) {
stream = ast_stream_topology_get_stream(existing_topology, i);
if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_AUDIO ||
ast_stream_get_state(stream) == AST_STREAM_STATE_REMOVED) {
continue;
}
audio_formats = ast_stream_get_formats(stream);
break;
}
if (audio_formats) {
for (i = 0; i < ast_stream_topology_get_count(new_topology); ++i) {
struct ast_format_cap *joint;
stream = ast_stream_topology_get_stream(new_topology, i);
if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_AUDIO ||
ast_stream_get_state(stream) == AST_STREAM_STATE_REMOVED) {
continue;
}
joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!joint) {
continue;
}
ast_format_cap_append_from_cap(joint, ast_stream_get_formats(stream),
AST_MEDIA_TYPE_AUDIO);
ast_format_cap_append_from_cap(joint, audio_formats, AST_MEDIA_TYPE_AUDIO);
ast_stream_set_formats(stream, joint);
ao2_ref(joint, -1);
}
}
for (i = 0; i < ast_stream_topology_get_count(new_topology); ++i) {
stream = ast_stream_topology_get_stream(new_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 renegotiating a remote
* party 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.
*/
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);
}
}
return new_topology;
}
static void native_rtp_stream_topology_changed(struct ast_bridge *bridge,
struct ast_bridge_channel *bridge_channel)
{
struct ast_channel *c0 = bridge_channel->chan;
struct ast_channel *c1 = AST_LIST_FIRST(&bridge->channels)->chan;
struct ast_stream_topology *req_top;
struct ast_stream_topology *existing_top;
struct ast_stream_topology *new_top;
ast_bridge_channel_stream_map(bridge_channel);
if (ast_channel_get_stream_topology_change_source(bridge_channel->chan)
== &native_rtp_bridge) {
return;
}
if (c0 == c1) {
c1 = AST_LIST_LAST(&bridge->channels)->chan;
}
if (c0 == c1) {
return;
}
/* If a party renegotiates we want to renegotiate their counterpart to a matching
* topology.
*/
ast_channel_lock_both(c0, c1);
req_top = ast_channel_get_stream_topology(c0);
existing_top = ast_channel_get_stream_topology(c1);
new_top = native_rtp_request_stream_topology_update(existing_top, req_top);
ast_channel_unlock(c0);
ast_channel_unlock(c1);
if (!new_top) {
/* Failure. We'll just have to live with the current topology. */
return;
}
ast_channel_request_stream_topology_change(c1, new_top, &native_rtp_bridge);
ast_stream_topology_free(new_top);
}
/*!
* \internal
* \brief Called by the bridge core 'join' callback for each channel joining he bridge
*/
static int native_rtp_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
{
struct ast_stream_topology *req_top;
struct ast_stream_topology *existing_top;
struct ast_stream_topology *new_top;
struct ast_channel *c0 = AST_LIST_FIRST(&bridge->channels)->chan;
struct ast_channel *c1 = AST_LIST_LAST(&bridge->channels)->chan;
ast_debug(2, "Bridge '%s'. Channel '%s' is joining bridge tech\n",
bridge->uniqueid, ast_channel_name(bridge_channel->chan));
@ -853,6 +1003,27 @@ static int native_rtp_bridge_join(struct ast_bridge *bridge, struct ast_bridge_c
return -1;
}
if (c0 != c1) {
/* When both channels are joined we want to try to improve the experience by
* raising the number of streams so they match.
*/
ast_channel_lock_both(c0, c1);
req_top = ast_channel_get_stream_topology(c0);
existing_top = ast_channel_get_stream_topology(c1);
if (ast_stream_topology_get_count(req_top) < ast_stream_topology_get_count(existing_top)) {
SWAP(req_top, existing_top);
SWAP(c0, c1);
}
new_top = native_rtp_request_stream_topology_update(existing_top, req_top);
ast_channel_unlock(c0);
ast_channel_unlock(c1);
if (new_top) {
ast_channel_request_stream_topology_change(c1, new_top, &native_rtp_bridge);
ast_stream_topology_free(new_top);
}
}
native_rtp_bridge_start(bridge, NULL);
return 0;
}
@ -934,18 +1105,6 @@ static int native_rtp_bridge_write(struct ast_bridge *bridge, struct ast_bridge_
return defer;
}
static struct ast_bridge_technology native_rtp_bridge = {
.name = "native_rtp",
.capabilities = AST_BRIDGE_CAPABILITY_NATIVE,
.preference = AST_BRIDGE_PREFERENCE_BASE_NATIVE,
.join = native_rtp_bridge_join,
.unsuspend = native_rtp_bridge_unsuspend,
.leave = native_rtp_bridge_leave,
.suspend = native_rtp_bridge_suspend,
.write = native_rtp_bridge_write,
.compatible = native_rtp_bridge_compatible,
};
static int unload_module(void)
{
ast_bridge_technology_unregister(&native_rtp_bridge);

View File

@ -46,9 +46,96 @@
static void simple_bridge_stream_topology_changed(struct ast_bridge *bridge,
struct ast_bridge_channel *bridge_channel);
static int simple_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel);
static int simple_bridge_write(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame);
static struct ast_bridge_technology simple_bridge = {
.name = "simple_bridge",
.capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX,
.preference = AST_BRIDGE_PREFERENCE_BASE_1TO1MIX,
.join = simple_bridge_join,
.write = simple_bridge_write,
.stream_topology_changed = simple_bridge_stream_topology_changed,
};
static struct ast_stream_topology *simple_bridge_request_stream_topology_update(
struct ast_stream_topology *existing_topology,
struct ast_stream_topology *requested_topology)
{
struct ast_stream *stream;
const struct ast_format_cap *audio_formats = NULL;
struct ast_stream_topology *new_topology;
int i;
new_topology = ast_stream_topology_clone(requested_topology);
if (!new_topology) {
return NULL;
}
/* We find an existing stream with negotiated audio formats that we can place into
* any audio streams in the new topology to ensure that negotiation succeeds. Some
* endpoints incorrectly terminate the call if SDP negotiation fails.
*/
for (i = 0; i < ast_stream_topology_get_count(existing_topology); ++i) {
stream = ast_stream_topology_get_stream(existing_topology, i);
if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_AUDIO ||
ast_stream_get_state(stream) == AST_STREAM_STATE_REMOVED) {
continue;
}
audio_formats = ast_stream_get_formats(stream);
break;
}
if (audio_formats) {
for (i = 0; i < ast_stream_topology_get_count(new_topology); ++i) {
struct ast_format_cap *joint;
stream = ast_stream_topology_get_stream(new_topology, i);
if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_AUDIO ||
ast_stream_get_state(stream) == AST_STREAM_STATE_REMOVED) {
continue;
}
joint = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!joint) {
continue;
}
ast_format_cap_append_from_cap(joint, ast_stream_get_formats(stream),
AST_MEDIA_TYPE_AUDIO);
ast_format_cap_append_from_cap(joint, audio_formats, AST_MEDIA_TYPE_AUDIO);
ast_stream_set_formats(stream, joint);
ao2_ref(joint, -1);
}
}
for (i = 0; i < ast_stream_topology_get_count(new_topology); ++i) {
stream = ast_stream_topology_get_stream(new_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 renegotiating a remote
* party 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.
*/
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);
}
}
return new_topology;
}
static int simple_bridge_join(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
{
struct ast_stream_topology *req_top;
struct ast_stream_topology *existing_top;
struct ast_stream_topology *new_top;
struct ast_channel *c0 = AST_LIST_FIRST(&bridge->channels)->chan;
struct ast_channel *c1 = AST_LIST_LAST(&bridge->channels)->chan;
@ -64,8 +151,28 @@ static int simple_bridge_join(struct ast_bridge *bridge, struct ast_bridge_chann
return -1;
}
/* Align stream topologies */
simple_bridge_stream_topology_changed(bridge, NULL);
/* When both channels are joined we want to try to improve the experience by
* raising the number of streams so they match.
*/
ast_channel_lock_both(c0, c1);
req_top = ast_channel_get_stream_topology(c0);
existing_top = ast_channel_get_stream_topology(c1);
if (ast_stream_topology_get_count(req_top) < ast_stream_topology_get_count(existing_top)) {
SWAP(req_top, existing_top);
SWAP(c0, c1);
}
new_top = simple_bridge_request_stream_topology_update(existing_top, req_top);
ast_channel_unlock(c0);
ast_channel_unlock(c1);
if (!new_top) {
/* Failure. We'll just have to live with the current topology. */
return 0;
}
ast_channel_request_stream_topology_change(c1, new_top, &simple_bridge);
ast_stream_topology_free(new_top);
return 0;
}
@ -104,105 +211,46 @@ static int simple_bridge_write(struct ast_bridge *bridge, struct ast_bridge_chan
return defer;
}
static struct ast_bridge_technology simple_bridge = {
.name = "simple_bridge",
.capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX,
.preference = AST_BRIDGE_PREFERENCE_BASE_1TO1MIX,
.join = simple_bridge_join,
.write = simple_bridge_write,
.stream_topology_changed = simple_bridge_stream_topology_changed,
};
static struct ast_stream_topology *simple_bridge_request_stream_topology_update(
struct ast_stream_topology *existing_topology,
struct ast_stream_topology *requested_topology)
{
struct ast_stream *stream;
struct ast_format_cap *audio_formats = NULL;
struct ast_stream_topology *new_topology;
int i;
new_topology = ast_stream_topology_clone(requested_topology);
if (!new_topology) {
return NULL;
}
/* We find an existing stream with negotiated audio formats that we can place into
* any audio streams in the new topology to ensure that negotiation succeeds. Some
* endpoints incorrectly terminate the call if SDP negotiation fails.
*/
for (i = 0; i < ast_stream_topology_get_count(existing_topology); ++i) {
stream = ast_stream_topology_get_stream(existing_topology, i);
if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_AUDIO ||
ast_stream_get_state(stream) == AST_STREAM_STATE_REMOVED) {
continue;
}
audio_formats = ast_stream_get_formats(stream);
break;
}
if (audio_formats) {
for (i = 0; i < ast_stream_topology_get_count(new_topology); ++i) {
stream = ast_stream_topology_get_stream(new_topology, i);
if (ast_stream_get_type(stream) != AST_MEDIA_TYPE_AUDIO ||
ast_stream_get_state(stream) == AST_STREAM_STATE_REMOVED) {
continue;
}
ast_format_cap_append_from_cap(ast_stream_get_formats(stream), audio_formats,
AST_MEDIA_TYPE_AUDIO);
}
}
return new_topology;
}
static void simple_bridge_stream_topology_changed(struct ast_bridge *bridge,
struct ast_bridge_channel *bridge_channel)
{
struct ast_channel *req_chan;
struct ast_channel *existing_chan;
struct ast_channel *c0 = bridge_channel->chan;
struct ast_channel *c1 = AST_LIST_FIRST(&bridge->channels)->chan;
struct ast_stream_topology *req_top;
struct ast_stream_topology *existing_top;
struct ast_stream_topology *new_top;
if (bridge_channel) {
ast_bridge_channel_stream_map(bridge_channel);
ast_bridge_channel_stream_map(bridge_channel);
if (ast_channel_get_stream_topology_change_source(bridge_channel->chan)
== &simple_bridge) {
return;
}
}
req_chan = AST_LIST_FIRST(&bridge->channels)->chan;
existing_chan = AST_LIST_LAST(&bridge->channels)->chan;
if (req_chan == existing_chan) {
/* Wait until both channels are in the bridge to align topologies. */
if (ast_channel_get_stream_topology_change_source(bridge_channel->chan)
== &simple_bridge) {
return;
}
/* Align topologies according to size or first channel to join */
ast_channel_lock_both(req_chan, existing_chan);
req_top = ast_channel_get_stream_topology(req_chan);
existing_top = ast_channel_get_stream_topology(existing_chan);
if (ast_stream_topology_get_count(req_top) < ast_stream_topology_get_count(existing_top)) {
SWAP(req_top, existing_top);
SWAP(req_chan, existing_chan);
if (c0 == c1) {
c1 = AST_LIST_LAST(&bridge->channels)->chan;
}
if (c0 == c1) {
return;
}
/* If a party renegotiates we want to renegotiate their counterpart to a matching
* topology.
*/
ast_channel_lock_both(c0, c1);
req_top = ast_channel_get_stream_topology(c0);
existing_top = ast_channel_get_stream_topology(c1);
new_top = simple_bridge_request_stream_topology_update(existing_top, req_top);
ast_channel_unlock(req_chan);
ast_channel_unlock(existing_chan);
ast_channel_unlock(c0);
ast_channel_unlock(c1);
if (!new_top) {
/* Failure. We'll just have to live with the current topology. */
return;
}
ast_channel_request_stream_topology_change(existing_chan, new_top, &simple_bridge);
ast_channel_request_stream_topology_change(c1, new_top, &simple_bridge);
ast_stream_topology_free(new_top);
}

View File

@ -88,12 +88,16 @@ struct softmix_stats {
unsigned int num_channels[16];
/*! The number of channels above the internal sample rate */
unsigned int num_above_internal_rate;
/*! The number of channels above the maximum sample rate */
unsigned int num_above_maximum_rate;
/*! The number of channels at the internal sample rate */
unsigned int num_at_internal_rate;
/*! The absolute highest sample rate preferred by any channel in the bridge */
unsigned int highest_supported_rate;
/*! Is the sample rate locked by the bridge, if so what is that rate.*/
unsigned int locked_rate;
/*! The maximum sample rate the bridge may use */
unsigned int maximum_rate;
};
struct softmix_translate_helper_entry {
@ -458,12 +462,12 @@ static int is_video_source(const struct ast_stream *stream)
*
* \param stream The stream to test
* \param source_channel_name The name of a source video channel to match
* \param source_stream_name The name of the source video stream to match
* \param source_channel_stream_position The position of the video on the source channel
* \retval 1 The stream is a video destination stream
* \retval 0 The stream is not a video destination stream
*/
static int is_video_dest(const struct ast_stream *stream, const char *source_channel_name,
const char *source_stream_name)
int source_channel_stream_position)
{
char *dest_video_name;
size_t dest_video_name_len;
@ -476,17 +480,17 @@ static int is_video_dest(const struct ast_stream *stream, const char *source_cha
dest_video_name_len = SOFTBRIDGE_VIDEO_DEST_LEN + 1;
if (!ast_strlen_zero(source_channel_name)) {
dest_video_name_len += strlen(source_channel_name) + 1;
if (!ast_strlen_zero(source_stream_name)) {
dest_video_name_len += strlen(source_stream_name) + 1;
if (source_channel_stream_position != -1) {
dest_video_name_len += 11;
}
dest_video_name = ast_alloca(dest_video_name_len);
if (!ast_strlen_zero(source_stream_name)) {
/* We are looking for an exact stream name */
snprintf(dest_video_name, dest_video_name_len, "%s%c%s%c%s",
if (source_channel_stream_position != -1) {
/* We are looking for an exact stream position */
snprintf(dest_video_name, dest_video_name_len, "%s%c%s%c%d",
SOFTBRIDGE_VIDEO_DEST_PREFIX, SOFTBRIDGE_VIDEO_DEST_SEPARATOR,
source_channel_name, SOFTBRIDGE_VIDEO_DEST_SEPARATOR,
source_stream_name);
source_channel_stream_position);
return !strcmp(ast_stream_get_name(stream), dest_video_name);
}
snprintf(dest_video_name, dest_video_name_len, "%s%c%s",
@ -499,46 +503,62 @@ static int is_video_dest(const struct ast_stream *stream, const char *source_cha
return !strncmp(ast_stream_get_name(stream), dest_video_name, dest_video_name_len - 1);
}
static int append_source_stream(struct ast_stream_topology *dest,
const char *channel_name, const char *sdp_label,
struct ast_stream *stream, int index)
{
char *stream_clone_name = NULL;
struct ast_stream *stream_clone;
/* We use the stream topology index for the stream to uniquely identify and recognize it.
* This is guaranteed to remain the same across renegotiation of the source channel and
* ensures that the stream name is unique.
*/
if (ast_asprintf(&stream_clone_name, "%s%c%s%c%d", SOFTBRIDGE_VIDEO_DEST_PREFIX,
SOFTBRIDGE_VIDEO_DEST_SEPARATOR, channel_name, SOFTBRIDGE_VIDEO_DEST_SEPARATOR,
index) < 0) {
return -1;
}
stream_clone = ast_stream_clone(stream, stream_clone_name);
ast_free(stream_clone_name);
if (!stream_clone) {
return -1;
}
/* Sends an "a:label" attribute in the SDP for participant event correlation */
if (!ast_strlen_zero(sdp_label)) {
ast_stream_set_metadata(stream_clone, "SDP:LABEL", sdp_label);
}
/* We will be sending them a stream and not expecting anything in return */
ast_stream_set_state(stream_clone, AST_STREAM_STATE_SENDONLY);
if (ast_stream_topology_append_stream(dest, stream_clone) < 0) {
ast_stream_free(stream_clone);
return -1;
}
return 0;
}
static int append_source_streams(struct ast_stream_topology *dest,
const char *channel_name, const char *sdp_label,
const struct ast_stream_topology *source)
{
int i;
const char *stream_identify;
for (i = 0; i < ast_stream_topology_get_count(source); ++i) {
struct ast_stream *stream;
struct ast_stream *stream_clone;
char *stream_clone_name = NULL;
stream = ast_stream_topology_get_stream(source, i);
if (!is_video_source(stream)) {
continue;
}
stream_identify = ast_stream_get_metadata(stream, "MSID:LABEL");
if (!stream_identify) {
stream_identify = ast_stream_get_name(stream);
}
if (ast_asprintf(&stream_clone_name, "%s_%s_%s", SOFTBRIDGE_VIDEO_DEST_PREFIX,
channel_name, stream_identify) < 0) {
return -1;
}
stream_clone = ast_stream_clone(stream, stream_clone_name);
ast_free(stream_clone_name);
if (!stream_clone) {
return -1;
}
/* Sends an "a:label" attribute in the SDP for participant event correlation */
if (!ast_strlen_zero(sdp_label)) {
ast_stream_set_metadata(stream_clone, "SDP:LABEL", sdp_label);
}
if (ast_stream_topology_append_stream(dest, stream_clone) < 0) {
ast_stream_free(stream_clone);
if (append_source_stream(dest, channel_name, sdp_label, stream, i)) {
return -1;
}
}
@ -726,6 +746,13 @@ static int softmix_bridge_join(struct ast_bridge *bridge, struct ast_bridge_chan
sfu_topologies_on_join(bridge, bridge_channel);
}
/* Complete any active hold before entering, or transitioning to softmix. */
if (ast_channel_hold_state(bridge_channel->chan) == AST_CONTROL_HOLD) {
ast_debug(1, "Channel %s simulating UNHOLD for bridge softmix join.\n",
ast_channel_name(bridge_channel->chan));
ast_indicate(bridge_channel->chan, AST_CONTROL_UNHOLD);
}
softmix_poke_thread(softmix_data);
return 0;
}
@ -741,7 +768,7 @@ static int remove_destination_streams(struct ast_stream_topology *topology,
stream = ast_stream_topology_get_stream(topology, i);
if (is_video_dest(stream, channel_name, NULL)) {
if (is_video_dest(stream, channel_name, -1)) {
ast_stream_set_state(stream, AST_STREAM_STATE_REMOVED);
stream_removed = 1;
}
@ -1534,7 +1561,9 @@ static void gather_softmix_stats(struct softmix_stats *stats,
if (stats->highest_supported_rate < channel_native_rate) {
stats->highest_supported_rate = channel_native_rate;
}
if (softmix_data->internal_rate < channel_native_rate) {
if (stats->maximum_rate && stats->maximum_rate < channel_native_rate) {
stats->num_above_maximum_rate++;
} else if (softmix_data->internal_rate < channel_native_rate) {
int i;
for (i = 0; i < ARRAY_LEN(stats->sample_rates); i++) {
@ -1586,6 +1615,15 @@ static unsigned int analyse_softmix_stats(struct softmix_stats *stats,
softmix_data->internal_rate = stats->locked_rate;
return 1;
}
} else if (stats->num_above_maximum_rate) {
/* if the bridge has a maximum rate set and channels are above it only
* update if it differs from the current rate we are using. */
if (softmix_data->internal_rate != stats->maximum_rate) {
ast_debug(1, "Locking at new maximum rate. Bridge changed from %u to %u.\n",
softmix_data->internal_rate, stats->maximum_rate);
softmix_data->internal_rate = stats->maximum_rate;
return 1;
}
} else if (stats->num_above_internal_rate >= 2) {
/* the highest rate is just used as a starting point */
unsigned int best_rate = stats->highest_supported_rate;
@ -1768,6 +1806,7 @@ static int softmix_mixing_loop(struct ast_bridge *bridge)
if (!stat_iteration_counter) {
memset(&stats, 0, sizeof(stats));
stats.locked_rate = bridge->softmix.internal_sample_rate;
stats.maximum_rate = bridge->softmix.maximum_sample_rate;
}
/* If the sample rate has changed, update the translator helper */
@ -2112,13 +2151,13 @@ static void softmix_bridge_destroy(struct ast_bridge *bridge)
/*!
* \brief Map a source stream to all of its destination streams.
*
* \param source_stream_name Name of the source stream
* \param source_channel_name Name of channel where the source stream originates
* \param bridge_stream_position The slot in the bridge where source video will come from
* \param participants The bridge_channels in the bridge
* \param source_channel_stream_position The position of the stream on the source channel
*/
static void map_source_to_destinations(const char *source_stream_name, const char *source_channel_name,
size_t bridge_stream_position, struct ast_bridge_channels_list *participants)
static void map_source_to_destinations(const char *source_channel_name,
size_t bridge_stream_position, struct ast_bridge_channels_list *participants, int source_channel_stream_position)
{
struct ast_bridge_channel *participant;
@ -2138,7 +2177,7 @@ static void map_source_to_destinations(const char *source_stream_name, const cha
struct ast_stream *stream;
stream = ast_stream_topology_get_stream(topology, i);
if (is_video_dest(stream, source_channel_name, source_stream_name)) {
if (is_video_dest(stream, source_channel_name, source_channel_stream_position)) {
struct softmix_channel *sc = participant->tech_pvt;
AST_VECTOR_REPLACE(&participant->stream_map.to_channel, bridge_stream_position, i);
@ -2205,6 +2244,137 @@ static void remb_enable_collection(struct ast_bridge *bridge, struct ast_bridge_
}
}
static void softmix_bridge_stream_sources_update(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel,
struct softmix_channel *sc)
{
int index;
struct ast_stream_topology *old_topology = sc->topology;
struct ast_stream_topology *new_topology = ast_channel_get_stream_topology(bridge_channel->chan);
int removed_streams[MAX(ast_stream_topology_get_count(sc->topology), ast_stream_topology_get_count(new_topology))];
size_t removed_streams_count = 0;
struct ast_stream_topology *added_streams;
struct ast_bridge_channels_list *participants = &bridge->channels;
struct ast_bridge_channel *participant;
added_streams = ast_stream_topology_alloc();
if (!added_streams) {
return;
}
/* We go through the old topology comparing it to the new topology to determine what streams
* changed state. A state transition can result in the stream being considered a new source
* (for example it was removed and is now present) or being removed (a stream became inactive).
* Added streams are copied into a topology and added to each other participant while for
* removed streams we merely store their position and mark them as removed later.
*/
for (index = 0; index < ast_stream_topology_get_count(sc->topology) && index < ast_stream_topology_get_count(new_topology); ++index) {
struct ast_stream *old_stream = ast_stream_topology_get_stream(sc->topology, index);
struct ast_stream *new_stream = ast_stream_topology_get_stream(new_topology, index);
/* Ignore all streams that don't carry video and streams that are strictly outgoing destination streams */
if ((ast_stream_get_type(old_stream) != AST_MEDIA_TYPE_VIDEO && ast_stream_get_type(new_stream) != AST_MEDIA_TYPE_VIDEO) ||
!strncmp(ast_stream_get_name(old_stream), SOFTBRIDGE_VIDEO_DEST_PREFIX,
SOFTBRIDGE_VIDEO_DEST_LEN)) {
continue;
}
if (ast_stream_get_type(old_stream) == AST_MEDIA_TYPE_VIDEO && ast_stream_get_type(new_stream) != AST_MEDIA_TYPE_VIDEO) {
/* If a stream renegotiates from video to non-video then we need to remove it as a source */
removed_streams[removed_streams_count++] = index;
} else if (ast_stream_get_type(old_stream) != AST_MEDIA_TYPE_VIDEO && ast_stream_get_type(new_stream) == AST_MEDIA_TYPE_VIDEO) {
if (ast_stream_get_state(new_stream) != AST_STREAM_STATE_REMOVED) {
/* If a stream renegotiates from non-video to video in a non-removed state we need to add it as a source */
if (append_source_stream(added_streams, ast_channel_name(bridge_channel->chan),
bridge->softmix.send_sdp_label ? ast_channel_uniqueid(bridge_channel->chan) : NULL,
new_stream, index)) {
goto cleanup;
}
}
} else if (ast_stream_get_state(old_stream) != AST_STREAM_STATE_REMOVED &&
ast_stream_get_state(new_stream) != AST_STREAM_STATE_SENDRECV && ast_stream_get_state(new_stream) != AST_STREAM_STATE_RECVONLY) {
/* If a stream renegotiates and is removed then we remove it */
removed_streams[removed_streams_count++] = index;
} else if (ast_stream_get_state(old_stream) == AST_STREAM_STATE_REMOVED &&
ast_stream_get_state(new_stream) != AST_STREAM_STATE_INACTIVE && ast_stream_get_state(new_stream) != AST_STREAM_STATE_SENDONLY &&
ast_stream_get_state(new_stream) != AST_STREAM_STATE_REMOVED) {
/* If a stream renegotiates and is added then we add it */
if (append_source_stream(added_streams, ast_channel_name(bridge_channel->chan),
bridge->softmix.send_sdp_label ? ast_channel_uniqueid(bridge_channel->chan) : NULL,
new_stream, index)) {
goto cleanup;
}
}
}
/* Any newly added streams that did not take the position of a removed stream
* will be present at the end of the new topology. Since streams are never
* removed from the topology but merely marked as removed we can pick up where we
* left off when comparing the old and new topologies.
*/
for (; index < ast_stream_topology_get_count(new_topology); ++index) {
struct ast_stream *stream = ast_stream_topology_get_stream(new_topology, index);
if (!is_video_source(stream)) {
continue;
}
if (append_source_stream(added_streams, ast_channel_name(bridge_channel->chan),
bridge->softmix.send_sdp_label ? ast_channel_uniqueid(bridge_channel->chan) : NULL,
stream, index)) {
goto cleanup;
}
}
/* We always update the stored topology if we can to reflect what is currently negotiated */
sc->topology = ast_stream_topology_clone(new_topology);
if (!sc->topology) {
sc->topology = old_topology;
} else {
ast_stream_topology_free(old_topology);
}
/* If there are no removed sources and no added sources we don't need to renegotiate the
* other participants.
*/
if (!removed_streams_count && !ast_stream_topology_get_count(added_streams)) {
goto cleanup;
}
/* Go through each participant adding in the new streams and removing the old ones */
AST_LIST_TRAVERSE(participants, participant, entry) {
if (participant == bridge_channel) {
continue;
}
sc = participant->tech_pvt;
/* We add in all the new streams first so that they do not take the place
* of any of our removed streams, allowing the remote side to reset the state
* for each removed stream. */
if (append_all_streams(sc->topology, added_streams)) {
goto cleanup;
}
/* Then we go through and remove any ones that were removed */
for (index = 0; removed_streams_count && index < ast_stream_topology_get_count(sc->topology); ++index) {
struct ast_stream *stream = ast_stream_topology_get_stream(sc->topology, index);
int removed_stream;
for (removed_stream = 0; removed_stream < removed_streams_count; ++removed_stream) {
if (is_video_dest(stream, ast_channel_name(bridge_channel->chan), removed_streams[removed_stream])) {
ast_stream_set_state(stream, AST_STREAM_STATE_REMOVED);
}
}
}
ast_channel_request_stream_topology_change(participant->chan, sc->topology, NULL);
}
cleanup:
ast_stream_topology_free(added_streams);
}
/*!
* \brief stream_topology_changed callback
*
@ -2218,7 +2388,7 @@ static void remb_enable_collection(struct ast_bridge *bridge, struct ast_bridge_
static void softmix_bridge_stream_topology_changed(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
{
struct softmix_bridge_data *softmix_data = bridge->tech_pvt;
struct softmix_channel *sc;
struct softmix_channel *sc = bridge_channel->tech_pvt;
struct ast_bridge_channel *participant;
struct ast_vector_int media_types;
int nths[AST_MEDIA_TYPE_END] = {0};
@ -2235,6 +2405,10 @@ static void softmix_bridge_stream_topology_changed(struct ast_bridge *bridge, st
break;
}
ast_channel_lock(bridge_channel->chan);
softmix_bridge_stream_sources_update(bridge, bridge_channel, sc);
ast_channel_unlock(bridge_channel->chan);
AST_VECTOR_INIT(&media_types, AST_MEDIA_TYPE_END);
/* The bridge stream identifiers may change, so reset the mapping for them.
@ -2284,7 +2458,6 @@ static void softmix_bridge_stream_topology_changed(struct ast_bridge *bridge, st
for (i = 0; i < ast_stream_topology_get_count(topology); ++i) {
struct ast_stream *stream = ast_stream_topology_get_stream(topology, i);
const char *stream_identify;
if (is_video_source(stream)) {
AST_VECTOR_APPEND(&media_types, AST_MEDIA_TYPE_VIDEO);
@ -2302,12 +2475,8 @@ static void softmix_bridge_stream_topology_changed(struct ast_bridge *bridge, st
ast_channel_unlock(participant->chan);
ast_bridge_channel_unlock(participant);
stream_identify = ast_stream_get_metadata(stream, "MSID:LABEL");
if (!stream_identify) {
stream_identify = ast_stream_get_name(stream);
}
map_source_to_destinations(stream_identify, ast_channel_name(participant->chan),
AST_VECTOR_SIZE(&media_types) - 1, &bridge->channels);
map_source_to_destinations(ast_channel_name(participant->chan),
AST_VECTOR_SIZE(&media_types) - 1, &bridge->channels, i);
ast_bridge_channel_lock(participant);
ast_channel_lock(participant->chan);
} else if (ast_stream_get_type(stream) == AST_MEDIA_TYPE_VIDEO) {
@ -2406,7 +2575,7 @@ fail:
static int validate_stream(struct ast_test *test, struct ast_stream *stream,
const struct stream_parameters *params)
{
struct ast_format_cap *stream_caps;
const struct ast_format_cap *stream_caps;
struct ast_format_cap *params_caps;
if (ast_stream_get_type(stream) != params->type) {
@ -2472,10 +2641,10 @@ AST_TEST_DEFINE(sfu_append_source_streams)
{ "alice_video", "vp8", AST_MEDIA_TYPE_VIDEO, },
};
static const struct stream_parameters alice_dest_stream = {
"softbridge_dest_PJSIP/Bob-00000001_bob_video", "h264,vp8", AST_MEDIA_TYPE_VIDEO,
"softbridge_dest_PJSIP/Bob-00000001_1", "h264,vp8", AST_MEDIA_TYPE_VIDEO,
};
static const struct stream_parameters bob_dest_stream = {
"softbridge_dest_PJSIP/Alice-00000000_alice_video", "vp8", AST_MEDIA_TYPE_VIDEO,
"softbridge_dest_PJSIP/Alice-00000000_1", "vp8", AST_MEDIA_TYPE_VIDEO,
};
struct ast_stream_topology *topology_alice = NULL;
struct ast_stream_topology *topology_bob = NULL;
@ -2622,7 +2791,7 @@ AST_TEST_DEFINE(sfu_remove_destination_streams)
goto end;
}
if (is_video_dest(actual, removal_results[i].channel_name, NULL) &&
if (is_video_dest(actual, removal_results[i].channel_name, -1) &&
ast_stream_get_state(actual) != AST_STREAM_STATE_REMOVED) {
ast_test_status_update(test, "Removed stream %s does not have a state of removed\n", ast_stream_get_name(actual));
goto end;

View File

@ -328,5 +328,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "ODBC CDR Backend",
.unload = unload_module,
.reload = reload,
.load_pri = AST_MODPRI_CDR_DRIVER,
.requires = "cdr",
.requires = "cdr,res_odbc",
);

View File

@ -707,7 +707,7 @@ static int config_module(int reload)
schemaname = ast_alloca(strlen(tmp_schemaname) * 2 + 1);
PQescapeStringConn(conn, schemaname, tmp_schemaname, strlen(tmp_schemaname), NULL);
snprintf(sqlcmd, sizeof(sqlcmd), "SELECT a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc, a.atttypmod FROM (((pg_catalog.pg_class c INNER JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace AND c.relname = '%s' AND n.nspname = %s%s%s) INNER JOIN pg_catalog.pg_attribute a ON (NOT a.attisdropped) AND a.attnum > 0 AND a.attrelid = c.oid) INNER JOIN pg_catalog.pg_type t ON t.oid = a.atttypid) LEFT OUTER JOIN pg_attrdef d ON a.atthasdef AND d.adrelid = a.attrelid AND d.adnum = a.attnum ORDER BY n.nspname, c.relname, attnum",
snprintf(sqlcmd, sizeof(sqlcmd), "SELECT a.attname, t.typname, a.attlen, a.attnotnull, pg_catalog.pg_get_expr(d.adbin, d.adrelid) adsrc, a.atttypmod FROM (((pg_catalog.pg_class c INNER JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace AND c.relname = '%s' AND n.nspname = %s%s%s) INNER JOIN pg_catalog.pg_attribute a ON (NOT a.attisdropped) AND a.attnum > 0 AND a.attrelid = c.oid) INNER JOIN pg_catalog.pg_type t ON t.oid = a.atttypid) LEFT OUTER JOIN pg_attrdef d ON a.atthasdef AND d.adrelid = a.attrelid AND d.adnum = a.attnum ORDER BY n.nspname, c.relname, attnum",
tablename,
ast_strlen_zero(schemaname) ? "" : "'", ast_strlen_zero(schemaname) ? "current_schema()" : schemaname, ast_strlen_zero(schemaname) ? "" : "'");
} else {

View File

@ -597,7 +597,7 @@ static int process_my_load_module(struct ast_config *cfg)
PQescapeStringConn(conn, schemaname, schema, lenschema, NULL);
snprintf(sqlcmd, sizeof(sqlcmd),
"SELECT a.attname, t.typname, a.attlen, a.attnotnull, d.adsrc, a.atttypmod "
"SELECT a.attname, t.typname, a.attlen, a.attnotnull, pg_catalog.pg_get_expr(d.adbin, d.adrelid) adsrc, a.atttypmod "
"FROM (((pg_catalog.pg_class c INNER JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace "
"AND c.relname = '%s' AND n.nspname = %s%s%s) "
"INNER JOIN pg_catalog.pg_attribute a ON ("

View File

@ -4382,7 +4382,7 @@ static char *alarm2str(int alm)
static const char *event2str(int event)
{
static char buf[256];
if ((event < (ARRAY_LEN(events))) && (event > -1))
if ((event > -1) && (event < (ARRAY_LEN(events))) )
return events[event];
sprintf(buf, "Event %d", event); /* safe */
return buf;
@ -9847,7 +9847,7 @@ static void *analog_ss_thread(void *data)
/* If starting a threeway call, never timeout on the first digit so someone
can use flash-hook as a "hold" feature */
if (p->subs[SUB_THREEWAY].owner)
timeout = 999999;
timeout = INT_MAX;
while (len < AST_MAX_EXTENSION-1) {
int is_exten_parking = 0;
@ -12770,8 +12770,10 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
struct ast_variable *v, *tmpvar;
for (v = conf->chan.vars ; v ; v = v->next) {
if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
tmpvar->next = tmp->vars;
tmp->vars = tmpvar;
if (ast_variable_list_replace(&tmp->vars, tmpvar)) {
tmpvar->next = tmp->vars;
tmp->vars = tmpvar;
}
}
}
}
@ -15158,10 +15160,12 @@ static void mfcr2_show_links_of(struct ast_cli_args *a, struct r2links *list_hea
int channo;
int prev_channo;
x++;
switch (mfcr2->r2master) {
case 0L: thread_status = "zero"; break;
case AST_PTHREADT_NULL: thread_status = "none"; break;
default: thread_status = "created"; break;
if (mfcr2->r2master == 0L) {
thread_status = "zero";
} else if (mfcr2->r2master == AST_PTHREADT_NULL) {
thread_status = "none";
} else {
thread_status = "created";
}
snprintf(index, sizeof(index), "%d", mfcr2->index);
snprintf(live_chans_str, sizeof(live_chans_str), "%d", mfcr2->live_chans);
@ -15170,7 +15174,7 @@ static void mfcr2_show_links_of(struct ast_cli_args *a, struct r2links *list_hea
inside_range = 0;
len = 0;
/* Prepare nice string in channel_list[] */
for (i = 0; i < mfcr2->numchans; i++) {
for (i = 0; i < mfcr2->numchans && len < sizeof(channel_list) - 1; i++) {
struct dahdi_pvt *p = mfcr2->pvts[i];
if (!p) {
continue;
@ -18128,13 +18132,17 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
} else if (!strcasecmp(v->name, "namedpickupgroup")) {
confp->chan.named_pickupgroups = ast_get_namedgroups(v->value);
} else if (!strcasecmp(v->name, "setvar")) {
char *varname = ast_strdupa(v->value), *varval = NULL;
struct ast_variable *tmpvar;
if (varname && (varval = strchr(varname, '='))) {
*varval++ = '\0';
if ((tmpvar = ast_variable_new(varname, varval, ""))) {
tmpvar->next = confp->chan.vars;
confp->chan.vars = tmpvar;
if (v->value) {
char *varval = NULL;
struct ast_variable *tmpvar;
char varname[strlen(v->value) + 1];
strcpy(varname, v->value); /* safe */
if ((varval = strchr(varname, '='))) {
*varval++ = '\0';
if ((tmpvar = ast_variable_new(varname, varval, ""))) {
tmpvar->next = confp->chan.vars;
confp->chan.vars = tmpvar;
}
}
}
} else if (!strcasecmp(v->name, "immediate")) {
@ -19078,9 +19086,12 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
} else if (!strcasecmp(v->name, "mfcr2_logging")) {
openr2_log_level_t tmplevel;
char *clevel;
char *logval = ast_strdupa(v->value);
char *logval;
char copy[strlen(v->value) + 1];
strcpy(copy, v->value); /* safe */
logval = copy;
while (logval) {
clevel = strsep(&logval,",");
clevel = strsep(&logval,",");
if (-1 == (tmplevel = openr2_log_get_level(clevel))) {
ast_log(LOG_WARNING, "Ignoring invalid logging level: '%s' at line %d.\n", clevel, v->lineno);
continue;

View File

@ -692,15 +692,15 @@ struct dahdi_pvt {
openr2_calling_party_category_t mfcr2_category;
int mfcr2_dnis_index;
int mfcr2_ani_index;
int mfcr2call:1;
int mfcr2_answer_pending:1;
int mfcr2_charge_calls:1;
int mfcr2_allow_collect_calls:1;
int mfcr2_forced_release:1;
int mfcr2_dnis_matched:1;
int mfcr2_call_accepted:1;
int mfcr2_accept_on_offer:1;
int mfcr2_progress_sent:1;
unsigned int mfcr2call:1;
unsigned int mfcr2_answer_pending:1;
unsigned int mfcr2_charge_calls:1;
unsigned int mfcr2_allow_collect_calls:1;
unsigned int mfcr2_forced_release:1;
unsigned int mfcr2_dnis_matched:1;
unsigned int mfcr2_call_accepted:1;
unsigned int mfcr2_accept_on_offer:1;
unsigned int mfcr2_progress_sent:1;
#endif /* defined(HAVE_OPENR2) */
/*! \brief DTMF digit in progress. 0 when no digit in progress. */
char begindigit;

View File

@ -7916,9 +7916,11 @@ static int check_access(int callno, struct ast_sockaddr *addr, struct iax_ies *i
/* We found our match (use the first) */
/* copy vars */
for (v = user->vars ; v ; v = v->next) {
if((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
tmpvar->next = iaxs[callno]->vars;
iaxs[callno]->vars = tmpvar;
if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
if (ast_variable_list_replace(&iaxs[callno]->vars, tmpvar)) {
tmpvar->next = iaxs[callno]->vars;
iaxs[callno]->vars = tmpvar;
}
}
}
/* If a max AUTHREQ restriction is in place, activate it */
@ -11111,18 +11113,18 @@ static int socket_process_helper(struct iax2_thread *thread)
if (iaxs[fr->callno]->pingtime <= peer->maxms) {
ast_log(LOG_NOTICE, "Peer '%s' is now REACHABLE! Time: %u\n", peer->name, iaxs[fr->callno]->pingtime);
ast_endpoint_set_state(peer->endpoint, AST_ENDPOINT_ONLINE);
blob = ast_json_pack("{s: s, s: i}",
blob = ast_json_pack("{s: s, s: I}",
"peer_status", "Reachable",
"time", iaxs[fr->callno]->pingtime);
"time", (ast_json_int_t)iaxs[fr->callno]->pingtime);
ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "IAX2/%s", peer->name); /* Activate notification */
}
} else if ((peer->historicms > 0) && (peer->historicms <= peer->maxms)) {
if (iaxs[fr->callno]->pingtime > peer->maxms) {
ast_log(LOG_NOTICE, "Peer '%s' is now TOO LAGGED (%u ms)!\n", peer->name, iaxs[fr->callno]->pingtime);
ast_endpoint_set_state(peer->endpoint, AST_ENDPOINT_ONLINE);
blob = ast_json_pack("{s: s, s: i}",
blob = ast_json_pack("{s: s, s: I}",
"peer_status", "Lagged",
"time", iaxs[fr->callno]->pingtime);
"time", (ast_json_int_t)iaxs[fr->callno]->pingtime);
ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "IAX2/%s", peer->name); /* Activate notification */
}
}
@ -13179,9 +13181,11 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, st
if ((varval = strchr(varname, '='))) {
*varval = '\0';
varval++;
if((tmpvar = ast_variable_new(varname, varval, ""))) {
tmpvar->next = user->vars;
user->vars = tmpvar;
if ((tmpvar = ast_variable_new(varname, varval, ""))) {
if (ast_variable_list_replace(&user->vars, tmpvar)) {
tmpvar->next = user->vars;
user->vars = tmpvar;
}
}
}
} else if (!strcasecmp(v->name, "allow")) {

View File

@ -2086,15 +2086,16 @@ static int jingle_interpret_description(struct jingle_session *session, iks *des
/* Iterate the codecs updating the relevant RTP instance as we go */
for (codec = iks_child(description); codec; codec = iks_next(codec)) {
char *id = iks_find_attrib(codec, "id"), *name = iks_find_attrib(codec, "name");
char *id = iks_find_attrib(codec, "id");
char *attr_name = iks_find_attrib(codec, "name");
char *clockrate = iks_find_attrib(codec, "clockrate");
int rtp_id, rtp_clockrate;
if (!ast_strlen_zero(id) && !ast_strlen_zero(name) && (sscanf(id, "%30d", &rtp_id) == 1)) {
if (!ast_strlen_zero(id) && !ast_strlen_zero(attr_name) && (sscanf(id, "%30d", &rtp_id) == 1)) {
if (!ast_strlen_zero(clockrate) && (sscanf(clockrate, "%30d", &rtp_clockrate) == 1)) {
ast_rtp_codecs_payloads_set_rtpmap_type_rate(&codecs, NULL, rtp_id, media, name, 0, rtp_clockrate);
ast_rtp_codecs_payloads_set_rtpmap_type_rate(&codecs, NULL, rtp_id, media, attr_name, 0, rtp_clockrate);
} else {
ast_rtp_codecs_payloads_set_rtpmap_type(&codecs, NULL, rtp_id, media, name, 0);
ast_rtp_codecs_payloads_set_rtpmap_type(&codecs, NULL, rtp_id, media, attr_name, 0);
}
}
}

View File

@ -332,6 +332,14 @@ static int check_for_rtp_changes(struct ast_channel *chan, struct ast_rtp_instan
ast_sockaddr_setnull(&media->direct_media_addr);
changed = 1;
if (media->rtp) {
/* Direct media has ended - reset time of last received RTP packet
* to avoid premature RTP timeout. Synchronisation between the
* modification of direct_mdedia_addr+last_rx here and reading the
* values in res_pjsip_sdp_rtp.c:rtp_check_timeout() is provided
* by the channel's lock (which is held while this function is
* executed).
*/
ast_rtp_instance_set_last_rx(media->rtp, time(NULL));
ast_rtp_instance_set_prop(media->rtp, AST_RTP_PROPERTY_RTCP, 1);
if (position != -1) {
ast_channel_set_fd(chan, position + AST_EXTENDED_FDS, ast_rtp_instance_fd(media->rtp, 1));
@ -749,7 +757,8 @@ static int chan_pjsip_answer(struct ast_channel *ast)
}
/*! \brief Internal helper function called when CNG tone is detected */
static struct ast_frame *chan_pjsip_cng_tone_detected(struct ast_sip_session *session, struct ast_frame *f)
static struct ast_frame *chan_pjsip_cng_tone_detected(struct ast_channel *ast, struct ast_sip_session *session,
struct ast_frame *f)
{
const char *target_context;
int exists;
@ -765,11 +774,11 @@ static struct ast_frame *chan_pjsip_cng_tone_detected(struct ast_sip_session *se
}
/* If already executing in the fax extension don't do anything */
if (!strcmp(ast_channel_exten(session->channel), "fax")) {
if (!strcmp(ast_channel_exten(ast), "fax")) {
return f;
}
target_context = S_OR(ast_channel_macrocontext(session->channel), ast_channel_context(session->channel));
target_context = S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast));
/*
* We need to unlock the channel here because ast_exists_extension has the
@ -778,29 +787,44 @@ static struct ast_frame *chan_pjsip_cng_tone_detected(struct ast_sip_session *se
*
* ast_async_goto() has its own restriction on not holding the channel lock.
*/
ast_channel_unlock(session->channel);
ast_channel_unlock(ast);
ast_frfree(f);
f = &ast_null_frame;
exists = ast_exists_extension(session->channel, target_context, "fax", 1,
S_COR(ast_channel_caller(session->channel)->id.number.valid,
ast_channel_caller(session->channel)->id.number.str, NULL));
exists = ast_exists_extension(ast, target_context, "fax", 1,
S_COR(ast_channel_caller(ast)->id.number.valid,
ast_channel_caller(ast)->id.number.str, NULL));
if (exists) {
ast_verb(2, "Redirecting '%s' to fax extension due to CNG detection\n",
ast_channel_name(session->channel));
pbx_builtin_setvar_helper(session->channel, "FAXEXTEN", ast_channel_exten(session->channel));
if (ast_async_goto(session->channel, target_context, "fax", 1)) {
ast_channel_name(ast));
pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast_channel_exten(ast));
if (ast_async_goto(ast, target_context, "fax", 1)) {
ast_log(LOG_ERROR, "Failed to async goto '%s' into fax extension in '%s'\n",
ast_channel_name(session->channel), target_context);
ast_channel_name(ast), target_context);
}
} else {
ast_log(LOG_NOTICE, "FAX CNG detected on '%s' but no fax extension in '%s'\n",
ast_channel_name(session->channel), target_context);
ast_channel_name(ast), target_context);
}
ast_channel_lock(session->channel);
/* It's possible for a masquerade to have occurred when doing the ast_async_goto resulting in
* the channel on the session having changed. Since we need to return with the original channel
* locked we lock the channel that was passed in and not session->channel.
*/
ast_channel_lock(ast);
return f;
}
/*! \brief Determine if the given frame is in a format we've negotiated */
static int is_compatible_format(struct ast_sip_session *session, struct ast_frame *f)
{
struct ast_stream_topology *topology = session->active_media_state->topology;
struct ast_stream *stream = ast_stream_topology_get_stream(topology, f->stream_num);
const struct ast_format_cap *cap = ast_stream_get_formats(stream);
return ast_format_cap_iscompatible_format(cap, f->subclass.format) != AST_FORMAT_CMP_NOT_EQUAL;
}
/*!
* \brief Function called by core to read any waiting frames
*
@ -813,6 +837,7 @@ static struct ast_frame *chan_pjsip_read_stream(struct ast_channel *ast)
struct ast_sip_session_media_read_callback_state *callback_state;
struct ast_frame *f;
int fdno = ast_channel_fdno(ast) - AST_EXTENDED_FDS;
struct ast_frame *cur;
if (fdno >= AST_VECTOR_SIZE(&session->active_media_state->read_callbacks)) {
return &ast_null_frame;
@ -825,8 +850,13 @@ static struct ast_frame *chan_pjsip_read_stream(struct ast_channel *ast)
return f;
}
if (f->frametype != AST_FRAME_VOICE ||
callback_state->session != session->active_media_state->default_session[callback_state->session->type]) {
for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
if (cur->frametype == AST_FRAME_VOICE) {
break;
}
}
if (!cur || callback_state->session != session->active_media_state->default_session[callback_state->session->type]) {
return f;
}
@ -838,35 +868,36 @@ static struct ast_frame *chan_pjsip_read_stream(struct ast_channel *ast)
* raw read format BEFORE the native format check
*/
if (!session->endpoint->asymmetric_rtp_codec &&
ast_format_cmp(ast_channel_rawwriteformat(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
ast_format_cmp(ast_channel_rawwriteformat(ast), cur->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL &&
is_compatible_format(session, cur)) {
struct ast_format_cap *caps;
/* For maximum compatibility we ensure that the formats match that of the received media */
ast_debug(1, "Oooh, got a frame with format of %s on channel '%s' when we're sending '%s', switching to match\n",
ast_format_get_name(f->subclass.format), ast_channel_name(ast),
ast_format_get_name(cur->subclass.format), ast_channel_name(ast),
ast_format_get_name(ast_channel_rawwriteformat(ast)));
caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (caps) {
ast_format_cap_append_from_cap(caps, ast_channel_nativeformats(ast), AST_MEDIA_TYPE_UNKNOWN);
ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_AUDIO);
ast_format_cap_append(caps, f->subclass.format, 0);
ast_format_cap_append(caps, cur->subclass.format, 0);
ast_channel_nativeformats_set(ast, caps);
ao2_ref(caps, -1);
}
ast_set_write_format_path(ast, ast_channel_writeformat(ast), f->subclass.format);
ast_set_read_format_path(ast, ast_channel_readformat(ast), f->subclass.format);
ast_set_write_format_path(ast, ast_channel_writeformat(ast), cur->subclass.format);
ast_set_read_format_path(ast, ast_channel_readformat(ast), cur->subclass.format);
if (ast_channel_is_bridged(ast)) {
ast_channel_set_unbridged_nolock(ast, 1);
}
}
if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), cur->subclass.format)
== AST_FORMAT_CMP_NOT_EQUAL) {
ast_debug(1, "Oooh, got a frame with format of %s on channel '%s' when it has not been negotiated\n",
ast_format_get_name(f->subclass.format), ast_channel_name(ast));
ast_format_get_name(cur->subclass.format), ast_channel_name(ast));
ast_frfree(f);
return &ast_null_frame;
}
@ -895,7 +926,11 @@ static struct ast_frame *chan_pjsip_read_stream(struct ast_channel *ast)
if (f->subclass.integer == 'f') {
ast_debug(3, "Channel driver fax CNG detected on %s\n",
ast_channel_name(ast));
f = chan_pjsip_cng_tone_detected(session, f);
f = chan_pjsip_cng_tone_detected(ast, session, f);
/* When chan_pjsip_cng_tone_detected returns it is possible for the
* channel pointed to by ast and by session->channel to differ due to a
* masquerade. It's best not to touch things after this.
*/
} else {
ast_debug(3, "* Detected inband DTMF '%c' on '%s'\n", f->subclass.integer,
ast_channel_name(ast));
@ -1648,6 +1683,7 @@ static int chan_pjsip_indicate(struct ast_channel *ast, int condition, const voi
if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), ast_format_vp8) != AST_FORMAT_CMP_NOT_EQUAL ||
ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), ast_format_vp9) != AST_FORMAT_CMP_NOT_EQUAL ||
ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), ast_format_h265) != AST_FORMAT_CMP_NOT_EQUAL ||
(channel->session->endpoint->media.webrtc &&
ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), ast_format_h264) != AST_FORMAT_CMP_NOT_EQUAL)) {
/* FIXME Fake RTP write, this will be sent as an RTCP packet. Ideally the
@ -1727,7 +1763,7 @@ static int chan_pjsip_indicate(struct ast_channel *ast, int condition, const voi
device_buf = alloca(device_buf_size);
ast_channel_get_device_name(ast, device_buf, device_buf_size);
ast_devstate_changed_literal(AST_DEVICE_ONHOLD, 1, device_buf);
if (!channel->session->endpoint->moh_passthrough) {
if (!channel->session->moh_passthrough) {
ast_moh_start(ast, data, NULL);
} else {
if (ast_sip_push_task(channel->session->serializer, remote_send_hold, ao2_bump(channel->session))) {
@ -1743,7 +1779,7 @@ static int chan_pjsip_indicate(struct ast_channel *ast, int condition, const voi
device_buf = alloca(device_buf_size);
ast_channel_get_device_name(ast, device_buf, device_buf_size);
ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, 1, device_buf);
if (!channel->session->endpoint->moh_passthrough) {
if (!channel->session->moh_passthrough) {
ast_moh_stop(ast);
} else {
if (ast_sip_push_task(channel->session->serializer, remote_send_unhold, ao2_bump(channel->session))) {
@ -2127,20 +2163,23 @@ static int chan_pjsip_digit_begin(struct ast_channel *chan, char digit)
{
struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(chan);
struct ast_sip_session_media *media;
int res = 0;
media = channel->session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO];
switch (channel->session->dtmf) {
case AST_SIP_DTMF_RFC_4733:
if (!media || !media->rtp) {
return -1;
return 0;
}
ast_rtp_instance_dtmf_begin(media->rtp, digit);
break;
case AST_SIP_DTMF_AUTO:
if (!media || !media->rtp || (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_INBAND)) {
if (!media || !media->rtp) {
return 0;
}
if (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_INBAND) {
return -1;
}
@ -2155,13 +2194,12 @@ static int chan_pjsip_digit_begin(struct ast_channel *chan, char digit)
case AST_SIP_DTMF_NONE:
break;
case AST_SIP_DTMF_INBAND:
res = -1;
break;
return -1;
default:
break;
}
return res;
return 0;
}
struct info_dtmf_data {
@ -2248,7 +2286,12 @@ static int chan_pjsip_digit_end(struct ast_channel *ast, char digit, unsigned in
{
struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
struct ast_sip_session_media *media;
int res = 0;
if (!channel || !channel->session) {
/* This happens when the channel is hungup while a DTMF digit is playing. See ASTERISK-28086 */
ast_debug(3, "Channel %s disappeared while calling digit_end\n", ast_channel_name(ast));
return -1;
}
media = channel->session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO];
@ -2256,8 +2299,9 @@ static int chan_pjsip_digit_end(struct ast_channel *ast, char digit, unsigned in
case AST_SIP_DTMF_AUTO_INFO:
{
if (!media || !media->rtp) {
return -1;
return 0;
}
if (ast_rtp_instance_dtmf_mode_get(media->rtp) != AST_RTP_DTMF_MODE_NONE) {
ast_debug(3, "Told to send end of digit on Auto-Info channel %s RFC4733 negotiated so using it.\n", ast_channel_name(ast));
ast_rtp_instance_dtmf_end_with_duration(media->rtp, digit, duration);
@ -2295,28 +2339,29 @@ static int chan_pjsip_digit_end(struct ast_channel *ast, char digit, unsigned in
}
case AST_SIP_DTMF_RFC_4733:
if (!media || !media->rtp) {
return -1;
return 0;
}
ast_rtp_instance_dtmf_end_with_duration(media->rtp, digit, duration);
break;
case AST_SIP_DTMF_AUTO:
if (!media || !media->rtp || (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_INBAND)) {
if (!media || !media->rtp) {
return 0;
}
if (ast_rtp_instance_dtmf_mode_get(media->rtp) == AST_RTP_DTMF_MODE_INBAND) {
return -1;
}
ast_rtp_instance_dtmf_end_with_duration(media->rtp, digit, duration);
break;
case AST_SIP_DTMF_NONE:
break;
case AST_SIP_DTMF_INBAND:
res = -1;
break;
return -1;
}
return res;
return 0;
}
static void update_initial_connected_line(struct ast_sip_session *session)
@ -3211,6 +3256,12 @@ static struct ast_custom_function dtmf_mode_function = {
.write = pjsip_acf_dtmf_mode_write
};
static struct ast_custom_function moh_passthrough_function = {
.name = "PJSIP_MOH_PASSTHROUGH",
.read = pjsip_acf_moh_passthrough_read,
.write = pjsip_acf_moh_passthrough_write
};
static struct ast_custom_function session_refresh_function = {
.name = "PJSIP_SEND_SESSION_REFRESH",
.write = pjsip_acf_session_refresh_write,
@ -3263,6 +3314,11 @@ static int load_module(void)
goto end;
}
if (ast_custom_function_register(&moh_passthrough_function)) {
ast_log(LOG_WARNING, "Unable to register PJSIP_MOH_PASSTHROUGH dialplan function\n");
goto end;
}
if (ast_custom_function_register(&session_refresh_function)) {
ast_log(LOG_WARNING, "Unable to register PJSIP_SEND_SESSION_REFRESH dialplan function\n");
goto end;
@ -3308,6 +3364,7 @@ end:
ast_sip_session_unregister_supplement(&call_pickup_supplement);
ast_sip_unregister_service(&refer_callback_module);
ast_custom_function_unregister(&dtmf_mode_function);
ast_custom_function_unregister(&moh_passthrough_function);
ast_custom_function_unregister(&media_offer_function);
ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);
ast_custom_function_unregister(&chan_pjsip_parse_uri_function);
@ -3335,6 +3392,7 @@ static int unload_module(void)
ast_sip_unregister_service(&refer_callback_module);
ast_custom_function_unregister(&dtmf_mode_function);
ast_custom_function_unregister(&moh_passthrough_function);
ast_custom_function_unregister(&media_offer_function);
ast_custom_function_unregister(&chan_pjsip_dial_contacts_function);
ast_custom_function_unregister(&chan_pjsip_parse_uri_function);

View File

@ -43,6 +43,7 @@
#include "asterisk/causes.h"
#include "asterisk/format_cache.h"
#include "asterisk/multicast_rtp.h"
#include "asterisk/dns_core.h"
/* Forward declarations */
static struct ast_channel *multicast_rtp_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause);
@ -293,9 +294,23 @@ static struct ast_channel *unicast_rtp_request(const char *type, struct ast_form
ast_log(LOG_ERROR, "Destination is required for the 'UnicastRTP' channel\n");
goto failure;
}
if (!ast_sockaddr_parse(&address, args.destination, PARSE_PORT_REQUIRE)) {
ast_log(LOG_ERROR, "Destination '%s' could not be parsed\n", args.destination);
goto failure;
int rc;
char *host;
char *port;
rc = ast_sockaddr_split_hostport(args.destination, &host, &port, PARSE_PORT_REQUIRE);
if (!rc) {
ast_log(LOG_ERROR, "Unable to parse destination '%s' into host and port\n", args.destination);
goto failure;
}
rc = ast_dns_resolve_ipv6_and_ipv4(&address, host, port);
if (rc != 0) {
ast_log(LOG_ERROR, "Unable to resolve host '%s'\n", host);
goto failure;
}
}
if (!ast_strlen_zero(args.options)

View File

@ -2619,12 +2619,16 @@ static int sip_tcptls_write(struct ast_tcptls_session_instance *tcptls_session,
ao2_lock(tcptls_session);
if (!tcptls_session->stream ||
!(th = ao2_t_find(threadt, &tmp, OBJ_POINTER, "ao2_find, getting sip_threadinfo in tcp helper thread")) ||
!(packet = ao2_alloc(sizeof(*packet), tcptls_packet_destructor)) ||
!(packet->data = ast_str_create(len))) {
goto tcptls_write_setup_error;
}
if (!(th = ao2_t_find(threadt, &tmp, OBJ_POINTER, "ao2_find, getting sip_threadinfo in tcp helper thread"))) {
ast_log(LOG_ERROR, "Unable to locate tcptls_session helper thread.\n");
goto tcptls_write_setup_error;
}
/* goto tcptls_write_error should _NOT_ be used beyond this point */
ast_str_set(&packet->data, 0, "%s", (char *) buf);
packet->len = len;
@ -3808,6 +3812,9 @@ static int __sip_xmit(struct sip_pvt *p, struct ast_str *data)
res = ast_sendto(p->socket.fd, ast_str_buffer(data), ast_str_strlen(data), 0, dst);
} else if (p->socket.tcptls_session) {
res = sip_tcptls_write(p->socket.tcptls_session, ast_str_buffer(data), ast_str_strlen(data));
if (res < -1) {
return res;
}
} else if (p->socket.ws_session) {
if (!(res = ast_websocket_write_string(p->socket.ws_session, ast_str_buffer(data)))) {
/* The WebSocket API just returns 0 on success and -1 on failure, while this code expects the payload length to be returned */
@ -3907,9 +3914,21 @@ static void ast_sip_ouraddrfor(const struct ast_sockaddr *them, struct ast_socka
/* for consistency, default to the externaddr port */
externtcpport = ast_sockaddr_port(&externaddr);
}
if (!externtcpport) {
externtcpport = ast_sockaddr_port(&sip_tcp_desc.local_address);
}
if (!externtcpport) {
externtcpport = STANDARD_SIP_PORT;
}
ast_sockaddr_set_port(us, externtcpport);
break;
case AST_TRANSPORT_TLS:
if (!externtlsport) {
externtlsport = ast_sockaddr_port(&sip_tls_desc.local_address);
}
if (!externtlsport) {
externtlsport = STANDARD_TLS_PORT;
}
ast_sockaddr_set_port(us, externtlsport);
break;
case AST_TRANSPORT_UDP:
@ -3927,23 +3946,27 @@ static void ast_sip_ouraddrfor(const struct ast_sockaddr *them, struct ast_socka
/* no remapping, but we bind to a specific address, so use it. */
switch (p->socket.type) {
case AST_TRANSPORT_TCP:
if (!ast_sockaddr_is_any(&sip_tcp_desc.local_address)) {
ast_sockaddr_copy(us,
&sip_tcp_desc.local_address);
} else {
ast_sockaddr_set_port(us,
ast_sockaddr_port(&sip_tcp_desc.local_address));
}
break;
if (!ast_sockaddr_isnull(&sip_tcp_desc.local_address)) {
if (!ast_sockaddr_is_any(&sip_tcp_desc.local_address)) {
ast_sockaddr_copy(us,
&sip_tcp_desc.local_address);
} else {
ast_sockaddr_set_port(us,
ast_sockaddr_port(&sip_tcp_desc.local_address));
}
break;
} /* fall through on purpose */
case AST_TRANSPORT_TLS:
if (!ast_sockaddr_is_any(&sip_tls_desc.local_address)) {
ast_sockaddr_copy(us,
&sip_tls_desc.local_address);
} else {
ast_sockaddr_set_port(us,
ast_sockaddr_port(&sip_tls_desc.local_address));
}
break;
if (!ast_sockaddr_isnull(&sip_tls_desc.local_address)) {
if (!ast_sockaddr_is_any(&sip_tls_desc.local_address)) {
ast_sockaddr_copy(us,
&sip_tls_desc.local_address);
} else {
ast_sockaddr_set_port(us,
ast_sockaddr_port(&sip_tls_desc.local_address));
}
break;
} /* fall through on purpose */
case AST_TRANSPORT_UDP:
/* fall through on purpose */
default:
@ -8193,8 +8216,11 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, const char *tit
/* Use only the preferred audio format, which is stored at the '0' index */
fmt = ast_format_cap_get_best_by_type(what, AST_MEDIA_TYPE_AUDIO); /* get the best audio format */
if (fmt) {
int framing;
ast_format_cap_remove_by_type(caps, AST_MEDIA_TYPE_AUDIO); /* remove only the other audio formats */
ast_format_cap_append(caps, fmt, 0); /* add our best choice back */
framing = ast_format_cap_get_format_framing(what, fmt);
ast_format_cap_append(caps, fmt, framing); /* add our best choice back */
} else {
/* If we don't have an audio format, try to get something */
fmt = ast_format_cap_get_format(caps, 0);
@ -9859,8 +9885,10 @@ static void lws2sws(struct ast_str *data)
int len = ast_str_strlen(data);
int h = 0, t = 0;
int lws = 0;
int just_read_eol = 0;
int done_with_headers = 0;
for (; h < len;) {
while (h < len) {
/* Eliminate all CRs */
if (msgbuf[h] == '\r') {
h++;
@ -9868,11 +9896,17 @@ static void lws2sws(struct ast_str *data)
}
/* Check for end-of-line */
if (msgbuf[h] == '\n') {
if (just_read_eol) {
done_with_headers = 1;
} else {
just_read_eol = 1;
}
/* Check for end-of-message */
if (h + 1 == len)
break;
/* Check for a continuation line */
if (msgbuf[h + 1] == ' ' || msgbuf[h + 1] == '\t') {
if (!done_with_headers
&& (msgbuf[h + 1] == ' ' || msgbuf[h + 1] == '\t')) {
/* Merge continuation line */
h++;
continue;
@ -9881,8 +9915,11 @@ static void lws2sws(struct ast_str *data)
msgbuf[t++] = msgbuf[h++];
lws = 0;
continue;
} else {
just_read_eol = 0;
}
if (msgbuf[h] == ' ' || msgbuf[h] == '\t') {
if (!done_with_headers
&& (msgbuf[h] == ' ' || msgbuf[h] == '\t')) {
if (lws) {
h++;
continue;
@ -11228,9 +11265,12 @@ process_sdp_cleanup:
static int process_sdp_o(const char *o, struct sip_pvt *p)
{
const char *o_copy_start;
char *o_copy;
char *token;
int64_t rua_version;
int offset;
int64_t sess_version;
char unique[128];
/* Store the SDP version number of remote UA. This will allow us to
distinguish between session modifications and session refreshes. If
@ -11248,35 +11288,49 @@ static int process_sdp_o(const char *o, struct sip_pvt *p)
return FALSE;
}
o_copy = ast_strdupa(o);
token = strsep(&o_copy, " "); /* Skip username */
/* o=<username> <sess-id> <sess-version> <nettype> <addrtype>
<unicast-address> */
o_copy_start = o_copy = ast_strdupa(o);
token = strsep(&o_copy, " "); /* Skip username */
if (!o_copy) {
ast_log(LOG_WARNING, "SDP syntax error in o= line username\n");
return FALSE;
}
token = strsep(&o_copy, " "); /* Skip session-id */
token = strsep(&o_copy, " "); /* sess-id */
if (!o_copy) {
ast_log(LOG_WARNING, "SDP syntax error in o= line session-id\n");
ast_log(LOG_WARNING, "SDP syntax error in o= line sess-id\n");
return FALSE;
}
token = strsep(&o_copy, " "); /* Version */
if (!o_copy) {
ast_log(LOG_WARNING, "SDP syntax error in o= line\n");
return FALSE;
}
if (!sscanf(token, "%30" SCNd64, &rua_version)) {
ast_log(LOG_WARNING, "SDP syntax error in o= line version\n");
token = strsep(&o_copy, " "); /* sess-version */
if (!o_copy || !sscanf(token, "%30" SCNd64, &sess_version)) {
ast_log(LOG_WARNING, "SDP syntax error in o= line sess-version\n");
return FALSE;
}
/* we need to check the SDP version number the other end sent us;
/* Copy all after sess-version on top of sess-version into unique.
* <sess-id> is a numeric string such that the tuple of <username>,
* <sess-id>, <nettype>, <addrtype>, and <unicast-address> forms a
* globally unique identifier for the session.
* I.e. all except the <sess-version> */
ast_copy_string(unique, o, sizeof(unique)); /* copy all of o= contents */
offset = (o_copy - o_copy_start); /* after sess-version */
if (offset < sizeof(unique)) {
/* copy all after sess-version on top of sess-version */
int sess_version_start = token - o_copy_start;
ast_copy_string(unique + sess_version_start, o + offset, sizeof(unique) - sess_version_start);
}
/* We need to check the SDP version number the other end sent us;
* our rules for deciding what to accept are a bit complex.
*
* 1) if 'ignoresdpversion' has been set for this dialog, then
* we will just accept whatever they sent and assume it is
* a modification of the session, even if it is not
* 2) otherwise, if this is the first SDP we've seen from them
* we accept it
* we accept it;
* note that _them_ may change, in which case the
* sessionunique_remote will be different
* 3) otherwise, if the new SDP version number is higher than the
* old one, we accept it
* 4) otherwise, if this SDP is in response to us requesting a switch
@ -11286,14 +11340,25 @@ static int process_sdp_o(const char *o, struct sip_pvt *p)
* not request a switch to T.38, then we stop parsing the SDP, as it
* has not changed from the previous version
*/
if (sip_debug_test_pvt(p)) {
if (ast_strlen_zero(p->sessionunique_remote)) {
ast_verbose("Got SDP version %" PRId64 " and unique parts [%s]\n",
sess_version, unique);
} else {
ast_verbose("Comparing SDP version %" PRId64 " -> %" PRId64 " and unique parts [%s] -> [%s]\n",
p->sessionversion_remote, sess_version, p->sessionunique_remote, unique);
}
}
if (ast_test_flag(&p->flags[1], SIP_PAGE2_IGNORESDPVERSION) ||
(p->sessionversion_remote < 0) ||
(p->sessionversion_remote < rua_version)) {
p->sessionversion_remote = rua_version;
sess_version > p->sessionversion_remote ||
strcmp(unique, S_OR(p->sessionunique_remote, ""))) {
p->sessionversion_remote = sess_version;
ast_string_field_set(p, sessionunique_remote, unique);
} else {
if (p->t38.state == T38_LOCAL_REINVITE) {
p->sessionversion_remote = rua_version;
p->sessionversion_remote = sess_version;
ast_string_field_set(p, sessionunique_remote, unique);
ast_log(LOG_WARNING, "Call %s responded to our T.38 reinvite without changing SDP version; 'ignoresdpversion' should be set for this peer.\n", p->callid);
} else {
p->session_modify = FALSE;
@ -15746,7 +15811,6 @@ static void update_connectedline(struct sip_pvt *p, const void *data, size_t dat
initialize_initreq(p, &req);
p->lastinvite = p->ocseq;
ast_set_flag(&p->flags[0], SIP_OUTGOING);
p->invitestate = INV_CALLING;
send_request(p, &req, XMIT_CRITICAL, p->ocseq);
} else if ((is_method_allowed(&p->allowed_methods, SIP_UPDATE)) && (!ast_strlen_zero(p->okcontacturi))) {
reqprep(&req, p, SIP_UPDATE, 0, 1);
@ -16201,8 +16265,15 @@ static int transmit_register(struct sip_registry *r, int sipmethod, const char *
/* Set transport and port so the correct contact is built */
set_socket_transport(&p->socket, r->transport);
if (r->transport == AST_TRANSPORT_TLS || r->transport == AST_TRANSPORT_TCP) {
p->socket.port =
htons(ast_sockaddr_port(&sip_tcp_desc.local_address));
if (ast_sockaddr_isnull(&sip_tcp_desc.local_address)) {
ast_log(LOG_ERROR,
"TCP/TLS clients without server were not tested.\n");
ast_log(LOG_ERROR,
"Please, follow-up and report at issue 28798.\n");
} else {
p->socket.port =
htons(ast_sockaddr_port(&sip_tcp_desc.local_address));
}
}
/*
@ -19245,18 +19316,6 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
bogus_peer = NULL;
}
/* build_peer, called through sip_find_peer, is not able to check the
* sip_pvt->natdetected flag in order to determine if the peer is behind
* NAT or not when SIP_PAGE3_NAT_AUTO_RPORT or SIP_PAGE3_NAT_AUTO_COMEDIA
* are set on the peer. So we check for that here and set the peer's
* address accordingly.
*/
set_peer_nat(p, peer);
if (p->natdetected && ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
ast_sockaddr_copy(&peer->addr, &p->recv);
}
if (!ast_apply_acl(peer->acl, addr, "SIP Peer ACL: ")) {
ast_debug(2, "Found peer '%s' for '%s', but fails host access\n", peer->name, of);
sip_unref_peer(peer, "sip_unref_peer: check_peer_ok: from sip_find_peer call, early return of AUTH_ACL_FAILED");
@ -19325,6 +19384,21 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
ast_string_field_set(p, peermd5secret, NULL);
}
if (!(res = check_auth(p, req, peer->name, p->peersecret, p->peermd5secret, sipmethod, uri2, reliable))) {
/* build_peer, called through sip_find_peer, is not able to check the
* sip_pvt->natdetected flag in order to determine if the peer is behind
* NAT or not when SIP_PAGE3_NAT_AUTO_RPORT or SIP_PAGE3_NAT_AUTO_COMEDIA
* are set on the peer. So we check for that here and set the peer's
* address accordingly. The address should ONLY be set once we are sure
* authentication was a success. If, for example, an INVITE was sent that
* matched the peer name but failed the authentication check, the address
* would be updated, which is bad.
*/
set_peer_nat(p, peer);
if (p->natdetected && ast_test_flag(&peer->flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
ast_sockaddr_copy(&peer->addr, &p->recv);
}
/* If we have a call limit, set flag */
if (peer->call_limit)
ast_set_flag(&p->flags[0], SIP_CALL_LIMIT);
@ -19424,6 +19498,7 @@ static enum check_auth_result check_peer_ok(struct sip_pvt *p, char *of,
}
}
sip_unref_peer(peer, "check_peer_ok: sip_unref_peer: tossing temp ptr to peer from sip_find_peer");
return res;
}
@ -19573,6 +19648,55 @@ static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod,
return check_user_full(p, req, sipmethod, uri, reliable, addr, NULL);
}
static void send_check_user_failure_response(struct sip_pvt *p, struct sip_request *req, int res, enum xmittype reliable)
{
const char *response;
switch (res) {
case AUTH_SECRET_FAILED:
case AUTH_USERNAME_MISMATCH:
case AUTH_NOT_FOUND:
case AUTH_UNKNOWN_DOMAIN:
case AUTH_PEER_NOT_DYNAMIC:
case AUTH_BAD_TRANSPORT:
case AUTH_ACL_FAILED:
ast_log(LOG_NOTICE, "Failed to authenticate device %s for %s, code = %d\n",
sip_get_header(req, "From"), sip_methods[p->method].text, res);
response = "403 Forbidden";
break;
case AUTH_SESSION_LIMIT:
/* Unexpected here, actually. As it's handled elsewhere. */
ast_log(LOG_NOTICE, "Call limit reached for device %s for %s, code = %d\n",
sip_get_header(req, "From"), sip_methods[p->method].text, res);
response = "480 Temporarily Unavailable";
break;
case AUTH_RTP_FAILED:
/* We don't want to send a 403 in the RTP_FAILED case.
* The cause could be any one of:
* - out of memory or rtp ports
* - dtls/srtp requested but not loaded/invalid
* Neither of them warrant a 403. A 503 makes more
* sense, as this node is broken/overloaded. */
ast_log(LOG_NOTICE, "RTP init failure for device %s for %s, code = %d\n",
sip_get_header(req, "From"), sip_methods[p->method].text, res);
response = "503 Service Unavailable";
break;
case AUTH_SUCCESSFUL:
case AUTH_CHALLENGE_SENT:
/* These should have been handled elsewhere. */
default:
ast_log(LOG_NOTICE, "Unexpected error for device %s for %s, code = %d\n",
sip_get_header(req, "From"), sip_methods[p->method].text, res);
response = "503 Service Unavailable";
}
if (reliable == XMIT_RELIABLE) {
transmit_response_reliable(p, response, req);
} else if (reliable == XMIT_UNRELIABLE) {
transmit_response(p, response, req);
}
}
static int set_message_vars_from_req(struct ast_msg *msg, struct sip_request *req)
{
size_t x;
@ -19689,8 +19813,7 @@ static void receive_message(struct sip_pvt *p, struct sip_request *req, struct a
return;
}
if (res < 0) { /* Something failed in authentication */
ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From"));
transmit_response(p, "403 Forbidden", req);
send_check_user_failure_response(p, req, res, XMIT_UNRELIABLE);
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
return;
}
@ -25805,8 +25928,7 @@ static int handle_request_options(struct sip_pvt *p, struct sip_request *req, st
return 0;
}
if (res < 0) { /* Something failed in authentication */
ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From"));
transmit_response(p, "403 Forbidden", req);
send_check_user_failure_response(p, req, res, XMIT_UNRELIABLE);
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
return 0;
}
@ -26599,8 +26721,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str
goto request_invite_cleanup;
}
if (res < 0) { /* Something failed in authentication */
ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From"));
transmit_response_reliable(p, "403 Forbidden", req);
send_check_user_failure_response(p, req, res, XMIT_RELIABLE);
p->invitestate = INV_COMPLETED;
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
goto request_invite_cleanup;
@ -28323,8 +28444,7 @@ static int handle_request_publish(struct sip_pvt *p, struct sip_request *req, st
p->lastinvite = seqno;
return 0;
} else if (auth_result < 0) {
ast_log(LOG_NOTICE, "Failed to authenticate device %s\n", sip_get_header(req, "From"));
transmit_response(p, "403 Forbidden", req);
send_check_user_failure_response(p, req, auth_result, XMIT_UNRELIABLE);
sip_scheddestroy(p, DEFAULT_TRANS_TIMEOUT);
ast_string_field_set(p, theirtag, NULL);
return 0;
@ -28542,9 +28662,7 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req,
if (res == AUTH_CHALLENGE_SENT) /* authpeer = NULL here */
return 0;
if (res != AUTH_SUCCESSFUL) {
ast_log(LOG_NOTICE, "Failed to authenticate device %s for SUBSCRIBE\n", sip_get_header(req, "From"));
transmit_response(p, "403 Forbidden", req);
send_check_user_failure_response(p, req, res, XMIT_UNRELIABLE);
pvt_set_needdestroy(p, "authentication failed");
return 0;
}
@ -29590,6 +29708,8 @@ static int sip_prepare_socket(struct sip_pvt *p)
goto create_tcptls_session_fail;
}
ast_set_qos(s->fd, global_tos_sip, global_cos_sip, "SIP");
return s->fd;
create_tcptls_session_fail:
@ -30376,6 +30496,9 @@ static int sip_send_keepalive(const void *data)
} else if ((peer->socket.type & (AST_TRANSPORT_TCP | AST_TRANSPORT_TLS)) &&
peer->socket.tcptls_session) {
res = sip_tcptls_write(peer->socket.tcptls_session, keepalive, count);
if (res < -1) {
return 0;
}
} else if (peer->socket.type == AST_TRANSPORT_UDP) {
res = ast_sendto(sipsock, keepalive, count, 0, &peer->addr);
}
@ -31366,8 +31489,10 @@ static struct ast_variable *add_var(const char *buf, struct ast_variable *list)
if ((varval = strchr(varname, '='))) {
*varval++ = '\0';
if ((tmpvar = ast_variable_new(varname, varval, ""))) {
tmpvar->next = list;
list = tmpvar;
if (ast_variable_list_replace(&list, tmpvar)) {
tmpvar->next = list;
list = tmpvar;
}
}
}
return list;
@ -32539,8 +32664,8 @@ static int reload_config(enum channelreloadreason reason)
default_primary_transport = AST_TRANSPORT_UDP;
ourport_tcp = STANDARD_SIP_PORT;
ourport_tls = STANDARD_TLS_PORT;
externtcpport = STANDARD_SIP_PORT;
externtlsport = STANDARD_TLS_PORT;
externtcpport = 0;
externtlsport = 0;
sip_cfg.srvlookup = DEFAULT_SRVLOOKUP;
global_tos_sip = DEFAULT_TOS_SIP;
global_tos_audio = DEFAULT_TOS_AUDIO;
@ -33031,10 +33156,9 @@ static int reload_config(enum channelreloadreason reason)
} else if (!strcasecmp(v->name, "externtcpport")) {
if (!(externtcpport = port_str2int(v->value, 0))) {
ast_log(LOG_WARNING, "Invalid externtcpport value, must be a positive integer between 1 and 65535 at line %d\n", v->lineno);
externtcpport = 0;
}
} else if (!strcasecmp(v->name, "externtlsport")) {
if (!(externtlsport = port_str2int(v->value, STANDARD_TLS_PORT))) {
if (!(externtlsport = port_str2int(v->value, 0))) {
ast_log(LOG_WARNING, "Invalid externtlsport value, must be a positive integer between 1 and 65535 at line %d\n", v->lineno);
}
} else if (!strcasecmp(v->name, "allow")) {
@ -33399,6 +33523,7 @@ static int reload_config(enum channelreloadreason reason)
if (setsockopt(sip_tcp_desc.accept_fd, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof(flags))) {
ast_log(LOG_ERROR, "Error enabling TCP keep-alive on sip socket: %s\n", strerror(errno));
}
ast_set_qos(sip_tcp_desc.accept_fd, global_tos_sip, global_cos_sip, "SIP");
}
}
@ -33426,6 +33551,7 @@ static int reload_config(enum channelreloadreason reason)
ast_log(LOG_ERROR, "Error enabling TCP keep-alive on sip socket: %s\n", strerror(errno));
sip_tls_desc.tls_cfg = NULL;
}
ast_set_qos(sip_tls_desc.accept_fd, global_tos_sip, global_cos_sip, "SIP");
}
} else if (sip_tls_desc.tls_cfg->enabled) {
sip_tls_desc.tls_cfg = NULL;
@ -35349,8 +35475,8 @@ static void deprecation_notice(void)
{
ast_log(LOG_WARNING, "chan_sip has no official maintainer and is deprecated. Migration to\n");
ast_log(LOG_WARNING, "chan_pjsip is recommended. See guides at the Asterisk Wiki:\n");
ast_log(LOG_WARNING, "https://wiki.asterisk.org/wiki/x/tAHOAQ\n");
ast_log(LOG_WARNING, "https://wiki.asterisk.org/wiki/x/hYCLAQ\n");
ast_log(LOG_WARNING, "https://wiki.asterisk.org/wiki/display/AST/Migrating+from+chan_sip+to+res_pjsip\n");
ast_log(LOG_WARNING, "https://wiki.asterisk.org/wiki/display/AST/Configuring+res_pjsip\n");
}
/*! \brief Event callback which indicates we're fully booted */

View File

@ -62,6 +62,7 @@
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/unaligned.h"
#include "asterisk/netsock2.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
@ -575,7 +576,7 @@ static const unsigned char packet_send_stream_based_tone_on[] =
{ 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
static const unsigned char packet_send_stream_based_tone_single_freq[] =
{ 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
static const unsigned char packet_send_stream_based_tone_dial_freq[] =
static const unsigned char packet_send_stream_based_tone_dual_freq[] =
{ 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
static const unsigned char packet_send_select_output[] =
{ 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
@ -1002,27 +1003,36 @@ static int get_to_address(int fd, struct sockaddr_in *toAddr)
{
#ifdef HAVE_PKTINFO
int err;
struct msghdr msg;
struct {
struct cmsghdr cm;
int len;
struct in_addr address;
} ip_msg;
/* Zero out the structures before we use them */
/* This sets several key values to NULL */
memset(&msg, 0, sizeof(msg));
memset(&ip_msg, 0, sizeof(ip_msg));
/* Initialize the message structure */
msg.msg_control = &ip_msg;
msg.msg_controllen = sizeof(ip_msg);
char cmbuf[0x100];
struct cmsghdr *cmsg;
struct sockaddr_in peeraddr;
struct in_addr addr;
struct msghdr mh = {
.msg_name = &peeraddr,
.msg_namelen = sizeof(peeraddr),
.msg_control = cmbuf,
.msg_controllen = sizeof(cmbuf),
};
memset(&addr, 0, sizeof(addr));
/* Get info about the incoming packet */
err = recvmsg(fd, &msg, MSG_PEEK);
err = recvmsg(fd, &mh, MSG_PEEK);
if (err == -1) {
ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
return err;
}
memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
for(cmsg = CMSG_FIRSTHDR(&mh);
cmsg != NULL;
cmsg = CMSG_NXTHDR(&mh, cmsg))
{
if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
struct in_pktinfo *pkt = (struct in_pktinfo*)CMSG_DATA(cmsg);
addr = pkt->ipi_addr;
if (unistimdebug) {
ast_verb(0, "message received on address %s\n", ast_inet_ntoa(addr));
}
}
}
memcpy(&toAddr->sin_addr, &addr, sizeof(struct in_addr));
return err;
#else
memcpy(toAddr, &public_ip, sizeof(*toAddr));
@ -1030,6 +1040,7 @@ static int get_to_address(int fd, struct sockaddr_in *toAddr)
#endif
}
/* Allocate memory & initialize structures for a new phone */
/* addr_from : ip address of the phone */
static struct unistimsession *create_client(const struct sockaddr_in *addr_from)
@ -1041,7 +1052,10 @@ static struct unistimsession *create_client(const struct sockaddr_in *addr_from)
return NULL;
memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
get_to_address(unistimsock, &s->sout);
if (get_to_address(unistimsock, &s->sout) < 0) {
ast_free(s);
return NULL;
}
s->sout.sin_family = AF_INET;
if (unistimdebug) {
ast_verb(0, "Creating a new entry for the phone from %s received via server ip %s\n",
@ -1208,19 +1222,16 @@ static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2
if (!tone2) {
memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
sizeof(packet_send_stream_based_tone_single_freq));
buffsend[10] = (tone1 & 0xff00) >> 8;
buffsend[11] = (tone1 & 0x00ff);
put_unaligned_uint16(&buffsend[10], htons(tone1));
send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_single_freq), buffsend,
pte);
} else {
tone2 *= 8;
memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dial_freq,
sizeof(packet_send_stream_based_tone_dial_freq));
buffsend[10] = (tone1 & 0xff00) >> 8;
buffsend[11] = (tone1 & 0x00ff);
buffsend[12] = (tone2 & 0xff00) >> 8;
buffsend[13] = (tone2 & 0x00ff);
send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dial_freq), buffsend,
memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dual_freq,
sizeof(packet_send_stream_based_tone_dual_freq));
put_unaligned_uint16(&buffsend[10], htons(tone1));
put_unaligned_uint16(&buffsend[12], htons(tone2));
send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dual_freq), buffsend,
pte);
}
@ -1340,7 +1351,7 @@ static void refresh_all_favorite(struct unistimsession *pte)
static int is_key_favorite(struct unistim_device *d, int fav)
{
if ((fav < 0) && (fav > 5)) {
if ((fav < 0) || (fav >= FAVNUM)) {
return 0;
}
if (d->sline[fav]) {
@ -1354,7 +1365,7 @@ static int is_key_favorite(struct unistim_device *d, int fav)
static int is_key_line(struct unistim_device *d, int fav)
{
if ((fav < 0) && (fav > 5)) {
if ((fav < 0) || (fav >= FAVNUM)) {
return 0;
}
if (!d->sline[fav]) {
@ -2747,7 +2758,7 @@ static void send_start_rtp(struct unistim_subchannel *sub)
sizeof(packet_send_jitter_buffer_conf));
send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend, pte);
if (pte->device->rtp_method != 0) {
uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
uint16_t rtcpsin_port = ntohs(us.sin_port) + 1; /* RTCP port is RTP + 1 */
if (unistimdebug) {
ast_verb(0, "Sending OpenAudioStreamTX using method #%d\n", pte->device->rtp_method);
@ -2761,20 +2772,14 @@ static void send_start_rtp(struct unistim_subchannel *sub)
}
if (pte->device->rtp_method != 2) {
memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
buffsend[21] = (htons(sin.sin_port) & 0x00ff);
buffsend[23] = (rtcpsin_port & 0x00ff);
buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
buffsend[25] = (us.sin_port & 0xff00) >> 8;
buffsend[24] = (us.sin_port & 0x00ff);
buffsend[27] = (rtcpsin_port & 0x00ff);
buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
put_unaligned_uint16(&buffsend[20], sin.sin_port);
put_unaligned_uint16(&buffsend[22], htons(rtcpsin_port));
put_unaligned_uint16(&buffsend[24], us.sin_port);
put_unaligned_uint16(&buffsend[26], htons(rtcpsin_port));
} else {
memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
buffsend[16] = (htons(sin.sin_port) & 0x00ff);
buffsend[20] = (us.sin_port & 0xff00) >> 8;
buffsend[19] = (us.sin_port & 0x00ff);
put_unaligned_uint16(&buffsend[15], sin.sin_port);
put_unaligned_uint16(&buffsend[19], us.sin_port);
}
buffsend[11] = codec; /* rx */
buffsend[12] = codec; /* tx */
@ -2792,20 +2797,14 @@ static void send_start_rtp(struct unistim_subchannel *sub)
}
if (pte->device->rtp_method != 2) {
memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
buffsend[21] = (htons(sin.sin_port) & 0x00ff);
buffsend[23] = (rtcpsin_port & 0x00ff);
buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
buffsend[25] = (us.sin_port & 0xff00) >> 8;
buffsend[24] = (us.sin_port & 0x00ff);
buffsend[27] = (rtcpsin_port & 0x00ff);
buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
put_unaligned_uint16(&buffsend[20], sin.sin_port);
put_unaligned_uint16(&buffsend[22], htons(rtcpsin_port));
put_unaligned_uint16(&buffsend[24], us.sin_port);
put_unaligned_uint16(&buffsend[26], htons(rtcpsin_port));
} else {
memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
buffsend[16] = (htons(sin.sin_port) & 0x00ff);
buffsend[20] = (us.sin_port & 0xff00) >> 8;
buffsend[19] = (us.sin_port & 0x00ff);
put_unaligned_uint16(&buffsend[15], sin.sin_port);
put_unaligned_uint16(&buffsend[19], us.sin_port);
}
buffsend[11] = codec; /* rx */
buffsend[12] = codec; /* tx */
@ -2820,11 +2819,9 @@ static void send_start_rtp(struct unistim_subchannel *sub)
memcpy(buffsend + SIZE_HEADER, packet_send_call, sizeof(packet_send_call));
memcpy(buffsend + 53, &public.sin_addr, sizeof(public.sin_addr));
/* Destination port when sending RTP */
buffsend[49] = (us.sin_port & 0x00ff);
buffsend[50] = (us.sin_port & 0xff00) >> 8;
put_unaligned_uint16(&buffsend[49], us.sin_port);
/* Destination port when sending RTCP */
buffsend[52] = (rtcpsin_port & 0x00ff);
buffsend[51] = (rtcpsin_port & 0xff00) >> 8;
put_unaligned_uint16(&buffsend[51], htons(rtcpsin_port));
/* Codec */
buffsend[40] = codec;
buffsend[41] = codec;
@ -2841,10 +2838,8 @@ static void send_start_rtp(struct unistim_subchannel *sub)
ast_format_get_name(ast_channel_readformat(sub->owner)));
}
/* Source port for transmit RTP and Destination port for receiving RTP */
buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
buffsend[46] = (htons(sin.sin_port) & 0x00ff);
buffsend[47] = (rtcpsin_port & 0xff00) >> 8;
buffsend[48] = (rtcpsin_port & 0x00ff);
put_unaligned_uint16(&buffsend[45], sin.sin_port);
put_unaligned_uint16(&buffsend[47], htons(rtcpsin_port));
send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend, pte);
}
}
@ -3331,22 +3326,12 @@ static void handle_call_incoming(struct unistimsession *s)
return;
}
static int unistim_do_senddigit(struct unistimsession *pte, char digit)
static int send_dtmf_tone(struct unistimsession *pte, char digit)
{
struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass.integer = digit, .src = "unistim" };
struct unistim_subchannel *sub;
int row, col;
int row, col;
sub = get_sub(pte->device, SUB_REAL);
if (!sub || !sub->owner || sub->alreadygone) {
ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit\n");
return -1;
}
/* Send DTMF indication _before_ playing sounds */
ast_queue_frame(sub->owner, &f);
if (unistimdebug) {
ast_verb(0, "Send Digit %c (%i ms)\n", digit, pte->device->dtmfduration);
ast_verb(0, "Phone Play Digit %c\n", digit);
}
if (pte->device->dtmfduration > 0) {
row = (digit - '1') % 3;
@ -3364,6 +3349,28 @@ static int unistim_do_senddigit(struct unistimsession *pte, char digit)
} else {
send_tone(pte, 500, 2000);
}
}
return 0;
}
static int unistim_do_senddigit(struct unistimsession *pte, char digit)
{
struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass.integer = digit, .src = "unistim" };
struct unistim_subchannel *sub;
sub = get_sub(pte->device, SUB_REAL);
if (!sub || !sub->owner || sub->alreadygone) {
ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit\n");
return -1;
}
/* Send DTMF indication _before_ playing sounds */
ast_queue_frame(sub->owner, &f);
if (pte->device->dtmfduration > 0) {
if (unistimdebug) {
ast_verb(0, "Send Digit %c (%i ms)\n", digit, pte->device->dtmfduration);
}
send_dtmf_tone(pte, digit);
usleep(pte->device->dtmfduration * 1000); /* XXX Less than perfect, blocking an important thread is not a good idea */
send_tone(pte, 0, 0);
}
@ -5506,34 +5513,21 @@ static int unistim_senddigit_begin(struct ast_channel *ast, char digit)
if (!pte) {
return -1;
}
return unistim_do_senddigit(pte, digit);
return send_dtmf_tone(pte, digit);
}
static int unistim_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
{
struct unistimsession *pte = channel_to_session(ast);
struct ast_frame f = { 0, };
struct unistim_subchannel *sub;
sub = get_sub(pte->device, SUB_REAL);
if (!sub || !sub->owner || sub->alreadygone) {
ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit_end\n");
if (!pte) {
return -1;
}
if (unistimdebug) {
ast_verb(0, "Send Digit off %c\n", digit);
}
if (!pte) {
return -1;
ast_verb(0, "Send Digit off %c (duration %d)\n", digit, duration);
}
send_tone(pte, 0, 0);
f.frametype = AST_FRAME_DTMF;
f.subclass.integer = digit;
f.src = "unistim";
ast_queue_frame(sub->owner, &f);
return 0;
}

View File

@ -2691,7 +2691,7 @@ static enum ast_module_load_result load_module()
ast_format_cap_append(vpb_tech_indicate.capabilities, ast_format_slin, 0);
try {
num_cards = vpb_get_num_cards();
} catch (std::exception e) {
} catch (std::exception&) {
ast_log(LOG_ERROR, "No Voicetronix cards detected\n");
return AST_MODULE_LOAD_DECLINE;
}

View File

@ -339,14 +339,14 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags)
struct ast_sip_cli_context *context = arg;
const struct ast_channel_snapshot *snapshot = obj;
struct ast_channel *channel = ast_channel_get_by_name(snapshot->base->name);
struct ast_sip_channel_pvt *cpvt = channel ? ast_channel_tech_pvt(channel) : NULL;
struct ast_sip_channel_pvt *cpvt = NULL;
struct ast_sip_session *session;
struct ast_sip_session_media *media;
struct ast_rtp_instance *rtp;
struct ast_rtp_instance_stats stats;
char *print_name = NULL;
char *print_time = alloca(32);
char codec_in_use[7];
int stats_res = -1;
ast_assert(context->output_buffer != NULL);
@ -357,7 +357,8 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags)
ast_channel_lock(channel);
session = cpvt->session;
cpvt = ast_channel_tech_pvt(channel);
session = cpvt ? cpvt->session : NULL;
if (!session) {
ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->base->name);
ast_channel_unlock(channel);
@ -373,14 +374,13 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags)
return 0;
}
rtp = ao2_bump(media->rtp);
codec_in_use[0] = '\0';
if (ast_channel_rawreadformat(channel)) {
ast_copy_string(codec_in_use, ast_format_get_name(ast_channel_rawreadformat(channel)), sizeof(codec_in_use));
}
stats_res = ast_rtp_instance_get_stats(media->rtp, &stats, AST_RTP_INSTANCE_STAT_ALL);
ast_channel_unlock(channel);
print_name = ast_strdupa(snapshot->base->name);
@ -389,7 +389,7 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags)
ast_format_duration_hh_mm_ss(ast_tvnow().tv_sec - snapshot->base->creationtime.tv_sec, print_time, 32);
if (ast_rtp_instance_get_stats(rtp, &stats, AST_RTP_INSTANCE_STAT_ALL)) {
if (stats_res == -1) {
ast_str_append(&context->output_buffer, 0, "%s direct media\n", snapshot->base->name);
} else {
ast_str_append(&context->output_buffer, 0,
@ -414,7 +414,6 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags)
);
}
ao2_cleanup(rtp);
ao2_cleanup(channel);
return 0;

View File

@ -80,6 +80,19 @@
<para>This function uses the same DTMF mode naming as the dtmf_mode configuration option</para>
</description>
</function>
<function name="PJSIP_MOH_PASSTHROUGH" language="en_US">
<synopsis>
Get or change the on-hold behavior for a SIP call.
</synopsis>
<syntax>
</syntax>
<description>
<para>When read, returns the current moh passthrough mode</para>
<para>When written, sets the current moh passthrough mode</para>
<para>If <replaceable>yes</replaceable>, on-hold re-INVITEs are sent. If <replaceable>no</replaceable>, music on hold is generated.</para>
<para>This function can be used to override the moh_passthrough configuration option</para>
</description>
</function>
<function name="PJSIP_SEND_SESSION_REFRESH" language="en_US">
<synopsis>
W/O: Initiate a session refresh via an UPDATE or re-INVITE on an established media session
@ -1222,7 +1235,7 @@ static int media_offer_read_av(struct ast_sip_session *session, char *buf,
struct ast_stream_topology *topology;
int idx;
struct ast_stream *stream = NULL;
struct ast_format_cap *caps;
const struct ast_format_cap *caps;
size_t accum = 0;
if (session->inv_session->dlg->state == PJSIP_DIALOG_STATE_ESTABLISHED) {
@ -1339,9 +1352,18 @@ static int media_offer_write_av(void *obj)
if (!stream) {
return 0;
}
caps = ast_stream_get_formats(stream);
caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
if (!caps) {
return -1;
}
ast_format_cap_append_from_cap(caps, ast_stream_get_formats(stream),
AST_MEDIA_TYPE_UNKNOWN);
ast_format_cap_remove_by_type(caps, data->media_type);
ast_format_cap_update_by_allow_disallow(caps, data->value, 1);
ast_stream_set_formats(stream, caps);
ao2_ref(caps, -1);
return 0;
}
@ -1431,6 +1453,34 @@ int pjsip_acf_dtmf_mode_read(struct ast_channel *chan, const char *cmd, char *da
return 0;
}
int pjsip_acf_moh_passthrough_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
struct ast_sip_channel_pvt *channel;
if (!chan) {
ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
return -1;
}
if (len < 3) {
ast_log(LOG_WARNING, "%s: buffer too small\n", cmd);
return -1;
}
ast_channel_lock(chan);
if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
ast_channel_unlock(chan);
return -1;
}
channel = ast_channel_tech_pvt(chan);
strncpy(buf, AST_YESNO(channel->session->moh_passthrough), len);
ast_channel_unlock(chan);
return 0;
}
struct refresh_data {
struct ast_sip_session *session;
enum ast_sip_session_refresh_method method;
@ -1574,6 +1624,30 @@ int pjsip_acf_dtmf_mode_write(struct ast_channel *chan, const char *cmd, char *d
return ast_sip_push_task_wait_serializer(channel->session->serializer, dtmf_mode_refresh_cb, &rdata);
}
int pjsip_acf_moh_passthrough_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
{
struct ast_sip_channel_pvt *channel;
if (!chan) {
ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
return -1;
}
ast_channel_lock(chan);
if (strcmp(ast_channel_tech(chan)->type, "PJSIP")) {
ast_log(LOG_WARNING, "Cannot call %s on a non-PJSIP channel\n", cmd);
ast_channel_unlock(chan);
return -1;
}
channel = ast_channel_tech_pvt(chan);
channel->session->moh_passthrough = ast_true(value);
ast_channel_unlock(chan);
return 0;
}
static int refresh_write_cb(void *obj)
{
struct refresh_data *data = obj;

View File

@ -72,6 +72,31 @@ int pjsip_acf_dtmf_mode_read(struct ast_channel *chan, const char *cmd, char *da
*/
int pjsip_acf_dtmf_mode_write(struct ast_channel *chan, const char *cmd, char *data, const char *value);
/*!
* \brief PJSIP_MOH_PASSTHROUGH function read callback
* \param chan The channel the function is called on
* \param cmd The name of the function
* \param data Arguments passed to the function
* \param buf Out buffer that should be populated with the data
* \param len Size of the buffer
*
* \retval 0 on success
* \retval -1 on failure
*/
int pjsip_acf_moh_passthrough_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
/*!
* \brief PJSIP_MOH_PASSTHROUGH function write callback
* \param chan The channel the function is called on
* \param cmd The name of the function
* \param data Arguments passed to the function
* \param value Value to be set by the function
*
* \retval 0 on success
* \retval -1 on failure
*/
int pjsip_acf_moh_passthrough_write(struct ast_channel *chan, const char *cmd, char *data, const char *value);
/*!
* \brief PJSIP_MEDIA_OFFER function read callback
* \param chan The channel the function is called on

View File

@ -1387,18 +1387,35 @@ static void pri_queue_control(struct sig_pri_span *pri, int chanpos, int subclas
* \note Assumes the pri->lock is already obtained.
* \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
*
* \note The unlocking/locking sequence now present has been stress tested
* without deadlocks. Please don't change it without consulting
* core development team members.
*
* \return Nothing
*/
static void sig_pri_queue_hangup(struct sig_pri_span *pri, int chanpos)
{
struct ast_channel *owner;
if (sig_pri_callbacks.queue_control) {
sig_pri_callbacks.queue_control(pri->pvts[chanpos]->chan_pvt, AST_CONTROL_HANGUP);
}
sig_pri_lock_owner(pri, chanpos);
if (pri->pvts[chanpos]->owner) {
ast_queue_hangup(pri->pvts[chanpos]->owner);
ast_channel_unlock(pri->pvts[chanpos]->owner);
owner = pri->pvts[chanpos]->owner;
if (owner) {
ao2_ref(owner, +1);
ast_queue_hangup(owner);
ast_channel_unlock(owner);
sig_pri_unlock_private(pri->pvts[chanpos]);
ast_mutex_unlock(&pri->lock);
/* Tell the CDR this DAHDI channel hung up */
ast_set_hangupsource(owner, ast_channel_name(owner), 0);
ast_mutex_lock(&pri->lock);
sig_pri_lock_private(pri->pvts[chanpos]);
ao2_ref(owner, -1);
}
}
@ -2230,7 +2247,7 @@ static void *pri_ss_thread(void *data)
void pri_event_alarm(struct sig_pri_span *pri, int index, int before_start_pri)
{
pri->dchanavail[index] &= ~(DCHAN_NOTINALARM | DCHAN_UP);
pri->dchanavail[index] &= ~DCHAN_NOTINALARM;
if (!before_start_pri) {
pri_find_dchan(pri);
}

View File

@ -1052,6 +1052,7 @@ struct sip_pvt {
AST_STRING_FIELD(last_presence_message); /*!< The last presence message for a subscription */
AST_STRING_FIELD(msg_body); /*!< Text for a MESSAGE body */
AST_STRING_FIELD(tel_phone_context); /*!< The phone-context portion of a TEL URI */
AST_STRING_FIELD(sessionunique_remote); /*!< Remote UA's SDP Session unique parts */
);
char via[128]; /*!< Via: header */
int maxforwards; /*!< SIP Loop prevention */

View File

@ -90,4 +90,5 @@ SPEEX_RESAMPLE_CFLAGS:=
endif
$(call MOD_ADD_C,codec_resample,speex/resample.c)
speex/resample.o: _ASTCFLAGS+=$(SPEEX_RESAMPLE_CFLAGS)
codec_resample.o: _ASTCFLAGS+=-DOUTSIDE_SPEEX
speex/resample.o: _ASTCFLAGS+=$(SPEEX_RESAMPLE_CFLAGS) -DOUTSIDE_SPEEX -DEXPORT=

View File

@ -7,6 +7,9 @@
*
*/
#ifndef ASTERISK_EX_ALAW_H
#define ASTERISK_EX_ALAW_H
static uint8_t ex_alaw[] = {
0x00, 0x03, 0x06, 0x09, 0x0c, 0x0f, 0x12, 0x15,
0x10, 0x18, 0x1b, 0x1e, 0x21, 0x24, 0x27, 0x2a,
@ -34,3 +37,5 @@ static struct ast_frame *alaw_sample(void)
f.subclass.format = ast_format_alaw;
return &f;
}
#endif /* ASTERISK_EX_ALAW_H */

View File

@ -7,6 +7,9 @@
*
*/
#ifndef ASTERISK_EX_G722_H
#define ASTERISK_EX_G722_H
static uint8_t ex_g722[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@ -46,3 +49,5 @@ static struct ast_frame *g722_sample(void)
return &f;
}
#endif /* ASTERISK_EX_G722_H */

View File

@ -7,6 +7,9 @@
*
*/
#ifndef ASTERISK_EX_ULAW_H
#define ASTERISK_EX_ULAW_H
static uint8_t ex_ulaw[] = {
0x00, 0x03, 0x06, 0x09, 0x0c, 0x0f, 0x12, 0x15,
0x10, 0x18, 0x1b, 0x1e, 0x21, 0x24, 0x27, 0x2a,
@ -36,3 +39,5 @@ static struct ast_frame *ulaw_sample(void)
return &f;
}
#endif /* ASTERISK_EX_ULAW_H */

View File

@ -35,14 +35,6 @@
#ifndef ARCH_H
#define ARCH_H
#ifndef SPEEX_VERSION
#define SPEEX_MAJOR_VERSION 1 /**< Major Speex version. */
#define SPEEX_MINOR_VERSION 1 /**< Minor Speex version. */
#define SPEEX_MICRO_VERSION 15 /**< Micro Speex version. */
#define SPEEX_EXTRA_VERSION "" /**< Extra Speex version. */
#define SPEEX_VERSION "speex-1.2beta3" /**< Speex version string. */
#endif
#define FIXED_POINT
/* A couple test to catch stupid option combinations */
@ -77,7 +69,7 @@
#endif
#ifndef OUTSIDE_SPEEX
#include "speex/speex_types.h"
#include "speex/speexdsp_types.h"
#endif
#define ABS(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute integer value. */
@ -91,7 +83,7 @@
#ifdef FIXED_POINT
typedef spx_int16_t spx_word16_t;
typedef spx_int32_t spx_word32_t;
typedef spx_int32_t spx_word32_t;
typedef spx_word32_t spx_mem_t;
typedef spx_word16_t spx_coef_t;
typedef spx_word16_t spx_lsp_t;
@ -173,6 +165,7 @@ typedef float spx_word32_t;
#define VSHR32(a,shift) (a)
#define SATURATE16(x,a) (x)
#define SATURATE32(x,a) (x)
#define SATURATE32PSHR(x,shift,a) (x)
#define PSHR(a,shift) (a)
#define SHR(a,shift) (a)

View File

@ -52,6 +52,10 @@
#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
#define SATURATE32PSHR(x,shift,a) (((x)>=(SHL32(a,shift))) ? (a) : \
(x)<=-(SHL32(a,shift)) ? -(a) : \
(PSHR32(x, shift)))
#define SHR(a,shift) ((a) >> (shift))
#define SHL(a,shift) ((spx_word32_t)(a) << (shift))
#define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))

View File

@ -61,18 +61,26 @@
#include "config.h"
#endif
#ifdef OUTSIDE_SPEEX
#include <stdlib.h>
static void *speex_alloc (int size) {return calloc(size,1);}
static void *speex_realloc (void *ptr, int size) {return realloc(ptr, size);}
static void speex_free (void *ptr) {free(ptr);}
#include "speex_resampler.h"
#include "arch.h"
#else /* OUTSIDE_SPEEX */
#include "speex/speex_resampler.h"
#include "arch.h"
#include "os_support.h"
#endif /* OUTSIDE_SPEEX */
#include "stack_alloc.h"
#include <math.h>
#include <limits.h>
#ifndef M_PI
#define M_PI 3.14159263
#define M_PI 3.14159265358979323846
#endif
#ifdef FIXED_POINT
@ -92,6 +100,10 @@ static void speex_free (void *ptr) {free(ptr);}
#include "resample_sse.h"
#endif
#ifdef _USE_NEON
#include "resample_neon.h"
#endif
/* Numer of elements to allocate on the stack */
#ifdef VAR_ARRAYS
#define FIXED_STACK_ALLOC 8192
@ -133,7 +145,7 @@ struct SpeexResamplerState_ {
int out_stride;
} ;
static double kaiser12_table[68] = {
static const double kaiser12_table[68] = {
0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076,
0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014,
0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601,
@ -147,7 +159,7 @@ static double kaiser12_table[68] = {
0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734,
0.00001000, 0.00000000};
/*
static double kaiser12_table[36] = {
static const double kaiser12_table[36] = {
0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741,
0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762,
0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274,
@ -155,7 +167,7 @@ static double kaiser12_table[36] = {
0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291,
0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000};
*/
static double kaiser10_table[36] = {
static const double kaiser10_table[36] = {
0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446,
0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347,
0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962,
@ -163,7 +175,7 @@ static double kaiser10_table[36] = {
0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739,
0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000};
static double kaiser8_table[36] = {
static const double kaiser8_table[36] = {
0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200,
0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126,
0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272,
@ -171,7 +183,7 @@ static double kaiser8_table[36] = {
0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490,
0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000};
static double kaiser6_table[36] = {
static const double kaiser6_table[36] = {
0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003,
0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565,
0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561,
@ -180,19 +192,19 @@ static double kaiser6_table[36] = {
0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000};
struct FuncDef {
double *table;
const double *table;
int oversample;
};
static struct FuncDef _KAISER12 = {kaiser12_table, 64};
static const struct FuncDef _KAISER12 = {kaiser12_table, 64};
#define KAISER12 (&_KAISER12)
/*static struct FuncDef _KAISER12 = {kaiser12_table, 32};
#define KAISER12 (&_KAISER12)*/
static struct FuncDef _KAISER10 = {kaiser10_table, 32};
static const struct FuncDef _KAISER10 = {kaiser10_table, 32};
#define KAISER10 (&_KAISER10)
static struct FuncDef _KAISER8 = {kaiser8_table, 32};
static const struct FuncDef _KAISER8 = {kaiser8_table, 32};
#define KAISER8 (&_KAISER8)
static struct FuncDef _KAISER6 = {kaiser6_table, 32};
static const struct FuncDef _KAISER6 = {kaiser6_table, 32};
#define KAISER6 (&_KAISER6)
struct QualityMapping {
@ -200,7 +212,7 @@ struct QualityMapping {
int oversample;
float downsample_bandwidth;
float upsample_bandwidth;
struct FuncDef *window_func;
const struct FuncDef *window_func;
};
@ -227,7 +239,7 @@ static const struct QualityMapping quality_map[11] = {
{256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 */ /* 96.6% cutoff (~100 dB stop) 10 */
};
/*8,24,40,56,80,104,128,160,200,256,320*/
static double compute_func(float x, struct FuncDef *func)
static double compute_func(float x, const struct FuncDef *func)
{
float y, frac;
double interp[4];
@ -262,7 +274,7 @@ int main(int argc, char **argv)
#ifdef FIXED_POINT
/* The slow way of computing a sinc for the table. Should improve that some day */
static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)
static spx_word16_t sinc(float cutoff, float x, int N, const struct FuncDef *window_func)
{
/*fprintf (stderr, "%f ", x);*/
float xx = x * cutoff;
@ -275,7 +287,7 @@ static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_fu
}
#else
/* The slow way of computing a sinc for the table. Should improve that some day */
static spx_word16_t sinc(float cutoff, float x, int N, struct FuncDef *window_func)
static spx_word16_t sinc(float cutoff, float x, int N, const struct FuncDef *window_func)
{
/*fprintf (stderr, "%f ", x);*/
float xx = x * cutoff;
@ -330,28 +342,35 @@ static int resampler_basic_direct_single(SpeexResamplerState *st, spx_uint32_t c
const int frac_advance = st->frac_advance;
const spx_uint32_t den_rate = st->den_rate;
spx_word32_t sum;
int j;
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
{
const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];
const spx_word16_t *sinct = & sinc_table[samp_frac_num*N];
const spx_word16_t *iptr = & in[last_sample];
#ifndef OVERRIDE_INNER_PRODUCT_SINGLE
float accum[4] = {0,0,0,0};
int j;
sum = 0;
for(j=0;j<N;j++) sum += MULT16_16(sinct[j], iptr[j]);
/* This code is slower on most DSPs which have only 2 accumulators.
Plus this this forces truncation to 32 bits and you lose the HW guard bits.
I think we can trust the compiler and let it vectorize and/or unroll itself.
spx_word32_t accum[4] = {0,0,0,0};
for(j=0;j<N;j+=4) {
accum[0] += sinc[j]*iptr[j];
accum[1] += sinc[j+1]*iptr[j+1];
accum[2] += sinc[j+2]*iptr[j+2];
accum[3] += sinc[j+3]*iptr[j+3];
accum[0] += MULT16_16(sinct[j], iptr[j]);
accum[1] += MULT16_16(sinct[j+1], iptr[j+1]);
accum[2] += MULT16_16(sinct[j+2], iptr[j+2]);
accum[3] += MULT16_16(sinct[j+3], iptr[j+3]);
}
sum = accum[0] + accum[1] + accum[2] + accum[3];
*/
sum = SATURATE32PSHR(sum, 15, 32767);
#else
sum = inner_product_single(sinc, iptr, N);
sum = inner_product_single(sinct, iptr, N);
#endif
out[out_stride * out_sample++] = PSHR32(sum, 15);
out[out_stride * out_sample++] = sum;
last_sample += int_advance;
samp_frac_num += frac_advance;
if (samp_frac_num >= den_rate)
@ -381,25 +400,25 @@ static int resampler_basic_direct_double(SpeexResamplerState *st, spx_uint32_t c
const int frac_advance = st->frac_advance;
const spx_uint32_t den_rate = st->den_rate;
double sum;
int j;
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
{
const spx_word16_t *sinc = & sinc_table[samp_frac_num*N];
const spx_word16_t *sinct = & sinc_table[samp_frac_num*N];
const spx_word16_t *iptr = & in[last_sample];
#ifndef OVERRIDE_INNER_PRODUCT_DOUBLE
int j;
double accum[4] = {0,0,0,0};
for(j=0;j<N;j+=4) {
accum[0] += sinc[j]*iptr[j];
accum[1] += sinc[j+1]*iptr[j+1];
accum[2] += sinc[j+2]*iptr[j+2];
accum[3] += sinc[j+3]*iptr[j+3];
accum[0] += sinct[j]*iptr[j];
accum[1] += sinct[j+1]*iptr[j+1];
accum[2] += sinct[j+2]*iptr[j+2];
accum[3] += sinct[j+3]*iptr[j+3];
}
sum = accum[0] + accum[1] + accum[2] + accum[3];
#else
sum = inner_product_double(sinc, iptr, N);
sum = inner_product_double(sinct, iptr, N);
#endif
out[out_stride * out_sample++] = PSHR32(sum, 15);
@ -428,7 +447,6 @@ static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint3
const int int_advance = st->int_advance;
const int frac_advance = st->frac_advance;
const spx_uint32_t den_rate = st->den_rate;
int j;
spx_word32_t sum;
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
@ -445,6 +463,7 @@ static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint3
#ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE
int j;
spx_word32_t accum[4] = {0,0,0,0};
for(j=0;j<N;j++) {
@ -456,13 +475,14 @@ static int resampler_basic_interpolate_single(SpeexResamplerState *st, spx_uint3
}
cubic_coef(frac, interp);
sum = MULT16_32_Q15(interp[0],accum[0]) + MULT16_32_Q15(interp[1],accum[1]) + MULT16_32_Q15(interp[2],accum[2]) + MULT16_32_Q15(interp[3],accum[3]);
sum = MULT16_32_Q15(interp[0],SHR32(accum[0], 1)) + MULT16_32_Q15(interp[1],SHR32(accum[1], 1)) + MULT16_32_Q15(interp[2],SHR32(accum[2], 1)) + MULT16_32_Q15(interp[3],SHR32(accum[3], 1));
sum = SATURATE32PSHR(sum, 15, 32767);
#else
cubic_coef(frac, interp);
sum = interpolate_product_single(iptr, st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, interp);
#endif
out[out_stride * out_sample++] = PSHR32(sum,15);
out[out_stride * out_sample++] = sum;
last_sample += int_advance;
samp_frac_num += frac_advance;
if (samp_frac_num >= den_rate)
@ -490,7 +510,6 @@ static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint3
const int int_advance = st->int_advance;
const int frac_advance = st->frac_advance;
const spx_uint32_t den_rate = st->den_rate;
int j;
spx_word32_t sum;
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
@ -507,6 +526,7 @@ static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint3
#ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE
int j;
double accum[4] = {0,0,0,0};
for(j=0;j<N;j++) {
@ -540,11 +560,47 @@ static int resampler_basic_interpolate_double(SpeexResamplerState *st, spx_uint3
}
#endif
static void update_filter(SpeexResamplerState *st)
/* This resampler is used to produce zero output in situations where memory
for the filter could not be allocated. The expected numbers of input and
output samples are still processed so that callers failing to check error
codes are not surprised, possibly getting into infinite loops. */
static int resampler_basic_zero(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_word16_t *in, spx_uint32_t *in_len, spx_word16_t *out, spx_uint32_t *out_len)
{
spx_uint32_t old_length;
int out_sample = 0;
int last_sample = st->last_sample[channel_index];
spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index];
const int out_stride = st->out_stride;
const int int_advance = st->int_advance;
const int frac_advance = st->frac_advance;
const spx_uint32_t den_rate = st->den_rate;
old_length = st->filt_len;
while (!(last_sample >= (spx_int32_t)*in_len || out_sample >= (spx_int32_t)*out_len))
{
out[out_stride * out_sample++] = 0;
last_sample += int_advance;
samp_frac_num += frac_advance;
if (samp_frac_num >= den_rate)
{
samp_frac_num -= den_rate;
last_sample++;
}
}
st->last_sample[channel_index] = last_sample;
st->samp_frac_num[channel_index] = samp_frac_num;
return out_sample;
}
static int update_filter(SpeexResamplerState *st)
{
spx_uint32_t old_length = st->filt_len;
spx_uint32_t old_alloc_size = st->mem_alloc_size;
int use_direct;
spx_uint32_t min_sinc_table_length;
spx_uint32_t min_alloc_size;
st->int_advance = st->num_rate/st->den_rate;
st->frac_advance = st->num_rate%st->den_rate;
st->oversample = quality_map[st->quality].oversample;
st->filt_len = quality_map[st->quality].base_length;
@ -554,8 +610,8 @@ static void update_filter(SpeexResamplerState *st)
st->cutoff = quality_map[st->quality].downsample_bandwidth * st->den_rate / st->num_rate;
/* FIXME: divide the numerator and denominator by a certain amount if they're too large */
st->filt_len = st->filt_len*st->num_rate / st->den_rate;
/* Round down to make sure we have a multiple of 4 */
st->filt_len &= (~0x3);
/* Round up to make sure we have a multiple of 8 for SSE */
st->filt_len = ((st->filt_len-1)&(~0x7))+8;
if (2*st->den_rate < st->num_rate)
st->oversample >>= 1;
if (4*st->den_rate < st->num_rate)
@ -572,16 +628,35 @@ static void update_filter(SpeexResamplerState *st)
}
/* Choose the resampling type that requires the least amount of memory */
if (st->den_rate <= st->oversample)
#ifdef RESAMPLE_FULL_SINC_TABLE
use_direct = 1;
if (INT_MAX/sizeof(spx_word16_t)/st->den_rate < st->filt_len)
goto fail;
#else
use_direct = st->filt_len*st->den_rate <= st->filt_len*st->oversample+8
&& INT_MAX/sizeof(spx_word16_t)/st->den_rate >= st->filt_len;
#endif
if (use_direct)
{
min_sinc_table_length = st->filt_len*st->den_rate;
} else {
if ((INT_MAX/sizeof(spx_word16_t)-8)/st->oversample < st->filt_len)
goto fail;
min_sinc_table_length = st->filt_len*st->oversample+8;
}
if (st->sinc_table_length < min_sinc_table_length)
{
spx_word16_t *sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,min_sinc_table_length*sizeof(spx_word16_t));
if (!sinc_table)
goto fail;
st->sinc_table = sinc_table;
st->sinc_table_length = min_sinc_table_length;
}
if (use_direct)
{
spx_uint32_t i;
if (!st->sinc_table)
st->sinc_table = (spx_word16_t *)speex_alloc(st->filt_len*st->den_rate*sizeof(spx_word16_t));
else if (st->sinc_table_length < st->filt_len*st->den_rate)
{
st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,st->filt_len*st->den_rate*sizeof(spx_word16_t));
st->sinc_table_length = st->filt_len*st->den_rate;
}
for (i=0;i<st->den_rate;i++)
{
spx_int32_t j;
@ -601,13 +676,6 @@ static void update_filter(SpeexResamplerState *st)
/*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff);*/
} else {
spx_int32_t i;
if (!st->sinc_table)
st->sinc_table = (spx_word16_t *)speex_alloc((st->filt_len*st->oversample+8)*sizeof(spx_word16_t));
else if (st->sinc_table_length < st->filt_len*st->oversample+8)
{
st->sinc_table = (spx_word16_t *)speex_realloc(st->sinc_table,(st->filt_len*st->oversample+8)*sizeof(spx_word16_t));
st->sinc_table_length = st->filt_len*st->oversample+8;
}
for (i=-4;i<(spx_int32_t)(st->oversample*st->filt_len+4);i++)
st->sinc_table[i+4] = sinc(st->cutoff,(i/(float)st->oversample - st->filt_len/2), st->filt_len, quality_map[st->quality].window_func);
#ifdef FIXED_POINT
@ -620,43 +688,39 @@ static void update_filter(SpeexResamplerState *st)
#endif
/*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff);*/
}
st->int_advance = st->num_rate/st->den_rate;
st->frac_advance = st->num_rate%st->den_rate;
/* Here's the place where we update the filter memory to take into account
the change in filter length. It's probably the messiest part of the code
due to handling of lots of corner cases. */
if (!st->mem)
/* Adding buffer_size to filt_len won't overflow here because filt_len
could be multiplied by sizeof(spx_word16_t) above. */
min_alloc_size = st->filt_len-1 + st->buffer_size;
if (min_alloc_size > st->mem_alloc_size)
{
spx_word16_t *mem;
if (INT_MAX/sizeof(spx_word16_t)/st->nb_channels < min_alloc_size)
goto fail;
else if (!(mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*min_alloc_size * sizeof(*mem))))
goto fail;
st->mem = mem;
st->mem_alloc_size = min_alloc_size;
}
if (!st->started)
{
spx_uint32_t i;
st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
st->mem = (spx_word16_t*)speex_alloc(st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
for (i=0;i<st->nb_channels*st->mem_alloc_size;i++)
st->mem[i] = 0;
/*speex_warning("init filter");*/
} else if (!st->started)
{
spx_uint32_t i;
st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
for (i=0;i<st->nb_channels*st->mem_alloc_size;i++)
st->mem[i] = 0;
/*speex_warning("reinit filter");*/
} else if (st->filt_len > old_length)
{
spx_int32_t i;
spx_uint32_t i;
/* Increase the filter length */
/*speex_warning("increase filter size");*/
int old_alloc_size = st->mem_alloc_size;
if ((st->filt_len-1 + st->buffer_size) > st->mem_alloc_size)
for (i=st->nb_channels;i--;)
{
st->mem_alloc_size = st->filt_len-1 + st->buffer_size;
st->mem = (spx_word16_t*)speex_realloc(st->mem, st->nb_channels*st->mem_alloc_size * sizeof(spx_word16_t));
}
for (i=st->nb_channels-1;i>=0;i--)
{
spx_int32_t j;
spx_uint32_t j;
spx_uint32_t olen = old_length;
/*if (st->magic_samples[i])*/
{
@ -664,7 +728,7 @@ static void update_filter(SpeexResamplerState *st)
/* FIXME: This is wrong but for now we need it to avoid going over the array bounds */
olen = old_length + 2*st->magic_samples[i];
for (j=old_length-2+st->magic_samples[i];j>=0;j--)
for (j=old_length-1+st->magic_samples[i];j--;)
st->mem[i*st->mem_alloc_size+j+st->magic_samples[i]] = st->mem[i*old_alloc_size+j];
for (j=0;j<st->magic_samples[i];j++)
st->mem[i*st->mem_alloc_size+j] = 0;
@ -705,18 +769,28 @@ static void update_filter(SpeexResamplerState *st)
st->magic_samples[i] += old_magic;
}
}
return RESAMPLER_ERR_SUCCESS;
fail:
st->resampler_ptr = resampler_basic_zero;
/* st->mem may still contain consumed input samples for the filter.
Restore filt_len so that filt_len - 1 still points to the position after
the last of these samples. */
st->filt_len = old_length;
return RESAMPLER_ERR_ALLOC_FAILED;
}
SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
EXPORT SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
{
return speex_resampler_init_frac(nb_channels, in_rate, out_rate, in_rate, out_rate, quality, err);
}
SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
EXPORT SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err)
{
spx_uint32_t i;
SpeexResamplerState *st;
int filter_err;
if (quality > 10 || quality < 0)
{
if (err)
@ -742,16 +816,12 @@ static void update_filter(SpeexResamplerState *st)
st->in_stride = 1;
st->out_stride = 1;
#ifdef FIXED_POINT
st->buffer_size = 160;
#else
st->buffer_size = 160;
#endif
/* Per channel data */
st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(int));
st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(int));
st->last_sample = (spx_int32_t*)speex_alloc(nb_channels*sizeof(spx_int32_t));
st->magic_samples = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t));
st->samp_frac_num = (spx_uint32_t*)speex_alloc(nb_channels*sizeof(spx_uint32_t));
for (i=0;i<nb_channels;i++)
{
st->last_sample[i] = 0;
@ -762,17 +832,21 @@ static void update_filter(SpeexResamplerState *st)
speex_resampler_set_quality(st, quality);
speex_resampler_set_rate_frac(st, ratio_num, ratio_den, in_rate, out_rate);
update_filter(st);
st->initialised = 1;
filter_err = update_filter(st);
if (filter_err == RESAMPLER_ERR_SUCCESS)
{
st->initialised = 1;
} else {
speex_resampler_destroy(st);
st = NULL;
}
if (err)
*err = RESAMPLER_ERR_SUCCESS;
*err = filter_err;
return st;
}
void speex_resampler_destroy(SpeexResamplerState *st)
EXPORT void speex_resampler_destroy(SpeexResamplerState *st)
{
speex_free(st->mem);
speex_free(st->sinc_table);
@ -829,9 +903,9 @@ static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_i
}
#ifdef FIXED_POINT
int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
#else
int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
#endif
{
int j;
@ -866,13 +940,13 @@ static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_i
}
*in_len -= ilen;
*out_len -= olen;
return RESAMPLER_ERR_SUCCESS;
return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS;
}
#ifdef FIXED_POINT
int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
EXPORT int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
#else
int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
EXPORT int speex_resampler_process_int(SpeexResamplerState *st, spx_uint32_t channel_index, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
#endif
{
int j;
@ -940,20 +1014,22 @@ static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_i
*in_len -= ilen;
*out_len -= olen;
return RESAMPLER_ERR_SUCCESS;
return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS;
}
int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
EXPORT int speex_resampler_process_interleaved_float(SpeexResamplerState *st, const float *in, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len)
{
spx_uint32_t i;
int istride_save, ostride_save;
spx_uint32_t bak_len = *out_len;
spx_uint32_t bak_out_len = *out_len;
spx_uint32_t bak_in_len = *in_len;
istride_save = st->in_stride;
ostride_save = st->out_stride;
st->in_stride = st->out_stride = st->nb_channels;
for (i=0;i<st->nb_channels;i++)
{
*out_len = bak_len;
*out_len = bak_out_len;
*in_len = bak_in_len;
if (in != NULL)
speex_resampler_process_float(st, i, in+i, in_len, out+i, out_len);
else
@ -961,20 +1037,22 @@ static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_i
}
st->in_stride = istride_save;
st->out_stride = ostride_save;
return RESAMPLER_ERR_SUCCESS;
return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS;
}
int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
EXPORT int speex_resampler_process_interleaved_int(SpeexResamplerState *st, const spx_int16_t *in, spx_uint32_t *in_len, spx_int16_t *out, spx_uint32_t *out_len)
{
spx_uint32_t i;
int istride_save, ostride_save;
spx_uint32_t bak_len = *out_len;
spx_uint32_t bak_out_len = *out_len;
spx_uint32_t bak_in_len = *in_len;
istride_save = st->in_stride;
ostride_save = st->out_stride;
st->in_stride = st->out_stride = st->nb_channels;
for (i=0;i<st->nb_channels;i++)
{
*out_len = bak_len;
*out_len = bak_out_len;
*in_len = bak_in_len;
if (in != NULL)
speex_resampler_process_int(st, i, in+i, in_len, out+i, out_len);
else
@ -982,21 +1060,21 @@ static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_i
}
st->in_stride = istride_save;
st->out_stride = ostride_save;
return RESAMPLER_ERR_SUCCESS;
return st->resampler_ptr == resampler_basic_zero ? RESAMPLER_ERR_ALLOC_FAILED : RESAMPLER_ERR_SUCCESS;
}
int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)
EXPORT int speex_resampler_set_rate(SpeexResamplerState *st, spx_uint32_t in_rate, spx_uint32_t out_rate)
{
return speex_resampler_set_rate_frac(st, in_rate, out_rate, in_rate, out_rate);
}
void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate)
EXPORT void speex_resampler_get_rate(SpeexResamplerState *st, spx_uint32_t *in_rate, spx_uint32_t *out_rate)
{
*in_rate = st->in_rate;
*out_rate = st->out_rate;
}
int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
EXPORT int speex_resampler_set_rate_frac(SpeexResamplerState *st, spx_uint32_t ratio_num, spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate)
{
spx_uint32_t fact;
spx_uint32_t old_den;
@ -1031,17 +1109,17 @@ static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_i
}
if (st->initialised)
update_filter(st);
return update_filter(st);
return RESAMPLER_ERR_SUCCESS;
}
void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den)
EXPORT void speex_resampler_get_ratio(SpeexResamplerState *st, spx_uint32_t *ratio_num, spx_uint32_t *ratio_den)
{
*ratio_num = st->num_rate;
*ratio_den = st->den_rate;
}
int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
EXPORT int speex_resampler_set_quality(SpeexResamplerState *st, int quality)
{
if (quality > 10 || quality < 0)
return RESAMPLER_ERR_INVALID_ARG;
@ -1049,46 +1127,46 @@ static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_i
return RESAMPLER_ERR_SUCCESS;
st->quality = quality;
if (st->initialised)
update_filter(st);
return update_filter(st);
return RESAMPLER_ERR_SUCCESS;
}
void speex_resampler_get_quality(SpeexResamplerState *st, int *quality)
EXPORT void speex_resampler_get_quality(SpeexResamplerState *st, int *quality)
{
*quality = st->quality;
}
void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride)
EXPORT void speex_resampler_set_input_stride(SpeexResamplerState *st, spx_uint32_t stride)
{
st->in_stride = stride;
}
void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride)
EXPORT void speex_resampler_get_input_stride(SpeexResamplerState *st, spx_uint32_t *stride)
{
*stride = st->in_stride;
}
void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride)
EXPORT void speex_resampler_set_output_stride(SpeexResamplerState *st, spx_uint32_t stride)
{
st->out_stride = stride;
}
void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride)
EXPORT void speex_resampler_get_output_stride(SpeexResamplerState *st, spx_uint32_t *stride)
{
*stride = st->out_stride;
}
int speex_resampler_get_input_latency(SpeexResamplerState *st)
EXPORT int speex_resampler_get_input_latency(SpeexResamplerState *st)
{
return st->filt_len / 2;
}
int speex_resampler_get_output_latency(SpeexResamplerState *st)
EXPORT int speex_resampler_get_output_latency(SpeexResamplerState *st)
{
return ((st->filt_len / 2) * st->den_rate + (st->num_rate >> 1)) / st->num_rate;
}
int speex_resampler_skip_zeros(SpeexResamplerState *st)
EXPORT int speex_resampler_skip_zeros(SpeexResamplerState *st)
{
spx_uint32_t i;
for (i=0;i<st->nb_channels;i++)
@ -1096,15 +1174,21 @@ static int speex_resampler_magic(SpeexResamplerState *st, spx_uint32_t channel_i
return RESAMPLER_ERR_SUCCESS;
}
int speex_resampler_reset_mem(SpeexResamplerState *st)
EXPORT int speex_resampler_reset_mem(SpeexResamplerState *st)
{
spx_uint32_t i;
for (i=0;i<st->nb_channels;i++)
{
st->last_sample[i] = 0;
st->magic_samples[i] = 0;
st->samp_frac_num[i] = 0;
}
for (i=0;i<st->nb_channels*(st->filt_len-1);i++)
st->mem[i] = 0;
return RESAMPLER_ERR_SUCCESS;
}
const char *speex_resampler_strerror(int err)
EXPORT const char *speex_resampler_strerror(int err)
{
switch (err)
{

View File

@ -39,8 +39,6 @@
#ifndef SPEEX_RESAMPLER_H
#define SPEEX_RESAMPLER_H
#define OUTSIDE_SPEEX
#ifdef OUTSIDE_SPEEX
/********* WARNING: MENTAL SANITY ENDS HERE *************/
@ -48,7 +46,7 @@
/* If the resampler is defined outside of Speex, we change the symbol names so that
there won't be any clash if linking with Speex later on. */
#define RANDOM_PREFIX ast
#define RANDOM_PREFIX speex
#ifndef RANDOM_PREFIX
#error "Please define RANDOM_PREFIX (above) to something specific to your project to prevent symbol name clashes"
#endif

View File

@ -36,6 +36,20 @@ exten = 2565551234,1,Verbose(1, "User ${CALLERID(num)} dialed into remote voicem
same = n,VoiceMailMain(example)
same = n,Hangup()
; Extension to queue for sales.
; The queue has a 300 second timeout.
exten = 2565551200,1,Verbose(1, "User ${CALLERID(num)} dialed the sales queue.")
same = n,Answer()
same = n,Queue(sales,,,,300)
same = n,Goto(operator,1)
; Extension to queue for a customer advocate.
; The queue has a 1200 second timeout.
exten = 2565551250,1,Verbose(1, "User ${CALLERID(num)} dialed the customer advocate queue.")
same = n,Answer()
same = n,Queue(customer_advocate,,,,1200)
same = n,Goto(operator,1)
[Dialing-Errors]
; Handle any extensions dialed internally that don't otherwise exist.
; Comment out or remove this extension if you would rather have the calls

View File

@ -14,6 +14,7 @@ load = app_verbose.so
load = app_voicemail.so
load = app_directory.so
load = app_confbridge.so
load = app_queue.so
; Bridging

View File

@ -0,0 +1,19 @@
[general]
monitor-type = MixMonitor
;========================Sales Queue ==
; Calls all sales persons in a ring-all fashion
[sales]
strategy=ringall
member => PJSIP/1109 ; Terry Jules - Director of Sales
member => PJSIP/1105 ; Garnet Claude - Sales Associate
member => PJSIP/1112 ; Franny Ocean - Sales Associate
;===================== Customer Advocate Queue ==
; Calls all customer advocates in a ring-all fashion
[customer_advocate]
strategy=ringall
member => PJSIP/1101 ; Maria Berny - Director of Customer Experience
member => PJSIP/1115 ; Dusty Williams - Customer Advocate
member => PJSIP/1102 ; Tommy Briar - Customer Advocate

View File

@ -118,6 +118,11 @@ documentation_language = en_US ; Set the language you want documentation
; calls are not accepted by a remote
; implementation, please report this and go
; back to value 96.
;hide_messaging_ami_events = no; This option, if enabled, will
; suppress all of the Message/ast_msg_queue channel's
; housekeeping AMI and ARI channel events. This can
; reduce the load on the manager and ARI applications
; when the Digium Phone Module for Asterisk is in use.
; Changing the following lines may compromise your security.
;[files]

View File

@ -162,6 +162,9 @@ type=user
; is ejected from the conference, the user's channel will have the CONFBRIDGE_RESULT
; variable set to "TIMEOUT". A value of 0 indicates that there is no timeout.
; Default: 0
;text_messaging=yes ; When set to yes text messages will be sent to this user. Text messages
; may occur as a result of events or can be received from other participants.
; When set to no text messages will not be sent to this user.
; --- ConfBridge Bridge Profile Options ---
[default_bridge]
@ -203,6 +206,10 @@ type=bridge
; closest sample rate Asterisk does support to the one requested
; will be used.
;maximum_sample_rate=none ; Sets the maximum sample rate the conference
; is mixed at. This is set to no maximum by default.
; Values can be anything from 8000-192000.
;mixing_interval=40 ; Sets the internal mixing interval in milliseconds for the bridge. This
; number reflects how tight or loose the mixing will be for the conference.
; In order to improve performance a larger mixing interval such as 40ms may

View File

@ -95,6 +95,7 @@
;queue_rules => odbc,asterisk
;acls => odbc,asterisk
;musiconhold => mysql,general
;musiconhold_entry => mysql,general
;queue_log => mysql,general
;
;

View File

@ -35,14 +35,15 @@
;
; The following options are available in this configuration file:
;
; dsn An alias for "writehandle."
; readhandle A comma-separated list of DSNs (from res_odbc.conf) to use when
; executing the readsql statement. Each DSN is tried, in
; succession, until the statement succeeds. You may specify up to
; 5 DSNs per function class. If not specified, it will default to
; the value of writehandle or dsn, if specified.
; the value of "writehandle" or "dsn," if specified.
; writehandle A comma-separated list of DSNs (from res_odbc.conf) to use when
; executing the writesql statement. The same rules apply as to
; readhandle. "dsn" is a synonym for "writehandle".
; readhandle.
; readsql The statement to execute when reading from the function class.
; writesql The statement to execute when writing to the function class.
; insertsql The statement to execute when writing to the function class
@ -60,6 +61,8 @@
; off is incompatible with the functionality of HASH().
; synopsis Appears in the synopsis field for the command
; 'core show function <function name>'
; syntax Appears in the syntax field for the command
; 'core show function <function name>'
; mode This option may be set to 'multirow' to allow the function
; specified to return more than a single row. However, this
; changes the way that func_odbc normally works. Instead of the
@ -88,22 +91,22 @@
; ODBC_SQL - Allow an SQL statement to be built entirely in the dialplan
[SQL]
dsn=mysql1
writehandle=mysql1
readsql=${ARG1}
; ODBC_ANTIGF - A blacklist.
[ANTIGF]
; ODBC_ANTISOLICIT - A blacklist for known solicitors.
[ANTISOLICIT]
dsn=mysql1,mysql2 ; Use mysql1 as the primary handle, but fall back to mysql2
; if mysql1 is down. Supports up to 5 comma-separated
; DSNs. "dsn" may also be specified as "readhandle" and
; "writehandle", if it is important to separate reads and
; writes to different databases.
readsql=SELECT COUNT(*) FROM exgirlfriends WHERE callerid='${SQL_ESC(${ARG1})}'
readsql=SELECT COUNT(*) FROM known_solicitors WHERE callerid='${SQL_ESC(${ARG1})}'
syntax=<callerid>
synopsis=Check if a specified callerid is contained in the ex-gf database
synopsis=Check if a specified callerid is contained in the known solicitors database
; ODBC_PRESENCE - Retrieve and update presence
[PRESENCE]
dsn=mysql1
writehandle=mysql1
readsql=SELECT location FROM presence WHERE id='${SQL_ESC(${ARG1})}'
writesql=UPDATE presence SET location='${SQL_ESC(${VAL1})}' WHERE id='${SQL_ESC(${ARG1})}'

View File

@ -1,5 +1,5 @@
;
; Asterisk Builtin mini-HTTP server
; Asterisk Built-in mini-HTTP server
;
;
; Note about Asterisk documentation:
@ -65,7 +65,13 @@ bindaddr=127.0.0.1
; Whether Asterisk should serve static content from static-http
; Default is no.
;
;enablestatic=yes
;enable_static=yes
;
; Whether Asterisk should serve a status page showing the running
; configuration of this built-in HTTP server.
; Default is yes.
;
;enable_status=no
;
; Redirect one URI to another. This is how you would set a
; default page.

View File

@ -348,6 +348,17 @@ record = 1400/400,0/15000
info = !950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,!950/330,!1400/330,!1800/330,!0/1000,0
stutter = 350+375+400
[id]
description = Indonesia
; Reference: http://www.itu.int/ITU-T/inr/forms/files/tones-0203.pdf
ringcadence = 1000,4000
dial = 425
busy = 425/500,0/500
ring = 425/1000,0/4000
congestion = 425/250,0/250
callwaiting = 425/150,0/150,425/150,0/10000
info = !950/330,!1400/330,!1800/330,0/1000
[il]
description = Israel
ringcadence = 1000,3000

View File

@ -13,6 +13,7 @@
; valid mode options:
; files -- read files from a directory in any Asterisk supported
; media format
; playlist -- provide a fixed list of filenames or URLs to play
; quietmp3 -- default
; mp3 -- loud
; mp3nb -- unbuffered
@ -44,6 +45,22 @@
; this, res_musiconhold will skip the files it is not able to
; understand when it loads.
;
; =========
; Playlist (native) music on hold
; =========
;
; This mode is similar to 'files' mode in that it plays through a list
; of files, but instead of scanning a directory the files are
; explicitly configured using one or more 'entry' options.
;
; Each entry must be one of:
;
; * An absolute path to the file to be played, without an extension.
; * A URL
;
; The entries are played in the order in which they appear in the
; configuration. The 'sort' option is not used for this mode.
;
[default]
mode=files
@ -71,6 +88,12 @@ directory=moh
;directory=moh
;sort=alpha ; Sort the files in alphabetical order.
;[sales-queue-hold]
;mode=playlist
;entry=/var/lib/asterisk/sounds/en/yourcallisimportant
;entry=http://example.local/sales-queue-hold-music.ulaw
;entry=/var/lib/asterisk/moh/macroform-robot_dity
; =========
; Other (non-native) playback methods
; =========

View File

@ -263,6 +263,7 @@
;endpoint=mytrunk
;match=198.51.100.1
;match=198.51.100.2
;match=192.168.10.0:5061/24
;=============ENDPOINT CONFIGURED AS A TRUNK, INBOUND AUTH AND REGISTRATION===

View File

@ -69,12 +69,14 @@ rtpend=20000
; the wildcard 0.0.0.0 address. e.g., A PJSIP endpoint binding RTP to a
; specific address using the bind_rtp_to_media_address and media_address
; options. Or the PJSIP endpoint specifies an explicit transport that binds
; to a specific IP address.
; to a specific IP address. Blacklisting is done via ACL infrastructure
; so it's possible to whitelist as well.
;
; e.g. stun_blacklist = 192.168.1.0/255.255.255.0
; stun_blacklist = 10.32.77.0/255.255.255.0
; stun_acl = named_acl
; stun_deny = 0.0.0.0/0
; stun_permit = 1.2.3.4/32
;
; stun_blacklist =
; For historic reasons stun_blacklist is an alias for stun_deny.
;
; Hostname or address for the TURN server to be used as a relay. The port
; number is optional. If omitted the default value of 3478 will be used.
@ -90,17 +92,19 @@ rtpend=20000
; Password used to authenticate with TURN relay server.
; turnpassword=
;
; Subnets to exclude from ICE host, srflx and relay discovery. This is useful
; to optimize the ICE process where a system has multiple host address ranges
; and/or physical interfaces and certain of them are not expected to be used
; for RTP. For example, VPNs and local interconnections may not be suitable or
; necessary for ICE. Multiple subnets may be listed. If left unconfigured,
; all discovered host addresses are used.
; An ACL can be used to determine which discovered addresses to include for
; ICE, srflx and relay discovery. This is useful to optimize the ICE process
; where a system has multiple host address ranges and/or physical interfaces
; and certain of them are not expected to be used for RTP. For example, VPNs
; and local interconnections may not be suitable or necessary for ICE. Multiple
; subnets may be listed. If left unconfigured, all discovered host addresses
; are used.
;
; e.g. ice_blacklist = 192.168.1.0/255.255.255.0
; ice_blacklist = 10.32.77.0/255.255.255.0
; ice_acl = named_acl
; ice_deny = 0.0.0.0/0
; ice_permit = 1.2.3.4/32
;
; ice_blacklist =
; For historic reasons ice_blacklist is an alias for ice_deny.
;
; The MTU to use for DTLS packet fragmentation. This option is set to 1200
; by default. The minimum MTU is 256.

View File

@ -1059,7 +1059,9 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls
; the device is actually behind NAT.
;directmediadeny=0.0.0.0/0 ; Use directmediapermit and directmediadeny to restrict
;directmediapermit=172.16.0.0/16; which peers should be able to pass directmedia to each other
;directmediapermit=172.16.0.0/16; which RTP source IPs should be able to pass directmedia to
; each other. Note that directmedia ACLs are not a global
; setting, but must be defined per peer.
; (There is no default setting, this is just an example)
; Use this if some of your phones are on IP addresses that
; can not reach each other directly. This way you can force

662
configure vendored
View File

@ -1249,9 +1249,6 @@ GIT
BASH
XMLSTARLET
XMLLINT
KPATHSEA
CATDVI
RUBBER
CURL
WGET
DOT
@ -1259,7 +1256,6 @@ DOXYGEN
LN
DIRNAME
BASENAME
COMPRESS
FIND
PYTHON
FLEX
@ -1282,6 +1278,7 @@ SED
CXXCPP
ac_ct_CXX
CXXFLAGS
CROSS_COMPILING
RANLIB
LD
CXX
@ -5330,6 +5327,8 @@ else
RANLIB="$ac_cv_prog_RANLIB"
fi
CROSS_COMPILING=1
fi
# Checks for programs.
@ -6838,8 +6837,10 @@ $as_echo "no" >&6; }
fi
# Extract the first word of "python", so it can be a program name with args.
set dummy python; ac_word=$2
for ac_prog in python2.7 python2 python python3
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_PYTHON+:} false; then :
@ -6865,7 +6866,6 @@ done
done
IFS=$as_save_IFS
test -z "$ac_cv_path_PYTHON" && ac_cv_path_PYTHON=":"
;;
esac
fi
@ -6879,6 +6879,10 @@ $as_echo "no" >&6; }
fi
test -n "$PYTHON" && break
done
test -n "$PYTHON" || PYTHON=":"
# Extract the first word of "find", so it can be a program name with args.
set dummy find; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
@ -6920,47 +6924,6 @@ $as_echo "no" >&6; }
fi
# Extract the first word of "compress", so it can be a program name with args.
set dummy compress; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_COMPRESS+:} false; then :
$as_echo_n "(cached) " >&6
else
case $COMPRESS in
[\\/]* | ?:[\\/]*)
ac_cv_path_COMPRESS="$COMPRESS" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_COMPRESS="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
test -z "$ac_cv_path_COMPRESS" && ac_cv_path_COMPRESS=":"
;;
esac
fi
COMPRESS=$ac_cv_path_COMPRESS
if test -n "$COMPRESS"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $COMPRESS" >&5
$as_echo "$COMPRESS" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "basename", so it can be a program name with args.
set dummy basename; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
@ -7289,129 +7252,6 @@ $as_echo "no" >&6; }
fi
# Extract the first word of "rubber", so it can be a program name with args.
set dummy rubber; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_RUBBER+:} false; then :
$as_echo_n "(cached) " >&6
else
case $RUBBER in
[\\/]* | ?:[\\/]*)
ac_cv_path_RUBBER="$RUBBER" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_RUBBER="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
test -z "$ac_cv_path_RUBBER" && ac_cv_path_RUBBER=":"
;;
esac
fi
RUBBER=$ac_cv_path_RUBBER
if test -n "$RUBBER"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $RUBBER" >&5
$as_echo "$RUBBER" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "catdvi", so it can be a program name with args.
set dummy catdvi; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_CATDVI+:} false; then :
$as_echo_n "(cached) " >&6
else
case $CATDVI in
[\\/]* | ?:[\\/]*)
ac_cv_path_CATDVI="$CATDVI" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_CATDVI="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
test -z "$ac_cv_path_CATDVI" && ac_cv_path_CATDVI=":"
;;
esac
fi
CATDVI=$ac_cv_path_CATDVI
if test -n "$CATDVI"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CATDVI" >&5
$as_echo "$CATDVI" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "kpsewhich", so it can be a program name with args.
set dummy kpsewhich; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_path_KPATHSEA+:} false; then :
$as_echo_n "(cached) " >&6
else
case $KPATHSEA in
[\\/]* | ?:[\\/]*)
ac_cv_path_KPATHSEA="$KPATHSEA" # Let the user override the test with a path.
;;
*)
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_path_KPATHSEA="$as_dir/$ac_word$ac_exec_ext"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
test -z "$ac_cv_path_KPATHSEA" && ac_cv_path_KPATHSEA=":"
;;
esac
fi
KPATHSEA=$ac_cv_path_KPATHSEA
if test -n "$KPATHSEA"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $KPATHSEA" >&5
$as_echo "$KPATHSEA" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "xmllint", so it can be a program name with args.
set dummy xmllint; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
@ -9354,91 +9194,93 @@ $as_echo "#define HAVE_JANSSON_BUNDLED 1" >>confdefs.h
as_fn_error $? "--with-pjproject and --with-pjproject-bundled can't both be specified" "$LINENO" 5
fi
ac_mandatory_list="$ac_mandatory_list PJPROJECT"
PJPROJECT_DIR="${ac_top_build_prefix}third-party/pjproject"
if test "${with_pjproject}" != "no" && test "${with_pjproject}" != "n" ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for embedded pjproject (may have to download)" >&5
ac_mandatory_list="$ac_mandatory_list PJPROJECT"
PJPROJECT_DIR="${ac_top_build_prefix}third-party/pjproject"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for embedded pjproject (may have to download)" >&5
$as_echo_n "checking for embedded pjproject (may have to download)... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: configuring" >&5
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: configuring" >&5
$as_echo "configuring" >&6; }
if test "x${DOWNLOAD_TO_STDOUT}" = "x" ; then
as_fn_error $? "A download utility (wget, curl, or fetch) is required to download bundled pjproject" "$LINENO" 5
fi
if test "${BZIP2}" = ":" ; then
as_fn_error $? "bzip2 is required to extract the pjproject tar file" "$LINENO" 5
fi
if test "${TAR}" = ":" ; then
as_fn_error $? "tar is required to extract the pjproject tar file" "$LINENO" 5
fi
if test "${PATCH}" = ":" ; then
as_fn_error $? "patch is required to configure bundled pjproject" "$LINENO" 5
fi
if test "${SED}" = ":" ; then
as_fn_error $? "sed is required to configure bundled pjproject" "$LINENO" 5
fi
if test "${NM}" = ":" ; then
as_fn_error $? "nm is required to build bundled pjproject" "$LINENO" 5
fi
if test "${MD5}" = ":" ; then
as_fn_error $? "md5sum is required to build bundled pjproject" "$LINENO" 5
fi
if test "${CAT}" = ":" ; then
as_fn_error $? "cat is required to build bundled pjproject" "$LINENO" 5
fi
if test "${CUT}" = ":" ; then
as_fn_error $? "cut is required to build bundled pjproject" "$LINENO" 5
fi
if test "${GREP}" = ":" ; then
as_fn_error $? "grep is required to build bundled pjproject" "$LINENO" 5
fi
if test "x${DOWNLOAD_TO_STDOUT}" = "x" ; then
as_fn_error $? "A download utility (wget, curl, or fetch) is required to download bundled pjproject" "$LINENO" 5
fi
if test "${BZIP2}" = ":" ; then
as_fn_error $? "bzip2 is required to extract the pjproject tar file" "$LINENO" 5
fi
if test "${TAR}" = ":" ; then
as_fn_error $? "tar is required to extract the pjproject tar file" "$LINENO" 5
fi
if test "${PATCH}" = ":" ; then
as_fn_error $? "patch is required to configure bundled pjproject" "$LINENO" 5
fi
if test "${SED}" = ":" ; then
as_fn_error $? "sed is required to configure bundled pjproject" "$LINENO" 5
fi
if test "${NM}" = ":" ; then
as_fn_error $? "nm is required to build bundled pjproject" "$LINENO" 5
fi
if test "${MD5}" = ":" ; then
as_fn_error $? "md5sum is required to build bundled pjproject" "$LINENO" 5
fi
if test "${CAT}" = ":" ; then
as_fn_error $? "cat is required to build bundled pjproject" "$LINENO" 5
fi
if test "${CUT}" = ":" ; then
as_fn_error $? "cut is required to build bundled pjproject" "$LINENO" 5
fi
if test "${GREP}" = ":" ; then
as_fn_error $? "grep is required to build bundled pjproject" "$LINENO" 5
fi
this_host=$(./config.sub $(./config.guess))
if test "$build" != "$this_host" ; then
PJPROJECT_CONFIGURE_OPTS+=" --build=$build_alias"
fi
if test "$host" != "$this_host" ; then
PJPROJECT_CONFIGURE_OPTS+=" --host=$host_alias"
fi
# This was a copy of the autoconf generated code from the root ./configure.
# Hopefully, when you read this, the code is still the same.
if test "${with_ssl+set}" = set; then :
case $with_ssl in
n|no)
PJPROJECT_CONFIGURE_OPTS+=" --disable-ssl"
;;
y|ye|yes)
# This is the default value in PJProject and means "autodetect".
# In Asterisk, "./configure --with-ssl" means "must be present".
PJPROJECT_CONFIGURE_OPTS+=" --enable-ssl"
;;
*)
PJPROJECT_CONFIGURE_OPTS+=" --with-ssl=${with_ssl}"
;;
esac
fi
this_host=$(./config.sub $(./config.guess))
if test "$build" != "$this_host" ; then
PJPROJECT_CONFIGURE_OPTS+=" --build=$build_alias"
fi
if test "$host" != "$this_host" ; then
PJPROJECT_CONFIGURE_OPTS+=" --host=$host_alias"
fi
# This was a copy of the autoconf generated code from the root ./configure.
# Hopefully, when you read this, the code is still the same.
if test "${with_ssl+set}" = set; then :
case $with_ssl in
n|no)
PJPROJECT_CONFIGURE_OPTS+=" --disable-ssl"
;;
y|ye|yes)
# Not to mention SSL is the default in PJProject and means "autodetect".
# In Asterisk, "./configure --with-ssl" means "must be present".
PJPROJECT_CONFIGURE_OPTS+=""
;;
*)
PJPROJECT_CONFIGURE_OPTS+=" --with-ssl=${with_ssl}"
;;
esac
fi
export TAR PATCH SED NM EXTERNALS_CACHE_DIR AST_DOWNLOAD_CACHE DOWNLOAD_TO_STDOUT DOWNLOAD_TIMEOUT DOWNLOAD MD5 CAT CUT GREP
export NOISY_BUILD AST_DEVMODE
${GNU_MAKE} --quiet --no-print-directory -C ${PJPROJECT_DIR} \
PJPROJECT_CONFIGURE_OPTS="$PJPROJECT_CONFIGURE_OPTS" \
EXTERNALS_CACHE_DIR="${EXTERNALS_CACHE_DIR:-${AST_DOWNLOAD_CACHE}}" \
configure
if test $? -ne 0 ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
export TAR PATCH SED NM EXTERNALS_CACHE_DIR AST_DOWNLOAD_CACHE DOWNLOAD_TO_STDOUT DOWNLOAD_TIMEOUT DOWNLOAD MD5 CAT CUT GREP
export NOISY_BUILD AST_DEVMODE
${GNU_MAKE} --quiet --no-print-directory -C ${PJPROJECT_DIR} \
PJPROJECT_CONFIGURE_OPTS="$PJPROJECT_CONFIGURE_OPTS" \
EXTERNALS_CACHE_DIR="${EXTERNALS_CACHE_DIR:-${AST_DOWNLOAD_CACHE}}" \
configure
if test $? -ne 0 ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
$as_echo "failed" >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: Unable to configure ${PJPROJECT_DIR}" >&5
{ $as_echo "$as_me:${as_lineno-$LINENO}: Unable to configure ${PJPROJECT_DIR}" >&5
$as_echo "$as_me: Unable to configure ${PJPROJECT_DIR}" >&6;}
as_fn_error $? "Re-run the ./configure command with 'NOISY_BUILD=yes' appended to see error details." "$LINENO" 5
fi
as_fn_error $? "Re-run the ./configure command with 'NOISY_BUILD=yes' appended to see error details." "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for bundled pjproject" >&5
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for bundled pjproject" >&5
$as_echo_n "checking for bundled pjproject... " >&6; }
PJPROJECT_INCLUDE=$(${GNU_MAKE} --quiet --no-print-directory -C ${PJPROJECT_DIR} PJPROJECT_CONFIGURE_OPTS="$PJPROJECT_CONFIGURE_OPTS" EXTERNALS_CACHE_DIR="${EXTERNALS_CACHE_DIR:-${AST_DOWNLOAD_CACHE}}" echo_cflags)
PJPROJECT_CFLAGS="$PJPROJECT_INCLUDE"
PBX_PJPROJECT=1
PJPROJECT_INCLUDE=$(${GNU_MAKE} --quiet --no-print-directory -C ${PJPROJECT_DIR} PJPROJECT_CONFIGURE_OPTS="$PJPROJECT_CONFIGURE_OPTS" EXTERNALS_CACHE_DIR="${EXTERNALS_CACHE_DIR:-${AST_DOWNLOAD_CACHE}}" echo_cflags)
PJPROJECT_CFLAGS="$PJPROJECT_INCLUDE"
PBX_PJPROJECT=1
$as_echo "#define HAVE_PJPROJECT 1" >>confdefs.h
@ -9493,16 +9335,21 @@ $as_echo "#define HAVE_PJSIP_TRANSPORT_DISABLE_CONNECTION_REUSE 1" >>confdefs.h
$as_echo "#define HAVE_PJSIP_OAUTH_AUTHENTICATION 1" >>confdefs.h
$as_echo "#define HAVE_PJPROJECT_ON_VALID_ICE_PAIR_CALLBACK 1" >>confdefs.h
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
fi
fi
# AST_EXT_LIB_SETUP is used to tell configure to handle variables for
@ -21361,7 +21208,7 @@ if test "${USE_IMAP_TK}" != "no"; then
saved_libs="${LIBS}"
switch_to_system_on_failure="no"
if test "${IMAP_TK_DIR}" = ""; then
IMAP_TK_DIR=`pwd`"/../imap-2004g"
IMAP_TK_DIR="`pwd`/../imap-2004g"
switch_to_system_on_failure="yes"
fi
if test "${IMAP_TK_DIR}" != "system"; then
@ -22958,6 +22805,7 @@ fi
fi
if test "x${PBX_MYSQLCLIENT}" != "x1" -a "${USE_MYSQLCLIENT}" != "no"; then
PBX_MYSQLCLIENT=0
if test -n "$ac_tool_prefix"; then
@ -23077,6 +22925,61 @@ $as_echo "#define HAVE_MYSQLCLIENT 1" >>confdefs.h
fi
if test "${PBX_MYSQLCLIENT}" = 1; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for MySQL client bool support" >&5
$as_echo_n "checking for MySQL client bool support... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <mysql/mysql.h>
int
main ()
{
bool test = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define HAVE_MYSQLCLIENT_BOOL 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for MySQL client my_bool support" >&5
$as_echo_n "checking for MySQL client my_bool support... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <mysql/mysql.h>
int
main ()
{
my_bool test = 1;
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define HAVE_MYSQLCLIENT_MY_BOOL 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
fi
if test "x${PBX_NBS}" != "x1" -a "${USE_NBS}" != "no"; then
pbxlibdir=""
@ -25046,7 +24949,7 @@ $as_echo "#define HAVE_PJPROJECT 1" >>confdefs.h
fi
fi
if test "x$PBX_PJPROJECT" = "x1" ; then
if test "x${PBX_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK}" != "x1" -a "${USE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK}" != "no"; then
pbxlibdir=""
@ -25240,10 +25143,10 @@ fi
saved_cppflags="${CPPFLAGS}"
saved_libs="${LIBS}"
CPPFLAGS="${CPPFLAGS} ${PJPROJECT_CFLAGS}"
LIBS="${LIBS} ${PJPROJECT_LIB}"
saved_cppflags="${CPPFLAGS}"
saved_libs="${LIBS}"
CPPFLAGS="${CPPFLAGS} ${PJPROJECT_CFLAGS}"
LIBS="${LIBS} ${PJPROJECT_LIB}"
if test "x${PBX_PJSIP_REPLACE_MEDIA_STREAM}" != "x1" -a "${USE_PJSIP_REPLACE_MEDIA_STREAM}" != "no"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if \"pjmedia_mod_offer_flag flag = PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE\" compiles using pjmedia.h" >&5
@ -25284,8 +25187,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
CPPFLAGS="${saved_cppflags}"
fi
LIBS="${saved_libs}"
CPPFLAGS="${saved_cppflags}"
LIBS="${saved_libs}"
CPPFLAGS="${saved_cppflags}"
if test "x${PBX_PJSIP_GET_DEST_INFO}" != "x1" -a "${USE_PJSIP_GET_DEST_INFO}" != "no"; then
@ -25576,10 +25479,10 @@ fi
saved_cppflags="${CPPFLAGS}"
saved_libs="${LIBS}"
CPPFLAGS="${CPPFLAGS} ${PJPROJECT_CFLAGS}"
LIBS="${LIBS} ${PJPROJECT_LIB}"
saved_cppflags="${CPPFLAGS}"
saved_libs="${LIBS}"
CPPFLAGS="${CPPFLAGS} ${PJPROJECT_CFLAGS}"
LIBS="${LIBS} ${PJPROJECT_LIB}"
if test "x${PBX_PJSIP_TLS_TRANSPORT_PROTO}" != "x1" -a "${USE_PJSIP_TLS_TRANSPORT_PROTO}" != "no"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if \"struct pjsip_tls_setting setting; int proto; proto = setting.proto;\" compiles using pjsip.h" >&5
@ -25780,8 +25683,45 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
CPPFLAGS="${saved_cppflags}"
fi
LIBS="${saved_libs}"
CPPFLAGS="${saved_cppflags}"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pjproject on_valid_pair callback" >&5
$as_echo_n "checking for pjproject on_valid_pair callback... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#include <pjsip.h>
#include <pjsip_ua.h>
#include <pjnath.h>
void on_valid_pair(pj_ice_sess *ice) {}
void on_ice_complete(pj_ice_sess *ice, pj_status_t status) {}
void on_rx_data(pj_ice_sess *ice, unsigned comp_id, unsigned transport_id, void *pkt, pj_size_t size, const pj_sockaddr_t *src_addr, unsigned src_addr_len) {}
pj_status_t on_tx_pkt(pj_ice_sess *ice, unsigned comp_id, unsigned transport_id, const void *pkt, pj_size_t size, const pj_sockaddr_t *dst_addr, unsigned dst_addr_len) {}
int
main ()
{
pj_ice_sess_cb ice_sess_cb = {
.on_valid_pair = on_valid_pair,
.on_ice_complete = on_ice_complete,
.on_rx_data = on_rx_data,
.on_tx_pkt = on_tx_pkt,
};
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
$as_echo "#define HAVE_PJPROJECT_ON_VALID_ICE_PAIR_CALLBACK 1" >>confdefs.h
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS="${saved_libs}"
CPPFLAGS="${saved_cppflags}"
if test "x${PBX_PJSIP_EVSUB_GRP_LOCK}" != "x1" -a "${USE_PJSIP_EVSUB_GRP_LOCK}" != "no"; then
@ -26167,11 +26107,189 @@ _ACEOF
fi
fi
fi
if test "x$PBX_PJPROJECT" = "x1" ; then
if test "x${AST_DEVMODE}" = "xyes" ; then
if test "x${PBX_PYTHONDEV}" != "x1" -a "${USE_PYTHONDEV}" != "no"; then
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PYTHONDEV" >&5
$as_echo_n "checking for PYTHONDEV... " >&6; }
if test -n "$PYTHONDEV_CFLAGS"; then
pkg_cv_PYTHONDEV_CFLAGS="$PYTHONDEV_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"python-2.7\""; } >&5
($PKG_CONFIG --exists --print-errors "python-2.7") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_PYTHONDEV_CFLAGS=`$PKG_CONFIG --cflags "python-2.7" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test -n "$PYTHONDEV_LIBS"; then
pkg_cv_PYTHONDEV_LIBS="$PYTHONDEV_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"python-2.7\""; } >&5
($PKG_CONFIG --exists --print-errors "python-2.7") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_PYTHONDEV_LIBS=`$PKG_CONFIG --libs "python-2.7" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test $pkg_failed = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
PYTHONDEV_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "python-2.7" 2>&1`
else
PYTHONDEV_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "python-2.7" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$PYTHONDEV_PKG_ERRORS" >&5
PBX_PYTHONDEV=0
elif test $pkg_failed = untried; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
PBX_PYTHONDEV=0
else
PYTHONDEV_CFLAGS=$pkg_cv_PYTHONDEV_CFLAGS
PYTHONDEV_LIBS=$pkg_cv_PYTHONDEV_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
PBX_PYTHONDEV=1
PYTHONDEV_INCLUDE=$(echo ${PYTHONDEV_CFLAGS} | $SED -e "s|-std=c99||g")
PYTHONDEV_LIB="$PYTHONDEV_LIBS"
$as_echo "#define HAVE_PYTHONDEV 1" >>confdefs.h
fi
fi
if test "x${PBX_PYTHONDEV}" != "x1" -a "${USE_PYTHONDEV}" != "no"; then
pkg_failed=no
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PYTHONDEV" >&5
$as_echo_n "checking for PYTHONDEV... " >&6; }
if test -n "$PYTHONDEV_CFLAGS"; then
pkg_cv_PYTHONDEV_CFLAGS="$PYTHONDEV_CFLAGS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"python2\""; } >&5
($PKG_CONFIG --exists --print-errors "python2") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_PYTHONDEV_CFLAGS=`$PKG_CONFIG --cflags "python2" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test -n "$PYTHONDEV_LIBS"; then
pkg_cv_PYTHONDEV_LIBS="$PYTHONDEV_LIBS"
elif test -n "$PKG_CONFIG"; then
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"python2\""; } >&5
($PKG_CONFIG --exists --print-errors "python2") 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
pkg_cv_PYTHONDEV_LIBS=`$PKG_CONFIG --libs "python2" 2>/dev/null`
test "x$?" != "x0" && pkg_failed=yes
else
pkg_failed=yes
fi
else
pkg_failed=untried
fi
if test $pkg_failed = yes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
_pkg_short_errors_supported=yes
else
_pkg_short_errors_supported=no
fi
if test $_pkg_short_errors_supported = yes; then
PYTHONDEV_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "python2" 2>&1`
else
PYTHONDEV_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "python2" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$PYTHONDEV_PKG_ERRORS" >&5
PBX_PYTHONDEV=0
elif test $pkg_failed = untried; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
PBX_PYTHONDEV=0
else
PYTHONDEV_CFLAGS=$pkg_cv_PYTHONDEV_CFLAGS
PYTHONDEV_LIBS=$pkg_cv_PYTHONDEV_LIBS
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
PBX_PYTHONDEV=1
PYTHONDEV_INCLUDE=$(echo ${PYTHONDEV_CFLAGS} | $SED -e "s|-std=c99||g")
PYTHONDEV_LIB="$PYTHONDEV_LIBS"
$as_echo "#define HAVE_PYTHONDEV 1" >>confdefs.h
fi
fi
if test "x${PBX_PYTHONDEV}" != "x1" -a "${USE_PYTHONDEV}" != "no"; then
@ -26260,6 +26378,16 @@ $as_echo "#define HAVE_PYTHONDEV 1" >>confdefs.h
fi
fi
# The PJProject offers a C extension to Python. That wrapper is used by the
# Asterisk Test Framework, which requires Asterisk to be in Developer Mode.
# However, the used wrapper (called 'PJSUA Python') is deprecated and was not
# ported from Python 2.7 to Python 3.x. This is confirmed; it simply does not
# build. For more see <http://www.pjsip.org/trac/wiki/Python_SIP_Tutorial>.
# Therefore, the C libraries for Python 3 are of no help in Asterisk:
#AST_PKG_CONFIG_CHECK([PYTHONDEV], [python3])
fi
fi
fi
if test "x${PBX_POPT}" != "x1" -a "${USE_POPT}" != "no"; then
@ -26639,6 +26767,7 @@ _ACEOF
fi
if test "x$PBX_PRI" = "x1" ; then
if test "x${PBX_PRI_SETUP_ACK_INBAND}" != "x1" -a "${USE_PRI_SETUP_ACK_INBAND}" != "no"; then
pbxlibdir=""
@ -28176,9 +28305,9 @@ fi
# ------------------------------------v
# TODO: The code can be changed to always include these features now.
# These features will always be present if pri_connected_line_update is available.
# ------------------------------------v
# TODO: The code can be changed to always include these features now.
# These features will always be present if pri_connected_line_update is available.
if test "x${PBX_PRI_PROG_W_CAUSE}" != "x1" -a "${USE_PRI_PROG_W_CAUSE}" != "no"; then
pbxlibdir=""
@ -28563,7 +28692,8 @@ _ACEOF
fi
# ------------------------------------^
# ------------------------------------^
fi
if test "x${PBX_RESAMPLE}" != "x1" -a "${USE_RESAMPLE}" != "no"; then
@ -32657,7 +32787,7 @@ fi
fi
fi
for ver in 2.0 2.2 2.4 2.6 3.0; do
for ver in 3.0 2.6 2.4 2.2 2.0; do
if test "x${PBX_GMIME}" != "x1" -a "${USE_GMIME}" != "no"; then
@ -36166,9 +36296,9 @@ fi
${ac_cv_path_EGREP} 'CURSES|GTK2|OSARCH|NEWT' makeopts > makeopts.acbak2
if test "x${ac_cv_path_CMP}" = "x:"; then
( cd `pwd`/menuselect && ./configure )
( cd "`pwd`/menuselect" && ./configure )
elif ${ac_cv_path_CMP} -s makeopts.acbak makeopts.acbak2; then : ; else
( cd `pwd`/menuselect && ./configure )
( cd "`pwd`/menuselect" && ./configure )
fi
rm makeopts.acbak makeopts.acbak2

View File

@ -230,6 +230,8 @@ then
AC_CHECK_TOOL(CXX, g++, :)
AC_CHECK_TOOL(LD, ld, :)
AC_CHECK_TOOL(RANLIB, ranlib, :)
CROSS_COMPILING=1
AC_SUBST(CROSS_COMPILING)
fi
# Checks for programs.
@ -261,9 +263,8 @@ AC_PATH_PROG([CAT], [cat], :)
AC_PATH_PROG([CUT], [cut], :)
AC_PATH_PROG([FLEX], [flex], :)
AC_PATH_PROG([GREP], [grep], :)
AC_PATH_PROG([PYTHON], [python], :)
AC_PATH_PROGS([PYTHON], [python2.7 python2 python python3], :)
AC_PATH_PROG([FIND], [find], :)
AC_PATH_PROG([COMPRESS], [compress], :)
AC_PATH_PROG([BASENAME], [basename], :)
AC_PATH_PROG([DIRNAME], [dirname], :)
AC_PATH_PROG([SHELL], [sh], :)
@ -272,9 +273,6 @@ AC_PATH_PROG([DOXYGEN], [doxygen], :)
AC_PATH_PROG([DOT], [dot], :)
AC_PATH_PROG([WGET], [wget], :)
AC_PATH_PROG([CURL], [curl], :)
AC_PATH_PROG([RUBBER], [rubber], :)
AC_PATH_PROG([CATDVI], [catdvi], :)
AC_PATH_PROG([KPATHSEA], [kpsewhich], :)
AC_PATH_PROG([XMLLINT], [xmllint], :)
AC_PATH_PROGS([XMLSTARLET], [xmlstarlet xml], :)
AC_PATH_PROG([BASH], [bash], :)
@ -1677,7 +1675,7 @@ if test "${USE_IMAP_TK}" != "no"; then
saved_libs="${LIBS}"
switch_to_system_on_failure="no"
if test "${IMAP_TK_DIR}" = ""; then
IMAP_TK_DIR=`pwd`"/../imap-2004g"
IMAP_TK_DIR="`pwd`/../imap-2004g"
switch_to_system_on_failure="yes"
fi
if test "${IMAP_TK_DIR}" != "system"; then
@ -2279,8 +2277,28 @@ if test "${PBX_MISDN}" = 1; then
AC_CHECK_MEMBER([Q931_info_t.redirect_dn], [], [PBX_MISDN=0], [#include <mISDNuser/mISDNlib.h>])
fi
AST_EXT_TOOL_CHECK([MYSQLCLIENT], [mysql_config])
if test "${PBX_MYSQLCLIENT}" = 1; then
AC_MSG_CHECKING(for MySQL client bool support)
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([#include <mysql/mysql.h>],
[bool test = 1;])],
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_MYSQLCLIENT_BOOL, 1, [Define to 1 if mysql/mysql.h has bool defined.]),
AC_MSG_RESULT(no)
)
AC_MSG_CHECKING(for MySQL client my_bool support)
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([#include <mysql/mysql.h>],
[my_bool test = 1;])],
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_MYSQLCLIENT_MY_BOOL, 1, [Define to 1 if mysql/mysql.h has my_bool defined.]),
AC_MSG_RESULT(no)
)
fi
AST_EXT_LIB_CHECK([NBS], [nbs], [nbs_connect], [nbs.h])
AST_EXT_TOOL_CHECK([NEON], [neon-config])
@ -2391,76 +2409,112 @@ fi
if test "$USE_PJPROJECT" != "no" ; then
if test "$PJPROJECT_BUNDLED" = "no" ; then
AST_PKG_CONFIG_CHECK([PJPROJECT], [libpjproject])
if test "x$PBX_PJPROJECT" = "x1" ; then
AST_EXT_LIB_CHECK([PJSIP_DLG_CREATE_UAS_AND_INC_LOCK], [pjsip], [pjsip_dlg_create_uas_and_inc_lock], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
AST_EXT_LIB_CHECK([PJ_TRANSACTION_GRP_LOCK], [pjsip], [pjsip_tsx_create_uac2], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
AST_EXT_LIB_CHECK([PJSIP_DLG_CREATE_UAS_AND_INC_LOCK], [pjsip], [pjsip_dlg_create_uas_and_inc_lock], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
AST_EXT_LIB_CHECK([PJ_TRANSACTION_GRP_LOCK], [pjsip], [pjsip_tsx_create_uac2], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
saved_cppflags="${CPPFLAGS}"
saved_libs="${LIBS}"
CPPFLAGS="${CPPFLAGS} ${PJPROJECT_CFLAGS}"
LIBS="${LIBS} ${PJPROJECT_LIB}"
AST_C_COMPILE_CHECK([PJSIP_REPLACE_MEDIA_STREAM], [pjmedia_mod_offer_flag flag = PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE], [pjmedia.h])
LIBS="${saved_libs}"
CPPFLAGS="${saved_cppflags}"
saved_cppflags="${CPPFLAGS}"
saved_libs="${LIBS}"
CPPFLAGS="${CPPFLAGS} ${PJPROJECT_CFLAGS}"
LIBS="${LIBS} ${PJPROJECT_LIB}"
AST_C_COMPILE_CHECK([PJSIP_REPLACE_MEDIA_STREAM], [pjmedia_mod_offer_flag flag = PJMEDIA_SDP_NEG_ALLOW_MEDIA_CHANGE], [pjmedia.h])
LIBS="${saved_libs}"
CPPFLAGS="${saved_cppflags}"
AST_EXT_LIB_CHECK([PJSIP_GET_DEST_INFO], [pjsip], [pjsip_get_dest_info], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
AST_EXT_LIB_CHECK([PJ_SSL_CERT_LOAD_FROM_FILES2], [pj], [pj_ssl_cert_load_from_files2], [pjlib.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
AST_EXT_LIB_CHECK([PJSIP_EXTERNAL_RESOLVER], [pjsip], [pjsip_endpt_set_ext_resolver], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
AST_EXT_LIB_CHECK([PJSIP_GET_DEST_INFO], [pjsip], [pjsip_get_dest_info], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
AST_EXT_LIB_CHECK([PJ_SSL_CERT_LOAD_FROM_FILES2], [pj], [pj_ssl_cert_load_from_files2], [pjlib.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
AST_EXT_LIB_CHECK([PJSIP_EXTERNAL_RESOLVER], [pjsip], [pjsip_endpt_set_ext_resolver], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
saved_cppflags="${CPPFLAGS}"
saved_libs="${LIBS}"
CPPFLAGS="${CPPFLAGS} ${PJPROJECT_CFLAGS}"
LIBS="${LIBS} ${PJPROJECT_LIB}"
AST_C_COMPILE_CHECK([PJSIP_TLS_TRANSPORT_PROTO], [struct pjsip_tls_setting setting; int proto; proto = setting.proto;], [pjsip.h])
AST_C_COMPILE_CHECK([PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS], [pjsip_cfg()->endpt.accept_multiple_sdp_answers = 0;], [pjsip.h])
AST_C_COMPILE_CHECK([PJSIP_ENDPOINT_COMPACT_FORM], [pjsip_cfg()->endpt.use_compact_form = PJ_TRUE;], [pjsip.h])
AST_C_COMPILE_CHECK([PJSIP_TRANSPORT_DISABLE_CONNECTION_REUSE], [struct pjsip_tpselector sel; sel.disable_connection_reuse = PJ_TRUE;], [pjsip.h])
AST_C_COMPILE_CHECK([PJSIP_OAUTH_AUTHENTICATION], [struct pjsip_oauth_credential credential;], [pjsip.h])
AC_MSG_CHECKING(for pjproject on_valid_pair callback)
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[#include <pjsip.h>
#include <pjsip_ua.h>
#include <pjnath.h>
void on_valid_pair(pj_ice_sess *ice) {}
void on_ice_complete(pj_ice_sess *ice, pj_status_t status) {}
void on_rx_data(pj_ice_sess *ice, unsigned comp_id, unsigned transport_id, void *pkt, pj_size_t size, const pj_sockaddr_t *src_addr, unsigned src_addr_len) {}
pj_status_t on_tx_pkt(pj_ice_sess *ice, unsigned comp_id, unsigned transport_id, const void *pkt, pj_size_t size, const pj_sockaddr_t *dst_addr, unsigned dst_addr_len) {}],
[pj_ice_sess_cb ice_sess_cb = {
.on_valid_pair = on_valid_pair,
.on_ice_complete = on_ice_complete,
.on_rx_data = on_rx_data,
.on_tx_pkt = on_tx_pkt,
};])],
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_PJPROJECT_ON_VALID_ICE_PAIR_CALLBACK, 1, [Define to 1 if on_valid_pair callback is present.]),
AC_MSG_RESULT(no)
)
LIBS="${saved_libs}"
CPPFLAGS="${saved_cppflags}"
saved_cppflags="${CPPFLAGS}"
saved_libs="${LIBS}"
CPPFLAGS="${CPPFLAGS} ${PJPROJECT_CFLAGS}"
LIBS="${LIBS} ${PJPROJECT_LIB}"
AST_C_COMPILE_CHECK([PJSIP_TLS_TRANSPORT_PROTO], [struct pjsip_tls_setting setting; int proto; proto = setting.proto;], [pjsip.h])
AST_C_COMPILE_CHECK([PJSIP_INV_ACCEPT_MULTIPLE_SDP_ANSWERS], [pjsip_cfg()->endpt.accept_multiple_sdp_answers = 0;], [pjsip.h])
AST_C_COMPILE_CHECK([PJSIP_ENDPOINT_COMPACT_FORM], [pjsip_cfg()->endpt.use_compact_form = PJ_TRUE;], [pjsip.h])
AST_C_COMPILE_CHECK([PJSIP_TRANSPORT_DISABLE_CONNECTION_REUSE], [struct pjsip_tpselector sel; sel.disable_connection_reuse = PJ_TRUE;], [pjsip.h])
AST_C_COMPILE_CHECK([PJSIP_OAUTH_AUTHENTICATION], [struct pjsip_oauth_credential credential;], [pjsip.h])
LIBS="${saved_libs}"
CPPFLAGS="${saved_cppflags}"
AST_EXT_LIB_CHECK([PJSIP_EVSUB_GRP_LOCK], [pjsip], [pjsip_evsub_add_ref], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
AST_EXT_LIB_CHECK([PJSIP_INV_SESSION_REF], [pjsip], [pjsip_inv_add_ref], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
AST_EXT_LIB_CHECK([PJSIP_AUTH_CLT_DEINIT], [pjsip], [pjsip_auth_clt_deinit], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
AST_EXT_LIB_CHECK([PJSIP_TSX_LAYER_FIND_TSX2], [pjsip], [pjsip_tsx_layer_find_tsx2], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
fi
fi
AST_EXT_LIB_CHECK([PJSIP_EVSUB_GRP_LOCK], [pjsip], [pjsip_evsub_add_ref], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
AST_EXT_LIB_CHECK([PJSIP_INV_SESSION_REF], [pjsip], [pjsip_inv_add_ref], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
AST_EXT_LIB_CHECK([PJSIP_AUTH_CLT_DEINIT], [pjsip], [pjsip_auth_clt_deinit], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
AST_EXT_LIB_CHECK([PJSIP_TSX_LAYER_FIND_TSX2], [pjsip], [pjsip_tsx_layer_find_tsx2], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
if test "x$PBX_PJPROJECT" = "x1" ; then
if test "x${AST_DEVMODE}" = "xyes" ; then
AC_SUBST([PYTHONDEV_LIB])
AC_SUBST([PYTHONDEV_INCLUDE])
AST_PKG_CONFIG_CHECK([PYTHONDEV], [python-2.7])
AST_PKG_CONFIG_CHECK([PYTHONDEV], [python2])
AST_PKG_CONFIG_CHECK([PYTHONDEV], [python])
# The PJProject offers a C extension to Python. That wrapper is used by the
# Asterisk Test Framework, which requires Asterisk to be in Developer Mode.
# However, the used wrapper (called 'PJSUA Python') is deprecated and was not
# ported from Python 2.7 to Python 3.x. This is confirmed; it simply does not
# build. For more see <http://www.pjsip.org/trac/wiki/Python_SIP_Tutorial>.
# Therefore, the C libraries for Python 3 are of no help in Asterisk:
#AST_PKG_CONFIG_CHECK([PYTHONDEV], [python3])
fi
fi
fi
AC_SUBST([PYTHONDEV_LIB])
AC_SUBST([PYTHONDEV_INCLUDE])
AST_PKG_CONFIG_CHECK([PYTHONDEV], [python])
AST_EXT_LIB_CHECK([POPT], [popt], [poptStrerror], [popt.h])
AST_PKG_CONFIG_CHECK([PORTAUDIO], [portaudio-2.0])
AST_EXT_LIB_CHECK([PORTAUDIO], [portaudio], [Pa_GetDeviceCount], [portaudio.h])
AST_EXT_LIB_CHECK([PRI], [pri], [pri_connected_line_update], [libpri.h])
AST_EXT_LIB_CHECK([PRI_SETUP_ACK_INBAND], [pri], [pri_setup_ack], [libpri.h])
AST_EXT_LIB_CHECK([PRI_L2_PERSISTENCE], [pri], [pri_persistent_layer2_option], [libpri.h])
AST_EXT_LIB_CHECK([PRI_DATETIME_SEND], [pri], [pri_date_time_send_option], [libpri.h])
AST_EXT_LIB_CHECK([PRI_MWI_V2], [pri], [pri_mwi_indicate_v2], [libpri.h])
AST_EXT_LIB_CHECK([PRI_DISPLAY_TEXT], [pri], [pri_display_text], [libpri.h])
AST_EXT_LIB_CHECK([PRI_MWI], [pri], [pri_mwi_indicate], [libpri.h])
AST_EXT_LIB_CHECK([PRI_MCID], [pri], [pri_mcid_enable], [libpri.h])
AST_EXT_LIB_CHECK([PRI_CALL_WAITING], [pri], [pri_connect_ack_enable], [libpri.h])
AST_EXT_LIB_CHECK([PRI_AOC_EVENTS], [pri], [pri_aoc_events_enable], [libpri.h])
AST_EXT_LIB_CHECK([PRI_TRANSFER], [pri], [pri_transfer_enable], [libpri.h])
AST_EXT_LIB_CHECK([PRI_CCSS], [pri], [pri_cc_enable], [libpri.h])
AST_EXT_LIB_CHECK([PRI_HANGUP_FIX], [pri], [pri_hangup_fix_enable], [libpri.h])
AST_EXT_LIB_CHECK([PRI_SUBADDR], [pri], [pri_sr_set_called_subaddress], [libpri.h])
AST_EXT_LIB_CHECK([PRI_CALL_HOLD], [pri], [pri_hold_enable], [libpri.h])
AST_EXT_LIB_CHECK([PRI_CALL_REROUTING], [pri], [pri_reroute_enable], [libpri.h])
AST_EXT_LIB_CHECK([PRI_SETUP_KEYPAD], [pri], [pri_sr_set_keypad_digits], [libpri.h])
if test "x$PBX_PRI" = "x1" ; then
AST_EXT_LIB_CHECK([PRI_SETUP_ACK_INBAND], [pri], [pri_setup_ack], [libpri.h])
AST_EXT_LIB_CHECK([PRI_L2_PERSISTENCE], [pri], [pri_persistent_layer2_option], [libpri.h])
AST_EXT_LIB_CHECK([PRI_DATETIME_SEND], [pri], [pri_date_time_send_option], [libpri.h])
AST_EXT_LIB_CHECK([PRI_MWI_V2], [pri], [pri_mwi_indicate_v2], [libpri.h])
AST_EXT_LIB_CHECK([PRI_DISPLAY_TEXT], [pri], [pri_display_text], [libpri.h])
AST_EXT_LIB_CHECK([PRI_MWI], [pri], [pri_mwi_indicate], [libpri.h])
AST_EXT_LIB_CHECK([PRI_MCID], [pri], [pri_mcid_enable], [libpri.h])
AST_EXT_LIB_CHECK([PRI_CALL_WAITING], [pri], [pri_connect_ack_enable], [libpri.h])
AST_EXT_LIB_CHECK([PRI_AOC_EVENTS], [pri], [pri_aoc_events_enable], [libpri.h])
AST_EXT_LIB_CHECK([PRI_TRANSFER], [pri], [pri_transfer_enable], [libpri.h])
AST_EXT_LIB_CHECK([PRI_CCSS], [pri], [pri_cc_enable], [libpri.h])
AST_EXT_LIB_CHECK([PRI_HANGUP_FIX], [pri], [pri_hangup_fix_enable], [libpri.h])
AST_EXT_LIB_CHECK([PRI_SUBADDR], [pri], [pri_sr_set_called_subaddress], [libpri.h])
AST_EXT_LIB_CHECK([PRI_CALL_HOLD], [pri], [pri_hold_enable], [libpri.h])
AST_EXT_LIB_CHECK([PRI_CALL_REROUTING], [pri], [pri_reroute_enable], [libpri.h])
AST_EXT_LIB_CHECK([PRI_SETUP_KEYPAD], [pri], [pri_sr_set_keypad_digits], [libpri.h])
# ------------------------------------v
# TODO: The code can be changed to always include these features now.
# These features will always be present if pri_connected_line_update is available.
AST_EXT_LIB_CHECK([PRI_PROG_W_CAUSE], [pri], [pri_progress_with_cause], [libpri.h])
AST_EXT_LIB_CHECK([PRI_INBANDDISCONNECT], [pri], [pri_set_inbanddisconnect], [libpri.h])
AST_EXT_LIB_CHECK([PRI_SERVICE_MESSAGES], [pri], [pri_maintenance_service], [libpri.h])
AST_EXT_LIB_CHECK([PRI_REVERSE_CHARGE], [pri], [pri_sr_set_reversecharge], [libpri.h])
# ------------------------------------^
# ------------------------------------v
# TODO: The code can be changed to always include these features now.
# These features will always be present if pri_connected_line_update is available.
AST_EXT_LIB_CHECK([PRI_PROG_W_CAUSE], [pri], [pri_progress_with_cause], [libpri.h])
AST_EXT_LIB_CHECK([PRI_INBANDDISCONNECT], [pri], [pri_set_inbanddisconnect], [libpri.h])
AST_EXT_LIB_CHECK([PRI_SERVICE_MESSAGES], [pri], [pri_maintenance_service], [libpri.h])
AST_EXT_LIB_CHECK([PRI_REVERSE_CHARGE], [pri], [pri_sr_set_reversecharge], [libpri.h])
# ------------------------------------^
fi
AST_EXT_LIB_CHECK([RESAMPLE], [resample], [resample_open], [libresample.h], [-lm])
AST_EXT_LIB_CHECK([FFTW3], [fftw3], [fftw_malloc], [fftw3.h])
@ -2659,7 +2713,7 @@ then
fi
fi
for ver in 2.0 2.2 2.4 2.6 3.0; do
for ver in 3.0 2.6 2.4 2.2 2.0; do
AST_PKG_CONFIG_CHECK([GMIME], gmime-$ver)
if test "$PBX_GMIME" = 1; then
break;
@ -2853,9 +2907,9 @@ AC_OUTPUT
${ac_cv_path_EGREP} 'CURSES|GTK2|OSARCH|NEWT' makeopts > makeopts.acbak2
if test "x${ac_cv_path_CMP}" = "x:"; then
( cd `pwd`/menuselect && ./configure )
( cd "`pwd`/menuselect" && ./configure )
elif ${ac_cv_path_CMP} -s makeopts.acbak makeopts.acbak2; then : ; else
( cd `pwd`/menuselect && ./configure )
( cd "`pwd`/menuselect" && ./configure )
fi
rm makeopts.acbak makeopts.acbak2

View File

@ -11,6 +11,7 @@ repositories include:
* `cdr` - Table used for Asterisk to store CDR records
* `config` - Tables used for Asterisk realtime configuration
* `queue_log` - Table used for Asterisk to store Queue Log records
* `voicemail` - Tables used for `ODBC_STOARGE` of voicemail messages
Alembic uses SQLAlchemy, which has support for

View File

@ -0,0 +1,54 @@
"""add playlist to moh
Revision ID: fbb7766f17bc
Revises: 3a094a18e75b
Create Date: 2019-09-18 10:24:18.731798
"""
# revision identifiers, used by Alembic.
revision = 'fbb7766f17bc'
down_revision = '3a094a18e75b'
from alembic import op
import sqlalchemy as sa
def enum_update(table_name, column_name, enum_name, enum_values):
if op.get_context().bind.dialect.name != 'postgresql':
if op.get_context().bind.dialect.name == 'mssql':
op.drop_constraint('ck_musiconhold_mode_moh_mode_values', 'musiconhold')
op.alter_column(table_name, column_name,
type_=sa.Enum(*enum_values, name=enum_name))
return
# Postgres requires a few more steps
tmp = enum_name + '_tmp'
op.execute('ALTER TYPE ' + enum_name + ' RENAME TO ' + tmp)
updated = sa.Enum(*enum_values, name=enum_name)
updated.create(op.get_bind(), checkfirst=False)
op.execute('ALTER TABLE ' + table_name + ' ALTER COLUMN ' + column_name +
' TYPE ' + enum_name + ' USING mode::text::' + enum_name)
op.execute('DROP TYPE ' + tmp)
def upgrade():
op.create_table(
'musiconhold_entry',
sa.Column('name', sa.String(80), primary_key=True, nullable=False),
sa.Column('position', sa.Integer, primary_key=True, nullable=False),
sa.Column('entry', sa.String(1024), nullable=False)
)
op.create_foreign_key('fk_musiconhold_entry_name_musiconhold', 'musiconhold_entry', 'musiconhold', ['name'], ['name'])
enum_update('musiconhold', 'mode', 'moh_mode_values',
['custom', 'files', 'mp3nb', 'quietmp3nb', 'quietmp3', 'playlist'])
def downgrade():
enum_update('musiconhold', 'mode', 'moh_mode_values',
['custom', 'files', 'mp3nb', 'quietmp3nb', 'quietmp3'])
op.drop_table('musiconhold_entry')

View File

@ -0,0 +1,58 @@
# A generic, single database configuration.
[alembic]
# path to migration scripts
script_location = queue_log
# template used to generate migration files
# file_template = %%(rev)s_%%(slug)s
# max length of characters to apply to the
# "slug" field
#truncate_slug_length = 40
# set to 'true' to run the environment during
# the 'revision' command, regardless of autogenerate
# revision_environment = false
#sqlalchemy.url = driver://user:pass@localhost/dbname
#sqlalchemy.url = mysql://user:pass@localhost/queue_log
sqlalchemy.url = postgresql://user:pass@localhost/queue_log
# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = WARN
handlers = console
qualname =
[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine
[logger_alembic]
level = INFO
handlers =
qualname = alembic
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S

View File

@ -0,0 +1 @@
../env.py

View File

@ -0,0 +1,24 @@
"""${message}
Revision ID: ${up_revision}
Revises: ${down_revision | comma,n}
Create Date: ${create_date}
"""
# revision identifiers, used by Alembic.
revision = ${repr(up_revision)}
down_revision = ${repr(down_revision)}
branch_labels = ${repr(branch_labels)}
depends_on = ${repr(depends_on)}
from alembic import op
import sqlalchemy as sa
${imports if imports else ""}
def upgrade():
${upgrades if upgrades else "pass"}
def downgrade():
${downgrades if downgrades else "pass"}

View File

@ -0,0 +1,38 @@
"""create queue_log table
Revision ID: 4105ee839f58
Revises:
Create Date: 2016-09-30 22:32:45.918340
"""
# revision identifiers, used by Alembic.
revision = '4105ee839f58'
down_revision = None
branch_labels = None
depends_on = None
from alembic import op
import sqlalchemy as sa
def upgrade():
op.create_table(
'queue_log',
sa.Column('id', sa.BigInteger, primary_key=True, nullable=False,
unique=True, autoincrement=True),
sa.Column('time', sa.DateTime()),
sa.Column('callid', sa.String(80)),
sa.Column('queuename', sa.String(256)),
sa.Column('agent', sa.String(80)),
sa.Column('event', sa.String(32)),
sa.Column('data1', sa.String(100)),
sa.Column('data2', sa.String(100)),
sa.Column('data3', sa.String(100)),
sa.Column('data4', sa.String(100)),
sa.Column('data5', sa.String(100))
)
def downgrade():
op.drop_table('queue_log')

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -383,14 +383,9 @@ if $running || $RUNNING ; then
unset pid
# Simplest case first...
pids=$(pgrep -f "$asterisk_bin")
pids=$(pgrep -f "$asterisk_bin" || : )
pidcount=$(echo $pids | wc -w)
if [ $pidcount -eq 0 ] ; then
>&2 echo "Asterisk is not running"
exit 1
fi
# Single process, great.
if [ $pidcount -eq 1 ] ; then
pid=$pids
@ -552,7 +547,7 @@ if $delete_coredumps_after ; then
fi
if $delete_results_after ; then
rm -rf "${cf//:/-}"-{brief,full,thread1,locks}.txt
rm -rf "${cf//:/-}"-{brief,full,thread1,locks,info}.txt
fi
done
@ -568,12 +563,400 @@ exit
#@@@SCRIPTSTART@@@
python
import datetime
def timeval_to_datetime(value):
"""Convert a timeval struct to a python datetime object
Args:
value: A gdb Value representing a C timeval
Return:
A python datetime object
"""
sec = int(value['tv_sec'])
usec = int(value['tv_usec'])
return datetime.datetime.fromtimestamp(sec + usec / float(1000000))
def s_strip(value):
"""Convert the given value to a string, and strip any leading/trailing
spaces and/or quotes.
Args:
name: The gdb Value to convert and strip
Return:
The stripped value as a string
"""
if value == None:
return "None"
try:
if 'char *' not in str(value.type) and 'char [' not in str(value.type):
# Use the string method for everything but string pointers (only
# points to first letter) and non-string values in general
return value.string().strip('" ') or "<None>"
except:
pass
return str(value).strip('" ') or "<None>"
def get(name):
"""Retrieve a named variable's value as a string using GDB.
Args:
name: The name of the variable to look up
Return:
The variable's value as a string
"""
return s_strip(gdb.parse_and_eval(name))
def get_container_hash_objects(name, type, on_object=None):
"""Retrieve a list of objects from an ao2_container_hash.
Expected on_object signature:
res, stop = on_object(GDB Value)
The given callback, on_object, is called for each object found in the
container. The callback is passed a dereferenced GDB Value object and
expects an object to be returned, which is then appended to a list of
objects to be returned by this function. Iteration can be stopped by
returning "True" for the second return value.
If on_object is not specified then the dereferenced GDB value is instead
added directly to the returned list.
Args:
name: The name of the ao2_container
type: The type of objects stored in the container
on_object: Optional function called on each object found
Return:
A list of container objects
"""
objs = []
try:
container = gdb.parse_and_eval(name).cast(
gdb.lookup_type('struct ao2_container_hash').pointer())
# Loop over every bucket searching for hash bucket nodes
for n in range(container['n_buckets']):
node = container['buckets'][n]['list']['last']
while node:
# Each node holds the needed object
obj = node.dereference()['common']['obj'].cast(
gdb.lookup_type(type).pointer()).dereference()
res, stop = on_object(obj) if on_object else (obj, False)
if res:
objs.append(res)
if stop:
return objs
node = node.dereference()['links']['last']
except Exception as e:
print("{0} - {1}".format(name, e))
pass
return objs
def get_container_rbtree_objects(name, type, on_object=None):
"""Retrieve a list of objects from an ao2_container_rbtree.
Expected on_object signature:
res, stop = on_object(GDB Value)
The given callback, on_object, is called for each object found in the
container. The callback is passed a dereferenced GDB Value object and
expects an object to be returned, which is then appended to a list of
objects to be returned by this function. Iteration can be stopped by
returning "True" for the second return value.
If on_object is not specified then the dereferenced GDB value is instead
added directly to the returned list.
Args:
name: The name of the ao2_container
type: The type of objects stored in the container
on_object: Optional function called on each object found
Return:
A list of container objects
"""
objs = []
def handle_node(node):
if not node:
return True
# Each node holds the needed object
obj = node.dereference()['common']['obj'].cast(
gdb.lookup_type(type).pointer()).dereference()
res, stop = on_object(obj) if on_object else (obj, False)
if res:
objs.append(res)
return not stop and (handle_node(node['left']) and
handle_node(node['right']))
try:
container = gdb.parse_and_eval(name).cast(
gdb.lookup_type('struct ao2_container_rbtree').pointer())
handle_node(container['root'])
except Exception as e:
print("{0} - {1}".format(name, e))
pass
return objs
def build_info():
try:
return ("Asterisk {0} built by {1} @ {2} on a {3} running {4} on {5}"
.format(get("asterisk_version"),
get("ast_build_user"),
get("ast_build_hostname"),
get("ast_build_machine"),
get("ast_build_os"),
get("ast_build_date")))
except:
return "Unable to retrieve build info"
def build_opts():
try:
return get("asterisk_build_opts")
except:
return "Unable to retrieve build options"
def uptime():
try:
started = timeval_to_datetime(gdb.parse_and_eval("ast_startuptime"))
loaded = timeval_to_datetime(gdb.parse_and_eval("ast_lastreloadtime"))
return ("System started: {0}\n"
"Last reload: {1}".format(started, loaded))
except:
return "Unable to retrieve uptime"
class TaskProcessor(object):
template = ("{name:70} {processed:>10} {in_queue:>10} {max_depth:>10} "
"{low_water:>10} {high_water:>10}")
header = {'name': 'Processor', 'processed': 'Processed',
'in_queue': 'In Queue', 'max_depth': 'Max Depth',
'low_water': 'Low water', 'high_water': 'High water'}
@staticmethod
def objects():
try:
objs = get_container_hash_objects('tps_singletons',
'struct ast_taskprocessor', TaskProcessor.from_value)
objs.sort(key=lambda x: x.name.lower())
except Exception as e:
return []
return objs
@staticmethod
def from_value(value):
return TaskProcessor(
value['name'],
value['stats']['_tasks_processed_count'],
value['tps_queue_size'],
value['stats']['max_qsize'],
value['tps_queue_low'],
value['tps_queue_high']), False
def __init__(self, name, processed, in_queue, max_depth,
low_water, high_water):
self.name = s_strip(name)
self.processed = int(processed)
self.in_queue = int(in_queue)
self.max_depth = int(max_depth)
self.low_water = int(low_water)
self.high_water = int(high_water)
class Channel(object):
template = ("{name:30} {context:>20} {exten:>20} {priority:>10} {state:>25} "
"{app:>20} {data:>30} {caller_id:>15} {created:>30} "
"{account_code:>15} {peer_account:>15} {bridge_id:>38}")
header = {'name': 'Channel', 'context': 'Context', 'exten': 'Extension',
'priority': 'Priority', 'state': "State", 'app': 'Application',
'data': 'Data', 'caller_id': 'CallerID', 'created': 'Created',
'account_code': 'Accountcode', 'peer_account': 'PeerAccount',
'bridge_id': 'BridgeID'}
@staticmethod
def objects():
try:
objs = get_container_hash_objects('channels',
'struct ast_channel', Channel.from_value)
objs.sort(key=lambda x: x.name.lower())
except:
return []
return objs
@staticmethod
def from_value(value):
bridge_id = None
if value['bridge']:
bridge_id = value['bridge']['uniqueid']
return Channel(
value['name'],
value['context'],
value['exten'],
value['priority'],
value['state'],
value['appl'],
value['data'],
value['caller']['id']['number']['str'],
timeval_to_datetime(value['creationtime']),
value['accountcode'],
value['peeraccount'],
bridge_id), False
@staticmethod
def summary():
try:
return ("{0} active channels\n"
"{1} active calls\n"
"{2} calls processed".format(
int(gdb.parse_and_eval(
'channels').dereference()['elements']),
get("countcalls"),
get("totalcalls")))
except:
return "Unable to retrieve channel summary"
def __init__(self, name, context=None, exten=None, priority=None,
state=None, app=None, data=None, caller_id=None,
created=None, account_code=None, peer_account=None,
bridge_id=None):
self.name = s_strip(name)
self.context = s_strip(context)
self.exten = s_strip(exten)
self.priority = int(priority)
self.state = s_strip(state)
self.app = s_strip(app)
self.data = s_strip(data)
self.caller_id = s_strip(caller_id)
self.created = s_strip(created)
self.account_code = s_strip(account_code)
self.peer_account = s_strip(peer_account)
self.bridge_id = s_strip(bridge_id)
class Bridge(object):
template = ("{uniqueid:38} {num_channels:>15} {subclass:>10} {tech:>20} "
"{created:>30}")
header = {'uniqueid': 'Bridge-ID', 'num_channels': 'Chans',
'subclass': 'Type', 'tech': 'Technology', 'created': 'Created'}
@staticmethod
def objects():
try:
objs = get_container_rbtree_objects('bridges',
'struct ast_bridge', Bridge.from_value)
objs.sort(key=lambda x: x.uniqueid.lower())
except:
return []
return objs
@staticmethod
def from_value(value):
return Bridge(
value['uniqueid'],
value['num_channels'],
timeval_to_datetime(value['creationtime']),
value['v_table']['name'],
value['technology']['name']), False
def __init__(self, uniqueid, num_channels=None, created=None, subclass=None,
tech=None):
self.uniqueid = s_strip(uniqueid)
self.num_channels = int(num_channels)
self.created = s_strip(created)
self.subclass = s_strip(subclass)
self.tech = s_strip(tech)
class DumpAsteriskCommand(gdb.Command):
def __init__(self):
super(DumpAsteriskCommand, self).__init__ ("dump-asterisk",
gdb.COMMAND_OBSCURE, gdb.COMPLETE_COMMAND)
def print_table(self, type):
plural = "{0}s".format(type.__name__)
objs = type.objects()
if not len(objs):
print("{0} not found\n".format(plural))
return
print("{0} ({1}):\n".format(plural, len(objs)))
print(type.template.format(**type.header))
for obj in objs:
print(type.template.format(**vars(obj)))
print("\n")
def invoke(self, arg, from_tty):
try:
gdb.execute("interrupt", from_tty)
@ -619,6 +1002,26 @@ class DumpAsteriskCommand(gdb.Command):
gdb.execute("show_locks", from_tty)
except:
pass
print("!@!@!@! info.txt !@!@!@!\n")
gdb.execute('set print addr off')
try:
print("{0}\n".format(build_info()))
print("{0}\n".format(uptime()))
print("Build options = {0}\n".format(build_opts()))
self.print_table(TaskProcessor)
self.print_table(Bridge)
self.print_table(Channel)
print(Channel.summary())
except:
pass
finally:
gdb.execute('set print addr on')
try:
gdb.execute("continue", from_tty)
except:

View File

@ -49,7 +49,7 @@ create_ca () {
create_cert () {
local base=${OUTPUT_DIR}/${OUTPUT_BASE}
echo "Creating certificate ${base}.key"
openssl genrsa -out ${base}.key 1024 > /dev/null
openssl genrsa -out ${base}.key ${KEYBITS:-1024} > /dev/null
if [ $? -ne 0 ];
then
echo "Failed"
@ -87,6 +87,7 @@ OPTIONS:
-f Config filename (openssl config file format)
-c CA cert filename (creates new CA cert/key as ca.crt/ca.key if not passed)
-k CA key filename
-b The desired size of the private key in bits. Default is 1024.
-C Common name (cert field)
This should be the fully qualified domain name or IP address for
the client or server. Make sure your certs have unique common
@ -128,7 +129,7 @@ OUTPUT_BASE=asterisk # Our default cert basename
CERT_MODE=server
ORG_NAME=${DEFAULT_ORG}
while getopts "hf:c:k:o:d:m:C:O:" OPTION
while getopts "hf:c:k:o:d:m:C:O:b:" OPTION
do
case ${OPTION} in
h)
@ -144,6 +145,9 @@ do
k)
CAKEY=${OPTARG}
;;
b)
KEYBITS=${OPTARG}
;;
o)
OUTPUT_BASE=${OPTARG}
;;

View File

@ -25,14 +25,14 @@ PACKAGES_DEBIAN="$PACKAGES_DEBIAN libedit-dev libjansson-dev libsqlite3-dev uuid
# Asterisk: for addons:
PACKAGES_DEBIAN="$PACKAGES_DEBIAN libspeex-dev libspeexdsp-dev libogg-dev libvorbis-dev libasound2-dev portaudio19-dev libcurl4-openssl-dev xmlstarlet bison flex"
PACKAGES_DEBIAN="$PACKAGES_DEBIAN libpq-dev unixodbc-dev libneon27-dev libgmime-2.6-dev liblua5.2-dev liburiparser-dev libxslt1-dev libssl-dev"
PACKAGES_DEBIAN="$PACKAGES_DEBIAN libvpb-dev libmysqlclient-dev libbluetooth-dev libradcli-dev freetds-dev libosptk-dev libjack-jackd2-dev bash"
PACKAGES_DEBIAN="$PACKAGES_DEBIAN libvpb-dev libmysqlclient-dev libbluetooth-dev libradcli-dev freetds-dev libosptk-dev libjack-jackd2-dev bash libcap-dev"
PACKAGES_DEBIAN="$PACKAGES_DEBIAN libsnmp-dev libiksemel-dev libcorosync-common-dev libcpg-dev libcfg-dev libnewt-dev libpopt-dev libical-dev libspandsp-dev"
PACKAGES_DEBIAN="$PACKAGES_DEBIAN libresample1-dev libc-client2007e-dev binutils-dev libsrtp0-dev libsrtp2-dev libgsm1-dev doxygen graphviz zlib1g-dev libldap2-dev"
PACKAGES_DEBIAN="$PACKAGES_DEBIAN libcodec2-dev libfftw3-dev libsndfile1-dev libunbound-dev"
# Asterisk: for the unpackaged below:
PACKAGES_DEBIAN="$PACKAGES_DEBIAN wget subversion"
# Asterisk: for ./configure --with-pjproject-bundled:
PACKAGES_DEBIAN="$PACKAGES_DEBIAN bzip2 patch python-dev"
PACKAGES_DEBIAN="$PACKAGES_DEBIAN bzip2 patch"
# Basic build system:
PACKAGES_RH="make gcc gcc-c++ pkgconfig"
@ -41,14 +41,14 @@ PACKAGES_RH="$PACKAGES_RH libedit-devel jansson-devel libuuid-devel sqlite-devel
# Asterisk: for addons:
PACKAGES_RH="$PACKAGES_RH speex-devel speexdsp-devel libogg-devel libvorbis-devel alsa-lib-devel portaudio-devel libcurl-devel xmlstarlet bison flex"
PACKAGES_RH="$PACKAGES_RH postgresql-devel unixODBC-devel neon-devel gmime-devel lua-devel uriparser-devel libxslt-devel openssl-devel"
PACKAGES_RH="$PACKAGES_RH mysql-devel bluez-libs-devel radcli-devel freetds-devel jack-audio-connection-kit-devel bash"
PACKAGES_RH="$PACKAGES_RH mysql-devel bluez-libs-devel radcli-devel freetds-devel jack-audio-connection-kit-devel bash libcap-devel"
PACKAGES_RH="$PACKAGES_RH net-snmp-devel iksemel-devel corosynclib-devel newt-devel popt-devel libical-devel spandsp-devel"
PACKAGES_RH="$PACKAGES_RH libresample-devel uw-imap-devel binutils-devel libsrtp-devel gsm-devel doxygen graphviz zlib-devel openldap-devel hoard"
PACKAGES_RH="$PACKAGES_RH codec2-devel fftw-devel libsndfile-devel unbound-devel"
# Asterisk: for the unpackaged below:
PACKAGES_RH="$PACKAGES_RH wget subversion"
# Asterisk: for ./configure --with-pjproject-bundled:
PACKAGES_RH="$PACKAGES_RH bzip2 patch python-devel"
PACKAGES_RH="$PACKAGES_RH bzip2 patch"
# Basic build system:
PACKAGES_SUSE="make gcc gcc-c++ pkg-config"
@ -57,14 +57,14 @@ PACKAGES_SUSE="$PACKAGES_SUSE libedit-devel libjansson-devel libuuid-devel sqlit
# Asterisk: for addons:
PACKAGES_SUSE="$PACKAGES_SUSE speex-devel speexdsp-devel libogg-devel libvorbis-devel alsa-devel portaudio-devel libcurl-devel xmlstarlet bison flex"
PACKAGES_SUSE="$PACKAGES_SUSE postgresql-devel unixODBC-devel libneon-devel gmime-devel lua-devel liburiparser-devel libxslt-devel libopenssl-devel"
PACKAGES_SUSE="$PACKAGES_SUSE libmysqlclient-devel bluez-devel freeradius-client-devel freetds-devel bash"
PACKAGES_SUSE="$PACKAGES_SUSE libmysqlclient-devel bluez-devel freeradius-client-devel freetds-devel bash libcap-devel"
PACKAGES_SUSE="$PACKAGES_SUSE net-snmp-devel iksemel-devel libcorosync-devel newt-devel popt-devel libical-devel spandsp-devel"
PACKAGES_SUSE="$PACKAGES_SUSE imap-devel libsrtp2-devel libgsm-devel doxygen graphviz zlib-devel openldap2-devel"
PACKAGES_SUSE="$PACKAGES_SUSE codec2-devel fftw3-devel libsndfile-devel unbound-devel"
# Asterisk: for the unpackaged below:
PACKAGES_SUSE="$PACKAGES_SUSE wget subversion"
# Asterisk: for ./configure --with-pjproject-bundled:
PACKAGES_SUSE="$PACKAGES_SUSE bzip2 patch python-devel"
PACKAGES_SUSE="$PACKAGES_SUSE bzip2 patch"
# Basic build system:
PACKAGES_ARCH="make gcc pkg-config"
@ -73,14 +73,14 @@ PACKAGES_ARCH="$PACKAGES_ARCH libedit jansson libutil-linux libxml2 sqlite"
# Asterisk: for addons:
PACKAGES_ARCH="$PACKAGES_ARCH speex speexdsp libogg libvorbis alsa-lib portaudio curl xmlstarlet bison flex"
PACKAGES_ARCH="$PACKAGES_ARCH postgresql-libs unixodbc neon gmime lua uriparser libxslt openssl"
PACKAGES_ARCH="$PACKAGES_ARCH libmariadbclient bluez-libs radcli freetds bash"
PACKAGES_ARCH="$PACKAGES_ARCH libmariadbclient bluez-libs radcli freetds bash libcap"
PACKAGES_ARCH="$PACKAGES_ARCH net-snmp libnewt popt libical spandsp"
PACKAGES_ARCH="$PACKAGES_ARCH c-client binutils libsrtp gsm doxygen graphviz zlib libldap"
PACKAGES_ARCH="$PACKAGES_ARCH fftw libsndfile unbound"
# Asterisk: for the unpackaged below:
PACKAGES_ARCH="$PACKAGES_ARCH wget subversion"
# Asterisk: for ./configure --with-pjproject-bundled:
PACKAGES_ARCH="$PACKAGES_ARCH bzip2 patch python2"
PACKAGES_ARCH="$PACKAGES_ARCH bzip2 patch"
# Basic build system:
PACKAGES_GENTOO="sys-devel/make sys-devel/gcc dev-util/pkgconfig"
@ -89,14 +89,14 @@ PACKAGES_GENTOO="$PACKAGES_GENTOO dev-libs/libedit dev-libs/jansson sys-libs/e2f
# Asterisk: for addons:
PACKAGES_GENTOO="$PACKAGES_GENTOO media-libs/speex media-libs/speexdsp media-libs/libogg media-libs/libvorbis media-libs/alsa-lib media-libs/portaudio net-misc/curl app-text/xmlstarlet sys-devel/bison sys-devel/flex"
PACKAGES_GENTOO="$PACKAGES_GENTOO dev-db/postgresql dev-db/unixODBC net-libs/neon dev-libs/gmime dev-lang/lua dev-libs/uriparser dev-libs/libxslt dev-libs/openssl"
PACKAGES_GENTOO="$PACKAGES_GENTOO virtual/libmysqlclient net-wireless/bluez net-dialup/radiusclient-ng dev-db/freetds app-shells/bash"
PACKAGES_GENTOO="$PACKAGES_GENTOO virtual/libmysqlclient net-wireless/bluez net-dialup/radiusclient-ng dev-db/freetds app-shells/bash sys-libs/libcap"
PACKAGES_GENTOO="$PACKAGES_GENTOO net-analyzer/net-snmp dev-libs/iksemel sys-cluster/corosync dev-libs/newt dev-libs/popt dev-libs/libical media-libs/spandsp"
PACKAGES_GENTOO="$PACKAGES_GENTOO net-libs/c-client sys-devel/binutils net-libs/libsrtp media-sound/gsm media-libs/libilbc app-doc/doxygen sys-libs/zlib net-nds/openldap"
PACKAGES_GENTOO="$PACKAGES_GENTOO sci-libs/fftw media-libs/libsndfile net-dns/unbound"
# Asterisk: for the unpackaged below:
PACKAGES_GENTOO="$PACKAGES_GENTOO net-misc/wget dev-vcs/subversion"
# Asterisk: for ./configure --with-pjproject-bundled:
PACKAGES_GENTOO="$PACKAGES_GENTOO app-arch/bzip2 sys-devel/patch dev-lang/python:2.7"
PACKAGES_GENTOO="$PACKAGES_GENTOO app-arch/bzip2 sys-devel/patch"
# Basic build system:
PACKAGES_NBSD="gmake pkg-config"
@ -112,7 +112,7 @@ PACKAGES_NBSD="$PACKAGES_NBSD codec2 fftw libsndfile unbound"
# Asterisk: for the unpackaged below:
PACKAGES_NBSD="$PACKAGES_NBSD wget subversion-base"
# Asterisk: for ./configure --with-pjproject-bundled:
PACKAGES_NBSD="$PACKAGES_NBSD bzip2 patch python27"
PACKAGES_NBSD="$PACKAGES_NBSD bzip2 patch"
# Basic build system:
PACKAGES_OBSD="gmake"
@ -128,7 +128,7 @@ PACKAGES_OBSD="$PACKAGES_OBSD fftw3 libsndfile"
# Asterisk: for the unpackaged below:
PACKAGES_OBSD="$PACKAGES_OBSD wget subversion"
# Asterisk: for ./configure --with-pjproject-bundled:
PACKAGES_OBSD="$PACKAGES_OBSD bzip2 python%2"
PACKAGES_OBSD="$PACKAGES_OBSD bzip2"
# Basic build system:
PACKAGES_FBSD="gmake pkgconf"
@ -144,7 +144,7 @@ PACKAGES_FBSD="$PACKAGES_FBSD codec2 fftw3 libsndfile unbound"
# Asterisk: for the unpackaged below:
PACKAGES_FBSD="$PACKAGES_FBSD wget subversion"
# Asterisk: for ./configure --with-pjproject-bundled:
PACKAGES_FBSD="$PACKAGES_FBSD bzip2 patch python"
PACKAGES_FBSD="$PACKAGES_FBSD bzip2 patch"
# Basic build system:
PACKAGES_DBSD="gmake pkgconf"
@ -160,7 +160,7 @@ PACKAGES_DBSD="$PACKAGES_DBSD codec2 fftw3 libsndfile unbound"
# Asterisk: for the unpackaged below:
PACKAGES_DBSD="$PACKAGES_DBSD wget subversion"
# Asterisk: for ./configure --with-pjproject-bundled:
PACKAGES_DBSD="$PACKAGES_DBSD bzip2 patch python"
PACKAGES_DBSD="$PACKAGES_DBSD bzip2 patch"
KVERS=`uname -r`
@ -261,7 +261,7 @@ check_installed_zypper() {
handle_debian() {
if ! [ -x "$(command -v aptitude)" ]; then
apt-get install aptitude
apt-get install -y aptitude
fi
extra_packs=`check_installed_debs $PACKAGES_DEBIAN`
$testcmd aptitude update

View File

@ -475,7 +475,7 @@ peer_map = [
['callerid', set_value], # callerid
['callingpres', set_value('callerid_privacy')],
['cid_tag', set_value('callerid_tag')],
['trustpid', set_value('trust_id_inbound')],
['trustrpid', set_value('trust_id_inbound')],
['sendrpid', from_sendrpid], # send_pai, send_rpid
['send_diversion', set_value],
['encryption', set_media_encryption],

View File

@ -5,26 +5,26 @@
{
dlclose-1
Memcheck:Addr1
fun:...
...
fun:dlclose
fun:load_dynamic_module
fun:...
...
}
{
dlclose-2
Memcheck:Addr2
fun:...
...
fun:dlclose
fun:load_dynamic_module
fun:...
...
}
{
dlclose-4
Memcheck:Addr4
fun:...
...
fun:dlclose
fun:load_dynamic_module
fun:...
...
}
@ -36,6 +36,6 @@
speex_decode
Memcheck:Cond
fun:speex_decode_int
fun:...
...
}

View File

@ -9,10 +9,10 @@ it probably should. If there are multiple items that need documenting, you can
add multiple files, each with their own description. If the message is going to
be the same for each subject, then you can add multiple subject headers to one
file. The "Subject: xxx" line is case sensitive! For example, if you are making
a change to PJSIP, then you might add the file "res_pjsip_my_cool_feature" to
this directory, with a short description of what it does. If you are adding
multiple entries, they should be done in the same commit to avoid merge
conflicts. Here's an example:
a change to PJSIP, then you might add the file "res_pjsip_my_cool_feature.txt" to
this directory, with a short description of what it does. The files must have
the ".txt" suffix. If you are adding multiple entries, they should be done in
the same commit to avoid merge conflicts. Here's an example:
> Subject: res_pjsip
> Subject: Core

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More