Compare commits
460 Commits
Author | SHA1 | Date |
---|---|---|
Asterisk Development Team | 4ed3cec580 | |
Asterisk Development Team | 21286195d5 | |
Guido Falsi | f44bd5c806 | |
Guido Falsi | 2a7a252ba1 | |
Asterisk Development Team | f3eaf2b7d1 | |
Asterisk Development Team | 3907b81397 | |
Joshua C. Colp | fe11bc7a2a | |
sungtae kim | 9a90ab3722 | |
Joshua C. Colp | e7b6736ba3 | |
DanielYK | 139cd912af | |
Alexander Traud | 2fc7780a3a | |
Alexander Traud | 6d4ddc3151 | |
Alexander Traud | 71c70dfbfb | |
Joshua C. Colp | 21f0759b2c | |
Alexander Traud | c4c259c3af | |
Alexander Traud | 9fc5654e5a | |
Alexander Traud | 2cd2852f57 | |
Alexander Traud | 12dda5d867 | |
Alexander Traud | fccfa256a3 | |
Pirmin Walthert | 7ed8078bdb | |
Alexander Traud | 3a5bdc68b2 | |
Alexander Traud | 3b4be152d5 | |
Alexander Traud | 39f5be81a3 | |
Pirmin Walthert | 26dec66598 | |
Alexander Traud | 77e2afe8cc | |
bernard merindol | 7544e6d095 | |
Jean Aunis | c23f899254 | |
Jaco Kroon | 7a568549ee | |
Alexander Traud | 84495aae4c | |
Jaco Kroon | c3d49c304b | |
Alexander Traud | 8bbc6605c9 | |
traud | 223da4dfa1 | |
Alexander Traud | 44f921bb13 | |
Alexander Traud | e832fb6f1c | |
Kevin Harwell | d38839067b | |
Alexander Traud | 1f7c32f397 | |
traud | 5aeb31e790 | |
Alexander Traud | dda530002a | |
traud | c971769db5 | |
Sebastien Duthil | a29fd59340 | |
Sean Bright | f56e4e73af | |
traud | a14690fc00 | |
traud | 45a4cb163c | |
Jaco Kroon | a5119e9600 | |
Joshua C. Colp | 79b453b579 | |
Kevin Harwell | a03cb75523 | |
traud | 96923ec871 | |
sungtae kim | 41c1e0b45d | |
traud | bdc0aaca9d | |
Torrey Searle | 46be4668e3 | |
Jaco Kroon | 1b01a6abfd | |
Joshua C. Colp | 5e24379cf2 | |
Joshua C. Colp | 26c75683bf | |
Joshua C. Colp | e181cbde63 | |
Joshua C. Colp | 4b2729e89d | |
Jaco Kroon | ba47752d0d | |
Kevin Harwell | 9255a17410 | |
Jaco Kroon | 836203a3fd | |
Jaco Kroon | 122ef44584 | |
Joshua C. Colp | 6c4e181b2f | |
Sungtae Kim | b58dfbc68a | |
Jaco Kroon | 6706af0d5b | |
Jaco Kroon | 9c911b0f9b | |
Joshua C. Colp | f0d6189032 | |
Michael Neuhauser | 580e260ff8 | |
Jaco Kroon | c7c52b8e7a | |
Jaco Kroon | af414ef015 | |
Sean Bright | 83981ad783 | |
Sean Bright | 31c6a20862 | |
Sean Bright | 7a38d5f4e2 | |
Joshua C. Colp | aa9e4f395b | |
George Joseph | 24f32eb138 | |
Torrey Searle | b8a67fc15d | |
George Joseph | a3599cc01d | |
George Joseph | 10149ad712 | |
George Joseph | c3bb94b1ee | |
George Joseph | 80c7f130a4 | |
Joshua Colp | 73641deedb | |
Torrey Searle | 1c6314627d | |
Paulo Vicentini | 8645a294ca | |
Sean Bright | 7eec090030 | |
Jared Smith | ff48a6cd56 | |
Rodrigo Ramírez Norambuena | 6857ba98d5 | |
Asterisk Development Team | 1d3256c5e4 | |
Kevin Harwell | 2f75f071d2 | |
Sean Bright | 2c26705a9b | |
Joshua Colp | c189ad1f7b | |
Joshua Colp | ada97a6724 | |
lvl | 88393db74d | |
Sebastian Kemper | 61f943d405 | |
Joshua C. Colp | 029c3e49d4 | |
Kevin Harwell | c07ed4e651 | |
Kevin Harwell | c47dbf1fbe | |
Kevin Harwell | ac95b79699 | |
Kevin Harwell | d1ad85622b | |
Torrey Searle | 1c8c560f39 | |
Kevin Harwell | d7bb1241ab | |
Kevin Harwell | 38e88f9469 | |
Kevin Harwell | 31e9c110f5 | |
Walter Doekes | a3f5a80a59 | |
Walter Doekes | b455d57f7d | |
Kevin Harwell | d77a89cb9e | |
Jaco Kroon | 77d4923307 | |
George Joseph | fd31ef67b9 | |
George Joseph | e4f5142e23 | |
George Joseph | 3e4752165d | |
George Joseph | e300d57134 | |
George Joseph | f1896e9279 | |
Joshua C. Colp | bc3c095e9f | |
Sean Bright | 9ef514ae98 | |
Sean Bright | cf26ce5d4f | |
George Joseph | 5f36196384 | |
Joshua C. Colp | 957681e08b | |
George Joseph | f93325ce52 | |
Ben Ford | 7a921cfe8c | |
George Joseph | 50704a8f4d | |
Sean Bright | 5f28ecc7af | |
Torrey Searle | fb7cff4103 | |
Joshua C. Colp | 5a0218a960 | |
Kevin Harwell | 08d8035599 | |
Joshua Colp | f424562a41 | |
Joshua Colp | b86ef296b3 | |
George Joseph | 8914a77f35 | |
Sean Bright | d1a96fa9ba | |
Sean Bright | 4b897f6fe4 | |
Joshua C. Colp | 3a8da5ece7 | |
George Joseph | 4d6346dc26 | |
Joshua Colp | 47a5e33280 | |
Joshua Colp | 78732ff08e | |
Joshua Colp | 5379c065ae | |
Sean Bright | eb33b0fb0b | |
Friendly Automation | 2f992bf800 | |
Friendly Automation | 3ec3d39676 | |
Friendly Automation | d9e625519a | |
Friendly Automation | 259edcf5c7 | |
Sylvain Afchain | cf87d63775 | |
Walter Doekes | a5ec14970d | |
Walter Doekes | d19dec53b5 | |
Joshua C. Colp | 325e3f8111 | |
George Joseph | 54cd865946 | |
Joshua Colp | 3efeb147bb | |
Friendly Automation | e7e65588e4 | |
George Joseph | 2c72e26478 | |
Friendly Automation | 82eb8e7097 | |
Sean Bright | 646789106f | |
Sean Bright | 8b8c1dd07f | |
Friendly Automation | e86c32b878 | |
Joshua C. Colp | 35c9332edf | |
Sean Bright | ef5702cef1 | |
Friendly Automation | 5192a045f6 | |
Kevin Harwell | 737bd8365e | |
Kevin Harwell | 7031c3b7bd | |
Sean Bright | 69cf67d8c6 | |
Walter Doekes | be6eec7b25 | |
Sean Bright | ace97a3786 | |
Asterisk Development Team | a0f44b1052 | |
Friendly Automation | 6747dd31b4 | |
George Joseph | f34a4d5a77 | |
Sean Bright | 1e79bf44fc | |
Friendly Automation | f7e0b6baf8 | |
Friendly Automation | f556efe0b9 | |
Friendly Automation | c8dc9365a4 | |
Joshua Colp | 73cd259895 | |
Friendly Automation | d6a4560016 | |
Andrew Siplas | 1c5116f842 | |
Sean Bright | 687890f734 | |
Sean Bright | d33cd39260 | |
Sean Bright | deed0f5706 | |
Friendly Automation | 503cac85ee | |
Joshua Colp | 7a9a4575bc | |
Friendly Automation | 88e3f5c315 | |
Rodrigo Ramírez Norambuena | 7b32763190 | |
Joshua Colp | 68b7ef924e | |
Joshua Colp | cf37de8a5d | |
Joshua Colp | f132679193 | |
Sean Bright | cb6f106d76 | |
Sean Bright | 9ff062f994 | |
Sean Bright | 7c137ebbd4 | |
Sean Bright | d1cd27ba1f | |
Joshua Colp | 8cad8db7d3 | |
Friendly Automation | af4e503005 | |
Sean Bright | b60dfac98e | |
Sean Bright | 62e5fa400e | |
Joshua Colp | 0bd7cd562e | |
Friendly Automation | acbe620d41 | |
Sean Bright | 3779e76b68 | |
Joshua Colp | 65bc8d70e3 | |
Sean Bright | a810025782 | |
Sean Bright | 28275609b3 | |
Sean Bright | 6898c8e0da | |
Jaco Kroon | 0a9e5febd5 | |
Kevin Harwell | 5dda6d49b0 | |
Joshua Colp | ec6598b1eb | |
Friendly Automation | f4f4519db6 | |
Friendly Automation | e98856b5c7 | |
Corey Farrell | 1675ab3ce2 | |
Kevin Harwell | 21d8d2426d | |
George Joseph | 40bfd895a9 | |
Joshua C. Colp | e17ba921f3 | |
Joshua Colp | 9bbb03f776 | |
Friendly Automation | 21334e00c5 | |
Sean Bright | eac6eb663d | |
Friendly Automation | 0b09aa087c | |
George Joseph | 09680cdaa4 | |
Friendly Automation | b2a7d6ccfb | |
Friendly Automation | 73131cefaf | |
Friendly Automation | 6406abc834 | |
Friendly Automation | 87958810d3 | |
George Joseph | 3cc8a1bb84 | |
Friendly Automation | 5d6b533005 | |
George Joseph | beaa14d721 | |
George Joseph | 015cdc9f64 | |
Richard Mudgett | 62a8750d2d | |
George Joseph | e0449939ec | |
Richard Mudgett | b3d0b0c484 | |
Richard Mudgett | f7c6a7df9f | |
Richard Mudgett | 919da21690 | |
Richard Mudgett | a82fc35606 | |
Richard Mudgett | 4dfa19eb27 | |
Sean Bright | a0d1197ab3 | |
Sean Bright | 7038c8676e | |
Sean Bright | f344356290 | |
Snuffy | c4cd2fa7b9 | |
Friendly Automation | e5446d7ffc | |
Friendly Automation | b401891036 | |
Boris P. Korzun | 6d2eced3d3 | |
George Joseph | 321b0c5041 | |
Jean Aunis | 811c7bdabe | |
Sean Bright | 843d601e2c | |
George Joseph | 86550a59f3 | |
Joshua C. Colp | 0c36ef530b | |
Joshua C. Colp | 7aa2445264 | |
Friendly Automation | 2dcb96a868 | |
Friendly Automation | 7d0757d660 | |
Sean Bright | 8c8989f205 | |
Kevin Reeves | 45f7f9bb85 | |
George Joseph | 2634e63f4d | |
Friendly Automation | 2725c885e8 | |
Joshua C. Colp | 3104c03476 | |
Joshua C. Colp | 58a6d4ecf5 | |
Pascal Cadotte Michaud | 69c9b74836 | |
Frederic LE FOLL | a0e31cc14e | |
Joshua C. Colp | 5a80c36d62 | |
Friendly Automation | c7966269f5 | |
Joshua C. Colp | 41fdcf7a65 | |
Friendly Automation | a7a5bf0129 | |
Joshua Colp | 895a66f772 | |
Joshua C. Colp | c9147a759e | |
Kevin Harwell | 68724425e4 | |
Asterisk Development Team | 08a6e8c553 | |
Jaco Kroon | 6041fc8b9c | |
Pascal Cadotte Michaud | 39aff53cff | |
George Joseph | 87d5fb1196 | |
Joshua Colp | 6a89784b78 | |
George Joseph | 86822722b6 | |
Friendly Automation | 5fb0d1d562 | |
Jaco Kroon | 32ce8fa046 | |
Friendly Automation | ffbfc09fc1 | |
George Joseph | fd14d7302f | |
George Joseph | 2526c8e562 | |
Friendly Automation | af079f5085 | |
Friendly Automation | 6685a1862c | |
Friendly Automation | e17bde758b | |
Friendly Automation | aa2765d366 | |
Friendly Automation | 478a602e70 | |
Friendly Automation | 77b5ec3e7a | |
Sean Bright | 4e057eb9d2 | |
Sean Bright | f26e5bacc0 | |
Walter Doekes | e1eb5e8dc2 | |
Frederic LE FOLL | 3e73893e53 | |
Sean Bright | 4d56adf8fb | |
George Joseph | c0ab241cc0 | |
George Joseph | 88150323a2 | |
George Joseph | 5b15a1c639 | |
Joshua Colp | 41d58a4ce2 | |
Sean Bright | cc59e21409 | |
Salah Ahmed | 4ac0299bfb | |
Friendly Automation | e9b9141d09 | |
Ben Ford | 665a94cb76 | |
George Joseph | 6b1ba58967 | |
George Joseph | 6aa9ee1661 | |
Friendly Automation | 715e4d0e72 | |
Pascal Cadotte Michaud | 450173a0ae | |
Kevin Harwell | b1c9176b3f | |
Kevin Harwell | 8c99930375 | |
Friendly Automation | ecdc5405f9 | |
George Joseph | 8a02454ec6 | |
George Joseph | 2a92e6b576 | |
George Joseph | f0d1ce50af | |
George Joseph | 46dceab33f | |
Friendly Automation | 43a7e44fbe | |
Sean Bright | 76ef36fafc | |
Michael Cargile | e23b2856d0 | |
Frederic LE FOLL | d3dd4c5459 | |
lvl | 6345a00228 | |
Friendly Automation | f1f28aa9e3 | |
George Joseph | 16066ce5fc | |
Friendly Automation | d75099b845 | |
Friendly Automation | cb58d4cc2d | |
Alexei Gradinari | 649733612d | |
Joshua Colp | 0c486e7edf | |
Sean Bright | 92bb381d5d | |
Kevin Harwell | 8b4610acfe | |
Kevin Harwell | 8bc6fa0fbd | |
Martin Tomec | d579ec9cdf | |
Joshua Colp | de433cdcaf | |
Joshua Colp | d638d9c6c6 | |
Kevin Harwell | 3084a6c617 | |
Kevin Harwell | ea3daa94c8 | |
George Joseph | 7202624b3b | |
George Joseph | 36b28c98dd | |
Joshua Colp | eea2d499f4 | |
Joshua Colp | 43ea6e21db | |
Sean Bright | b3792e1288 | |
Joshua Colp | e37d546109 | |
George Joseph | 1b4502ec5d | |
Friendly Automation | 8b0661df75 | |
Joshua Colp | 0cfe9186b0 | |
Friendly Automation | 500e5f488f | |
Sean Bright | b3c56c7fa5 | |
Joshua Colp | 4d67cd10ba | |
George Joseph | 2d665091a3 | |
Salah Ahmed | 40acd7d198 | |
Joshua Colp | b8ae799ca9 | |
Sean Bright | 4bc1c170cd | |
Joshua Colp | b590e8f23e | |
cmaj | aa0973f868 | |
George Joseph | 3c712391c6 | |
Joshua Colp | ba688e6891 | |
Friendly Automation | bbf995320e | |
Friendly Automation | 236ff0af7a | |
Christoph Moench-Tegeder | 79cc8ae3b8 | |
George Joseph | 5b77f572e3 | |
Kevin Harwell | 45c0d99185 | |
csavinovich | c84135d2a3 | |
Friendly Automation | b25e529ad8 | |
George Joseph | d869882697 | |
George Joseph | 82372fa816 | |
Friendly Automation | 804f5ddfeb | |
George Joseph | 2652bda3a0 | |
Kevin Harwell | ae761c7473 | |
Friendly Automation | 6bedd43b98 | |
Sean Bright | b903994987 | |
lvl | 71f86e78b6 | |
Kevin Harwell | 996fc40e2b | |
Kevin Harwell | 37ec88c4c8 | |
Kevin Harwell | 299ba78b09 | |
Friendly Automation | 119a18ef08 | |
Sean Bright | 1dc3451a34 | |
Corey Farrell | 25fbe79793 | |
Joshua Colp | 57fa604571 | |
Friendly Automation | f7ed688ae8 | |
Torrey Searle | 55b760d762 | |
Alexei Gradinari | 4b47d4774d | |
Sean Bright | 6527eb8213 | |
George Joseph | 0257a039e4 | |
George Joseph | 23858b7ef4 | |
George Joseph | a398196fd0 | |
George Joseph | cc82a0c66c | |
Jonathan Rose | d223419bcd | |
George Joseph | 2fcf9c7e49 | |
Sean Bright | 8d0edf2b37 | |
Ben Ford | 8269fcbf03 | |
Asterisk Development Team | 37139e16a5 | |
George Joseph | 048c0f3a04 | |
George Joseph | 93973eb90f | |
Friendly Automation | d8523dccb7 | |
Sean Bright | 7550a82fe0 | |
Sean Bright | 51cf060c6c | |
Friendly Automation | 5b8e0fef34 | |
George Joseph | ad4a358595 | |
Kevin Harwell | 175a7ccac7 | |
Corey Farrell | 5bedd4a9b4 | |
Ben Ford | f181dfc065 | |
George Joseph | d95a76edd3 | |
George Joseph | 7c0435f854 | |
Friendly Automation | 3b485b3e5a | |
Kevin Harwell | 1d322dc071 | |
Friendly Automation | 09d211b611 | |
Corey Farrell | ec712cfab2 | |
Kevin Harwell | f821e81071 | |
George Joseph | b1c5753b78 | |
Corey Farrell | af0ccbc45e | |
Corey Farrell | fd7fc3d7a5 | |
Corey Farrell | 78f329dad9 | |
Joshua Colp | 6e75e2565d | |
Joshua Colp | d2087607b6 | |
Joshua Colp | 926053d7bd | |
Joshua Colp | 69e8a44039 | |
George Joseph | b7e9c8437e | |
Florian Floimair | d7a3e4f5cf | |
Joshua Colp | 4d1baa3ae8 | |
Guido Falsi | 5ff2f7a016 | |
Ben Ford | 1d960195c2 | |
Sean Bright | 2fa296e7d4 | |
Friendly Automation | cb9fdc21d1 | |
George Joseph | 492da93771 | |
Friendly Automation | db1da38649 | |
Joshua Colp | 377f56bdc0 | |
Joshua Colp | 9f5a027aa3 | |
Joshua Colp | e82a765169 | |
sungtae kim | 9e26136ee6 | |
Ben Ford | 5dad4f4ea1 | |
Frederic LE FOLL | 50997de887 | |
Frederic LE FOLL | 9e67c92502 | |
George Joseph | 44068cc6bf | |
Friendly Automation | 03625b4bc6 | |
Friendly Automation | 70ebcf26c0 | |
George Joseph | c060ef7dee | |
Sean Bright | 75d6418d8e | |
George Joseph | e35918235e | |
Joshua Colp | 61c01df560 | |
Kevin Harwell | 9d4f1e8ebe | |
Chris-Savinovich | 7d99710fa6 | |
Igor Goncharovsky | 056ddf76ce | |
George Joseph | 16ae4cd2db | |
George Joseph | 2cd5b84af8 | |
George Joseph | 0aae0499da | |
Kevin Harwell | a36fb473fe | |
Igor Goncharovsky | 95b3c9839d | |
Igor Goncharovsky | e7f1f7eefd | |
Sean Bright | 34ab9964f5 | |
Friendly Automation | 7f64921a37 | |
Friendly Automation | e33ab894bf | |
Alexei Gradinari | a0b0c7540c | |
George Joseph | 581ffdf6a9 | |
George Joseph | b3d9f6ef6c | |
Dan Cropp | a1d38e19a2 | |
Friendly Automation | 61edef60a1 | |
Friendly Automation | 8f7052f8dc | |
Stas Kobzar | 3a246c2a69 | |
George Joseph | f6ab42df26 | |
Sean Bright | e123d1ccc5 | |
Alexei Gradinari | 052ab9d966 | |
Sean Bright | a5f05eed70 | |
George Joseph | 5c9ae25090 | |
George Joseph | 71f89ce175 | |
George Joseph | 5489ad5574 | |
Kevin Harwell | 5daa9bbaee | |
George Joseph | aa44e723c5 | |
Friendly Automation | 90a14a0a90 | |
Friendly Automation | b4ab3dab90 | |
Joshua Colp | 108b1abbd9 | |
George Joseph | ec7cd3b0a5 | |
George Joseph | 8652140794 | |
Friendly Automation | 261cb42ccb | |
Friendly Automation | a2a4e9c717 | |
Sean Bright | 87f8ca2812 | |
Kevin Harwell | a305f2fdcb | |
Sean Bright | 1976db6ffd | |
Joshua Colp | 20459d4cac | |
George Joseph | 7300bdd382 | |
George Joseph | cccad75517 | |
Torrey Searle | 44af3e9018 | |
Sean Bright | c748187bbf | |
Asterisk Development Team | f1e0c9d1b8 | |
George Joseph | 4f2ad5a55d | |
Sean Bright | a66ccb90ac | |
George Joseph | e821a637a8 | |
George Joseph | 80d8dce6af |
|
@ -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
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
40
|
355
CHANGES
355
CHANGES
|
@ -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 ----------
|
||||
------------------------------------------------------------------------------
|
||||
|
|
4
Makefile
4
Makefile
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
192
UPGRADE.txt
192
UPGRADE.txt
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -51,16 +51,18 @@ static const char app[] = "ChanIsAvail";
|
|||
Check channel availability
|
||||
</synopsis>
|
||||
<syntax>
|
||||
<parameter name="Technology/Resource" required="true" argsep="&">
|
||||
<parameter name="Technology/Resource" required="false" argsep="&">
|
||||
<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&Technology3/Resource3&.....</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"
|
||||
);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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="&">
|
||||
<parameter name="Technology/Resource" required="false" argsep="&">
|
||||
<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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<depend>res_adsi</depend>
|
||||
<support_level>deprecated</support_level>
|
||||
***/
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
Page series of phones
|
||||
</synopsis>
|
||||
<syntax>
|
||||
<parameter name="Technology/Resource" required="true" argsep="&">
|
||||
<parameter name="Technology/Resource" required="false" argsep="&">
|
||||
<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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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"><asteriskteam@digium.com></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>
|
|
@ -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(-)
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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",
|
||||
);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 ("
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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")) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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=
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
;queue_rules => odbc,asterisk
|
||||
;acls => odbc,asterisk
|
||||
;musiconhold => mysql,general
|
||||
;musiconhold_entry => mysql,general
|
||||
;queue_log => mysql,general
|
||||
;
|
||||
;
|
||||
|
|
|
@ -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})}'
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
; =========
|
||||
|
|
|
@ -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===
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
182
configure.ac
182
configure.ac
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
|
@ -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
|
|
@ -0,0 +1 @@
|
|||
../env.py
|
|
@ -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"}
|
|
@ -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')
|
|
@ -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
|
@ -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';
|
||||
|
|
@ -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
|
@ -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;
|
||||
|
|
@ -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:
|
||||
|
|
|
@ -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}
|
||||
;;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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:...
|
||||
...
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
Subject: AttendedTransfer
|
||||
|
||||
A new application, this will queue up attended transfer to the given extension.
|
|
@ -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
Loading…
Reference in New Issue