Compare commits

..

891 Commits

Author SHA1 Message Date
Kevin P. Fleming
ef83b5943e Convert all release tags to Opsound music-on-hold.
For more details:
http://blogs.digium.com/2009/08/18/asterisk-music-on-hold-changes/



git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.2.25-netsec@212958 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-08-18 20:42:51 +00:00
Russell Bryant
5162e5d425 importing files for 1.2.25-netsec release
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.2.25-netsec@90179 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-11-29 21:41:32 +00:00
Russell Bryant
c247ee8720 Creating tag for the release of asterisk-1.2.25-netsec
git-svn-id: https://origsvn.digium.com/svn/asterisk/tags/1.2.25-netsec@90178 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-11-29 21:40:33 +00:00
Russell Bryant
ca81e571ae sync with 1.2 branch
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@90175 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-11-29 21:36:31 +00:00
Automerge script
c357e38925 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@82455 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-09-14 21:21:56 +00:00
Automerge Script
a97c27fc27 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@78412 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-08-07 18:44:16 +00:00
Automerge Script
53e28cba18 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@77992 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-08-02 20:11:13 +00:00
Automerge Script
09d0b6be60 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@77937 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-08-02 16:03:57 +00:00
Automerge Script
220d01134a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@76982 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-25 00:09:53 +00:00
Automerge Script
611c08e453 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@76957 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-24 22:22:33 +00:00
Automerge Script
08e42004f4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@76850 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-24 17:27:41 +00:00
Automerge Script
46cb5961ea automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@76702 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-23 19:30:11 +00:00
Automerge Script
307d4cea91 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@76609 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-23 15:30:57 +00:00
Automerge Script
6f745b034e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@76456 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-22 22:29:15 +00:00
Automerge Script
8915e3a3af automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@76277 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-21 06:32:33 +00:00
Automerge Script
ad320254c8 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@76101 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-20 17:26:48 +00:00
Automerge Script
98e4e37123 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@75976 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-19 16:29:34 +00:00
Automerge Script
51c1456d6b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@75797 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-18 21:29:47 +00:00
Automerge Script
309f89e5cb automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@75704 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-18 18:32:40 +00:00
Russell Bryant
40ef94cfe6 get branch up to date to include ASA fixes
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@75462 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-17 21:09:39 +00:00
Automerge Script
6f0882b296 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@75350 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-16 21:30:49 +00:00
Automerge Script
0b7104eaa0 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@75303 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-16 19:33:26 +00:00
Automerge Script
8872e64252 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@75155 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-13 21:29:00 +00:00
Automerge Script
28c632b1c4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@75106 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-13 20:29:46 +00:00
Automerge Script
3c7d002b0b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@74863 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-12 16:27:50 +00:00
Automerge Script
6cf12e669e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@74811 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-11 23:27:32 +00:00
Automerge Script
e5bf71bed5 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@74742 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-11 21:24:40 +00:00
Automerge Script
c6fa0ff3f4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@74702 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-11 19:31:14 +00:00
Automerge Script
14dd3b2f1a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@74615 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-11 17:31:25 +00:00
Automerge Script
15355af8ac automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@74473 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-10 20:30:13 +00:00
Automerge Script
88ef48486e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@74424 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-10 19:32:41 +00:00
Russell Bryant
bb95ee53b0 sync with 1.2 branch
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@74320 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-10 15:45:46 +00:00
Automerge Script
9419406541 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@74312 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-10 15:28:47 +00:00
Automerge Script
e3388c0ac3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@74210 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-09 21:28:52 +00:00
Automerge Script
9f83205714 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@73812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-06 23:26:12 +00:00
Automerge Script
ff0b4e97a1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@73725 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-06 16:27:34 +00:00
Automerge Script
badfa8a03e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@73597 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-05 23:27:07 +00:00
Automerge Script
6aa25ce9bc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@73511 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-05 20:27:16 +00:00
Automerge Script
bd82c72a14 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@73366 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-05 14:26:28 +00:00
Automerge Script
2e87b185eb automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@73296 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-04 15:25:49 +00:00
Automerge Script
471f3c9d00 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@73251 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-04 09:25:30 +00:00
Automerge Script
e50a47efdb automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@73096 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-03 13:26:27 +00:00
Automerge Script
1379057370 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@73051 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-03 12:24:58 +00:00
Automerge Script
09213b43a2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@72983 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-02 22:28:05 +00:00
Automerge Script
3c25796afa automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@72847 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-07-02 00:29:41 +00:00
Automerge Script
09088bc7cc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@72662 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-29 17:17:36 +00:00
Automerge Script
38b6686e31 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@72596 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-29 14:10:42 +00:00
Automerge Script
15c88aba92 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@72380 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-27 23:25:08 +00:00
Automerge Script
df950e24ee automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@72303 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-27 21:27:00 +00:00
Automerge Script
bd917ea9f4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@72231 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-27 19:25:45 +00:00
Automerge Script
ba8c3da0bc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@72110 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-27 14:10:46 +00:00
Automerge Script
bf645cc37f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@72098 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-27 10:10:30 +00:00
Automerge Script
d52d223fa4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@72073 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-27 08:19:10 +00:00
Automerge Script
ecf72b84c8 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@71875 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-26 18:18:19 +00:00
Automerge Script
70c1717a10 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@71795 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-26 13:26:53 +00:00
Automerge Script
c3c2b96ef7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@71703 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-25 19:27:59 +00:00
Automerge Script
3b367afabf automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@71462 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-25 01:26:23 +00:00
Automerge Script
c887c5bad7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@71370 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-24 20:09:44 +00:00
Automerge Script
586aa67aff automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@71337 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-24 18:26:00 +00:00
Automerge Script
61f0a56fb9 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@71173 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-22 16:27:30 +00:00
Automerge Script
8cec922b04 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@71119 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-22 15:27:54 +00:00
Automerge Script
891600bfdf automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@70998 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-21 23:25:50 +00:00
Automerge Script
0efd501d6b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@70946 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-21 22:25:55 +00:00
Automerge Script
3519216fb1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@70805 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-21 19:13:44 +00:00
Automerge Script
f64c485a1c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@70675 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-21 13:12:43 +00:00
Automerge Script
4a623ce514 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@70609 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-20 23:26:55 +00:00
Automerge Script
a65fcc6950 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@70492 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-20 20:26:16 +00:00
Automerge Script
d391cd13e9 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@70443 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-20 19:25:30 +00:00
Automerge Script
8cd0f0afe1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@70353 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-20 16:10:16 +00:00
Automerge Script
632070eda1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@70340 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-20 15:18:19 +00:00
Automerge Script
aae179ee5f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@70061 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-19 18:12:44 +00:00
Automerge Script
dd4f8ab9bd automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@70043 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-19 17:29:28 +00:00
Automerge Script
abe5474fae automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@69941 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-19 14:25:35 +00:00
Automerge Script
a06cd4d098 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@69893 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-19 13:25:59 +00:00
Automerge Script
4cd913f575 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@69793 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-18 18:27:36 +00:00
Automerge Script
d36f734cca automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@69515 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-15 00:25:07 +00:00
Automerge Script
91a9884b7a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@69391 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-14 21:30:45 +00:00
Automerge Script
db56721c38 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@69307 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-14 16:34:48 +00:00
Automerge Script
42e9e81c21 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@69180 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-13 19:28:07 +00:00
Automerge Script
e956a271f4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@69065 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-13 10:10:30 +00:00
Automerge Script
d839836db9 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@68969 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-12 15:27:09 +00:00
Automerge Script
b9eb88b5f1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@68899 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-12 09:10:08 +00:00
Automerge Script
eec5ae4566 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@68886 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-12 08:10:38 +00:00
Automerge Script
ec4df45550 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@68773 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-11 17:23:01 +00:00
Automerge Script
b1e34e49e1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@68731 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-11 15:25:48 +00:00
Automerge Script
ebfa098f5e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@68643 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-11 10:10:21 +00:00
Automerge Script
a7efc714a3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@68574 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-08 23:25:52 +00:00
Automerge Script
513c40ddc1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@68419 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-08 00:25:46 +00:00
Automerge Script
1f30a0a0f2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@68367 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-07 23:20:58 +00:00
Automerge Script
3fb70a640c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@68252 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-07 20:26:12 +00:00
Automerge Script
d5fd3ada2e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@68117 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-07 15:25:21 +00:00
Automerge Script
39f997c3b6 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@67969 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-07 00:26:56 +00:00
Automerge Script
4a5df3824d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@67769 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-06 17:27:55 +00:00
Automerge Script
56944e5dfc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@67696 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-06 14:25:31 +00:00
Automerge Script
d3a4f7091a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@67648 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-06 13:26:20 +00:00
Automerge Script
8e9529a8ac automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@67358 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-05 16:25:27 +00:00
Automerge Script
4797a33efc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@67269 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-05 12:17:36 +00:00
Automerge Script
6e2816fbea automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@67238 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-05 11:17:13 +00:00
Automerge Script
7699bb25d7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@67208 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-05 00:24:22 +00:00
Automerge Script
8120d0bb68 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@67118 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-06-04 22:28:38 +00:00
Automerge Script
5645d79958 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@66767 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-31 16:14:18 +00:00
Automerge Script
4e357e2d87 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@66584 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-29 22:24:55 +00:00
Automerge Script
114c74d647 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@66362 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-29 08:10:24 +00:00
Automerge Script
67ae4be5de automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@66156 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-25 14:16:47 +00:00
Automerge Script
f008f7914d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@65900 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-24 15:24:07 +00:00
Automerge Script
f370c578e7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@65813 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-24 10:23:53 +00:00
Automerge Script
43d3d20de0 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@65730 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-23 21:23:10 +00:00
Automerge Script
ded0401bdf automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@65636 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-23 14:22:34 +00:00
Automerge Script
7aa91a5a20 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@65393 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-22 13:09:03 +00:00
Automerge Script
3588aa6808 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@65341 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-22 08:08:59 +00:00
Automerge Script
e94c895d68 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@65199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-18 21:14:50 +00:00
Automerge Script
30a1360663 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@65167 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-18 19:21:46 +00:00
Automerge Script
133c75b2c7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@65120 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-18 16:24:42 +00:00
Automerge Script
b44549660f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@65038 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-18 12:19:14 +00:00
Automerge Script
e6e9e6d65a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@64950 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-18 09:24:59 +00:00
Automerge Script
244d4723de automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@64867 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-17 22:22:24 +00:00
Automerge Script
468bc9d600 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@64807 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-17 17:23:29 +00:00
Automerge Script
05330a8979 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@64648 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-16 11:21:30 +00:00
Automerge Script
cc9be2b488 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@64562 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-16 09:22:26 +00:00
Automerge Script
7198591adf automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@64321 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-14 19:20:38 +00:00
Automerge Script
5f242f10f3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@63945 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-11 17:19:05 +00:00
Automerge Script
9898fcd5b8 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@63836 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-10 23:19:20 +00:00
Automerge Script
97762cc682 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@63791 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-10 21:28:39 +00:00
Automerge Script
7afe67bd95 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@63696 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-09 18:18:21 +00:00
Automerge Script
ce63f274ae automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@63652 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-09 17:18:48 +00:00
Automerge Script
af42b7d2ed automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@63607 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-09 15:17:30 +00:00
Automerge Script
e2b988cb13 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@63531 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-09 12:05:41 +00:00
Automerge Script
ff4fd44751 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@63518 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-08 23:17:50 +00:00
Automerge Script
e567c36080 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@63444 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-08 16:19:14 +00:00
Automerge Script
5518268ad7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@63399 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-08 07:17:28 +00:00
Automerge Script
948f8837ce automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@63328 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-07 22:18:20 +00:00
Automerge Script
34a23ed281 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@63223 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-07 15:12:42 +00:00
Automerge Script
328f25d8df automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@63029 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-03 17:17:45 +00:00
Automerge Script
790e031070 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@62985 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-03 16:17:41 +00:00
Automerge Script
cf88fd1109 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@62910 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-03 14:11:27 +00:00
Automerge Script
c45d0c0b54 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@62882 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-03 01:17:11 +00:00
Automerge Script
2b4aac55ff automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@62840 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-03 00:18:05 +00:00
Automerge Script
6d9fe8c8a5 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@62782 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-02 21:18:33 +00:00
Automerge Script
fa0aba61e8 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@62733 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-02 18:18:44 +00:00
Automerge Script
da66cc3c63 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@62592 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-01 22:18:10 +00:00
Automerge Script
76291fdcfe automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@62538 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-05-01 17:18:36 +00:00
Automerge Script
9d01c89d54 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@62461 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-30 16:18:42 +00:00
Automerge Script
99c9f6c477 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@62413 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-30 15:18:32 +00:00
Automerge Script
aef2e33196 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@62216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-27 17:18:32 +00:00
Automerge Script
7a793c9201 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@62139 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-27 14:05:20 +00:00
Automerge Script
0ce8de0404 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@62081 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-26 17:21:20 +00:00
Automerge Script
57f9282134 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@62004 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-26 02:17:37 +00:00
Automerge Script
c1c3b2d9f2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@61957 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-26 00:18:36 +00:00
Automerge Script
09bf2e006f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@61912 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-25 22:18:28 +00:00
Automerge Script
969e276b1e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@61861 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-25 20:26:05 +00:00
Automerge Script
a66029756b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@61752 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-21 14:23:55 +00:00
Automerge Script
0c81d2e046 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@61521 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-11 16:56:45 +00:00
Automerge Script
9c2c0004a8 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@61475 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-11 15:56:57 +00:00
Automerge Script
242a90d01f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@61425 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-11 14:58:05 +00:00
Automerge Script
b850893d6c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@61371 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-11 12:40:12 +00:00
Automerge Script
31a1692162 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@61182 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-10 12:38:39 +00:00
Automerge Script
0401150187 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@61069 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-09 19:52:12 +00:00
Automerge Script
e278c92503 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@60983 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-09 17:54:55 +00:00
Automerge Script
d691fa4d17 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@60897 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-09 03:54:41 +00:00
Automerge Script
d5b4a6c3c0 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@60845 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-09 01:54:24 +00:00
Automerge Script
2f76122f9a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@60761 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-08 14:54:53 +00:00
Automerge Script
6e2e94e498 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@60708 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-08 02:56:53 +00:00
Automerge Script
dc14a89f78 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@60483 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-06 17:44:10 +00:00
Automerge Script
3dbf6e09a7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@60447 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-06 15:54:39 +00:00
Automerge Script
bf5b3a7fca automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@60318 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-05 16:53:46 +00:00
Automerge Script
4f9d0e28e4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@60261 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-05 13:54:18 +00:00
Automerge Script
aca1adfe03 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@60166 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-04 17:53:11 +00:00
Automerge Script
6e8d96fcd1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@60117 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-04 16:51:41 +00:00
Automerge Script
e70e937cb1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@60062 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-03 23:52:51 +00:00
Automerge Script
7a1390a0c6 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@59989 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-03 19:53:08 +00:00
Automerge Script
624988bd1e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@59935 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-03 18:53:24 +00:00
Automerge Script
e668aad746 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@59850 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-03 11:52:19 +00:00
Automerge Script
48e2d876ff automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@59802 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-03 10:38:41 +00:00
Automerge Script
5901452ecb automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@59771 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-02 19:53:36 +00:00
Automerge Script
5b029cfcb6 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@59653 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-02 12:38:35 +00:00
Automerge Script
faa652eeb4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@59638 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-02 07:38:38 +00:00
Automerge Script
e421382a07 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@59622 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-04-01 23:39:01 +00:00
Automerge Script
f309e69638 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@59413 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-29 18:54:38 +00:00
Automerge Script
c23816ba19 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@59354 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-29 17:04:00 +00:00
Automerge Script
58500a4c7f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@59137 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-21 21:56:42 +00:00
Automerge Script
28d60b864c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@59007 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-16 16:22:58 +00:00
Automerge Script
70c96b9bc6 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@58603 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-09 20:59:16 +00:00
Automerge Script
f525f6de36 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@58571 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-09 14:55:56 +00:00
Automerge Script
902b16bdda automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@58432 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-08 17:06:27 +00:00
Automerge Script
3951e4addf automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@58284 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-07 19:05:38 +00:00
Automerge Script
c52232f4f4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@58207 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-07 01:05:32 +00:00
Automerge Script
be2a021189 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@58118 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-06 22:54:26 +00:00
Automerge Script
39605fc510 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@58095 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-06 21:05:51 +00:00
Automerge Script
c590b397ea automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@58022 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-06 15:54:14 +00:00
Automerge Script
b7f5c1ddf4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@57976 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-05 23:54:12 +00:00
Automerge Script
b38e464dd3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@57913 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-05 19:05:34 +00:00
Automerge Script
97942ba44c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@57867 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-05 16:07:47 +00:00
Automerge Script
2673fcd2d2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@57767 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-04 10:54:07 +00:00
Automerge Script
224316634a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@57690 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-03 07:05:14 +00:00
Automerge Script
a85da9ebec automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@57552 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-02 19:00:51 +00:00
Automerge Script
44ebb34bee automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@57522 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-02 18:06:59 +00:00
Automerge Script
4423ae672e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@57472 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-02 16:54:02 +00:00
Automerge Script
c3a5b0d8e1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@57362 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-03-01 23:07:54 +00:00
Automerge Script
3f98583e26 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@57138 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-28 19:22:31 +00:00
Automerge Script
df5009b564 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@57048 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-28 17:11:28 +00:00
Automerge Script
e16cd7369d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@56883 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-26 20:21:25 +00:00
Automerge Script
3b6d2f2633 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@56777 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-26 01:20:36 +00:00
Automerge Script
c31b4a6a2e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@56728 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-25 15:21:12 +00:00
Automerge Script
518d9c6dd1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@56547 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-24 00:20:55 +00:00
Automerge Script
131fcf61e6 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@56455 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-23 21:26:04 +00:00
Automerge Script
2954de75bb automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@56322 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-23 00:21:13 +00:00
Automerge Script
33ec4fecf5 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@56275 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-22 19:21:50 +00:00
Automerge Script
870af81ca1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@56054 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-22 01:23:41 +00:00
Automerge Script
17679c25cf automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@56003 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-21 21:22:51 +00:00
Automerge Script
96300341b9 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@55913 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-21 15:21:36 +00:00
Automerge Script
229aed7457 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@55796 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-21 01:21:39 +00:00
Automerge Script
48b43e1a92 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@55715 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-20 23:21:22 +00:00
Automerge Script
dc1836f854 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@55633 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-20 20:22:54 +00:00
Automerge Script
b507853850 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@55478 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-19 19:22:08 +00:00
Automerge Script
a7bd9aec9c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@55322 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-18 13:20:26 +00:00
Automerge Script
7c6c6a0d7b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@55273 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-18 11:12:51 +00:00
Automerge Script
23c17817ae automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@55196 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-17 04:19:41 +00:00
Automerge Script
57122c46c5 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@55085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-17 01:15:23 +00:00
Automerge Script
b7765f3783 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@55049 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-16 23:21:15 +00:00
Automerge Script
c1063541e5 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@55001 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-16 22:14:32 +00:00
Automerge Script
be9e3c0778 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@54968 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-16 21:07:50 +00:00
Automerge Script
93d501e3b3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@54821 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-16 12:21:47 +00:00
Automerge Script
d55ae8cc0e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@54671 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-15 17:21:50 +00:00
Automerge Script
6bfe3a4244 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@54463 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-14 19:12:21 +00:00
Automerge Script
a88490a68c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@54422 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-14 17:23:39 +00:00
Automerge Script
155aee0b84 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@54203 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-13 19:37:42 +00:00
Kevin P. Fleming
dd0edc0f9c merge up to branch 1.2 and re-enable automerge
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@53671 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-08 22:48:47 +00:00
Automerge Script
03161d7a82 automerge cancel
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@53199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-02-05 21:53:01 +00:00
Automerge Script
e9b9632fef automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@52995 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-30 20:13:10 +00:00
Automerge Script
1308ebf409 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@52949 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-30 18:14:52 +00:00
Automerge Script
20b69b892a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@52902 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-30 16:13:24 +00:00
Automerge Script
f29eee96ec automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@52855 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-30 14:59:43 +00:00
Automerge Script
ff730c46b0 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@52806 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-30 01:13:13 +00:00
Automerge Script
33228042e7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@52761 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-30 00:13:10 +00:00
Automerge Script
c58c4e83a2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@52521 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-29 17:02:13 +00:00
Automerge Script
2911d1ab26 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@52459 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-27 03:17:51 +00:00
Automerge Script
263d1100fd automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@52369 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-27 00:07:40 +00:00
Automerge Script
fb41b21e01 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@52307 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-25 20:17:14 +00:00
Automerge Script
29a132d611 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@52202 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-25 02:15:23 +00:00
Automerge Script
1c9163443a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@52157 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-25 01:04:30 +00:00
Automerge Script
3f1a198f45 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@52048 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-24 18:19:06 +00:00
Automerge Script
ff2ae14a9b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@51978 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-24 11:00:29 +00:00
Automerge Script
260eccbb03 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@51880 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-24 01:19:59 +00:00
Automerge Script
a94d625209 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@51557 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-23 02:12:58 +00:00
Automerge Script
5030563084 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@51455 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-22 20:27:07 +00:00
Automerge Script
a4e9dffea0 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@51403 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-22 17:22:37 +00:00
Automerge Script
ab1111631a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@51118 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-16 06:09:57 +00:00
Automerge Script
80da8dcaac automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@51029 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-16 00:11:13 +00:00
Automerge Script
a552b8298c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@50956 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-15 21:00:41 +00:00
Automerge Script
f80eaea4ee automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@50819 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-14 06:13:36 +00:00
Automerge Script
075c32cbb9 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@50599 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-12 15:18:07 +00:00
Automerge Script
a05d42a3ef automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@50529 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-11 19:00:39 +00:00
Automerge Script
0517ed834e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@50516 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-11 14:59:58 +00:00
Automerge Script
fa061fa339 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@50505 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-11 14:00:15 +00:00
Automerge Script
a20330b393 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@50345 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-10 10:02:43 +00:00
Automerge Script
b8612623a2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@50330 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-10 05:10:20 +00:00
Automerge Script
28de5dbaa9 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@50265 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-10 03:10:55 +00:00
Automerge Script
97f57029d5 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@50185 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-09 14:09:37 +00:00
Automerge Script
272ff651de automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@49944 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-08 09:04:16 +00:00
Automerge Script
325d362076 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@49921 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-08 06:08:16 +00:00
Automerge Script
ac96ab8b01 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@49865 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-07 22:09:13 +00:00
Automerge Script
f7e49a14fd automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@49667 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-05 18:09:06 +00:00
Automerge Script
b99c6b0329 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@49456 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-04 17:58:59 +00:00
Automerge Script
8672b596af automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@49446 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-04 17:09:25 +00:00
Automerge Script
e42fdeeea1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@49387 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-04 00:09:00 +00:00
Automerge Script
84041c2b8b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@49312 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-03 08:58:33 +00:00
Automerge Script
9dbe6ac46e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@49144 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-02 10:59:16 +00:00
Automerge Script
6459d34ade automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@49131 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-02 01:15:10 +00:00
Automerge Script
8866f912c1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@48812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-12-21 21:14:02 +00:00
Automerge Script
8e36da5699 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@48657 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-12-20 20:11:07 +00:00
Kevin P. Fleming
32ef26d652 manual update
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@48469 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-12-14 13:18:15 +00:00
Kevin P. Fleming
05f6188c69 manual update, since automerge is not running at this time
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@48421 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-12-12 22:58:49 +00:00
Automerge script
3bb733a7c7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@46990 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-02 18:05:19 +00:00
Automerge script
74c70148ac automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@46927 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-02 16:03:21 +00:00
Automerge script
e993f73211 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@46882 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-02 14:01:53 +00:00
Automerge script
ace0f74f27 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@46844 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-01 22:01:12 +00:00
Automerge script
30448e4bac automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@46821 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-01 20:03:05 +00:00
Automerge script
e41860927e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@46800 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-11-01 19:03:30 +00:00
Automerge script
830d07c933 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@46680 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-31 16:02:51 +00:00
Automerge script
9a6cfc6866 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@46627 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-31 10:21:42 +00:00
Automerge script
026b3a3fc7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@46602 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-31 09:04:28 +00:00
Automerge script
088684b275 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@46581 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-31 07:03:05 +00:00
Automerge script
4a00839358 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@46456 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-30 17:05:38 +00:00
Automerge script
5c99f456a9 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@46427 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-30 15:03:50 +00:00
Automerge script
cc1353522f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@46274 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-25 20:02:43 +00:00
Automerge script
5d49b657f6 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@46232 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-25 16:02:50 +00:00
Automerge script
bea7528f5e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@46182 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-25 09:02:09 +00:00
Automerge script
d7a7695b91 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@45944 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-23 01:04:59 +00:00
Automerge script
ab1188c1f2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@45814 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-21 13:01:41 +00:00
Automerge script
2a0b7672d2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@45711 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-19 18:02:35 +00:00
Automerge script
6c4758530a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@45397 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-17 21:02:28 +00:00
Automerge script
83852bc8c1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@45350 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-17 18:02:33 +00:00
Automerge script
225c4931fa automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@45312 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-17 16:01:39 +00:00
Automerge script
e3a3e8377d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@45279 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-16 20:04:13 +00:00
Automerge script
1a0892dbeb automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@45139 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-14 01:00:59 +00:00
Automerge script
2489f46365 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@45124 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-13 23:01:13 +00:00
Automerge script
dfafe2f958 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@45102 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-13 20:02:02 +00:00
Automerge script
0485f6b149 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@45065 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-13 17:02:15 +00:00
Automerge script
2097c7e87d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@45046 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-13 16:02:27 +00:00
Automerge script
eacb11ad56 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@45025 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-13 14:01:03 +00:00
Automerge script
d70d558bef automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@44999 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-13 08:02:20 +00:00
Automerge script
bf9aaf7beb automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@44970 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-12 19:02:56 +00:00
Automerge script
2c9a7acf54 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@44804 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-10 16:03:06 +00:00
Automerge script
3dfd319062 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@44594 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-06 17:02:27 +00:00
Automerge script
d2cbfe3d21 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@44515 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-05 20:02:26 +00:00
Automerge script
b45cbc48f2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@44464 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-05 11:00:47 +00:00
Automerge script
213c6afa9b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@44449 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-05 02:02:12 +00:00
Automerge script
50841b3a96 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@44406 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-04 22:02:08 +00:00
Automerge script
029b67fd32 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@44351 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-04 16:05:59 +00:00
Automerge script
41c63cf7f5 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@44311 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-03 21:02:12 +00:00
Automerge script
e1fbeb0c7f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@44230 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-02 21:02:14 +00:00
Automerge script
e609b4070c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@44212 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-02 20:02:11 +00:00
Automerge script
1db6355b21 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@44184 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-02 18:01:57 +00:00
Automerge script
b628bed1c3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@44165 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-02 17:05:27 +00:00
Automerge script
d81ec738b2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@44124 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-10-01 16:01:57 +00:00
Automerge script
b2d3f68e87 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43991 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-29 14:01:57 +00:00
Automerge script
ae1a27ae61 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43931 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-28 18:01:52 +00:00
Automerge script
93efe68235 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43911 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-28 17:01:35 +00:00
Automerge script
3da0f0e59d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43887 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-28 16:01:36 +00:00
Automerge script
2b76e9e216 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43826 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-27 21:01:34 +00:00
Automerge script
854e0369df automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43813 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-27 20:01:41 +00:00
Automerge script
97834bbed9 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43791 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-27 17:02:12 +00:00
Automerge script
7502860910 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43773 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-27 13:01:41 +00:00
Automerge script
4c6fb3dd37 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43720 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-26 21:01:50 +00:00
Automerge script
1de86fd7fc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43639 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-25 22:00:50 +00:00
Automerge script
d4026a11b1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43563 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-24 14:01:51 +00:00
Automerge script
c5056e1736 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43516 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-22 22:01:20 +00:00
Automerge script
bb63a367e3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43421 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-21 17:01:53 +00:00
Automerge script
24279ed40d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43321 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-20 06:01:11 +00:00
Automerge script
e2354a5244 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43280 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-19 17:01:01 +00:00
Automerge script
9ae33412c5 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43255 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-19 13:01:18 +00:00
Automerge script
daeb228bb3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43229 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-18 21:00:57 +00:00
Automerge script
8911aced89 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43181 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-18 16:02:39 +00:00
Automerge script
1e4fd6f9b5 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43087 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-17 14:02:31 +00:00
Automerge script
60b84e7a31 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43023 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-16 08:01:02 +00:00
Automerge script
0d4e8df3d6 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@43007 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-16 05:00:50 +00:00
Automerge script
0eb84ea1b0 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42963 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-14 23:03:37 +00:00
Automerge script
3f4ef02de2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42909 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-13 20:02:40 +00:00
Automerge script
cb1e08addc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42787 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-11 22:00:50 +00:00
Automerge script
e1f5e8e583 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42736 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-11 17:02:51 +00:00
Automerge script
a270e65e11 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42714 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-11 15:02:39 +00:00
Automerge script
b2b2ea5901 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42620 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-09 21:02:51 +00:00
Automerge script
558c7ade17 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42554 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-09 13:03:03 +00:00
Automerge script
380d8d80ba automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42470 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-08 19:02:43 +00:00
Automerge script
1134ad9412 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42440 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-08 17:03:06 +00:00
Automerge script
0b7de19b00 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42419 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-08 05:02:32 +00:00
Automerge script
6f41dcb8a3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42372 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-08 00:02:42 +00:00
Automerge script
67f0bd0d79 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42282 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-07 17:03:13 +00:00
Automerge script
fe6193c75b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42207 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-07 03:00:58 +00:00
Automerge script
8bb17660d7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42169 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-06 21:03:10 +00:00
Automerge script
cfb503c6a7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42147 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-06 19:02:18 +00:00
Automerge script
a4beaa7dc7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42132 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-06 18:03:25 +00:00
Automerge script
942974c8df automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42107 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-06 16:06:48 +00:00
Joshua Colp
6480d28862 Merged revisions 41768,41827,41830,41880,41882,41989,42014,42054 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.2

........
r41768 | file | 2006-09-01 18:49:07 -0400 (Fri, 01 Sep 2006) | 2 lines

Only wipe the redirected audio & video IP/port if it's specified, and trigger a reinvite.

........
r41827 | bweschke | 2006-09-03 10:16:08 -0400 (Sun, 03 Sep 2006) | 3 lines

 Setting a retry of 0 is generally not a good idea and shouldn't be allowed. (#7574 - reported by regin)


........
r41830 | bweschke | 2006-09-03 10:50:59 -0400 (Sun, 03 Sep 2006) | 3 lines

 Let's NOT spy on Zap/psuedo channels, mmmmmmmmk? 


........
r41880 | bweschke | 2006-09-03 13:13:38 -0400 (Sun, 03 Sep 2006) | 3 lines

 Don't keep trying the same member in certain strategies when members of the queue are unavailable (#7278 - diLLec reported and patched) - This should have been patched here first and then merged into /trunk. My bad!


........
r41882 | bweschke | 2006-09-03 13:38:22 -0400 (Sun, 03 Sep 2006) | 3 lines

 Make sure the forwarded channel inherits variables appropriately when we receive a call forward in the queue. (#7867 - raarts reported and patched)


........
r41989 | oej | 2006-09-04 11:46:07 -0400 (Mon, 04 Sep 2006) | 2 lines

Don't kill the pvt before we have sent ACK on CANCEL (needs more testing before making a release)

........
r42014 | qwell | 2006-09-05 12:27:46 -0400 (Tue, 05 Sep 2006) | 4 lines

Small typo in zapata.conf.sample

Reported by ppyy in 7881

........
r42054 | file | 2006-09-05 16:02:48 -0400 (Tue, 05 Sep 2006) | 2 lines

Merge in last round of spy fixes. This should hopefully eliminate all the issues people have been seeing by distinctly separating what each component (core/spy) is responsible for. Core is responsible for adding a spy to a channel, feeding frames to the spy, removing the spy from a channel, and telling the spy to stop. Spy is responsible for reading frames in, and cleaning up after itself.

........


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@42081 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-05 23:48:48 +00:00
Automerge script
e9cce1551a automerge cancel
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@41787 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-01 23:03:07 +00:00
Automerge script
aee92d097a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@41734 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-01 18:02:51 +00:00
Automerge script
ecfce7b643 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@41714 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-09-01 17:03:18 +00:00
Automerge script
aada1f902b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@41432 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-30 19:03:07 +00:00
Automerge script
008cf36d00 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@41410 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-30 18:03:00 +00:00
Automerge script
5d95ba629c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@41356 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-30 15:03:12 +00:00
Automerge script
37f7d1e3f0 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@41301 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-30 00:03:06 +00:00
Automerge script
d4b10c9036 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@41266 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-29 06:00:50 +00:00
Automerge script
a37739a0d9 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@41258 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-28 21:02:56 +00:00
Automerge script
53a30e84eb automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@41085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-25 16:02:33 +00:00
Automerge script
a8350ac22f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@41003 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-24 20:01:23 +00:00
Automerge script
26eba15ec8 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@40987 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-24 18:01:06 +00:00
Automerge script
38990b3d2c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@40978 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-24 17:01:04 +00:00
Automerge script
c05bc793fe automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@40920 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-23 17:06:32 +00:00
Automerge script
65d8d50962 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@40825 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-22 03:00:53 +00:00
Automerge script
e51b44628a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@40806 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-21 23:01:24 +00:00
Automerge script
672df19a39 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@40720 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-20 23:04:09 +00:00
Automerge script
d8220c853c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@40629 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-20 05:04:37 +00:00
Automerge script
38504cba52 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@40451 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-19 01:04:07 +00:00
Automerge script
c45aa02c13 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@40423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-18 20:04:23 +00:00
Automerge script
3e1daa8f94 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@40332 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-17 22:04:22 +00:00
Automerge script
1e38d97c40 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@40253 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-17 17:04:18 +00:00
Automerge script
e6906d738b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@40083 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-16 19:04:10 +00:00
Automerge script
8c1e784711 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@39962 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-15 23:04:36 +00:00
Automerge script
02e6c4f9f3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@39397 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-08 19:02:51 +00:00
Automerge script
e7e8d3d4a2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@39377 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-08 18:03:57 +00:00
Automerge script
e4c08a03c8 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@39104 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-07 02:03:39 +00:00
Automerge script
3cafe77949 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@39080 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-07 01:03:45 +00:00
Automerge script
76f5300793 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38995 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-05 09:03:31 +00:00
Automerge script
d5061be770 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38971 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-05 08:04:05 +00:00
Automerge script
e91c55a99d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38949 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-05 07:03:24 +00:00
Automerge script
ee2918d783 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38927 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-05 06:04:09 +00:00
Automerge script
06352345c1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38849 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-03 20:03:36 +00:00
Automerge script
03a63f510a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38784 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-03 06:03:31 +00:00
Automerge script
809a32c851 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38754 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-02 20:04:16 +00:00
Automerge script
561838ab6a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38709 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-02 00:03:25 +00:00
Automerge script
c535882053 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38675 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-01 20:03:13 +00:00
Automerge script
1f18490cdd automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38631 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-31 22:03:05 +00:00
Automerge script
3a4688c5ba automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38605 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-31 18:03:36 +00:00
Automerge script
6088318e55 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38568 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-31 05:02:43 +00:00
Automerge script
0e601bac9b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38520 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-30 00:02:52 +00:00
Automerge script
ac9938f84a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38438 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-28 19:02:55 +00:00
Automerge script
e076d9d41f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38388 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-27 23:02:39 +00:00
Automerge script
109237c04f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38364 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-27 16:02:48 +00:00
Automerge script
4dc5c42b30 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38346 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-27 05:02:49 +00:00
Automerge script
0375e58b2f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38327 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-27 03:02:35 +00:00
Automerge script
f8bb8d5eab automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38307 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-27 02:03:01 +00:00
Automerge script
7211dd853e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38249 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-26 16:03:00 +00:00
Automerge script
6342e0c54a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38215 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-25 20:02:30 +00:00
Automerge script
38b6e7dd94 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@38185 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-24 18:02:36 +00:00
Automerge script
ebdb3d95b2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37972 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-19 18:03:16 +00:00
Automerge script
2d035ab9a4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37875 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-18 01:02:23 +00:00
Automerge script
861ecb091a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37851 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-18 00:02:33 +00:00
Automerge script
7d70ecfe81 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37826 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-17 23:02:47 +00:00
Automerge script
95e2fd1571 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37783 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-17 16:02:46 +00:00
Automerge script
0b482e3f1c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37714 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-16 00:02:36 +00:00
Automerge script
0aaae9f118 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37628 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-14 14:02:33 +00:00
Automerge script
a2be0f0c4a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37585 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-13 22:02:15 +00:00
Automerge script
25ba50fb8f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37560 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-13 19:02:05 +00:00
Automerge script
4469bcc1a2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37545 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-13 17:02:17 +00:00
Automerge script
13c52205fb automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37530 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-13 16:02:53 +00:00
Automerge script
51c1fc4c90 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37472 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-12 19:02:06 +00:00
Automerge script
afb25c2c40 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37455 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-12 16:02:19 +00:00
Automerge script
94755549d7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37432 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-12 14:02:32 +00:00
Automerge script
fac0ba002f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37416 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-12 04:02:08 +00:00
Automerge script
9fe475f0df automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37395 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-11 20:02:43 +00:00
Automerge script
36f56a5e9e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37375 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-10 22:02:08 +00:00
Automerge script
424b3fd4eb automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37317 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-08 00:01:47 +00:00
Automerge script
a07938ea7e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37253 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-06 22:04:42 +00:00
Automerge script
da8d720b2a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37221 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-06 21:01:31 +00:00
Automerge script
2fb94832b5 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37200 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-06 16:04:31 +00:00
Automerge script
e11ef6ebe9 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37170 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-06 14:04:30 +00:00
Automerge script
aa3c2d5acb automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@37026 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-05 16:04:30 +00:00
Automerge script
c6e79104a3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@36939 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-04 15:04:52 +00:00
Automerge script
0fb5b6dcf2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@36863 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-03 16:04:11 +00:00
Automerge script
b051dd6899 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@36776 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-03 06:03:44 +00:00
Automerge script
fd757fcf51 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@36750 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-03 05:04:12 +00:00
Automerge script
ec42b4f2b1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@36724 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-07-03 04:04:11 +00:00
Automerge script
77d5bacce8 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@36405 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-30 15:04:39 +00:00
Automerge script
603eaab120 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@36297 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-29 20:01:30 +00:00
Automerge script
402cef20d8 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@36283 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-29 08:04:58 +00:00
Automerge script
d7b1425124 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@36225 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-28 20:05:10 +00:00
Automerge script
47b80cf742 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@36108 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-26 18:04:18 +00:00
Automerge script
6f9b26b7e3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@36050 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-26 16:01:40 +00:00
Automerge script
5a25b96143 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@35942 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-25 16:04:25 +00:00
Automerge script
031b53f451 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@35695 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-23 12:04:14 +00:00
Automerge script
12ebb1d7b4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@35364 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-21 20:04:35 +00:00
Automerge script
59a4279fb5 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@35158 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-20 16:05:25 +00:00
Automerge script
e1583210e7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@35092 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-20 11:05:33 +00:00
Automerge script
1386fb291b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@34950 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-19 21:05:53 +00:00
Automerge script
d9cfa818c4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@34909 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-19 19:04:53 +00:00
Automerge script
0af302cf60 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@34661 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-18 21:04:55 +00:00
Automerge script
5b7b71ebc9 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@34432 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-16 04:07:04 +00:00
Automerge script
c6323087fc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@34336 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-15 15:04:55 +00:00
Automerge script
a98f0bf56d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@34304 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-15 14:04:55 +00:00
Automerge script
36fbb43884 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@34273 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-15 13:05:40 +00:00
Automerge script
4d1ed8bde0 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@34192 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-14 23:11:07 +00:00
Automerge script
05c3bd0de5 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@34125 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-14 15:06:38 +00:00
Automerge script
36cacf788f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@34021 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-14 03:04:51 +00:00
Automerge script
641ab6d1bc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@33868 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-13 14:03:54 +00:00
Automerge script
c364c5efdd automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@33840 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-13 13:04:08 +00:00
Automerge script
279b842888 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@33812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-13 05:04:22 +00:00
Automerge script
e7648cca42 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@33780 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-13 04:03:56 +00:00
Automerge script
449c9c191f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@33750 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-12 22:04:00 +00:00
Automerge script
bfae89ea9e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@33723 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-12 21:04:26 +00:00
Automerge script
20fe40f872 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@33642 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-12 16:04:02 +00:00
Automerge script
8aa9a0e17f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@33575 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-11 22:04:09 +00:00
Automerge script
9de1f31bbc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@33544 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-11 21:04:25 +00:00
Automerge script
fae968612e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@33509 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-11 16:04:09 +00:00
Automerge script
d21d275cc3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@33478 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-11 15:04:26 +00:00
Automerge script
62866c9fda automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@33327 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-09 19:04:18 +00:00
Automerge script
f6a39fbcc2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@33292 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-09 17:04:09 +00:00
Automerge script
e7e0030d6b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@33262 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-09 16:04:26 +00:00
Automerge script
6fcb0a1a43 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@33062 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-08 17:04:02 +00:00
Automerge script
ec8919adcf automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@32844 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-07 18:04:56 +00:00
Automerge script
cbf462c3c7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@32632 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-06 17:05:29 +00:00
Automerge script
e89976c879 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@32595 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-06 16:05:13 +00:00
Automerge script
bc79efe36f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@32400 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-05 20:04:59 +00:00
Automerge script
b54594651c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@31951 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-04 04:05:13 +00:00
Automerge script
e655848772 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@31807 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-03 18:05:16 +00:00
Automerge script
0de3815b2a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@31769 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-03 15:05:26 +00:00
Automerge script
214df108f8 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@31585 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-01 22:05:50 +00:00
Automerge script
e5d6dfc0b9 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@31551 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-01 21:05:20 +00:00
Automerge script
6b24a23364 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@31352 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-01 13:05:15 +00:00
Automerge script
fc18e3a448 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@31224 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-06-01 00:05:30 +00:00
Automerge script
c7a667391b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@31192 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-31 23:05:21 +00:00
Automerge script
98b7b027be automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@31157 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-31 21:05:23 +00:00
Automerge script
9b23589112 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@30905 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-30 20:05:55 +00:00
Automerge script
99cf427def automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@30834 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-30 17:05:14 +00:00
Automerge script
f16891f03f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@30799 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-30 15:07:02 +00:00
Automerge script
b2fb09bd73 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@30577 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-26 18:06:03 +00:00
Automerge script
b752fe2fb0 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@30462 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-25 22:05:58 +00:00
Automerge script
ad5a410b70 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@30385 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-25 20:05:54 +00:00
Automerge script
bc94429e8c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@30358 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-25 19:05:14 +00:00
Automerge script
4f6e1f4878 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@30327 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-25 18:05:26 +00:00
Automerge script
a5cfea7f28 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@30270 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-25 16:05:31 +00:00
Automerge script
aa4d7f8df9 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@30127 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-24 22:04:41 +00:00
Automerge script
b5b89d732c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@30097 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-24 21:05:13 +00:00
Automerge script
a71ff914c6 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@30067 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-24 20:05:12 +00:00
Automerge script
b30db14404 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@30001 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-24 17:05:22 +00:00
Automerge script
0d1e7be6ea automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@29966 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-24 13:01:36 +00:00
Automerge script
4bcedb93cc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@29934 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-24 04:05:45 +00:00
Automerge script
0a4881b51f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@29877 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-23 22:05:06 +00:00
Automerge script
c96816d287 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@29798 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-23 19:05:12 +00:00
Automerge script
ca89b4e76c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@29762 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-23 18:05:13 +00:00
Automerge script
cfd6e75c53 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@29702 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-23 16:01:16 +00:00
Automerge script
ebfd515ca7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@29591 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-22 22:06:43 +00:00
Automerge script
db4f8886bd automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@29551 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-22 21:05:40 +00:00
Automerge script
1683b50452 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@29502 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-22 17:06:30 +00:00
Automerge script
49be813673 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@29433 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-22 15:06:09 +00:00
Automerge script
bb59b231d3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@29233 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-21 16:06:29 +00:00
Automerge script
c8d73b95a0 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@29092 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-20 20:07:15 +00:00
Automerge script
dac92a6182 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@29006 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-20 03:06:40 +00:00
Automerge script
142165cb92 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@28933 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-20 01:07:21 +00:00
Automerge script
3e6f1fe864 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@28831 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-19 20:06:50 +00:00
Automerge script
134eb7c8f6 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@28788 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-19 19:07:56 +00:00
Automerge script
7633ebabe8 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@28702 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-19 17:04:55 +00:00
Automerge script
a2ebf8a0fb automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@28674 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-19 16:07:43 +00:00
Automerge script
54282f4e4b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@28392 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-18 21:01:36 +00:00
Automerge script
f360986593 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@28379 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-18 20:07:21 +00:00
Automerge script
7f5e1b4abe automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@28299 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-18 18:07:34 +00:00
Automerge script
1da1f4e939 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@28256 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-18 17:08:06 +00:00
Automerge script
f209b6fe9b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@28211 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-18 15:07:38 +00:00
Automerge script
1dea733878 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@28167 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-18 13:06:54 +00:00
Automerge script
7b5e3d8fd5 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@28015 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-17 23:08:25 +00:00
Automerge script
2c8f7e39f6 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@27969 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-17 20:07:31 +00:00
Automerge script
64fa2ed07a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@27890 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-17 18:07:31 +00:00
Automerge script
2a3e4e3a38 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@27811 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-17 16:07:08 +00:00
Automerge script
8c111c6a6c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@27765 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-17 10:07:11 +00:00
Automerge script
f16c918188 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@27677 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-17 03:07:25 +00:00
Automerge script
c161ad3074 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@27635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-17 00:06:52 +00:00
Automerge script
fcdf61c4b3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@27475 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-16 20:06:30 +00:00
Automerge script
2e4c3cac8a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@27127 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-13 05:07:32 +00:00
Automerge script
a84ea4f014 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@27085 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-12 00:05:45 +00:00
Automerge script
e9ee611581 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@26798 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-11 09:10:58 +00:00
Automerge script
d83e489d61 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@26130 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-09 15:07:09 +00:00
Automerge script
269783fdff automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@26089 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-09 14:06:34 +00:00
Automerge script
c43ec5a1bc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@25650 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-08 16:07:44 +00:00
Automerge script
407350f13d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@25607 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-08 15:07:01 +00:00
Automerge script
626a5228e3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@25561 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-08 14:07:31 +00:00
Automerge script
d4b1647374 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@25486 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-08 12:06:46 +00:00
Automerge script
151fc69ffc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@25355 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-07 14:05:27 +00:00
Automerge script
fcdcbf879a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@25321 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-07 13:05:43 +00:00
Automerge script
91096b7368 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@25200 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-06 03:06:16 +00:00
Automerge script
034337fb07 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@25158 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-06 01:06:20 +00:00
Automerge script
0d352c2e09 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@25055 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-05 21:07:01 +00:00
Automerge script
f923e2c1b8 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@24949 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-05 18:06:18 +00:00
Automerge script
5c40f5053f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@24875 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-05 15:08:18 +00:00
Automerge script
b4c09a0b95 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@24742 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-04 17:05:55 +00:00
Automerge script
218672370e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@24705 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-04 12:05:58 +00:00
Automerge script
696ef06866 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@24603 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-03 21:06:33 +00:00
Automerge script
fa4103cc3b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@24533 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-03 19:06:04 +00:00
Automerge script
ef55cff62a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@24420 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-03 13:08:48 +00:00
Automerge script
95c0040574 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@24338 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-02 20:07:59 +00:00
Automerge script
d46854d378 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@24128 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-02 03:06:29 +00:00
Automerge script
622352f2c9 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@24049 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-01 21:05:01 +00:00
Automerge script
1a02e1b9c1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@24018 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-01 20:05:24 +00:00
Automerge script
8cb576b993 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@23981 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-01 16:05:04 +00:00
Automerge script
ab900f7fad automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@23927 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-05-01 11:04:46 +00:00
Automerge script
8192165970 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@23734 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-30 16:05:12 +00:00
Automerge script
5e0ea8da27 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@23703 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-30 15:05:31 +00:00
Automerge script
a8798960dd automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@23668 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-30 14:05:02 +00:00
Automerge script
ac5119e455 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@23610 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-30 12:04:51 +00:00
Automerge script
c67540d87b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@23333 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-29 12:04:34 +00:00
Automerge script
49e844c0e6 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@23206 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-28 17:05:06 +00:00
Automerge script
b51560eaa1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@22987 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-27 20:05:17 +00:00
Automerge script
3190fe1c57 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@22899 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-27 17:06:05 +00:00
Automerge script
0529a7f84a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@22629 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-26 20:05:58 +00:00
Automerge script
c292909f2e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@22123 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-21 23:02:41 +00:00
Automerge script
37a6092b27 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@21678 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-19 22:05:55 +00:00
Automerge script
f73cbceaf6 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@21635 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-19 19:06:20 +00:00
Automerge script
940c220642 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@21274 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-19 00:06:11 +00:00
Automerge script
ccc668b5d6 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@21076 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-18 07:06:21 +00:00
Automerge script
dd12cba9d0 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@21001 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-17 17:06:46 +00:00
Automerge script
6e6a00609d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@20074 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-14 18:05:52 +00:00
Automerge script
ee263ee87e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@19929 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-13 21:06:44 +00:00
Kevin P. Fleming
63566eac42 Merged revisions 19812 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.2

........
r19812 | kpfleming | 2006-04-13 12:40:21 -0500 (Thu, 13 Apr 2006) | 2 lines

oops... let's not set a variable and then immediately overwrite it while assuming its old value will magically return

........


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@19818 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-13 17:52:23 +00:00
Automerge script
b64b6ef1f7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@19808 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-13 16:06:43 +00:00
Automerge script
54e190dacb automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@19435 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-11 23:06:48 +00:00
Automerge script
27b633c817 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@19391 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-11 22:06:47 +00:00
Automerge script
4099114189 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@19344 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-11 21:06:53 +00:00
Automerge script
2c897a8b8c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@19055 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-11 02:06:45 +00:00
Automerge script
2aac61e6ad automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@18903 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-10 18:06:02 +00:00
Automerge script
1db17b168a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@18532 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-08 20:06:31 +00:00
Automerge script
24298e447c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@18478 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-07 23:05:40 +00:00
Automerge script
d3a87c1f69 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@18297 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-07 15:06:19 +00:00
Automerge script
c72b1b15c4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@18259 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-07 14:01:46 +00:00
Automerge script
09609b0510 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@18125 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-06 23:05:57 +00:00
Automerge script
63bd37a91e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@17985 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-06 18:06:57 +00:00
Automerge script
760352a196 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@17942 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-06 17:06:45 +00:00
Automerge script
1fce77dc68 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@17734 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-05 20:06:32 +00:00
Automerge script
bde8fa877f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@17529 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-05 07:06:34 +00:00
Automerge script
08aecbb1ed automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@17403 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-04 19:05:53 +00:00
Automerge script
6f8262c9b4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@17362 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-04 18:04:52 +00:00
Automerge script
f7feba82bc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@17310 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-04 16:04:23 +00:00
Automerge script
c0bff2ac09 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@17177 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-03 21:04:38 +00:00
Automerge script
8839755956 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@17102 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-04-03 18:04:56 +00:00
Automerge script
2648e9f039 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@16797 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-31 20:03:56 +00:00
Automerge script
15e7ec94e1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@16770 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-31 19:04:28 +00:00
Automerge script
b877a5b0f7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@16599 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-30 23:02:42 +00:00
Automerge script
27405fac27 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@16577 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-30 22:02:13 +00:00
Automerge script
d2f451ef0c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@16545 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-30 18:01:47 +00:00
Automerge script
b4d9cb0418 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@16385 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-30 02:06:27 +00:00
Automerge script
c116009930 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@16343 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-30 01:06:54 +00:00
Automerge script
99a4cd1de2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@16233 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-29 20:06:56 +00:00
Automerge script
9a26882461 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@16123 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-29 15:06:30 +00:00
Automerge script
e167a9a350 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@16050 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-29 05:06:52 +00:00
Automerge script
f86140a213 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@15937 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-29 01:06:53 +00:00
Automerge script
b4589618c4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@15783 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-28 21:06:54 +00:00
Automerge script
fd1d8cdf10 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@15742 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-28 20:06:56 +00:00
Automerge script
7a879ed598 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@15698 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-28 19:06:50 +00:00
Automerge script
2764568353 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@15657 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-28 18:06:51 +00:00
Automerge script
e8862556fd automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@15423 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-28 00:07:31 +00:00
Automerge script
1e59a857ae automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@15374 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-27 23:01:43 +00:00
Automerge script
b705a62dc5 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@14914 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-25 06:07:49 +00:00
Automerge script
98ba3160e7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@14867 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-25 05:07:29 +00:00
Automerge script
0345a25e6a automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@14751 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-24 15:07:22 +00:00
Automerge script
ce930f8e2d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@14703 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-24 05:07:41 +00:00
Automerge script
0314e5efc6 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@14655 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-24 01:07:12 +00:00
Automerge script
c1d5aad112 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@14566 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-23 22:07:47 +00:00
Automerge script
7cae785261 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@14515 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-23 21:07:45 +00:00
Automerge script
de670a217d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@14319 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-22 23:06:30 +00:00
Automerge script
78104df395 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@14274 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-22 22:06:45 +00:00
Automerge script
ba4b234d34 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@14229 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-22 21:07:01 +00:00
Kevin P. Fleming
97b3a1c5a4 use proper email address for merge failures
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@14182 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-22 20:06:03 +00:00
Automerge script
2a14dad0f0 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@14178 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-22 10:10:37 +00:00
Automerge script
c614f4d869 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@13999 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-21 19:06:07 +00:00
Automerge script
e2ad8bd804 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@13960 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-21 18:05:42 +00:00
Automerge script
f06bd477c0 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@13924 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-21 17:05:44 +00:00
Automerge script
a0e595febf automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@13886 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-21 16:06:13 +00:00
Automerge script
2395b09fef automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@13849 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-21 15:05:43 +00:00
Automerge script
e3bc797a82 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@13784 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-21 07:06:15 +00:00
Automerge script
00461229c2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@13747 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-21 06:06:20 +00:00
Automerge script
c9d7d267cd automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@13673 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-20 19:07:11 +00:00
Automerge script
380d8cfcc4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@13586 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-19 10:10:38 +00:00
Automerge script
fe83f9421b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@13318 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-16 21:05:36 +00:00
Automerge script
2b3941fcbf automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@13274 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-16 18:06:16 +00:00
Automerge script
aad583ff1d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@13204 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-16 07:01:26 +00:00
Automerge script
9b1e1fe199 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@13196 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-15 23:05:42 +00:00
Automerge script
ca6ae319c7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@13130 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-15 19:05:45 +00:00
Automerge script
5e338e72ba automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@13062 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-15 14:06:15 +00:00
Automerge script
10fe0e9c67 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@12959 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-14 19:05:40 +00:00
Automerge script
f1fade4fa6 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@12825 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-13 16:05:25 +00:00
Automerge script
00e45fc396 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@12686 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-12 20:05:47 +00:00
Automerge script
0e3f10b86f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@12644 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-12 19:05:14 +00:00
Automerge script
d008cda808 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@12609 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-12 18:05:51 +00:00
Automerge script
ba70bebc38 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@12538 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-12 16:08:23 +00:00
Automerge script
eb6fc20dc8 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@12231 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-07 01:05:29 +00:00
Automerge script
db6920d628 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@12196 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-07 00:05:29 +00:00
Automerge script
0fcae43d36 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@12103 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-06 15:05:03 +00:00
Automerge script
8d808bd9d3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@12040 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-06 11:04:25 +00:00
Automerge script
c0763951ba automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11975 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-06 03:04:43 +00:00
Automerge script
e483c1945d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11879 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-05 13:05:27 +00:00
Automerge script
0397dba5a4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11804 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-04 12:04:16 +00:00
Automerge script
c19212f8d0 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11745 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-03 18:04:19 +00:00
Automerge script
d848cb43b3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11683 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-03 09:04:18 +00:00
Automerge script
50464af8c2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11658 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-03 01:03:41 +00:00
Automerge script
7f9c385052 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11633 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-02 23:03:50 +00:00
Automerge script
0840844421 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11585 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-02 20:03:53 +00:00
Automerge script
924be1c3b9 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11553 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-02 07:03:41 +00:00
Automerge script
b2b717e61f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11527 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-01 18:04:00 +00:00
Automerge script
2f6c81bbc5 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11502 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-03-01 07:03:42 +00:00
Automerge script
490cd4ada5 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11434 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-28 20:04:13 +00:00
Automerge script
ee69978cdc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11406 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-28 19:03:52 +00:00
Automerge script
0a4506d0dd automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11306 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-27 16:04:08 +00:00
Automerge script
b7ad6d8c2d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11275 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-27 03:04:02 +00:00
Automerge script
6f665a50e0 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11191 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-26 17:04:15 +00:00
Automerge script
0bc176e6b8 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11145 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-25 20:04:12 +00:00
Automerge script
b9b4ae4c34 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11115 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-25 06:04:09 +00:00
Automerge script
2719e0aa02 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@11088 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-25 05:04:25 +00:00
Automerge script
2dc3679b6e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@10986 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-24 00:04:40 +00:00
Automerge script
74879cff5b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@10870 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-23 15:01:21 +00:00
Automerge script
d58f08a1a9 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@10760 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-22 18:03:52 +00:00
Automerge script
2d948fe31e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@10601 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-21 00:03:56 +00:00
Automerge script
5efaf11018 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@10558 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-20 07:03:44 +00:00
Automerge script
b055431b5c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@10534 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-20 06:03:40 +00:00
Automerge script
e3bf4c14dc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@10509 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-19 19:03:29 +00:00
Automerge script
d291491eb6 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@10486 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-19 18:03:48 +00:00
Automerge script
e098adeaf7 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@10430 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-18 01:03:27 +00:00
Automerge script
304e39b8ec automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@10389 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-17 02:03:24 +00:00
Automerge script
d075508cf0 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@10322 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-16 19:03:22 +00:00
Automerge script
bf7f1e75da automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@10162 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-15 02:03:35 +00:00
Automerge script
72e192fc42 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@10136 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-15 01:04:13 +00:00
Automerge script
86a106023b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@10044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-14 21:05:23 +00:00
Automerge script
3a0ec4568d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@10017 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-14 20:11:19 +00:00
Automerge script
13d5513465 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9987 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-14 19:04:48 +00:00
Automerge script
b670fe8554 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9879 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-14 05:01:18 +00:00
Automerge script
beff9bb972 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9868 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-14 04:01:20 +00:00
Automerge script
19c52a797b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9842 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-14 01:03:47 +00:00
Automerge script
edbaad38fc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9782 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-13 18:04:04 +00:00
Automerge script
266010c7f2 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9627 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-11 20:03:02 +00:00
Automerge script
9bfab982fd automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9606 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-11 19:03:03 +00:00
Automerge script
18dbcd321d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9547 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-11 16:03:16 +00:00
Automerge script
744ec2c02e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9505 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-11 07:00:53 +00:00
Automerge script
c0dce52a12 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9422 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-10 21:03:04 +00:00
Automerge script
cfe7565123 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9346 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-09 22:03:14 +00:00
Automerge script
a6d8e03be5 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9273 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-09 03:01:45 +00:00
Automerge script
5fc4e0d280 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9258 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-09 02:01:45 +00:00
Automerge script
1c4e84f888 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9237 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-08 23:00:44 +00:00
Kevin P. Fleming
f6d4da1706 simplify automerge setup
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9169 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-06 20:47:11 +00:00
Automerge script
f5bbba29fb automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9159 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-05 18:00:23 +00:00
Kevin P. Fleming
4f44b40d33 update to current 1.2 branch
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9131 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-02 23:47:35 +00:00
Kevin P. Fleming
08e0a56f32 setup for new automerge process
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9130 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-02 23:45:00 +00:00
Automerge script
a0b6fe01f4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9097 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-02 19:01:36 +00:00
Automerge script
a03cf25014 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@9083 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-02-02 17:01:37 +00:00
Automerge script
9acbdbcc6d automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8916 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-30 18:01:34 +00:00
Automerge script
06765cc9d1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8818 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-28 14:01:17 +00:00
Automerge script
2cfee72f8e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8795 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-27 09:01:17 +00:00
Automerge script
8ff712f50f automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8767 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-27 01:01:17 +00:00
Automerge script
6a02d8a8d9 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8740 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-26 20:01:20 +00:00
Automerge script
02e4d63d7e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8721 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-26 15:01:17 +00:00
Automerge script
6f4c9d5739 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8686 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-25 20:01:00 +00:00
Automerge script
0bd1631812 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8675 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-25 19:01:09 +00:00
Automerge script
edfe61308b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8641 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-25 10:01:13 +00:00
Automerge script
9d4b0ced46 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8627 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-25 06:00:59 +00:00
Automerge script
9a8533488e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8617 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-25 02:01:00 +00:00
Automerge script
d7812f6634 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8607 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-24 23:00:59 +00:00
Automerge script
2e10d5244e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8581 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-24 21:01:03 +00:00
Automerge script
e295ae92f3 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8570 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-24 20:00:59 +00:00
Automerge script
0ca5e4125e automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8546 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-24 14:01:00 +00:00
Automerge script
86f0c7bfcc automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8449 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-22 20:00:19 +00:00
Automerge script
30c9cea332 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8440 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-22 18:00:19 +00:00
Automerge script
ea091271c8 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8435 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-22 16:00:19 +00:00
Automerge script
bea37cf37b automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8431 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-22 09:00:21 +00:00
Automerge script
b2d320b259 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8425 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-22 03:00:19 +00:00
Automerge script
749b766a8c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8415 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-22 00:00:10 +00:00
Automerge script
6fae615794 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8396 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-21 19:00:20 +00:00
Automerge script
abcbea02c1 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8355 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-20 19:01:00 +00:00
Automerge script
65850c0467 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8322 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-20 01:00:57 +00:00
Automerge script
413b215b6c automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8288 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-19 20:00:55 +00:00
Automerge script
30185fdff4 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8247 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-19 05:00:39 +00:00
Kevin P. Fleming
8cedcec2bc add README note to the proper place for future releases
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-18 23:14:04 +00:00
Automerge script
1cc6f6d3bb automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8202 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-18 22:00:37 +00:00
Automerge script
ca0a371996 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8176 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-18 03:00:42 +00:00
Automerge script
b0fd9f9b74 automerge commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8172 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-18 02:00:34 +00:00
Kevin P. Fleming
396f6561a4 set up for automerge
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8159 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-17 23:58:15 +00:00
Kevin P. Fleming
f16619507a updating to current 1.2
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@8046 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-13 03:52:45 +00:00
Kevin P. Fleming
69ac155838 initial import of Asterisk SIP support for network security devices
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@7927 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-10 03:10:34 +00:00
Kevin P. Fleming
a6bae85952 prepare for merging changes from main 1.2 branch
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@7926 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-10 03:05:18 +00:00
Kevin P. Fleming
494b9c486e create branch to hold network security device code
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2-netsec@7925 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-10 03:03:29 +00:00
Kevin P. Fleming
d8c5d338cb re-initialize _all_ sequence numbers when transfer completes
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7917 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 22:48:48 +00:00
Russell Bryant
417438fea0 add missing unlock (issue #6112)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7915 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 22:07:26 +00:00
Tilghman Lesher
5488ffb6d4 Bug 6157 - Memory leak
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7908 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 20:08:24 +00:00
Tilghman Lesher
e8725ce940 Update variable documentation to match the code
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7904 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 18:37:50 +00:00
Kevin P. Fleming
0e734920e8 commit user/group-related changes from trunk
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7900 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 18:11:23 +00:00
Kevin P. Fleming
ad598a2060 backport fix from revision 7856 of trunk
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7899 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 18:09:53 +00:00
Kevin P. Fleming
bb47f95262 fix breakage introduced in revision 7871
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7898 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 18:08:07 +00:00
Russell Bryant
a7a2115b9c fix seg fault when using greek syntax in VoicemMailMain (issue #6142)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7871 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 05:11:44 +00:00
Russell Bryant
18429f2a69 backport fix for unnecessary unlock (issue #6171)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7870 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-09 04:52:16 +00:00
Tilghman Lesher
7e6430787c Bug 6156 - catch all threading errors, not just simple failure
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7848 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-07 07:27:18 +00:00
Tilghman Lesher
dc3ba8c223 Dumb error messages - "Context 'context' already included in 'in' context"
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7831 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-06 00:34:40 +00:00
Kevin P. Fleming
2fd6520a7e update agent persistence when an agent gets logged off by autologoff
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7829 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-06 00:21:00 +00:00
Tilghman Lesher
7a61b36104 Bug 6076 - Fix documentation of ast_trim_blank return value
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7827 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-05 23:53:07 +00:00
Kevin P. Fleming
2f4783a770 eliminate rounding errors that caused call time limits to be inaccurate (issue #5913)
round 'time left' reported during call limit warnings up to sound more accurate


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7825 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-05 23:49:50 +00:00
Tilghman Lesher
6056391a78 Bug 6081 - fix for memory leak, formatting fixes
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7823 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-05 23:07:08 +00:00
Kevin P. Fleming
213b3575ce ensure that variable is initialized
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7819 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-05 20:52:38 +00:00
Olle Johansson
3821e18d08 Fix copyright of changed file
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7812 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-05 09:13:21 +00:00
Kevin P. Fleming
224c6e3f7c send device state updates for auto-logoff of agents as well
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7809 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-05 00:58:29 +00:00
Kevin P. Fleming
18ab6f429c doh... fseek() has no useful return value
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7807 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-05 00:18:46 +00:00
Kevin P. Fleming
07f8542ce7 use proper fwrite() parameters and return value
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7805 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-04 23:51:03 +00:00
Kevin P. Fleming
cf293c224d return properly after extending file
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7803 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-04 23:45:34 +00:00
Kevin P. Fleming
e234ad0011 ensure that ulaw/alaw sound files are filled with silence when extended (not zeroes)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7800 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-04 23:27:57 +00:00
Kevin P. Fleming
229b778b0b make monitoring more tolerant of peers that deliver frames in bursts
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7799 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-04 23:02:38 +00:00
Olle Johansson
66f484defe Issue #5980: Removing extra CR+LF in manager events - needs port to trunk
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7795 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-04 21:46:40 +00:00
Olle Johansson
ed523e248a Fixing typo in XML for video updates.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7792 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-04 21:43:14 +00:00
Russell Bryant
3c49f27bf4 use a more correct way of determining the size of the destination buffer
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7773 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-04 07:06:50 +00:00
BJ Weschke
226d146b25 Fix the 'if' clause to be true under the right conditions. Bug #6126
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7771 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-04 05:27:38 +00:00
Kevin P. Fleming
1892289329 remove unused 'old' expression parser
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7746 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-03 20:22:18 +00:00
Tilghman Lesher
5529fc0355 Bug 6121 - typo in application description
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7743 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-03 18:15:12 +00:00
Kevin P. Fleming
73ef559240 revert incorrect fix for bug #6048 from revision 7709
put in correct (simpler) fix
add doxygen docs for channel spy 'state' values


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7740 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-03 17:24:56 +00:00
Kevin P. Fleming
b59a63c8cd backport rport scanning fix from trunk (bug #6071)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7738 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-03 17:00:01 +00:00
Kevin P. Fleming
c36927137f don't leak memory for (most) expression evaluations
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7736 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-03 16:34:12 +00:00
Tilghman Lesher
649aaad100 Bug 6084 - MixMonitor after a 'cli stop monitor' deadlocks
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7709 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-02 07:31:54 +00:00
BJ Weschke
ea4c262482 Fix compiler warnings.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7706 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-01-02 02:04:14 +00:00
Tilghman Lesher
89de6c9df6 Bug 6091 - Fix race condition around uniqueid
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7677 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-30 14:54:19 +00:00
Russell Bryant
4578bc3b0c fix memory leak in build_rpid (issue #6070)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7665 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-28 17:35:56 +00:00
Russell Bryant
8df1e4866a backport fix for permissions of created recordings (issue #6067)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7663 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-27 21:07:08 +00:00
Kevin P. Fleming
9f92220a9c backport fix to ensure that DSP is never enabled on pseudo channels
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7641 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-27 00:07:45 +00:00
Tilghman Lesher
09a9e7bcb7 Remove copy of code in libc, preferring code in utils.c (public domain code)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7637 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-26 20:32:50 +00:00
Russell Bryant
a434f8877a cast time_t to an int in printf/scanf (issue #5635)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7634 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-26 18:19:12 +00:00
Tilghman Lesher
ef891dc0a7 Bug 6051 - VMCOUNT should work as documented and count all, not quit after finding 1
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7608 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-23 06:38:08 +00:00
Kevin P. Fleming
3ebe29c983 add license reference to copyright notice displayed when CLI session begins
add 'show warranty' and 'show license' CLI commands (still need a complete list of non-GPL components included in Asterisk)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7606 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-23 03:01:24 +00:00
BJ Weschke
1028e43464 Another app documentation tweak.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7605 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-23 00:00:11 +00:00
Tilghman Lesher
4979f66f28 Bug 6050 SQL requires the use of single ticks to delimit values, not quotes
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7601 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-22 22:04:13 +00:00
Russell Bryant
a5e9fe97c8 revert changes to videosupport to allow per-peer setting, since it isn't quite
complete and there is not an obvious fix at this point


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7599 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-22 20:36:47 +00:00
Russell Bryant
2293cfaf84 remove stray unlock (issue #5955)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7595 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-22 16:17:43 +00:00
Josh Roberson
d252dde933 Actually put in the per-peer settings for sip video, as they didn't make it in at astricon somehow, and I've been too busy up until now to redo it.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7586 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-21 22:23:39 +00:00
Tilghman Lesher
37a49a5992 Allow a chan_alsa that failed to open sound devices to be unloaded.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7582 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-21 20:01:16 +00:00
BJ Weschke
2783801610 Bug #6040 - Documentation correction
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7580 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-21 19:53:49 +00:00
Tilghman Lesher
82f19c9a91 Bug 5777 - Remove parentheses on Goto in AEL, so that it parses correctly
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7577 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-21 19:23:12 +00:00
Russell Bryant
71d9531e45 check array bounds when parsing arguments to AGI (issue #5868)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7557 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-20 20:21:26 +00:00
Russell Bryant
3bbeaefa57 backport fix for reloading peer context (issue #6007)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7552 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-20 18:05:45 +00:00
Russell Bryant
4611be805a backport fix for segfault on directed pickup when no CDR is available (issue #5998)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7550 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-20 17:34:00 +00:00
Kevin P. Fleming
587493fdfc backport fix for larger-than-20ms-frames from trunk (bug #5697)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7546 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-20 12:58:37 +00:00
Russell Bryant
50079144e3 I messed up and accidently committed this to the trunk first ...
- add note on required values of sip_methods struct
- remove duplicate function prototype
- remove duplicate ast_mutex_lock (issue #6025)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7529 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-19 23:47:23 +00:00
Tilghman Lesher
2ca80e76a0 Bug 5988 - record append option not working
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7523 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-19 19:06:46 +00:00
Tilghman Lesher
68e6502484 Bug 6026 - segfault for the sequence NoCDR(), SetAMAFlags()
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7521 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-19 05:38:44 +00:00
Tilghman Lesher
1e91dfa5df Document that curley braces must be on the same line as the keyword.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7519 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-17 18:55:38 +00:00
Tilghman Lesher
e4e5f7c65b Bug 6009 - off by one error
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7517 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-17 17:19:32 +00:00
Kevin P. Fleming
8ef66261f1 Max-Forwards headers must only be present on requests, not responses
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7515 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-17 03:59:05 +00:00
Kevin P. Fleming
90812b536c forcibly expire previous subscriptions from a peer when they resubscribe (keeps them from building up and waiting for expiration, and stops us sending unwanted NOTIFY messages to devices)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7513 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-17 03:44:30 +00:00
Kevin P. Fleming
2b880d3ef8 fix some buglet when building team branch version strings
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7510 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-17 02:20:04 +00:00
Tilghman Lesher
6ab729aeb3 We want to check the previous value, not the current value (which was just changed).
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7508 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-17 01:02:29 +00:00
Tilghman Lesher
c9f97f49c5 First field is truncated
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7497 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-16 00:49:39 +00:00
Christian Richter
8b352fcb94 * Added mISDN/mISDNuser Echo cancel Patch
* Fixed Makefiles so that chan_misdn can be compiled again
* added some hints, that mISDN cannot be compiled against gcc-4, SMP, Spinlock Debug
* fixed some Minor issues in chan_misdn, regarding Type Of Number and Presentation






git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7490 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-15 10:52:30 +00:00
BJ Weschke
5a06af4d57 Bug #6003 - Don't free the channel structure until after having sent the manager event.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7482 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-15 02:51:54 +00:00
Kevin P. Fleming
2ede900bfd clarify substring documentation
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7470 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-13 18:54:22 +00:00
Kevin P. Fleming
fb0ffc7784 correct broken math in tvfix() for timestamp values over one million
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7468 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-13 16:06:27 +00:00
Kevin P. Fleming
e69171dc06 restore ability of caller to hangup calls that are still ringing (issue #5839)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7453 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-13 05:53:00 +00:00
Kevin P. Fleming
8452f6b494 ensure that hangups while incoming calls are in early state are handled properly (issue #5919)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7451 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-13 05:14:27 +00:00
Kevin P. Fleming
f9bc6f8afc only report AGENT_IDLE for callback mode agents when they are actually idle (issue #5902)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7449 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-13 04:43:38 +00:00
Kevin P. Fleming
f9f44d7d9b use the stream's current point when pausing/unpausing, instead of elapsed time (which doesn't work when the stream has been skipped forward or backward) (issue #5897)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7448 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-13 04:25:14 +00:00
Kevin P. Fleming
86bb1472cc set all the child file descriptors to non-blocking so that we don't hang if the child fails to send a newline-terminated command or error message
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7435 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-12 17:30:59 +00:00
Tilghman Lesher
ef09c506c8 Typo
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7433 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-12 17:19:29 +00:00
Russell Bryant
af7b3b420e silence a couple of compiler warnings about pointer signedness
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7430 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-11 06:08:56 +00:00
Tilghman Lesher
3b80a35a66 Bug 5965 - major bug in AST_LIST_REMOVE
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7429 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-11 01:26:51 +00:00
Tilghman Lesher
f59b27258c Bug 5967
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7427 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-11 01:15:15 +00:00
BJ Weschke
d38fff38f9 Bug #5877
Make sure the digit string from E&M wink DNIS collection is properly null terminated as it grows.



git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7425 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-10 18:10:50 +00:00
Tilghman Lesher
91c5b12f25 Bug 5960
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7406 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-08 23:45:36 +00:00
Tilghman Lesher
894bdd5cda Documenting two keywords that were previously missing
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7404 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-08 23:32:08 +00:00
Kevin P. Fleming
d8c58ca6c8 initialize the buffer before using it...
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7386 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-08 01:05:43 +00:00
Kevin P. Fleming
43f7956422 ensure that hints are allowed to use global variable references
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7382 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-07 20:46:55 +00:00
Kevin P. Fleming
96fcc02900 ensure that sound/music files are handled as binary
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7351 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-06 00:23:05 +00:00
Kevin P. Fleming
2e8b6e7f20 replace with unmodified file
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7349 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-06 00:19:17 +00:00
Kevin P. Fleming
3ed93398e9 _really_ don't mess with line endings
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7347 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-06 00:08:19 +00:00
Kevin P. Fleming
d84e0caea8 don't try to expand keywords in this file
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7346 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-06 00:07:48 +00:00
Kevin P. Fleming
5c1da58b90 set this file to binary mode, so it won't be mangled on export/checkout
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7345 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-06 00:02:08 +00:00
Russell Bryant
018c617199 remove ASTERISKVERSIONNUM from the version string given to doxygen
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7340 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-05 06:47:51 +00:00
Russell Bryant
a49f954f6a don't delete dynamic queue members when reloading the static members from a realtime database (issue #5922)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7337 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-05 00:09:12 +00:00
Russell Bryant
03a8791440 fix the order of arguments to an error message (issue #5927)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7335 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-05 00:01:17 +00:00
Kevin P. Fleming
78ad17381e use a more efficient way to get the revision number, that will also report if the working copy contains uncommitted modifications
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7329 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-04 18:03:07 +00:00
Tilghman Lesher
5b03803e2f Bug 5925: check for "Unknown", as that's what app_voicemail puts into the field for Unknown callerid
Also, remove useless res checks (initialized to 0; never set)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7310 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-03 19:55:05 +00:00
Olle Johansson
ee1e461a57 Documenting the default registerattempts setting as 0, continue hammering the server for ever and ever ;-)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7299 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-03 01:24:40 +00:00
Tilghman Lesher
a543725311 Turn on executable bits for startup scripts, and fix bash var interpolation for Mandrake
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7285 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-02 21:12:05 +00:00
Olle Johansson
8c701a0861 Bug #5907. Improve SIP INFO DTMF debugging output. (1.2 & Trunk)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7275 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-02 00:52:13 +00:00
Kevin P. Fleming
5fbe566524 inherit channel variables into channels created by Page() application (issue #5888)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7274 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-02 00:51:15 +00:00
Kevin P. Fleming
e14cf31bc9 allow previous context-searching behavior to be used if desired (issue #5899)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7273 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-02 00:42:40 +00:00
Kevin P. Fleming
0042c03c7e properly handle password changes when mailbox is last line of config file and not followed by a newline (issue #5870)
reformat password changing code to conform to coding guidelines (issue #5870)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-02 00:39:00 +00:00
Kevin P. Fleming
41023ecb9c protect agent_bridgedchannel() from segfaulting when there is no bridged channel (issue #5879)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7271 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-02 00:28:48 +00:00
Kevin P. Fleming
fb8d0a544d allow variables to exist on both 'halves' of the Local channel (issue #5810)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7270 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-02 00:26:12 +00:00
Kevin P. Fleming
acaf8c9cc9 don't block waiting for the Festival server forever when it goes away (issue #5882)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7269 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 23:49:44 +00:00
Kevin P. Fleming
0d3fc8d103 ensure channel's scheduling context is freed (issue #5788)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7268 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 23:34:58 +00:00
Kevin P. Fleming
9bbfbacacc Makefile 'update' target now supports updating from Subversion repositories (issue #5875)
remove support for 'patches' subdirectory, it's no longer useful


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7266 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 23:18:29 +00:00
Olle Johansson
8e301c629f Changing bug report address to the Asterisk issue tracker
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7265 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 23:18:14 +00:00
Olle Johansson
9576d8a081 Removing references to 1.1dev, replacing with 1.2, in documentation files.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7263 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 22:21:13 +00:00
Olle Johansson
7db96672bf Fixing some spelling errors, as well as changing "cvs" to "subversion" in misdn documentation.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7261 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 21:38:38 +00:00
Kevin P. Fleming
0d8f099ca2 ensure that 'svn info' output is in the expected language for the script to parse (issue #5880)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7257 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 19:25:06 +00:00
Russell Bryant
0a4d7e5068 use ast_app_separate_args to split arguments (issue #5686)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7251 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 02:33:58 +00:00
Russell Bryant
a32f75b800 fix queue weight feature - compare member interfaces instead of pointers to
the members, since each queue has its own list of members. (issue #5863)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7249 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 01:19:04 +00:00
Russell Bryant
78f37c51ef use '=' instead of '==' for string comparisons. /bin/bash is ok with this, but
/bin/sh is not.  (issue #5885)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7247 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-12-01 00:44:34 +00:00
Russell Bryant
d6e5eb75ee remove outdated redhat init script and provide the updated one in 'make rpm' (issue #5786)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7244 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 21:31:18 +00:00
Russell Bryant
6f433a7e7b Comment out LD_ASSUME_KERNEL by default.
Print error messages if the asterisk executable or the asterisk configuration
directory are not found. (issue #5785, #5708)


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7242 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 21:24:52 +00:00
Russell Bryant
ce2ecb5582 fix DIALEDTIME when call has not been answered (issue #5862)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7234 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 17:39:36 +00:00
Russell Bryant
45c15e8561 do not allow an rtp message with zero type (issue #5749)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7233 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 14:27:59 +00:00
Russell Bryant
5e3f4186da fix hint case sensitivity (issue #5856)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7231 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 07:22:42 +00:00
Russell Bryant
d03694df19 add description of the "fromdomain" option (issue #5874)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7228 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 05:26:26 +00:00
Josh Roberson
d52e8fa7d2 backport fix from trunk
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7227 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 03:52:18 +00:00
Kevin P. Fleming
77c6cd0bff remove remaining CVS references
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7226 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 03:37:37 +00:00
Kevin P. Fleming
463ebe8b4b port memory leak fix from rev 7223 in trunk
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7224 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-30 03:20:42 +00:00
Kevin P. Fleming
a563eab49a remove extraneous svn:executable properties
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7221 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-29 18:24:39 +00:00
Kevin P. Fleming
bf9d4b103d do the multiple-lock check for cond_wait properly...
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7219 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-29 14:26:22 +00:00
Russell Bryant
7dc2449f3a print an error message if invalid arguments are specified
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7218 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-29 06:12:29 +00:00
Russell Bryant
27cc20db11 fix a couple of typos and a buglet
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7216 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-29 05:11:05 +00:00
Kevin P. Fleming
4e04f5f731 if the lock protected a pthread_cond is held recursively, warn before waiting onthe condition
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7213 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-29 01:25:28 +00:00
Kevin P. Fleming
5ec3844077 remove CVS ignore lists, set SVN ignore lists
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7212 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-29 00:46:54 +00:00
Kevin P. Fleming
f641c7cd0d port version string computation from trunk
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7208 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-28 04:01:06 +00:00
Kevin P. Fleming
49aa54cafc branch renames
remove unneeded branches


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.2@7199 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-27 16:04:52 +00:00
Russell Bryant
e3b81e66a1 issue #5850
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7196 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-25 14:17:38 +00:00
Russell Bryant
7bb6b928b5 fix typo - thanks twisted :)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7194 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-23 06:02:32 +00:00
Russell Bryant
ad4dc7c4a9 fix the date
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7193 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-23 05:59:05 +00:00
Russell Bryant
feb9764721 issue #5828
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7191 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-23 05:57:10 +00:00
Russell Bryant
8c74501001 issue #5826
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7190 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-23 05:49:35 +00:00
Russell Bryant
5861d3fd64 issue #5829
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7189 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-23 05:43:27 +00:00
Kevin P. Fleming
08acdc6a86 backport fix from HEAD branch
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7186 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 19:34:09 +00:00
Kevin P. Fleming
3b50570c9b backport fix from HEAD branch
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7184 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 19:31:26 +00:00
Kevin P. Fleming
00d7e962a7 backport fix from HEAD branch
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7183 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 19:29:51 +00:00
Russell Bryant
192f7413c2 revert previous change for Darwin
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7174 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 15:57:51 +00:00
Russell Bryant
5bdb8074aa issue #5789
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7170 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 13:40:34 +00:00
Russell Bryant
6abe5e1b23 don't hardcode poll.o for Darwin
fix incorrect portion of yesterday's Solaris fixes


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7169 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 13:23:53 +00:00
Russell Bryant
4612b4ccca issue #5815
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7167 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 13:17:32 +00:00
Russell Bryant
3245bf61a1 issue #5775
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7165 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 02:44:06 +00:00
Russell Bryant
9ee13167bb issue #5787
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7163 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 02:03:23 +00:00
Russell Bryant
ca9633ca9b issue #5794
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7157 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 01:00:51 +00:00
Russell Bryant
e04884545c issue #5806
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7155 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-21 00:03:40 +00:00
Russell Bryant
aa2239a050 issue #5773
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7154 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:56:49 +00:00
Russell Bryant
40a1b60cbd issue #5774
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7153 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:51:58 +00:00
Russell Bryant
cccb11916f fix logic for n+101 jumps
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7152 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:42:43 +00:00
Russell Bryant
49641825eb issue #5795
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7151 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:36:45 +00:00
Russell Bryant
c14c078405 issue #5792
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7150 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:33:03 +00:00
Russell Bryant
f2af073588 issue #5799
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7149 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:27:28 +00:00
Russell Bryant
b9a5eddb6d fix issue number for previous commit
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7148 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:22:10 +00:00
Russell Bryant
bffc815375 issue #5791
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7147 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:21:40 +00:00
Russell Bryant
5c3f322364 Shorten the module description (issue #5791)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7146 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-20 23:18:01 +00:00
Russell Bryant
3a6fae817c fix the output of Makefile generated variables to doxygen
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7133 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-18 04:13:39 +00:00
Russell Bryant
d8f74ecb94 Add missing carriage return and line feed to the SDP line indicating that we don't support VAD (issue #5780)
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7131 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-17 20:26:27 +00:00
Kevin P. Fleming
f7f2b1b033 fix remaining breakage related to chan_modem modules
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7127 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-17 04:26:07 +00:00
Admin Commit
601ab7ff82 This commit was manufactured by cvs2svn to create branch 'v1-2'.
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/v1-2@7126 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2005-11-16 22:40:43 +00:00
1511 changed files with 163414 additions and 380000 deletions

View File

@@ -1 +1 @@
36
9

1
.lastclean Normal file
View File

@@ -0,0 +1 @@
9

1
.version Normal file
View File

@@ -0,0 +1 @@
1.2.25-netsec

4
BUGS
View File

@@ -4,10 +4,10 @@ Asterisk Bug Tracking Information
To learn about and report Asterisk bugs, please visit
the official Asterisk Bug Tracker at:
https://issues.asterisk.org
http://bugs.digium.com
For more information on using the bug tracker, or to
learn how you can contribute by acting as a bug marshal
learn how you can contribute by acting as a bug marshall
please see:
http://www.asterisk.org/developers/bug-guidelines

743
CHANGES
View File

@@ -1,628 +1,127 @@
======================================================================
===
=== This file documents the new and/or enhanced functionality added in
=== the Asterisk versions listed below. This file does NOT include
=== changes in behavior that would not be backwards compatible with
=== previous versions; for that information see the UPGRADE.txt file
=== and the other UPGRADE files for older releases.
===
======================================================================
Changes since Asterisk 1.2.0-beta2:
SIP changes
-----------
* Added a new option "prematuremedia" that defaults to "no". If you turn this
option on, chan_sip will not automatically initiate early media if it receives
audio from the incoming channel before there's been a progress indication.
* Cygwin build system portability
* Optional generation of outbound silence during channel recording
-----------------------------------------------------------------------------------
--- Functionality changes from Asterisk 1.6.0.10 to Asterisk 1.6.0.11 -------------
-----------------------------------------------------------------------------------
Changes since Asterisk 1.2.0-beta1:
SIP Changes
-----------
* Added a new 'ignoresdpversion' option to sip.conf. When this is enabled
(either globally or for a specific peer), chan_sip will treat any SDP data
it receives as new data and update the media stream accordingly. By
default, Asterisk will only modify the media stream if the SDP session
version received is different from the current SDP session version. This
option is required to interoperate with devices that have non-standard SDP
session version implementations (observed with Microsoft OCS). This option
is disabled by default. In addition, this behavior is automatic when the SDP received
is in response to a T.38 re-INVITE that Asterisk initiated. In this situation,
since the call will fail if Asterisk does not process the incoming SDP, Asterisk
will accept the SDP even if the SDP version number is not properly incremented,
but will generate a warning in the log indicating that the SIP peer that sent
the SDP should have the 'ignoresdpversion' option set.
* Many, many bug fixes
* Documentation and sample configuration updates
* Vastly improved presence/subscription support in the SIP channel driver
* A new (experimental) mISDN channel driver
* A new monitoring application (MixMonitor)
* More portability fixes for non-Linux platforms
* New dialplan functions replacing old applications
* Significant deadlock and performance upgrades for the Manager interface
* An upgrade to the 'new' dialplan expression parser for all users
* New Zaptel echo cancellers with improved performance
* Support for the latest OSP toolkit from TransNexus
* Support user-controlled volume adjustment in MeetMe application
* More dialplan applications now return status variables instead of priority jumping
* Much more powerful ENUM support in the dialplan
* SIP domain support for authentication and virtual hosting
* Many PRI protocol updates and fixes, including more complete Q.SIG support
* New applications: Pickup() and Page()
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 1.4.X to Asterisk 1.6.0 -------------
------------------------------------------------------------------------------
Changes since Asterisk 1.0:
AMI - The manager (TCP/TLS/HTTP)
--------------------------------
* Manager has undergone a lot of changes, all of them documented
in doc/manager_1_1.txt
* Manager version has changed to 1.1
* Added a new action 'CoreShowChannels' to list currently defined channels
and some information about them.
* Added a new action 'SIPshowregistry' to list SIP registrations.
* Added TLS support for the manager interface and HTTP server
* Added the URI redirect option for the built-in HTTP server
* The output of CallerID in Manager events is now more consistent.
CallerIDNum is used for number and CallerIDName for name.
* Enable https support for builtin web server.
See configs/http.conf.sample for details.
* Added a new action, GetConfigJSON, which can return the contents of an
Asterisk configuration file in JSON format. This is intended to help
improve the performance of AJAX applications using the manager interface
over HTTP.
* SIP and IAX manager events now use "ChannelType" in all cases where we
indicate channel driver. Previously, we used a mixture of "Channel"
and "ChannelDriver" headers.
* Added a "Bridge" action which allows you to bridge any two channels that
are currently active on the system.
* Added a "ListAllVoicemailUsers" action that allows you to get a list of all
the voicemail users setup.
* Added 'DBDel' and 'DBDelTree' manager commands.
* cdr_manager now reports events via the "cdr" level, separating it from
the very verbose "call" level.
* Manager users are now stored in memory. If you change the manager account
list (delete or add accounts) you need to reload manager.
* Added Masquerade manager event for when a masquerade happens between
two channels.
* Added "manager reload" command for the CLI
* Lots of commands that only provided information are now allowed under the
Reporting privilege, instead of only under Call or System.
* The IAX* commands now require either System or Reporting privilege, to
mirror the privileges of the SIP* commands.
* Added ability to retrieve list of categories in a config file.
* Added ability to retrieve the content of a particular category.
* Added ability to empty a context.
* Created new action to create a new file.
* Updated delete action to allow deletion by line number with respect to category.
* Added new action insert to add new variable to category at specified line.
* Updated action newcat to allow new category to be inserted in file above another
existing category.
* Added new event "JitterBufStats" in the IAX2 channel
* Originate now requires the Originate privilege and, if you want to call out
to a subshell, it requires the System privilege, as well. This was done to
enhance manager security.
This list currently only containts changes made from the end of November until
March 26, 2005.
Dialplan functions
------------------
* Added the DEVICE_STATE() dialplan function which allows retrieving any device
state in the dialplan, as well as creating custom device states that are
controllable from the dialplan.
* Extend CALLERID() function with "pres" and "ton" parameters to
fetch string representation of calling number presentation indicator
and numeric representation of type of calling number value.
* MailboxExists converted to dialplan function
* A new option to Dial() for telling IP phones not to count the call
as "missed" when dial times out and cancels.
* Added LOCK(), TRYLOCK(), and UNLOCK(), which provide a single level dialplan
mutex. No deadlocks are possible, as LOCK() only allows a single lock to be
held for any given channel. Also, locks are automatically freed when a
channel is hung up.
* Added HINT() dialplan function that allows retrieving hint information.
Hints are mappings between extensions and devices for the sake of
determining the state of an extension. This function can retrieve the list
of devices or the name associated with a hint.
* Added EXTENSION_STATE() dialplan function which allows retrieving the state
of any extension.
* Added SYSINFO() dialplan function which allows retrieval of system information
* Added a new dialplan function, DIALPLAN_EXISTS(), which allows you to check for
the existence of a dialplan target.
* Added two new dialplan functions, TOUPPER and TOLOWER, which convert a string to
upper and lower case, respectively.
* When bridging, Asterisk sets the BRIDGEPVTCALLID to the channel drivers unique
ID for the call (not the Asterisk call ID or unique ID), provided that the
channel driver supports this. For SIP, you get the SIP call-ID for the
bridged channel which you can store in the CDR with a custom field.
* Added the function AUDIOHOOK_INHERIT. This actually is already in Asterisk
1.4, but since it was added late in the release cycle, I felt it was a good
idea to list it here as well. See the CLI output for "core show function
AUDIOHOOK_INHERIT" for more details
CLI Changes
-----------
* New CLI command "core show hint" (usage: core show hint <exten>)
* New CLI command "core show settings"
* Added 'core show channels count' CLI command.
* Added the ability to set the core debug and verbose values on a per-file basis.
* Added 'queue pause member' and 'queue unpause member' CLI commands
* Ability to set process limits ("ulimit") without restarting Asterisk
* Enhanced "agi debug" to print the channel name as a prefix to the debug
output to make debugging on busy systems much easier.
* New CLI commands "dialplan set extenpatternmatching true/false"
* New CLI command: "core set chanvar" to set a channel variable from the CLI.
* Added an easy way to execute Asterisk CLI commands at startup. Any commands
listed in the startup_commands section of cli.conf will get executed.
* Added a CLI command, "devstate change", which allows you to set custom device
states from the func_devstate module that provides the DEVICE_STATE() function
and handling of the "Custom:" devices.
SIP changes
-----------
* Added a new 'faxdetect=yes|no' configuration option to sip.conf. When this
option is enabled, Asterisk will watch for a CNG tone in the incoming audio
for a received call. If it is detected, the channel will jump to the
'fax' extension in the dialplan.
* Improved NAT and STUN support.
chan_sip now can use port numbers in bindaddr, externip and externhost
options, as well as contact a STUN server to detect its external address
for the SIP socket. See sip.conf.sample, 'NAT' section.
* The default SIP useragent= identifier now includes the Asterisk version
* A new option, match_auth_username in sip.conf changes the matching of incoming requests.
If set, and the incoming request carries authentication info,
the username to match in the users list is taken from the Digest header
rather than from the From: field. This feature is considered experimental.
* The "musiconhold" and "musicclass" settings in sip.conf are now removed,
since they where replaced by "mohsuggest" and "mohinterpret" in version 1.4
* The "localmask" setting was removed in version 1.2 and the reminder about it
being removed is now also removed.
* A new option "busylevel" for setting a level of calls where asterisk reports
a device as busy, to separate it from call-limit. This value is also added
to the SIP_PEER dialplan function.
* A new realtime family called "sipregs" is now supported to store SIP registration
data. If this family is defined, "sippeers" will be used for configuration and
"sipregs" for registrations. If it's not defined, "sippeers" will be used for
registration data, as before.
* The SIPPEER function have new options for port address, call and pickup groups
* Added support for T.140 realtime text in SIP/RTP
* The "checkmwi" option has been removed from sip.conf, as it is no longer
required due to the restructuring of how MWI is handled. See the descriptions
in this file of the "pollmailboxes" and "pollfreq" options to voicemail.conf
for more information.
* Added rtpdest option to CHANNEL() dialplan function.
* Added SIPREFERRINGCONTEXT and SIPREFERREDBYHDR variables which are set when a transfer takes place.
* SIP now adds a header to the CANCEL if the call was answered by another phone
in the same dial command, or if the new c option in dial() is used.
* The new default is that 100 Trying is not sent on REGISTER attempts as the RFC specifically
states it is not needed. For phones, however, that do require it the "registertrying" option
has been added so it can be enabled.
* A new option called "callcounter" (global/peer/user level) enables call counters needed
for better status reports needed for queues and SIP subscriptions. (Call-Limit was previously
used to enable this functionality).
* New settings for timer T1 and timer B on a global level or per device. This makes it
possible to force timeout faster on non-responsive SIP servers. These settings are
considered advanced, so don't use them unless you have a problem.
* Added a dial string option to be able to set the To: header in an INVITE to any
SIP uri.
* Added a new global and per-peer option, qualifyfreq, which allows you to configure
the qualify frequency.
* Added SIP Session Timers support (RFC 4028). This prevents stuck SIP sessions that
were not properly torn down due to network or endpoint failures during an established
SIP session.
* Added experimental TCP and TLS support for SIP. See doc/siptls.txt and
configs/sip.conf.sample for more information on how it is used.
* Added t38pt_usertpsource option. See sip.conf.sample for details.
IAX2 changes
------------
* Added the trunkmaxsize configuration option to chan_iax2.
* Added the srvlookup option to iax.conf
* Added support for OSP. The token is set and retrieved through the CHANNEL()
dialplan function.
XMPP Google Talk/Jingle changes
-------------------------------
* Added the bindaddr option to gtalk.conf.
Skinny changes
-------------
* Added skinny show device, skinny show line, and skinny show settings CLI commands.
* Proper codec support in chan_skinny.
* Added settings for IP and Ethernet QoS requests
MGCP changes
------------
* Added separate settings for media QoS in mgcp.conf
Console Channel Driver changes
------------------------------
* Added experimental support for video send & receive to chan_oss.
This requires SDL and ffmpeg/avcodec, plus Video4Linux or X11 to act as
a video source.
Phone channel changes (chan_phone)
----------------------------------
* Added G729 passthrough support to chan_phone for Sigma Designs boards.
H.323 channel Changes
---------------------
* H323 remote hold notification support added (by NOTIFY message
and/or H.450 supplementary service)
Local channel changes
---------------------
* The device state functionality in the Local channel driver has been updated
to indicate INUSE or NOT_INUSE when a Local channel is being used as opposed
to just UNKNOWN if the extension exists.
* Added jitterbuffer support for chan_local. This allows you to use the
generic jitterbuffer on incoming calls going to Asterisk applications.
For example, this would allow you to use a jitterbuffer for an incoming
SIP call to Voicemail by putting a Local channel in the middle. This
feature is enabled by using the 'j' option in the Dial string to the Local
channel in conjunction with the existing 'n' option for local channels.
DAHDI channel driver (chan_dahdi) Changes
----------------------------------------
* SS7 support (via libss7 library)
* In India, some carriers transmit CID via dtmf. Some code has been added
that will handle some situations. The cidstart=polarity_IN choice has been added for
those carriers that transmit CID via dtmf after a polarity change.
* CID matching information is now shown when doing 'dialplan show'.
* Added dahdi show version CLI command.
* Added setvar support to chan_dahdi.conf channel entries.
* Added two new options: mwimonitor and mwimonitornotify. These options allow
you to enable MWI monitoring on FXO lines. When the MWI state changes,
the script specified in the mwimonitornotify option is executed. An internal
event indicating the new state of the mailbox is also generated, so that
the normal MWI facilities in Asterisk work as usual.
* Added signalling type 'auto', which attempts to use the same signalling type
for a channel as configured in DAHDI. This is primarily designed for analog
ports, but will also work for digital ports that are configured for FXS or FXO
signalling types. This mode is also the default now, so if your chan_dahdi.conf
does not specify signalling for a channel (which is unlikely as the sample
configuration file has always recommended specifying it for every channel) then
the 'auto' mode will be used for that channel if possible.
* Added a 'dahdi set dnd' command to allow CLI control of the Do-Not-Disturb
state for a channel; also ensured that the DNDState Manager event is
emitted no matter how the DND state is set or cleared.
New Channel Drivers
-------------------
* Added a new channel driver, chan_unistim. See doc/unistim.txt and
configs/unistim.conf.sample for details. This new channel driver allows
you to use Nortel i2002, i2004, and i2050 phones with Asterisk.
* Added a new channel driver, chan_console, which uses portaudio as a cross
platform audio interface. It was written as a channel driver that would
work with Mac CoreAudio, but portaudio supports a number of other audio
interfaces, as well. Note that this channel driver requires v19 or higher
of portaudio; older versions have a different API.
DUNDi changes
-------------
* Added the ability to specify arguments to the Dial application when using
the DUNDi switch in the dialplan.
* Added the ability to set weights for responses dynamically. This can be
done using a global variable or a dialplan function. Using the SHELL()
function would allow you to have an external script set the weight for
each response.
* Added two new dialplan functions, DUNDIQUERY and DUNDIRESULT. These
functions will allow you to initiate a DUNDi query from the dialplan,
find out how many results there are, and access each one.
ENUM changes
------------
* Added two new dialplan functions, ENUMQUERY and ENUMRESULT. These
functions will allow you to initiate an ENUM lookup from the dialplan,
and Asterisk will cache the results. ENUMRESULT can be used to access
the results without doing multiple DNS queries.
Voicemail Changes
-----------------
* Added the ability to customize which sound files are used for some of the
prompts within the Voicemail application by changing them in voicemail.conf
* Added the ability for the "voicemail show users" CLI command to show users
configured by the dynamic realtime configuration method.
* MWI (Message Waiting Indication) handling has been significantly
restructured internally to Asterisk. It is now totally event based
instead of polling based. The voicemail application will notify other
modules that have subscribed to MWI events when something in the mailbox
changes.
This also means that if any other entity outside of Asterisk is changing
the contents of mailboxes, then the voicemail application still needs to
poll for changes. Examples of situations that would require this option
are web interfaces to voicemail or an email client in the case of using
IMAP storage. So, two new options have been added to voicemail.conf
to account for this: "pollmailboxes" and "pollfreq". See the sample
configuration file for details.
* Added "tw" language support
* Added support for storage of greetings using an IMAP server
* Added ability to customize forward, reverse, stop, and pause keys for message playback
* SMDI is now enabled in voicemail using the smdienable option.
* A "lockmode" option has been added to asterisk.conf to configure the file
locking method used for voicemail, and potentially other things in the
future. The default is the old behavior, lockfile. However, there is a
new method, "flock", that uses a different method for situations where the
lockfile will not work, such as on SMB/CIFS mounts.
* Added the ability to backup deleted messages, to ease recovery in the case
that a user accidentally deletes a message, and discovers that they need it.
* Reworked the SMDI interface in Asterisk. The new way to access SMDI information
is through the new functions, SMDI_MSG_RETRIEVE() and SMDI_MSG(). The file
smdi.conf can now be configured with options to map SMDI station IDs to Asterisk
voicemail boxes. The SMDI interface can also poll for MWI changes when some
outside entity is modifying the state of the mailbox (such as IMAP storage or
a web interface of some kind).
Queue changes
-------------
* Added the general option 'shared_lastcall' so that member's wrapuptime may be
used across multiple queues.
* Added QUEUE_VARIABLES function to set queue variables added setqueuevar and
setqueueentryvar options for each queue, see queues.conf.sample for details.
* Added keepstats option to queues.conf which will keep queue
statistics during a reload.
* setinterfacevar option in queues.conf also now sets a variable
called MEMBERNAME which contains the member's name.
* Added 'Strategy' field to manager event QueueParams which represents
the queue strategy in use.
* Added option to run macro when a queue member is connected to a caller,
see queues.conf.sample for details.
* app_queue now has a 'loose' option which is almost exactly like 'strict' except it
does not count paused queue members as unavailable.
* Added min-announce-frequency option to queues.conf which allows you to control the
minimum amount of time between queue announcements for use when the caller's queue
position changes frequently.
* Added additional information to EXITWITHTIMEOUT and EXITWITHKEY events in the
queue log.
* Added ability for non-realtime queues to have realtime members
* Added the "linear" strategy to queues.
* Added the "wrandom" strategy to queues.
* Added new channel variable QUEUE_MIN_PENALTY
* QUEUE_MAX_PENALTY and QUEUE_MIN_PENALTY may be adjusted in mid-call by defining
rules in queuerules.conf. See configs/queuerules.conf.sample for details
* Added a new parameter for member definition, called state_interface. This may be
used so that a member may be called via one interface but have a different interface's
device state reported.
MeetMe Changes
--------------
* The 'o' option to provide an optimization has been removed and its functionality
has been enabled by default.
* When a conference is created, the UNIQUEID of the channel that caused it to be
created is stored. Then, every channel that joins the conference will have the
MEETMEUNIQUEID channel variable set with this ID. This can be used to relate
callers that come and go from long standing conferences.
* Added a new application, MeetMeChannelAdmin, which is similar to MeetMeAdmin,
except it does operations on a channel by name, instead of number in a conference.
This is a very useful feature in combination with the 'X' option to ChanSpy.
* Added 'C' option to Meetme which causes a caller to continue in the dialplan
when kicked out.
* Added new RealTime functionality to provide support for scheduled conferencing.
This includes optional messages to the caller if they attempt to join before
the schedule start time, or to allow the caller to join the conference early.
Also included is optional support for limiting the number of callers per
RealTime conference.
* Added the S() and L() options to the MeetMe application. These are pretty
much identical to the S() and L() options to Dial(). They let you set
timeouts for the conference, as well as have warning sounds played to
let the caller know how much time is left, and when it is running out.
* Added the ability to do "meetme concise" with the "meetme" CLI command.
This extends the concise capabilities of this CLI command to include
listing all conferences, instead of an addition to the other sub commands
for the "meetme" command.
* Added the ability to specify the music on hold class used to play into the
conference when there is only one member and the M option is used.
Other Dialplan Application Changes
----------------------------------
* Argument support for Gosub application
* From the to-do lists: straighten out the app timeout args:
Wait() app now really does 0.3 seconds- was truncating arg to an int.
WaitExten() same as Wait().
Congestion() - Now takes floating pt. argument.
Busy() - now takes floating pt. argument.
Read() - timeout now can be floating pt.
WaitForRing() now takes floating pt timeout arg.
SpeechBackground() -- clarified in the docstrings that the timeout is an integer seconds.
* Added 's' option to Page application.
* Added 'E', 'V', and 'P' commands to ExternalIVR.
* Added 'o' and 'X' options to Chanspy.
* Added a new dialplan application, Bridge, which allows you to bridge the
calling channel to any other active channel on the system.
* Added the ability to specify a music on hold class to play instead of ringing
for the SLATrunk application.
* The Read application no longer exits the dialplan on error. Instead, it sets
READSTATUS to ERROR, which you can catch and handle separately.
* Added 'm' option to Directory, which lists out names, 8 at a time, instead
of asking for verification of each name, one at a time.
* Privacy() no longer uses privacy.conf, as all options are specifyable as
direct options to the app.
* AMD() has a new "maximum word length" option. "show application AMD" from the CLI
for more details
* GotoIfTime() now may branch based on a "false" condition, like other Goto-related applications
* The ChannelRedirect application no longer exits the dialplan if the given channel
does not exist. It will now set the CHANNELREDIRECT_STATUS variable to SUCCESS upon success
or NOCHANNEL if the given channel was not found.
* ForkCDR has new options: 'a' updates the answer time on the new CDR; 'A' locks
answer times, disposition, on orig CDR against updates; 'D' Copies the disposition
from the orig CDR to the new CDR after reset; 'e' sets the 'end' time on the
original CDR; 'R' prevents the new CDR from being reset; 's(var=val)' adds/changes
the 'var' variable on the original CDR; 'T' forces ast_cdr_end(), ast_cdr_answer(),
to obey the LOCKED flag on cdr's in the chain, and also the ast_cdr_setvar() func.
Music On Hold Changes
---------------------
* A new option, "digit", has been added for music on hold classes in
musiconhold.conf. If this is set for a music on hold class, a caller
listening to music on hold can press this digit to switch to listening
to this music on hold class.
* Support for realtime music on hold has been added.
* In conjunction with the realtime music on hold, a general section has
been added to musiconhold.conf, its sole variable is cachertclasses. If this
is set, then music on hold classes found in realtime will be cached in memory.
AEL Changes
-----------
* AEL upgraded to use the Gosub with Arguments instead
of Macro application, to hopefully reduce the problems
seen with the artificially low stack ceiling that
Macro bumps into. Macros can only call other Macros
to a depth of 7. Tests run using gosub, show depths
limited only by virtual memory. A small test demonstrated
recursive call depths of 100,000 without problems.
-- in addition to this, all apps that allowed a macro
to be called, as in Dial, queues, etc, are now allowing
a gosub call in similar fashion.
* AEL now generates LOCAL(argname) declarations when it
Set()'s the each arg name to the value of ${ARG1}, ${ARG2),
etc. That makes the arguments local in scope. The user
can define their own local variables in macros, now,
by saying "local myvar=someval;" or using Set() in this
fashion: Set(LOCAL(myvar)=someval); ("local" is now
an AEL keyword).
* utils/conf2ael introduced. Will convert an extensions.conf
file into extensions.ael. Very crude and unfinished, but
will be improved as time goes by. Should be useful for a
first pass at conversion.
* aelparse will now read extensions.conf to see if a referenced
macro or context is there before issueing a warning.
Call Features (res_features) Changes
------------------------------------
* Added the parkedcalltransfers option to features.conf
* Added parkedcallparking option to control one touch parking w/ parking
pickup
* Added parkedcallhangup option to control disconnect feature w/ parking
pickup
* Added parkedcallrecording option to control one-touch record w/ parking
pickup
* Added BRIDGE_FEATURES variable to set available features for a channel
* The built-in method for doing attended transfers has been updated to
include some new options that allow you to have the transferee sent
back to the person that did the transfer if the transfer is not successful.
See the options "atxferdropcall", "atxferloopdelay", and "atxfercallbackretries"
in features.conf.sample.
* Added support for configuring named groups of custom call features in
features.conf. This means that features can be written a single time, and
then mapped into groups of features for different key mappings or easier
access control.
* Updated the ParkedCall application to allow you to not specify a parking
extension. If you don't specify a parking space to pick up, it will grab
the first one available.
* Added cli command 'features reload' to reload call features from features.conf
* Moved into core asterisk binary.
Language Support Changes
------------------------
* Brazilian Portuguese (pt-BR) in VM, and say.c was added
* Added support for the Hungarian language for saying numbers, dates, and times.
AGI Changes
-----------
* Added SPEECH commands for speech recognition. A complete listing can be found
using agi show.
* If app_stack is loaded, GOSUB is a native AGI command that may be used to
invoke subroutines in the dialplan. Note that calling EXEC with Gosub
does not behave as expected; the native command needs to be used, instead.
Logger changes
--------------
* Added rotatestrategy option to logger.conf, along with two new options:
"timestamp" which will use the time to name the logger files instead of
sequence number; and "rotate", which rotates the names of the logfiles,
similar to the way syslog rotates files.
* Added exec_after_rotate option to logger.conf, which allows a system
command to be run after rotation. This is primarily useful with
rotatestrategry=rotate, to allow a limit on the number of logfiles kept
and to ensure that the oldest log file gets deleted.
* Added realtime support for the queue log
Call Detail Records
-------------------
* The cdr_manager module has a [mappings] feature, like cdr_custom,
to add fields to the manager event from the CDR variables.
* Added cdr_adaptive_odbc, a new module that adapts to the structure of your
backend database CDR table. Specifically, additional, non-standard
columns are supported, merely by setting the corresponding CDR variable in
your dialplan. In addition, you may alias any column to another name (for
example, if you want the 'src' CDR variable to be column 'ANI' in the DB,
simply "alias src => ANI" in the configuration file). Records may be
posted to more than one backend, simply by specifying multiple categories
in the configuration file. And finally, you may filter which CDRs get
posted to each backend, by specifying a filter (which the record must
match) for the particular category. Filters are additive (meaning all
rules must match to post that CDR).
* The Postgres CDR module now supports some features of the cdr_adaptive_odbc
module. Specifically, you may add additional columns into the table and
they will be set, if you set the corresponding CDR variable name. Also,
if you omit columns in your database table, they will be silently skipped
(but a record will still be inserted, based on what columns remain). Note
that the other two features from cdr_adaptive_odbc (alias and filter) are
not currently supported.
* The ResetCDR application now has an 'e' option that re-enables a CDR if it
has been disabled using the NoCDR application.
Miscellaneous New Modules
-------------------------
* Added a new CDR module, cdr_sqlite3_custom.
* Added a new realtime configuration module, res_config_sqlite
* Added a new codec translation module, codec_resample, which re-samples
signed linear audio between 8 kHz and 16 kHz to help support wideband
codecs.
* Added a new module, res_phoneprov, which allows auto-provisioning of phones
based on configuration templates that use Asterisk dialplan function and
variable substitution. It should be possible to create phone profiles and
templates that work for the majority of phones provisioned over http. It
is currently only intended to provision a single user account per phone.
An example profile and set of templates for Polycom phones is provided.
NOTE: Polycom firmware is not included, but should be placed in
AST_DATA_DIR/phoneprov/configs to match up with the included templates.
* Added a new module, app_jack, which provides interfaces to JACK, the Jack
Audio Connection Kit (http://www.jackaudio.org/). Two interfaces are
provided; there is a JACK() application, and a JACK_HOOK() function. Both
interfaces create an input and output JACK port. The application makes
these ports the endpoint of the call. The audio coming from the channel
goes out the output port and whatever comes back in on the input port is
what gets sent to the channel. The JACK_HOOK() function turns on a JACK
audiohook on the channel. This lets you run the audio coming from a
channel through JACK, and whatever comes back in is what gets forwarded
on as the channel's audio. This is very useful for building custom
vocoders or doing recording or analysis of the channel's audio in another
application.
* Added a new module, res_config_curl, which permits using a HTTP POST url
to retrieve, create, update, and delete realtime information from a remote
web server. Note that this module requires func_curl.so to be loaded for
backend functionality.
* Added a new module, res_config_ldap, which permits the use of an LDAP
server for realtime data access.
* Added support for writing and running your dialplan in lua using the pbx_lua
module. See configs/extensions.lua.sample for examples of how to do this.
Miscellaneous
-------------
* res_jabber: autoprune has been disabled by default, to avoid misconfiguration
that would end up being interpreted as a bug once Asterisk started removing
the contacts from a user list.
* Ability to use libcap to set high ToS bits when non-root
on Linux. If configure is unable to find libcap then you
can use --with-cap to specify the path.
* Added maxfiles option to options section of asterisk.conf which allows you to specify
what Asterisk should set as the maximum number of open files when it loads.
* Added the jittertargetextra configuration option.
* Added support for setting the CoS for VLAN traffic (802.1p). See the sample
configuration files for the IP channel drivers. The new option is "cos".
This information is also documented in doc/qos.tex, or the IP Quality of Service
section of asterisk.pdf.
* When originating a call using AMI or pbx_spool that fails the reason for failure
will now be available in the failed extension using the REASON dialplan variable.
* Added support for reading the TOUCH_MONITOR_PREFIX channel variable.
It allows you to configure a prefix for auto-monitor recordings.
* A new extension pattern matching algorithm, based on a trie, is introduced
here, that could noticeably speed up mid-sized to large dialplans.
It is NOT used by default, as duplicating the behaviour of the old pattern
matcher is still under development. A config file option, in extensions.conf,
in the [general] section, called "extenpatternmatchingnew", is by default
set to false; setting that to true will force the use of the new algorithm.
Also, the cli commands "dialplan set extenpatternmatchingnew true/false" can
be used to switch the algorithms at run time.
* A new option when starting a remote asterisk (rasterisk, asterisk -r) for
specifying which socket to use to connect to the running Asterisk daemon
(-s)
* Added logging to 'make update' command. See update.log
* Added strictrtp option to rtp.conf. If enabled this will drop RTP packets that
do not come from the remote party.
* Added the 'n' option to the SpeechBackground application to tell it to not
answer the channel if it has not already been answered.
* Added a compiler flag, CHANNEL_TRACE, which permits channel tracing to be
turned on, via the CHANNEL(trace) dialplan function. Could be useful for
dialplan debugging.
* iLBC source code no longer included (see UPGRADE.txt for details)
* A new option for the configure script, --enable-internal-poll, has been added
for use with systems which may have a buggy implementation of the poll system
call. If you notice odd behavior such as the CLI being unresponsive on remote
consoles, you may want to try using this option. This option is enabled by default
on Darwin systems since it is known that the Darwin poll() implementation has
odd issues.
* Add new applications:
-- AgentMonitorOutgoing
-- Curl
-- ExecIf
-- ExecIfTime
-- IAX2Provision
-- MacroExit
-- MacroIf
-- PauseQueueMember
-- ReadFile
-- SetRDNIS
-- SIPAddHeader
-- SIPGetHeader
-- StartMusicOnHold
-- StopMusicOnHold
-- UnpauseQueueMember
-- WaitForSilence
-- While / EndWhile
* app Answer
-- added delay option
* app ChanIsAvail
-- added 's' option
* app Dial
-- add option to specify the class for musiconhold with m option
* app EnumLookup
-- added "reload enum" for configuration
* app Goto
-- added relative priorities
* app GotoIf
-- added relative priorities
* app MeetMe
-- added 'i' option
-- added 'r' option
-- added 'T' option
-- added 'P' option
-- added 'c' option
-- added adminpin to meetme.conf
-- added reload command
* app PrivacyManager
-- add config file privacy.conf
* app queue
-- queues.conf
-- added persistentmembers option to queues.conf
-- changed music option to musiconhold
-- added weight option
-- added note about why agent groups probably shouldn't be used
-- added timeoutrestart option
* app Read
-- added attempts parameter
-- added timeout parameter
* app Record
-- added 'q' option
* app SendDTMF
-- add timeout option
* app SMS
-- document alternative syntax for queueing messages
* app Voicemail
-- add info about VM_CATEGORY
-- voicemail.conf
-- added usedirectory option
-- added VM_CIDNUM and VM_CIDNAME in message config
* chan IAX2
-- new jitterbuffer
-- added setvar option
-- added regex to iax2 show peers/users
-- allow multiple bindaddr lines in iax.conf
-- added reload command
-- added forcejitterbuffer option
-- added note about specifying bindport before bindaddr
-- added trunktimestamps option
* chan Agent
-- added agent logoff CLI command
* chan OSS
-- added Flash CLI command
* chan SIP
-- added setvar option
-- added compactheaders option
-- added usereqphone option
-- added registertimeout option
-- added externhost option
-- added sip notify CLI command
-- added sip_notify.conf
-- added allowguest option
* chan Zap
-- added hanguponplarityswitch option
-- added sendcalleridafter option
-- added priresetinterval option
-- added TON/NPI config options (the ones right above the resetinterval option)
-- added answeronpolarityswitch option
-- added "never" for resetinterval
* extensions
-- allow '*' when including files (#include "sip-*.conf")
-- added eswitch
* General
-- added #exec syntax for including output from a command
-- added show features CLI command
-- added configuration templates for category inheritance

183
CREDITS
View File

@@ -17,9 +17,6 @@ nic.at - ENUM support in Asterisk
Paul Bagyenda, Digital Solutions - for initial Voicetronix driver development
John Todd, TalkPlus, Inc. and JR Richardson, Ntegrated Solutions. - for funding
the development of SIP Session Timers support.
=== WISHLIST CONTRIBUTERS ===
Jeremy McNamara - SpeeX support
Nick Seraphin - RDNIS support
@@ -30,183 +27,77 @@ Wasim - Hangup detect
* Thanks to QuickNet Technologies for their donation of an Internet
PhoneJack and Linejack card to the project. (http://www.quicknet.net)
* Thanks to VoipSupply for their donation of Sipura ATAs to the project for
T.38 testing. (http://www.voipsupply.com)
* Thanks to Grandstream for their donation of ATAs to the project for
T.38 testing. (http://www.grandstream.com)
=== MISCELLANEOUS PATCHES ===
Jim Dixon - Zapata Telephony and app_rpt
http://www.zapatatelephony.org/app_rpt.html
Russell Bryant - Asterisk release manager and countless enhancements and bug
fixes.
russell(AT)digium.com
Anthony Minessale II - Countless big and small fixes, and relentless forward
push. ChanSpy, ForkCDR, ControlPlayback, While/EndWhile, DumpChan, Dictate,
MacroIf, ExecIf, ExecIfTime, RetryDial, MixMonitor applications; many
realtime concepts and implementation pieces, including res_config_odbc;
Russell Bryant - Asterisk 1.0 maintainer and misc. enhancements
russelb@clemson.edu
Anthony Minessale II - Countless big and small fixes, and relentless forward push
ChanSpy, ForkCDR, ControlPlayback, While/EndWhile, DumpChan, Dictate,
MacroIf, ExecIf, ExecIfTime, RetryDial, MixMonitor applications; res_odbc;
many realtime concepts and implementation pieces, including res_config_odbc;
format_slin; cdr_custom; several features in Dial including L(), G() and
enhancements to M() and D(); several CDR enhancements including CDR
variables; attended transfer; one touch record; native MOH; manager
eventmask; command line '-t' flag to allow recording/voicemail on nfs
shares; #exec command and multiline comments in config files; setvar in iax
and sip configs.
anthmct(AT)yahoo.com http://www.asterlink.com
James Golovich - Innumerable contributions, including SIP TCP and TLS support.
enhancements to M() and D(); several CDR enhancements including CDR variables;
attended transfer; one touch record; native MOH; manager eventmask; command
line '-t' flag to allow recording/voicemail on nfs shares; #exec command and
multiline comments in config files; setvar in iax and sip configs.
anthmct@yahoo.com http://www.asterlink.com
James Golovich - Innumerable contributions
You can find him and asterisk-perl at http://asterisk.gnuinter.net
Andre Bierwirth - Extension hints and status
Oliver Daudey - ISDN4Linux fixes
Pauline Middelink - ISDN4Linux patches and some general patches.
She can be found at http://www.polyware.nl/~middelink/En/
Jean-Denis Girard - Various contributions from the South Pacific Islands
jd-girard(AT)esoft.pf http://www.esoft.pf
jd-girard@esoft.pf http://www.esoft.pf
William Jordan / Vonage - MySQL enhancements to Voicemail
wjordan(AT)vonage.com
wjordan@vonage.com
Jac Kersing - Various fixes
Steven Critchfield - Seek and Trunc functions for playback and recording
critch(AT)basesys.com
critch@basesys.com
Jefferson Noxon - app_lookupcidname, app_db, and various other contributions
Klaus-Peter Junghanns - in-band DTMF on SIP and MGCP
Ross Finlayson - Dynamic RTP payload support
Mahmut Fettahlioglu - Audio recording, music-on-hold changes, alaw file
format, and various fixes. Can be contacted at mahmut(AT)oa.com.au
format, and various fixes. Can be contacted at mahmut@oa.com.au
James Dennis - Cisco SIP compatibility patches to work with SIP service
providers. Can be contacted at asterisk(AT)jdennis.net
providers. Can be contacted at asterisk@jdennis.net
Tilghman Lesher - ast_localtime(); ast_say_date_with_format();
GotoIfTime, SayUnixTime, HasNewVoicemail applications;
CUT, SORT, EVAL, CURL, FIELDQTY, STRFTIME, some QUEUE* functions;
func_odbc, cdr_adaptive_odbc, and other innumerable bug fixes.
tilghman(AT)digium.com http://asterisk.drunkcoder.com/
GotoIfTime, Random, SayUnixTime, HasNewVoicemail applications;
CUT, SORT, EVAL, CURL, FIELDQTY, STRFTIME, QUEUEAGENT* functions;
and other innumerable bug fixes. http://asterisk.drunkcoder.com/
Jayson Vantuyl - Manager protocol changes, various other bugs.
jvantuyl(AT)computingedge.net
jvantuyl@computingedge.net
Thorsten Lockert - OpenBSD, FreeBSD ports, making MacOS X port run on 10.3,
dialplan include verification, route lookup on OpenBSD, SNMP agent
support (res_snmp), various other bugs. tholo(AT)sigmasoft.com
Josh Roberson - chan_zap reload support, Advanced Voicemail Features, & other
misc. patches. - josh(AT)asteriasgi.com, http://www.asteriasgi.com
William Waites - syslog support, SIP NAT traversal for SIP-UA. ww(AT)styx.org
dialplan include verification, route lookup on OpenBSD, various other
bugs. tholo@sigmasoft.com
Brian West - ODBC support and Bug Marshaling
Josh Roberson - chan_zap reload support, Advanced Voicemail Features, other misc. patches,
and Bug Marshalling. - josh@asteriasgi.com, http://www.asteriasgi.com
William Waites - syslog support, SIP NAT traversal for SIP-UA. ww@styx.org
Rich Murphey - Porting to FreeBSD, NetBSD, OpenBSD, and Darwin.
rich(AT)whiteoaklabs.com http://whiteoaklabs.com
rich@whiteoaklabs.com http://whiteoaklabs.com
Simon Lockhart - Porting to Solaris (based on work of Logan ???)
simon(AT)slimey.org
Olle E. Johansson - SIP RFC compliance, documentation and testing, testing,
SIP outbound proxy support, Manager 1.1 update, SIP transfer support,
SIP presence support, SIP call state updates (dialog-info),
MiniVM - the small voicemail system, many documentation
updates/corrections, and many bug fixes.
oej(AT)edvina.net, http://edvina.net
simon@slimey.org
Olle E. Johansson - SIP RFC compliance, documentation and testing, testing, testing
oej@edvina.net, http://edvina.net
Steve Kann - new jitter buffer for IAX2
stevek(AT)stevek.com
stevek@stevek.com
Constantine Filin - major contributions to the Asterisk Realtime Architecture
Steve Murphy - privacy support, $[ ] parser upgrade, AEL2 parser upgrade.
murf(AT)digium.com
Steve Murphy - privacy support
Claude Patry - bug fixes, feature enhancements, and bug marshalling
cpatry(AT)gmail.com
Miroslav Nachev, miro(AT)space-comm.com COSMOS Software Enterprises, Ltd.
- for Variable for No Answer Timeout for Attended Transfer
Slav Klenov & Vanheuverzwijn Joachim - development of the generic jitterbuffer
Securax Ltd. info(AT)securax.be
Roy Sigurd Karlsbakk - providing funding for generic jitterbuffer development
roy(AT)karlsbakk.net, Briiz Telecom AS
Voop AS, Nuvio Inc, Inotel S.A and Foniris Telecom A/S - funding for rewrite
of SIP transfers
Philippe Sultan - RADIUS CDR module, many fixes to res_jabber and gtalk/jingle
channel drivers.
INRIA, http://www.inria.fr/
John Martin, Aupix - Improved video support in the SIP channel
T.140 text support in RTP/SIP
Steve Underwood - Provided T.38 pass through support.
George Konstantoulakis - Support for Greek in voicemail added by InAccess
Networks (work funded by HOL, www.hol.gr) gkon(AT)inaccessnetworks.com
Daniel Nylander - Support for Swedish and Norwegian languages in voicemail.
http://www.danielnylander.se/
Stojan Sljivic - An option for maximum number of messsages per mailbox in
voicemail. Also an issue with voicemail synchronization has been fixed.
GDS Partners www.gdspartners.com . stojan.sljivic(AT)gdspartners.com
Bartosz Supczinski - Support for Polish added by DIR (www.dir.pl)
Bartosz.Supczinski(AT)dir.pl
James Rothenberger - Support for IMAP storage integration added by
OneBizTone LLC Work funded by University of Pennsylvania jar(AT)onebiztone.com
Paul Cadach - Bringing chan_h323 up to date, bug fixes, and more!
Voop AS - Financial support for a lot of work with the SIP driver and the IAX
trunk MTU patch
Cedric Hans - Development of chan_unistim
cedric.hans(AT)mlkj.net
Sergio Fadda - console_video: video support for chan_oss and chan_alsa
Marta Carbone - console_video and the astobj2 framework
Luigi Rizzo - astobj2, console_video, windows build, chan_oss cleanup,
and a bunch of infrastructure work (loader, new_cli, ...)
Brett Bryant - digit option for musiconhold selection, ENUMQUERY and ENUMRESULT functions,
feature group configuration for features.conf, per-file CLI debug and verbose settings,
TCP and TLS support for SIP, and various bug fixes.
brettbryant(AT)gmail.com
Sergey Tamkovich - Realtime support for MusicOnHold, store and destroy realtime methods and
implementations for odbc, sqlite, and pgsql realtime drivers, attended transfer updates,
multiple speeds for ControlPlayback, and multiple bug fixes
- See http://voip-info.org/users/view/sergee
serg(AT)voipsolutions.ru
cpatry@gmail.com
=== OTHER CONTRIBUTIONS ===
John Todd - Monkey sounds and associated teletorture prompt
Michael Jerris - bug marshaling
Leif Madsen, Jared Smith and Jim van Meggelen - the Asterisk book
available under a Creative Commons License at http://www.asteriskdocs.org
Brian M. Clapper - poll.c emulation
This product includes software developed by Brian M. Clapper <bmc(AT)clapper.org>
=== HOLD MUSIC ===
Music provided by www.opsound.org
=== OTHER SOURCE CODE IN ASTERISK ===
Asterisk uses libedit, the lightweight readline replacement from NetBSD.
The cdr_radius module uses libradiusclient-ng, which is also from NetBSD.
They are BSD-licensed and require the following statement:
This product includes software developed by the NetBSD
Foundation, Inc. and its contributors.
Digium did not implement the codecs in Asterisk. Here is the copyright on the
GSM source:

6495
ChangeLog Normal file

File diff suppressed because it is too large Load Diff

70
HARDWARE Normal file
View File

@@ -0,0 +1,70 @@
A PBX is only really useful if you can get calls into it. Of course, you
can use Asterisk with VoIP calls (SIP, H.323, IAX), but you can also talk
to the real PSTN through various cards.
Supported Hardware is divided into two general groups: Zaptel devices and
non-zaptel devices. The Zaptel compatible hardware supports pseudo-TDM
conferencing and all call features through chan_zap, whereas non-zaptel
compatible hardware may have different features.
Zaptel compatible hardware
==========================
-- Digium (Primary author of Asterisk)
http://www.digium.com, http://store.yahoo.com/asteriskpbx
* Wildcard X100P - Single FXO interface connects to Loopstart phone
line
* Wildcard T400P (obsolete) - Quad T1 interface connects to four T1/PRI
interfaces. Supports RBS and PRI voice and PPP, FR, and HDLC data.
* Wildcard E400P (obsolete)- Quad E1 interface connects to four E1/PRI
(or PRA) interfaces. Supports PRA/PRI, EuroISDN voice and data.
* Wildcard T100P - Single T1 interface connects to a single T1/PRI
interface. Supports RBS and PRI voice and PPP, FR, and HDLC data.
* Wildcard E100P - Single E1 interface connects to a single E1/PRI (or PRA)
interface. Supports PRA/PRI, EuroISDN voice and PPP, FR, HDLC data.
* Wildcard S100U - Single FXS interface connects to a standard analog
telephone.
* Wildcard TDM400P - Quad Modular FXS interface connects to standard
analog telephones.
* Wildcard TE410P - Quad T1/E1 switchable interface. Supports PRI and
RBS signalling, as well as PPP, FR, and HDLC data modes.
Non-zaptel compatible hardware
==============================
-- QuickNet, Inc.
http://www.quicknet.net
* Internet PhoneJack - Single FXS interface. Supports Linux telephony
interface. DSP compression built-in.
* Internet LineJack - Single FXS or FXO interface. Supports Linux
telephony interface.
Miscellaneous other interfaces
==============================
-- ISDN4Linux
http://www.isdn4linux.de/
* Any ISDN terminal adapter supported by isdn4linux should provide
connectivity.
-- ALSA
http://www.alsa-project.org
* Any ALSA compatible full-duplex sound card
-- OSS
http://www.opensound.com
* Any OSS compatible full-duplex sound card

26
LICENSE
View File

@@ -7,8 +7,15 @@ source tree in the file COPYING.
This package also includes various components that are not part of
Asterisk itself; these components are in the 'contrib' directory
and its subdirectories. These components are also distributed under the
GPL version 2 as well.
and its subdirectories. Most of these components are also
distributed under the GPL version 2 as well, except for the following:
contrib/firmware/iax/iaxy.bin:
This file is Copyright (C) Digium, Inc. and is licensed for
use with Digium IAXy hardware devices only. It can be
distributed freely as long as the distribution is in the
original form present in this package (not reformatted or
modified).
Digium, Inc. (formerly Linux Support Services) holds copyright
and/or sufficient licenses to all components of the Asterisk
@@ -24,8 +31,8 @@ there is no requirement that you provide the same exception in your
GPL'd products (although if you've written a module for Asterisk we
would strongly encourage you to make the same exception that we do).
Specific permission is also granted to link Asterisk with OpenSSL, OpenH323
and/or the UW IMAP Toolkit and distribute the resulting binary files.
Specific permission is also granted to link Asterisk with OpenSSL and
OpenH323 and distribute the resulting binary files.
In addition, Asterisk implements two management/control protocols: the
Asterisk Manager Interface (AMI) and the Asterisk Gateway Interface
@@ -43,20 +50,19 @@ and use of them is subject to our trademark licensing policies. If you
wish to use these trademarks for purposes other than simple
redistribution of Asterisk source code obtained from Digium, you
should contact our licensing department to determine the necessary
steps you must take. For more information on this policy, please read:
http://www.digium.com/en/company/profile/trademarkpolicy.php
steps you must take.
If you have any questions regarding our licensing policy, please
contact us:
+1.877.344.4861 (via telephone in the USA)
+1.877.546.8963 (via telephone in the USA)
+1.256.428.6000 (via telephone outside the USA)
+1.256.864.0464 (via FAX inside or outside the USA)
IAX2/pbx.digium.com (via IAX2)
IAX2/misery.digium.com/6000 (via IAX2)
licensing@digium.com (via email)
Digium, Inc.
445 Jan Davis Drive
150 West Park Loop
Suite 100
Huntsville, AL 35806
USA

1268
Makefile

File diff suppressed because it is too large Load Diff

View File

@@ -1,160 +0,0 @@
#
# Asterisk -- A telephony toolkit for Linux.
#
# Makefile rules for subdirectories containing modules
#
# Copyright (C) 2006, Digium, Inc.
#
# Kevin P. Fleming <kpfleming@digium.com>
#
# This program is free software, distributed under the terms of
# the GNU General Public License
#
# Makefile rules for building modules.
# In most cases, we set target-specific variables for certain targets
# (remember that they apply recursively to prerequisites).
# Also note that we can only set one variable per rule, so we have to
# repeat the left hand side to set multiple variables.
ifeq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),)
_ASTCFLAGS+=${GC_CFLAGS}
endif
ifneq ($(findstring STATIC_BUILD,$(MENUSELECT_CFLAGS)),)
STATIC_BUILD=-static
endif
include $(ASTTOPDIR)/Makefile.rules
# If MODULE_PREFIX is defined, use it to run the standard functions to set
# C_MODS, CC_MODS, LOADABLE_MODS and EMBEDDED_MODS.
# Each word of MODULE_PREFIX is a prefix for filenames that we consider
# valid C or CC modules (eg. app, func ...). Note that the underscore
# is added here, and does not need to be in MODULE_PREFIX
#
# Use MODULE_EXCLUDE to specify additional modules to exclude.
ifneq ($(MODULE_PREFIX),)
ALL_C_MODS:=
ALL_C_MODS+=$(foreach p,$(MODULE_PREFIX),$(patsubst %.c,%,$(wildcard $(p)_*.c)))
ALL_CC_MODS:=
ALL_CC_MODS+=$(foreach p,$(MODULE_PREFIX),$(patsubst %.cc,%,$(wildcard $(p)_*.cc)))
C_MODS:=$(filter-out $(MENUSELECT_$(MENUSELECT_CATEGORY)),$(ALL_C_MODS))
CC_MODS:=$(filter-out $(MENUSELECT_$(MENUSELECT_CATEGORY)),$(ALL_CC_MODS))
# and store in the list of embedded or loadable modules
ifneq ($(findstring $(MENUSELECT_CATEGORY),$(MENUSELECT_EMBED)),)
EMBEDDED_MODS:=$(C_MODS) $(CC_MODS)
else
LOADABLE_MODS:=$(C_MODS) $(CC_MODS)
endif
endif
# Both C++ and C++ sources need their module name in AST_MODULE
# We also pass whatever _INCLUDE list is generated by menuselect
# (they are stored in file 'makeopts')
$(addsuffix .oo,$(CC_MODS)) $(addsuffix .o,$(C_MODS)): \
_ASTCFLAGS+= -DAST_MODULE=\"$*\" $(MENUSELECT_OPTS_$*:%=-D%) $(foreach dep,$(MENUSELECT_DEPENDS_$*),$(value $(dep)_INCLUDE))
ifeq ($(findstring $(OSARCH), mingw32 cygwin ),)
# don't define -fPIC on mingw32 and cygwin, it is the default
$(LOADABLE_MODS:%=%.so): _ASTCFLAGS+=-fPIC
endif
# For loadable modules, pass _LIB and _LDFLAGS from menuselect.
$(LOADABLE_MODS:%=%.so): LIBS+=$(foreach dep,$(MENUSELECT_DEPENDS_$*),$(value $(dep)_LIB))
$(LOADABLE_MODS:%=%.so): _ASTLDFLAGS+=$(foreach dep,$(MENUSELECT_DEPENDS_$*),$(value $(dep)_LDFLAGS))
$(EMBEDDED_MODS:%=%.o): _ASTCFLAGS+=-DEMBEDDED_MODULE=$*
$(addsuffix .so,$(filter $(LOADABLE_MODS),$(C_MODS))): %.so: %.o
$(addsuffix .so,$(filter $(LOADABLE_MODS),$(CC_MODS))): %.so: %.oo
modules.link: $(addsuffix .eo,$(filter $(EMBEDDED_MODS),$(C_MODS)))
.PHONY: clean uninstall _all moduleinfo makeopts
ifneq ($(LOADABLE_MODS),)
_all: $(LOADABLE_MODS:%=%.so)
ifneq ($(findstring $(OSARCH), mingw32 cygwin ),)
# linker options and extra libraries for cygwin
SOLINK=-Wl,--out-implib=lib$@.a -shared
LIBS+=-L$(ASTTOPDIR)/main -lasterisk -L$(ASTTOPDIR)/res $($@_LIBS)
# additional libraries in res/
endif
endif
ifneq ($(EMBEDDED_MODS),)
_all: modules.link
__embed_ldscript:
@echo "../$(SUBDIR)/modules.link"
__embed_ldflags:
@echo "$(foreach mod,$(filter $(EMBEDDED_MODS),$(C_MODS)),$(foreach dep,$(MENUSELECT_DEPENDS_$(mod)),$(dep)_LDFLAGS))"
@echo "$(foreach mod,$(filter $(EMBEDDED_MODS),$(CC_MODS)),$(foreach dep,$(MENUSELECT_DEPENDS_$(mod)),$(dep)_LDFLAGS))"
__embed_libs:
@echo "$(foreach mod,$(filter $(EMBEDDED_MODS),$(C_MODS)),$(foreach dep,$(MENUSELECT_DEPENDS_$(mod)),$(dep)_LIB))"
@echo "$(foreach mod,$(filter $(EMBEDDED_MODS),$(CC_MODS)),$(foreach dep,$(MENUSELECT_DEPENDS_$(mod)),$(dep)_LIB))"
else
__embed_ldscript:
__embed_ldflags:
__embed_libs:
endif
modules.link:
@rm -f $@
@for file in $(patsubst %,$(SUBDIR)/%,$(filter %.eo,$^)); do echo "INPUT (../$${file})" >> $@; done
@for file in $(patsubst %,$(SUBDIR)/%,$(filter-out %.eo,$^)); do echo "INPUT (../$${file})" >> $@; done
clean::
rm -f *.so *.o *.oo *.eo *.i *.ii
rm -f .*.d
rm -f *.s *.i
rm -f modules.link
install:: all
@echo "Installing modules from `basename $(CURDIR)`..."
@for x in $(LOADABLE_MODS:%=%.so); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
uninstall::
dist-clean::
rm -f .*.moduleinfo .moduleinfo
rm -f .*.makeopts .makeopts
.%.moduleinfo: %.c
@echo "<member name=\"$*\" displayname=\"$(shell $(GREP) -e AST_MODULE_INFO $< | head -n 1 | cut -d '"' -f 2)\" remove_on_change=\"$(SUBDIR)/$*.o $(SUBDIR)/$*.so\">" > $@
$(AWK) -f $(ASTTOPDIR)/build_tools/get_moduleinfo $< >> $@
echo "</member>" >> $@
.%.moduleinfo: %.cc
@echo "<member name=\"$*\" displayname=\"$(shell $(GREP) -e AST_MODULE_INFO $< | head -n 1 | cut -d '"' -f 2)\" remove_on_change=\"$(SUBDIR)/$*.oo $(SUBDIR)/$*.so\">" > $@
$(AWK) -f $(ASTTOPDIR)/build_tools/get_moduleinfo $< >> $@
echo "</member>" >> $@
.moduleinfo:: $(addsuffix .moduleinfo,$(addprefix .,$(ALL_C_MODS) $(ALL_CC_MODS)))
@echo "<category name=\"MENUSELECT_$(MENUSELECT_CATEGORY)\" displayname=\"$(MENUSELECT_DESCRIPTION)\" remove_on_change=\"$(SUBDIR)/modules.link\">" > $@
@cat $^ >> $@
@echo "</category>" >> $@
moduleinfo: .moduleinfo
@cat $<
.%.makeopts: %.c
@$(AWK) -f $(ASTTOPDIR)/build_tools/get_makeopts $< > $@
.%.makeopts: %.cc
@$(AWK) -f $(ASTTOPDIR)/build_tools/get_makeopts $< > $@
.makeopts:: $(addsuffix .makeopts,$(addprefix .,$(ALL_C_MODS) $(ALL_CC_MODS)))
@cat $^ > $@
makeopts: .makeopts
@cat $<
ifneq ($(wildcard .*.d),)
include .*.d
endif

View File

@@ -1,135 +0,0 @@
#
# Asterisk -- A telephony toolkit for Linux.
#
# Makefile rules
#
# Copyright (C) 2006-2008, Digium, Inc.
#
# Kevin P. Fleming <kpfleming@digium.com>
#
# This program is free software, distributed under the terms of
# the GNU General Public License
#
# Each command is preceded by a short comment on what to do.
# Prefixing one or the other with @\# or @ or nothing makes the desired
# behaviour. ECHO_PREFIX prefixes the comment, CMD_PREFIX prefixes the command.
-include $(ASTTOPDIR)/makeopts
.PHONY: dist-clean
# If 'make' decides to create intermediate files to satisfy a build requirement
# (like producing a .i from a .c), we want to keep them, so tell make to keep
# all intermediate files
.SECONDARY:
# extra cflags to build dependencies. Recursively expanded.
MAKE_DEPS=-MD -MT $@ -MF .$(subst /,_,$@).d -MP
ifeq ($(NOISY_BUILD),)
ECHO_PREFIX=@
CMD_PREFIX=@
else
ECHO_PREFIX=@\#
CMD_PREFIX=
endif
OPTIMIZE?=-O6
ifneq ($(findstring darwin,$(OSARCH)),)
ifeq ($(shell /usr/bin/sw_vers -productVersion | cut -c1-4),10.6)
# Snow Leopard has an issue with this optimization flag on large files (like chan_sip)
OPTIMIZE+=-fno-inline-functions
endif
endif
ifeq ($(findstring DONT_OPTIMIZE,$(MENUSELECT_CFLAGS)),)
_ASTCFLAGS+=$(OPTIMIZE)
else
_ASTCFLAGS+=-O0
endif
# shortcuts for common combinations of flags; these must be recursively expanded so that
# per-target settings will be applied
CC_CFLAGS=$(PTHREAD_CFLAGS) $(_ASTCFLAGS) $(ASTCFLAGS)
CXX_CFLAGS=$(PTHREAD_CFLAGS) $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(AST_DECLARATION_AFTER_STATEMENT),$(_ASTCFLAGS) $(ASTCFLAGS))
CC_LDFLAGS_SO=$(PTHREAD_CFLAGS) $(_ASTLDFLAGS) $(SOLINK) $(ASTLDFLAGS)
CXX_LDFLAGS_SO=$(PTHREAD_CFLAGS) $(_ASTLDFLAGS) $(SOLINK) $(ASTLDFLAGS)
CC_LIBS=$(PTHREAD_LIBS) $(LIBS)
CXX_LIBS=$(PTHREAD_LIBS) $(LIBS)
# determine whether to double-compile so that the optimizer can report code path problems
# this is only done when developer mode and DONT_OPTIMIZE are both enabled
# in that case, we run the preprocessor to produce a .i or .ii file from the source
# code, then compile once with optimizer enabled (and the output to /dev/null),
# and if that doesn't fail then compile again with optimizer disabled
ifeq ($(findstring DONT_OPTIMIZE,$(MENUSELECT_CFLAGS))$(AST_DEVMODE),DONT_OPTIMIZEyes)
COMPILE_DOUBLE=yes
endif
%.o: %.s
$(ECHO_PREFIX) echo " [AS] $< -> $@"
ifeq ($(COMPILE_DOUBLE),yes)
$(CMD_PREFIX) $(CC) -o /dev/null -c $< $(OPTIMIZE) $(CC_CFLAGS)
endif
$(CMD_PREFIX) $(CC) -o $@ -c $< $(CC_CFLAGS)
%.o: %.i
$(ECHO_PREFIX) echo " [CCi] $< -> $@"
ifeq ($(COMPILE_DOUBLE),yes)
$(CMD_PREFIX) $(CC) -o /dev/null -c $< $(OPTIMIZE) $(CC_CFLAGS)
endif
$(CMD_PREFIX) $(CC) -o $@ -c $< $(CC_CFLAGS)
ifneq ($(COMPILE_DOUBLE),yes)
%.o: %.c
$(ECHO_PREFIX) echo " [CC] $< -> $@"
$(CMD_PREFIX) $(CC) -o $@ -c $< $(MAKE_DEPS) $(CC_CFLAGS)
endif
%.i: %.c
$(ECHO_PREFIX) echo " [CPP] $< -> $@"
$(CMD_PREFIX) $(CC) -o $@ -E $< $(MAKE_DEPS) $(CC_CFLAGS)
%.oo: %.ii
$(ECHO_PREFIX) echo " [CXXi] $< -> $@"
ifeq ($(COMPILE_DOUBLE),yes)
$(CMD_PREFIX) $(CXX) -o /dev/null -c $< $(OPTIMIZE) $(CXX_CFLAGS)
endif
$(CMD_PREFIX) $(CXX) -o $@ -c $< $(CXX_CFLAGS)
ifneq ($(COMPILE_DOUBLE),yes)
%.oo: %.cc
$(ECHO_PREFIX) echo " [CXX] $< -> $@"
$(CMD_PREFIX) $(CXX) -o $@ -c $< $(MAKE_DEPS) $(CXX_CFLAGS)
endif
%.ii: %.cc
$(ECHO_PREFIX) echo " [CPP] $< -> $@"
$(CMD_PREFIX) $(CXX) -o $@ -E $< $(MAKE_DEPS) $(CXX_CFLAGS)
%.so: %.o
$(ECHO_PREFIX) echo " [LD] $^ -> $@"
$(CMD_PREFIX) $(CC) $(STATIC_BUILD) -o $@ $(CC_LDFLAGS_SO) $^ $(CC_LIBS)
%.so: %.oo
$(ECHO_PREFIX) echo " [LDXX] $^ -> $@"
$(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(CXX_LDFLAGS_SO) $^ $(CXX_LIBS)
%.eo: %.o
$(ECHO_PREFIX) echo " [EMBED] $< -> $@"
$(CMD_PREFIX) $(ASTTOPDIR)/build_tools/make_linker_eo_script $* > .$@.ld
$(CMD_PREFIX) $(LD) -r -T .$@.ld -o $@ $<
$(CMD_PREFIX) rm -f .$@.ld
%.eo: %.oo
$(ECHO_PREFIX) echo " [EMBED] $< -> $@"
$(CMD_PREFIX) $(ASTTOPDIR)/build_tools/make_linker_eo_script $* > .$@.ld
$(CMD_PREFIX) $(LD) -r -T .$@.ld -o $@ $<
$(CMD_PREFIX) rm -f .$@.ld
%: %.o
$(ECHO_PREFIX) echo " [LD] $^ -> $@"
$(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(PTHREAD_CFLAGS) $(_ASTLDFLAGS) $^ $(CXX_LIBS) $(ASTLDFLAGS)
dist-clean:: clean

198
README
View File

@@ -1,81 +1,63 @@
===============================================================================
=== The Asterisk(R) Open Source PBX
===
=== by Mark Spencer <markster@digium.com>
=== and the Asterisk.org developer community
===
=== Copyright (C) 2001-2008 Digium, Inc.
=== and other copyright holders.
===============================================================================
The Asterisk Open Source PBX
by Mark Spencer <markster@digium.com>
and the Asterisk.org developer community
-------------------------------------------------------------------------------
--- SECURITY ------------------------------------------------------------------
Copyright (C) 2001-2005 Digium, Inc.
and other copyright holders.
================================================================
* SECURITY
It is imperative that you read and fully understand the contents of
the security information document before you attempt to configure and run
an Asterisk server.
If you downloaded Asterisk as a tarball, see the security section in the PDF
version of the documentation in doc/tex/asterisk.pdf. Alternatively, pull up
the HTML version of the documentation in doc/tex/asterisk/index.html. The
source for the security document is available in doc/tex/security.tex.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- WHAT IS ASTERISK ? --------------------------------------------------------
the SECURITY file before you attempt to configure and run an Asterisk
server.
* WHAT IS ASTERISK ?
Asterisk is an Open Source PBX and telephony toolkit. It is, in a
sense, middleware between Internet and telephony channels on the bottom,
and Internet and telephony applications at the top. However, Asterisk supports
more telephony interfaces than just Internet telephony. Asterisk also has a
vast amount of support for traditional PSTN telephony, as well. For more
information on the project itself, please visit the Asterisk home page at:
and Internet and telephony applications at the top. For more information
on the project itself, please visit the Asterisk home page at:
http://www.asterisk.org
In addition you'll find lots of information compiled by the Asterisk
In addition you'll find lots of information compiled by the Asterisk
community on this Wiki:
http://www.voip-info.org/wiki-Asterisk
There is a book on Asterisk published by O'Reilly under the Creative Commons
License. It is available in book stores as well as in a downloadable version on
the http://www.asteriskdocs.org web site.
-------------------------------------------------------------------------------
There is a book on Asterisk published by O'Reilly under the
Creative Commons License. It is available in book stores as well
as in a downloadable version on the http://www.asteriskdocs.org
web site.
-------------------------------------------------------------------------------
--- SUPPORTED OPERATING SYSTEMS -----------------------------------------------
* SUPPORTED OPERATING SYSTEMS
--- Linux
== Linux ==
The Asterisk Open Source PBX is developed and tested primarily on the
GNU/Linux operating system, and is supported on every major GNU/Linux
distribution.
--- Others
== Others ==
Asterisk has also been 'ported' and reportedly runs properly on other
operating systems as well, including Sun Solaris, Apple's Mac OS X, Cygwin,
and the BSD variants.
-------------------------------------------------------------------------------
operating systems as well, including Sun Solaris, Apple's Mac OS X, and
the BSD variants.
-------------------------------------------------------------------------------
--- GETTING STARTED -----------------------------------------------------------
* GETTING STARTED
First, be sure you've got supported hardware (but note that you don't need
ANY special hardware, not even a sound card) to install and run Asterisk.
ANY special hardware, not even a soundcard) to install and run Asterisk.
Supported telephony hardware includes:
* All Analog and Digital Interface cards from Digium (www.digium.com)
* All Wildcard (tm) products from Digium (www.digium.com)
* QuickNet Internet PhoneJack and LineJack (http://www.quicknet.net)
* any full duplex sound card supported by ALSA, OSS, or PortAudio
* any ISDN card supported by mISDN on Linux (BRI)
* The Xorcom AstriBank channel bank
* VoiceTronix OpenLine products
* any full duplex sound card supported by ALSA or OSS
* VoiceTronix OpenLine products
-------------------------------------------------------------------------------
The are several drivers for ISDN BRI cards available from third party sources.
Check the voip-info.org wiki for more information on chan_capi, chan_misdn and
zaphfc.
-------------------------------------------------------------------------------
--- UPGRADING FROM AN EARLIER VERSION -----------------------------------------
* UPGRADING FROM VERSION 1.0
If you are updating from a previous version of Asterisk, make sure you
read the UPGRADE.txt file in the source directory. There are some files
@@ -83,59 +65,44 @@ and configuration options that you will have to change, even though we
made every effort possible to maintain backwards compatibility.
In order to discover new features to use, please check the configuration
examples in the /configs directory of the source code distribution. For a
list of new features in this version of Asterisk, see the CHANGES file.
-------------------------------------------------------------------------------
examples in the /configs directory of the source code distribution.
To discover the major new features of Asterisk 1.2, please visit
http://edvina.net/asterisk1-2/
-------------------------------------------------------------------------------
--- NEW INSTALLATIONS ---------------------------------------------------------
* NEW INSTALLATIONS
Ensure that your system contains a compatible compiler and development
libraries. Asterisk requires either the GNU Compiler Collection (GCC) version
3.0 or higher, or a compiler that supports the C99 specification and some of
the gcc language extensions. In addition, your system needs to have the C
library headers available, and the headers and libraries for ncurses.
library headers available, and the headers and libraries for OpenSSL,
ncurses and zlib.
On many distributions, these files are installed by packages with names like
'glibc-devel', 'ncurses-devel', 'openssl-devel' and 'zlib-devel' or similar.
There are many modules that have additional dependencies. To see what
libraries are being looked for, see ./configure --help, or run
"make menuselect" to view the dependencies for specific modules.
So let's proceed:
On many distributions, these dependencies are installed by packages with names
like 'glibc-devel', 'ncurses-devel', 'openssl-devel' and 'zlib-devel'
or similar.
So, let's proceed:
1) Read this README file.
There are more documents than this one in the doc/ directory. You may also
want to check the configuration files that contain examples and reference
guides. They are all in the configs/ directory.
2) Run "./configure"
Execute the configure script to guess values for system-dependent
variables used during compilation.
3) Run "make menuselect" [optional]
This is needed if you want to select the modules that will be compiled and to
check dependencies for various optional modules.
4) Run "make"
1) Run "make"
Assuming the build completes successfully:
5) Run "make install"
2) Run "make install"
Each time you update or checkout from CVS, you are strongly encouraged
to ensure all previous object files are removed to avoid internal
inconsistency in Asterisk. Normally, this is automatically done with
the presence of the file .cleancount, which increments each time a 'make clean'
is required, and the file .lastclean, which contains the last .cleancount used.
If this is your first time working with Asterisk, you may wish to install
the sample PBX, with demonstration extensions, etc. If so, run:
6) "make samples"
3) "make samples"
Doing so will overwrite any existing configuration files you have installed.
Doing so will overwrite any existing config files you have.
Finally, you can launch Asterisk in the foreground mode (not a daemon) with:
Finally, you can launch Asterisk in the foreground mode (not a daemon)
with:
# asterisk -vvvc
@@ -148,22 +115,20 @@ like this:
You can type "help" at any time to get help with the system. For help
with a specific command, type "help <command>". To start the PBX using
your sound card, you can type "console dial" to dial the PBX. Then you can use
"console answer", "console hangup", and "console dial" to simulate the actions
of a telephone. Remember that if you don't have a full duplex sound card
(and Asterisk will tell you somewhere in its verbose messages if you do/don't)
then it won't work right (not yet).
your sound card, you can type "dial" to dial the PBX. Then you can use
"answer", "hangup", and "dial" to simulate the actions of a telephone.
Remember that if you don't have a full duplex sound card (and Asterisk
will tell you somewhere in its verbose messages if you do/don't) then it
won't work right (not yet).
"man asterisk" at the Unix/Linux command prompt will give you detailed
information on how to start and stop Asterisk, as well as all the command
line options for starting Asterisk.
Feel free to look over the configuration files in /etc/asterisk, where you
will find a lot of information about what you can do with Asterisk.
-------------------------------------------------------------------------------
Feel free to look over the configuration files in /etc/asterisk, where
you'll find a lot of information about what you can do with Asterisk.
-------------------------------------------------------------------------------
--- ABOUT CONFIGURATION FILES -------------------------------------------------
* ABOUT CONFIGURATION FILES
All Asterisk configuration files share a common format. Comments are
delimited by ';' (since '#' of course, being a DTMF digit, may occur in
@@ -175,11 +140,11 @@ they're used only to help make the configuration file easier to
understand, and do not affect how it is actually parsed.
Entries of the form 'variable=value' set the value of some parameter in
asterisk. For example, in dahdi.conf, one might specify:
asterisk. For example, in zapata.conf, one might specify:
switchtype=national
In order to indicate to Asterisk that the switch they are connecting to is
in order to indicate to Asterisk that the switch they are connecting to is
of the type "national". In general, the parameter will apply to
instantiations which occur below its specification. For example, if the
configuration file read:
@@ -190,7 +155,7 @@ configuration file read:
switchtype = dms100
channel => 25-47
The "national" switchtype would be applied to channels one through
the "national" switchtype would be applied to channels one through
four and channels 10 through 12, whereas the "dms100" switchtype would
apply to channels 25 through 47.
@@ -198,10 +163,16 @@ apply to channels 25 through 47.
parameters. For example, the line "channel => 25-47" creates objects for
the channels 25 through 47 of the card, obtaining the settings
from the variables specified above.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- SPECIAL NOTE ON TIME ------------------------------------------------------
* NETWORK SECURITY DEVICES
This release of Asterisk contains support for network security devices
manufactured by Ranch Networks, Inc., using their MIDCOM interface
library. You will need the companion libmidcom-0.1.0.tar.gz file to
build the library. Contact Ranch Networks' support department for assistance
in building and configuring MIDCOM support.
* SPECIAL NOTE ON TIME
Those using SIP phones should be aware that Asterisk is sensitive to
large jumps in time. Manually changing the system time using date(1)
@@ -224,10 +195,8 @@ on UTC. UTC does not use daylight savings time.
Also note that this issue is separate from the clocking of TDM
channels, and is known to at least affect SIP registrations.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- FILE DESCRIPTORS ----------------------------------------------------------
* FILE DESCRIPTORS
Depending on the size of your system and your configuration,
Asterisk can consume a large number of file descriptors. In UNIX,
@@ -240,13 +209,11 @@ everything from configuration information to voicemail storage.
Most systems limit the number of file descriptors that Asterisk can
have open at one time. This can limit the number of simultaneous
calls that your system can handle. For example, if the limit is set
at 1024 (a common default value) Asterisk can handle approximately 150
at 1024 (a common default value) Asterisk can handle approxiately 150
SIP calls simultaneously. To change the number of file descriptors
follow the instructions for your system below:
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- PAM-based Linux System ----------------------------------------------------
== PAM-based Linux System ==
If your system uses PAM (Pluggable Authentication Modules) edit
/etc/security/limits.conf. Add these lines to the bottom of the file:
@@ -264,29 +231,18 @@ these changes to take effect.
If there are no instructions specifically adapted to your system
above you can try adding the command "ulimit -n 8192" to the script
that starts Asterisk.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
--- MORE INFORMATION ----------------------------------------------------------
* MORE INFORMATION
See the doc directory for more documentation on various features. Again,
please read all the configuration samples that include documentation on
the configuration options.
If this release of Asterisk was downloaded from a tarball, then some
additional documentation should have been included.
* doc/tex/asterisk.pdf --- PDF version of the documentation
* doc/tex/asterisk/index.html --- HTML version of the documentation
Finally, you may wish to visit the web site and join the mailing list if
you're interested in getting more information.
http://www.asterisk.org/support
Welcome to the growing worldwide community of Asterisk users!
-------------------------------------------------------------------------------
--- Mark Spencer, and the Asterisk.org development community
-------------------------------------------------------------------------------
Asterisk is a trademark of Digium, Inc.
Mark Spencer

View File

@@ -1,295 +0,0 @@
==================
| Best Practices |
==================
The purpose of this document is to define best practices when working with
Asterisk in order to minimize possible security breaches and to provide tried
examples in field deployments. This is a living document and is subject to
change over time as best practices are defined.
--------
Sections
--------
* Filtering Data:
How to protect yourself from redial attacks
* Proper Device Naming:
Why to not use numbered extensions for devices
* Secure Passwords:
Secure passwords limit your risk to brute force attacks
* Reducing Pattern Match Typos:
Using the 'same' prefix, or using Goto()
----------------
Additional Links
----------------
Additional links that contain useful information about best practices or
security are listed below.
* Seven Steps to Better SIP Security:
http://blogs.digium.com/2009/03/28/sip-security/
* Asterisk VoIP Security (webinar):
http://www.asterisk.org/security/webinar/
==============
Filtering Data
==============
In the Asterisk dialplan, several channel variables contain data potentially
supplied by outside sources. This could lead to a potential security concern
where those outside sources may send cleverly crafted strings of data which
could be utilized, e.g. to place calls to unexpected locations.
An example of this can be found in the use of pattern matching and the ${EXTEN}
channel variable. Note that ${EXTEN} is not the only system created channel
variable, so it is important to be aware of where the data you're using is
coming from.
For example, this common dialplan takes 2 or more characters of data, starting
with a number 0-9, and then accepts any additional information supplied by the
request.
[NOTE: We use SIP in this example, but is not limited to SIP only; protocols
such as Jabber/XMPP or IAX2 are also susceptible to the same sort of
injection problem.]
[incoming]
exten => _X.,1,Verbose(2,Incoming call to extension ${EXTEN})
exten => _X.,n,Dial(SIP/${EXTEN})
exten => _X.,n,Hangup()
This dialplan may be utilized to accept calls to extensions, which then dial a
numbered device name configured in one of the channel configuration files (such
as sip.conf, iax.conf, etc...) (see the section Proper Device Naming for more
information on why this approach is flawed).
The example we've given above looks harmless enough until you take into
consideration that several channel technologies accept characters that could
be utilized in a clever attack. For example, instead of just sending a request
to dial extension 500 (which in our example above would create the string
SIP/500 and is then used by the Dial() application to place a call), someone
could potentially send a string like "500&SIP/itsp/14165551212".
The string "500&SIP/itsp/14165551212" would then be contained within the
${EXTEN} channel variable, which is then utilized by the Dial() application in
our example, thereby giving you the dialplan line of:
exten => _X.,n,Dial(SIP/500&SIP/itsp/14165551212)
Our example above has now provided someone with a method to place calls out of
your ITSP in a place where you didn't expect to allow it. There are a couple of
ways in which you can mitigate this impact: stricter pattern matching, or using
the FILTER() dialplan function.
Strict Pattern Matching
-----------------------
The simple way to mitigate this problem is with a strict pattern match that does
not utilize the period (.) or bang (!) characters to match on one-or-more
characters or zero-or-more characters (respectively). To fine tune our example
to only accept three digit extensions, we could change our pattern match to
be:
exten => _XXX,n,Dial(SIP/${EXTEN})
In this way, we have minimized our impact because we're not allowing anything
other than the numbers zero through nine. But in some cases we really do need to
handle variable pattern matches, such as when dialing international numbers
or when we want to handle something like a SIP URI. In this case, we'll need to
utilize the FILTER() dialplan function.
Using FILTER()
--------------
The FILTER() dialplan function is used to filter strings by only allowing
characters that you have specified. This is a perfect candidate for controlling
which characters you want to pass to the Dial() application, or any other
application which will contain dynamic information passed to Asterisk from an
external source. Lets take a look at how we can use FILTER() to control what
data we allow.
Using our previous example to accept any string length of 2 or more characters,
starting with a number of zero through nine, we can use FILTER() to limit what
we will accept to just numbers. Our example would then change to something like:
[incoming]
exten => _X.,1,Verbose(2,Incoming call to extension ${EXTEN})
exten => _X.,n,Dial(SIP/${FILTER(0-9,${EXTEN})})
exten => _X.,n,Hangup()
Note how we've wrapped the ${EXTEN} channel variable with the FILTER() function
which will then only pass back characters that fit into the numerical range that
we've defined.
Alternatively, if we didn't want to utilize the FILTER() function within the
Dial() application directly, we could save the value to a channel variable,
which has a side effect of being usable in other locations of your dialplan if
necessary, and to handle error checking in a separate location.
[incoming]
exten => _X.,1,Verbose(2,Incoming call to extension ${EXTEN})
exten => _X.,n,Set(SAFE_EXTEN=${FILTER(0-9,${EXTEN})})
exten => _X.,n,Dial(SIP/${SAFE_EXTEN})
exten => _X.,n,Hangup()
Now we can use the ${SAFE_EXTEN} channel variable anywhere throughout the rest
of our dialplan, knowing we've already filtered it. We could also perform an
error check to verify that what we've received in ${EXTEN} also matches the data
passed back by FILTER(), and to fail the call if things do not match.
[incoming]
exten => _X.,1,Verbose(2,Incoming call to extension ${EXTEN})
exten => _X.,n,Set(SAFE_EXTEN=${FILTER(0-9,${EXTEN})})
exten => _X.,n,GotoIf($[${EXTEN} != ${SAFE_EXTEN}]?error,1)
exten => _X.,n,Dial(SIP/${SAFE_EXTEN})
exten => _X.,n,Hangup()
exten => error,1,Verbose(2,Values of EXTEN and SAFE_EXTEN did not match.)
exten => error,n,Verbose(2,EXTEN: "${EXTEN}" -- SAFE_EXTEN: "${SAFE_EXTEN}")
exten => error,n,Playback(silence/1&invalid)
exten => error,n,Hangup()
Another example would be using FILTER() to control the characters we accept when
we're expecting to get a SIP URI for dialing.
[incoming]
exten => _[0-9a-zA-Z].,1,Verbose(2,Incoming call to extension ${EXTEN})
exten => _[0-9a-zA-Z].,n,Dial(SIP/${FILTER(.@0-9a-zA-Z,${EXTEN})
exten => _[0-9a-zA-Z].,n,Hangup()
Of course the FILTER() function doesn't check the formatting of the incoming
request. There is also the REGEX() dialplan function which can be used to
determine if the string passed to it matches the regular expression you've
created, and to take proper action on whether it matches or not. The creation of
regular expressions is left as an exercise for the reader.
More information about the FILTER() and REGEX() dialplan functions can be found
by typing "core show function FILTER" and "core show function REGEX" from your
Asterisk console.
====================
Proper Device Naming
====================
In Asterisk, the concept of an extension number being tied to a specific device
does not exist. Asterisk is aware of devices it can call or receive calls from,
and how you define in your dialplan how to reach those devices is up to you.
Because it has become common practice to think of a specific device as having an
extension number associated with it, it only becomes natural to think about
naming your devices the same as the extension number you're providing it. But
by doing this, you're limiting the powerful concept of separating user from
extensions, and extensions from devices.
It can also be a security hazard to name your devices with a number, as this can
open you up to brute force attacks. Many of the current exploits deal with
device configurations which utilize a number, and even worse, a password that
matches the devices name. For example, take a look at this poorly created device
in sip.conf:
[1000]
type=friend
context=international_dialing
secret=1000
As implied by the context, we've permitted a device named 1000 with a password
of 1000 to place calls internationally. If your PBX system is accessible via
the internet, then your system will be vulnerable to expensive international
calls. Even if your system is not accessible via the internet, people within
your organization could get access to dialing rules you'd prefer to reserve only
for certain people.
A more secure example for the device would be to use something like the MAC
address of the device, along with a strong password (see the section Secure
Passwords). The following example would be more secure:
[0004f2040001]
type=friend
context=international_dialing
secret=aE3%B8*$jk^G
Then in your dialplan, you would reference the device via the MAC address of the
device (or if using the softphone, a MAC address of a network interface on the
computer).
Also note that you should NOT use this password, as it will likely be one of the
first ones added to the dictionary for brute force attacks.
================
Secure Passwords
================
Secure passwords are necessary in many (if not all) environments, and Asterisk
is certainly no exception, especially when it comes to expensive long distance
calls that could potentially cost your company hundreds or thousands of dollars
on an expensive monthly phone bill, with little to no recourse to fight the
charges.
Whenever you are positioned to add a password to your system, whether that is
for a device configuration, a database connection, or any other secure
connection, be sure to use a secure password. A good example of a secure
password would be something like:
aE3%B8*$jk^G
Our password also contains 12 characters with a mixture of upper and
lower case characters, numbers, and symbols. Because these passwords are likely
to only be entered once, or loaded via a configuration file, there is
no need to create simple passwords, even in testing. Some of the holes found in
production systems used for exploitations involve finding the one test extension
that contains a weak password that was forgotten prior to putting a system into
production.
Using a web search you can find several online password generators such as
http://www.strongpasswordgenerator.com or there are several scripts that can be
used to generate a strong password.
============================
Reducing Pattern Match Typos
============================
As of Asterisk 1.6.2, a new method for reducing the number of complex pattern
matches you need to enter, which can reduce typos in your dialplan, has been
implemented. Traditionally, a dialplan with a complex pattern match would look
something like:
exten => _[3-5]XXX,1,Verbose(Incoming call to ${EXTEN})
exten => _[3-5]XXX,n,Set(DEVICE=${DB(device/mac_address/${EXTEN})})
exten => _[3-5]XXX,n,Set(TECHNOLOGY=${DB(device/technology/${EXTEN})})
exten => _[3-5]XXX,n,GotoIf($[${ISNULL(${TECHNOLOGY})} | ${ISNULL(${DEVICE})}]?error,1)
exten => _[3-5]XXX,n,Dial(${TECHNOLOGY}/${DEVICE},${GLOBAL(TIMEOUT)})
exten => _[3-5]XXX,n,Set(vmFlag=${IF($[${DIALSTATUS} = BUSY]?b:u)})
exten => _[3-5]XXX,n,Voicemail(${EXTEN}@${GLOBAL(VOICEMAIL_CONTEXT)},${vmFlag})
exten => _[3-5]XXX,n,Hangup()
exten => error,1,Verbose(2,Unable to lookup technology or device for extension)
exten => error,n,Playback(silence/1&num-not-in-db)
exten => error,n,Hangup()
Of course there exists the possibility for a typo when retyping the pattern
match _[3-5]XXX which will match on extensions 3000 through 5999. We can
minimize this error by utilizing the same => prefix on all lines beyond the
first one. Our same dialplan with using same => would look like the following:
exten => _[3-5]XXX,1,Verbose(Incoming call to ${EXTEN})
same => n,Set(DEVICE=${DB(device/mac_address/${EXTEN})})
same => n,Set(TECHNOLOGY=${DB(device/technology/${EXTEN})})
same => n,GotoIf($[${ISNULL(${TECHNOLOGY})} | ${ISNULL(${DEVICE})}]?error,1)
same => n,Dial(${TECHNOLOGY}/${DEVICE},${GLOBAL(TIMEOUT)})
same => n,Set(vmFlag=${IF($[${DIALSTATUS} = BUSY]?b:u)})
same => n,Voicemail(${EXTEN}@${GLOBAL(VOICEMAIL_CONTEXT)},${vmFlag})
same => n,Hangup()
exten => error,1,Verbose(2,Unable to lookup technology or device for extension)
same => n,Playback(silence/1&num-not-in-db)
same => n,Hangup()

22
README.opsound Normal file
View File

@@ -0,0 +1,22 @@
About Hold Music
================
These files were obtained from http://opsound.org, where the authors placed them
under the Creative Commons Attribution-Share Alike 2.5 license, a copy of which
may be found at http://creativecommons.org.
Credits
================
macroform-cold_day - Paul Shuler (Macroform)
paulshuler@gmail.com - http://macroform.bandcamp.com/
macroform-robot_dity - Paul Shuler (Macroform)
paulshuler@gmail.com - http://macroform.bandcamp.com/
macroform-the_simplicity - Paul Shuler (Macroform)
paulshuler@gmail.com - http://macroform.bandcamp.com/
manolo_camp-morning_coffee - Manolo Camp
beatbastard@gmx.net - http://ccmixter.org/people/ManoloCamp
reno_project-system - Reno Project
renoproject@hotmail.com - http://www.jamendo.com/en/album/23661

View File

@@ -1,15 +1,15 @@
\subsection{Introduction}
==== Security Notes with Asterisk ====
PLEASE READ THE FOLLOWING IMPORTANT SECURITY RELATED INFORMATION.
PLEASE READ THE FOLLOWING IMPORTANT SECURITY RELATED INFORMATION.
IMPROPER CONFIGURATION OF ASTERISK COULD ALLOW UNAUTHORIZED USE OF YOUR
FACILITIES, POTENTIALLY INCURRING SUBSTANTIAL CHARGES.
Asterisk security involves both network security (encryption, authentication)
as well as dialplan security (authorization - who can access services in
as well as dialplan security (authorization - who can access services in
your pbx). If you are setting up Asterisk in production use, please make
sure you understand the issues involved.
\subsection{Network Security}
* NETWORK SECURITY
If you install Asterisk and use the "make samples" command to install
a demonstration configuration, Asterisk will open a few ports for accepting
@@ -28,7 +28,7 @@ The IAX2 protocol supports strong RSA key authentication as well as
AES encryption of voice and signalling. The SIP channel does not
support encryption in this version of Asterisk.
\subsection{Dialplan Security}
* DIALPLAN SECURITY
First and foremost remember this:
@@ -37,7 +37,7 @@ INCOMING CONNECTIONS.
You should consider that if any channel, incoming line, etc can enter an
extension context that it has the capability of accessing any extension
within that context.
within that context.
Therefore, you should NOT allow access to outgoing or toll services in
contexts that are accessible (especially without a password) from incoming
@@ -46,35 +46,28 @@ stations within you network. In particular, never ever put outgoing toll
services in the "default" context. To make things easier, you can include
the "default" context within other private contexts by using:
\begin{astlisting}
\begin{verbatim}
include => default
\end{verbatim}
\end{astlisting}
in the appropriate section. A well designed PBX might look like this:
\begin{astlisting}
\begin{verbatim}
[longdistance]
exten => _91NXXNXXXXXX,1,Dial(DAHDI/g2/${EXTEN:1})
exten => _91NXXNXXXXXX,1,Dial(Zap/g2/${EXTEN:1})
include => local
[local]
exten => _9NXXNXXX,1,Dial(DAHDI/g2/${EXTEN:1})
exten => _9NXXNXXX,1,Dial(Zap/g2/${EXTEN:1})
include => default
[default]
exten => 6123,Dial(DAHDI/1)
\end{verbatim}
\end{astlisting}
exten => 6123,Dial(Zap/1)
DON'T FORGET TO TAKE THE DEMO CONTEXT OUT OF YOUR DEFAULT CONTEXT. There
isn't really a security reason, it just will keep people from wanting to
isn't really a security reason, it just will keep people from wanting to
play with your Asterisk setup remotely.
\subsection{Log Security}
* LOG SECURITY
Please note that the Asterisk log files, as well as information printed to the
Asterisk CLI, may contain sensitive information such as passwords and call
Asterisk CLI, may contain sensitive information such as passwords and call
history. Keep this in mind when providing access to these resources.

View File

@@ -1,218 +0,0 @@
=========================================================
===
=== Information for upgrading from Asterisk 1.0 to 1.2
===
=== This file documents all the changes that MUST be taken
=== into account when upgrading between the Asterisk
=== versions listed below. These changes may require that
=== you modify your configuration files, dialplan or (in
=== some cases) source code if you have your own Asterisk
=== modules or patches. These files also includes advance
=== notice of any functionality that has been marked as
=== 'deprecated' and may be removed in a future release,
=== along with the suggested replacement functionality.
===
=========================================================
Compiling:
* The Asterisk 1.2 source code now uses C language features
supported only by 'modern' C compilers. Generally, this means GCC
version 3.0 or higher, although some GCC 2.96 releases will also
work. Some non-GCC compilers that support C99 and the common GCC
extensions (including anonymous structures and unions) will also
work. All releases of GCC 2.95 do _not_ have the requisite feature
support; systems using that compiler will need to be upgraded to
a more recent compiler release.
Dialplan Expressions:
* The dialplan expression parser (which handles $[ ... ] constructs)
has gone through a major upgrade, but has one incompatible change:
spaces are no longer required around expression operators, including
string comparisons. However, you can now use quoting to keep strings
together for comparison. For more details, please read the
doc/README.variables file, and check over your dialplan for possible
problems.
Agents:
* The default for ackcall has been changed to "no" instead of "yes"
because of a bug which caused the "yes" behavior to generally act like
"no". You may need to adjust the value if your agents behave
differently than you expect with respect to acknowledgement.
* The AgentCallBackLogin application now requires a second '|' before
specifying an extension@context. This is to distinguish the options
string from the extension, so that they do not conflict. See
'show application AgentCallbackLogin' for more details.
Parking:
* Parking behavior has changed slightly; when a parked call times out,
Asterisk will attempt to deliver the call back to the extension that
parked it, rather than the 's' extension. If that extension is busy
or unavailable, the parked call will be lost.
Dialing:
* The Caller*ID of the outbound leg is now the extension that was
called, rather than the Caller*ID of the inbound leg of the call. The
"o" flag for Dial can be used to restore the original behavior if
desired. Note that if you are looking for the originating callerid
from the manager event, there is a new manager event "Dial" which
provides the source and destination channels and callerid.
IAX:
* The naming convention for IAX channels has changed in two ways:
1. The call number follows a "-" rather than a "/" character.
2. The name of the channel has been simplified to IAX2/peer-callno,
rather than IAX2/peer@peer-callno or even IAX2/peer@peer/callno.
SIP:
* The global option "port" in 1.0.X that is used to set which port to
bind to has been changed to "bindport" to be more consistent with
the other channel drivers and to avoid confusion with the "port"
option for users/peers.
* The "Registry" event now uses "Username" rather than "User" for
consistency with IAX.
Applications:
* With the addition of dialplan functions (which operate similarly
to variables), the SetVar application has been renamed to Set.
* The CallerPres application has been removed. Use SetCallerPres
instead. It accepts both numeric and symbolic names.
* The applications GetGroupCount, GetGroupMatchCount, SetGroup, and
CheckGroup have been deprecated in favor of functions. Here is a
table of their replacements:
GetGroupCount([groupname][@category] GROUP_COUNT([groupname][@category]) Set(GROUPCOUNT=${GROUP_COUNT()})
GroupMatchCount(groupmatch[@category]) GROUP_MATCH_COUNT(groupmatch[@category]) Set(GROUPCOUNT=${GROUP_MATCH_COUNT(SIP/.*)})
SetGroup(groupname[@category]) GROUP([category])=groupname Set(GROUP()=test)
CheckGroup(max[@category]) N/A GotoIf($[ ${GROUP_COUNT()} > 5 ]?103)
Note that CheckGroup does not have a direct replacement. There is
also a new function called GROUP_LIST() which will return a space
separated list of all of the groups set on a channel. The GROUP()
function can also return the name of the group set on a channel when
used in a read environment.
* The applications DBGet and DBPut have been deprecated in favor of
functions. Here is a table of their replacements:
DBGet(foo=family/key) Set(foo=${DB(family/key)})
DBPut(family/key=${foo}) Set(DB(family/key)=${foo})
* The application SetLanguage has been deprecated in favor of the
function LANGUAGE().
SetLanguage(fr) Set(LANGUAGE()=fr)
The LANGUAGE function can also return the currently set language:
Set(MYLANG=${LANGUAGE()})
* The applications AbsoluteTimeout, DigitTimeout, and ResponseTimeout
have been deprecated in favor of the function TIMEOUT(timeouttype):
AbsoluteTimeout(300) Set(TIMEOUT(absolute)=300)
DigitTimeout(15) Set(TIMEOUT(digit)=15)
ResponseTimeout(15) Set(TIMEOUT(response)=15)
The TIMEOUT() function can also return the currently set timeouts:
Set(DTIMEOUT=${TIMEOUT(digit)})
* The applications SetCIDName, SetCIDNum, and SetRDNIS have been
deprecated in favor of the CALLERID(datatype) function:
SetCIDName(Joe Cool) Set(CALLERID(name)=Joe Cool)
SetCIDNum(2025551212) Set(CALLERID(number)=2025551212)
SetRDNIS(2024561414) Set(CALLERID(RDNIS)=2024561414)
* The application Record now uses the period to separate the filename
from the format, rather than the colon.
* The application VoiceMail now supports a 'temporary' greeting for each
mailbox. This greeting can be recorded by using option 4 in the
'mailbox options' menu, and 'change your password' option has been
moved to option 5.
* The application VoiceMailMain now only matches the 'default' context if
none is specified in the arguments. (This was the previously
documented behavior, however, we didn't follow that behavior.) The old
behavior can be restored by setting searchcontexts=yes in voicemail.conf.
Queues:
* A queue is now considered empty not only if there are no members but if
none of the members are available (e.g. agents not logged on). To
restore the original behavior, use "leavewhenempty=strict" or
"joinwhenempty=strict" instead of "=yes" for those options.
* It is now possible to use multi-digit extensions in the exit context
for a queue (although you should not have overlapping extensions,
as there is no digit timeout). This means that the EXITWITHKEY event
in queue_log can now contain a key field with more than a single
character in it.
Extensions:
* By default, there is a new option called "autofallthrough" in
extensions.conf that is set to yes. Asterisk 1.0 (and earlier)
behavior was to wait for an extension to be dialed after there were no
more extensions to execute. "autofallthrough" changes this behavior
so that the call will immediately be terminated with BUSY,
CONGESTION, or HANGUP based on Asterisk's best guess. If you are
writing an extension for IVR, you must use the WaitExten application
if "autofallthrough" is set to yes.
AGI:
* AGI scripts did not always get SIGHUP at the end, previously. That
behavior has been fixed. If you do not want your script to terminate
at the end of AGI being called (e.g. on a hangup) then set SIGHUP to
be ignored within your application.
* CallerID is reported with agi_callerid and agi_calleridname instead
of a single parameter holding both.
Music On Hold:
* The preferred format for musiconhold.conf has changed; please see the
sample configuration file for the new format. The existing format
is still supported but will generate warnings when the module is loaded.
chan_modem:
* All the chan_modem channel drivers (aopen, bestdata and i4l) are deprecated
in this release, and will be removed in the next major Asterisk release.
Please migrate to chan_misdn for ISDN interfaces; there is no upgrade
path for aopen and bestdata modem users.
MeetMe:
* The conference application now allows users to increase/decrease their
speaking volume and listening volume (independently of each other and
other users); the 'admin' and 'user' menus have changed, and new sound
files are included with this release. However, if a user calling in
over a Zaptel channel that does NOT have hardware DTMF detection
increases their speaking volume, it is likely they will no longer be
able to enter/exit the menu or make any further adjustments, as the
software DTMF detector will not be able to recognize the DTMF coming
from their device.
GetVar Manager Action:
* Previously, the behavior of the GetVar manager action reported the value
of a variable in the following manner:
> name: value
This has been changed to a manner similar to the SetVar action and is now
> Variable: name
> Value: value

View File

@@ -1,498 +0,0 @@
=========================================================
===
=== Information for upgrading from Asterisk 1.2 to 1.4
===
=== These files document all the changes that MUST be taken
=== into account when upgrading between the Asterisk
=== versions listed below. These changes may require that
=== you modify your configuration files, dialplan or (in
=== some cases) source code if you have your own Asterisk
=== modules or patches. These files also includes advance
=== notice of any functionality that has been marked as
=== 'deprecated' and may be removed in a future release,
=== along with the suggested replacement functionality.
===
=== UPGRADE-1.2.txt -- Upgrade info for 1.0 to 1.2
===
=========================================================
Build Process (configure script):
Asterisk now uses an autoconf-generated configuration script to learn how it
should build itself for your system. As it is a standard script, running:
$ ./configure --help
will show you all the options available. This script can be used to tell the
build process what libraries you have on your system (if it cannot find them
automatically), which libraries you wish to have ignored even though they may
be present, etc.
You must run the configure script before Asterisk will build, although it will
attempt to automatically run it for you with no options specified; for most
users, that will result in a similar build to what they would have had before
the configure script was added to the build process (except for having to run
'make' again after the configure script is run). Note that the configure script
does NOT need to be re-run just to rebuild Asterisk; you only need to re-run it
when your system configuration changes or you wish to build Asterisk with
different options.
Build Process (module selection):
The Asterisk source tree now includes a basic module selection and build option
selection tool called 'menuselect'. Run 'make menuselect' to make your choices.
In this tool, you can disable building of modules that you don't care about,
turn on/off global options for the build and see which modules will not
(and cannot) be built because your system does not have the required external
dependencies installed.
The resulting file from menuselect is called 'menuselect.makeopts'. Note that
the resulting menuselect.makeopts file generally contains which modules *not*
to build. The modules listed in this file indicate which modules have unmet
dependencies, a present conflict, or have been disabled by the user in the
menuselect interface. Compiler Flags can also be set in the menuselect
interface. In this case, the resulting file contains which CFLAGS are in use,
not which ones are not in use.
If you would like to save your choices and have them applied against all
builds, the file can be copied to '~/.asterisk.makeopts' or
'/etc/asterisk.makeopts'.
Build Process (Makefile targets):
The 'valgrind' and 'dont-optimize' targets have been removed; their functionality
is available by enabling the DONT_OPTIMIZE setting in the 'Compiler Flags' menu
in the menuselect tool.
It is now possible to run most make targets against a single subdirectory; from
the top level directory, for example, 'make channels' will run 'make all' in the
'channels' subdirectory. This also is true for 'clean', 'distclean' and 'depend'.
Sound (prompt) and Music On Hold files:
Beginning with Asterisk 1.4, the sound files and music on hold files supplied for
use with Asterisk have been replaced with new versions produced from high quality
master recordings, and are available in three languages (English, French and
Spanish) and in five formats (WAV (uncompressed), mu-Law, a-Law, GSM and G.729).
In addition, the music on hold files provided by opsound.org Music are now available
in the same five formats, but no longer available in MP3 format.
The Asterisk 1.4 tarball packages will only include English prompts in GSM format,
(as were supplied with previous releases) and the opsound.org MOH files in WAV format.
All of the other variations can be installed by running 'make menuselect' and
selecting the packages you wish to install; when you run 'make install', those
packages will be downloaded and installed along with the standard files included
in the tarball.
If for some reason you expect to not have Internet access at the time you will be
running 'make install', you can make your package selections using menuselect and
then run 'make sounds' to download (only) the sound packages; this will leave the
sound packages in the 'sounds' subdirectory to be used later during installation.
WARNING: Asterisk 1.4 supports a new layout for sound files in multiple languages;
instead of the alternate-language files being stored in subdirectories underneath
the existing files (for French, that would be digits/fr, letters/fr, phonetic/fr,
etc.) the new layout creates one directory under /var/lib/asterisk/sounds for the
language itself, then places all the sound files for that language under that
directory and its subdirectories. This is the layout that will be created if you
select non-English languages to be installed via menuselect, HOWEVER Asterisk does
not default to this layout and will not find the files in the places it expects them
to be. If you wish to use this layout, make sure you put 'languageprefix=yes' in your
/etc/asterisk/asterisk.conf file, so that Asterisk will know how the files were
installed.
PBX Core:
* The (very old and undocumented) ability to use BYEXTENSION for dialing
instead of ${EXTEN} has been removed.
* Builtin (res_features) transfer functionality attempts to use the context
defined in TRANSFER_CONTEXT variable of the transferer channel first. If
not set, it uses the transferee variable. If not set in any channel, it will
attempt to use the last non macro context. If not possible, it will default
to the current context.
* The autofallthrough setting introduced in Asterisk 1.2 now defaults to 'yes';
if your dialplan relies on the ability to 'run off the end' of an extension
and wait for a new extension without using WaitExten() to accomplish that,
you will need set autofallthrough to 'no' in your extensions.conf file.
Command Line Interface:
* 'show channels concise', designed to be used by applications that will parse
its output, previously used ':' characters to separate fields. However, some
of those fields can easily contain that character, making the output not
parseable. The delimiter has been changed to '!'.
Applications:
* In previous Asterisk releases, many applications would jump to priority n+101
to indicate some kind of status or error condition. This functionality was
marked deprecated in Asterisk 1.2. An option to disable it was provided with
the default value set to 'on'. The default value for the global priority
jumping option is now 'off'.
* The applications Cut, Sort, DBGet, DBPut, SetCIDNum, SetCIDName, SetRDNIS,
AbsoluteTimeout, DigitTimeout, ResponseTimeout, SetLanguage, GetGroupCount,
and GetGroupMatchCount were all deprecated in version 1.2, and therefore have
been removed in this version. You should use the equivalent dialplan
function in places where you have previously used one of these applications.
* The application SetGlobalVar has been deprecated. You should replace uses
of this application with the following combination of Set and GLOBAL():
Set(GLOBAL(name)=value). You may also access global variables exclusively by
using the GLOBAL() dialplan function, instead of relying on variable
interpolation falling back to globals when no channel variable is set.
* The application SetVar has been renamed to Set. The syntax SetVar was marked
deprecated in version 1.2 and is no longer recognized in this version. The
use of Set with multiple argument pairs has also been deprecated. Please
separate each name/value pair into its own dialplan line.
* app_read has been updated to use the newer options codes, using "skip" or
"noanswer" will not work. Use s or n. Also there is a new feature i, for
using indication tones, so typing in skip would give you unexpected results.
* OSPAuth is added to authenticate OSP tokens in in_bound call setup messages.
* The CONNECT event in the queue_log from app_queue now has a second field
in addition to the holdtime field. It contains the unique ID of the
queue member channel that is taking the call. This is useful when trying
to link recording filenames back to a particular call from the queue.
* The old/current behavior of app_queue has a serial type behavior
in that the queue will make all waiting callers wait in the queue
even if there is more than one available member ready to take
calls until the head caller is connected with the member they
were trying to get to. The next waiting caller in line then
becomes the head caller, and they are then connected with the
next available member and all available members and waiting callers
waits while this happens. This cycle continues until there are
no more available members or waiting callers, whichever comes first.
The new behavior, enabled by setting autofill=yes in queues.conf
either at the [general] level to default for all queues or
to set on a per-queue level, makes sure that when the waiting
callers are connecting with available members in a parallel fashion
until there are no more available members or no more waiting callers,
whichever comes first. This is probably more along the lines of how
one would expect a queue should work and in most cases, you will want
to enable this new behavior. If you do not specify or comment out this
option, it will default to "no" to keep backward compatability with the old
behavior.
* Queues depend on the channel driver reporting the proper state
for each member of the queue. To get proper signalling on
queue members that use the SIP channel driver, you need to
enable a call limit (could be set to a high value so it
is not put into action) and also make sure that both inbound
and outbound calls are accounted for.
Example:
[general]
limitonpeer = yes
[peername]
type=friend
call-limit=10
* The app_queue application now has the ability to use MixMonitor to
record conversations queue members are having with queue callers. Please
see configs/queues.conf.sample for more information on this option.
* The app_queue application strategy called 'roundrobin' has been deprecated
for this release. Users are encouraged to use 'rrmemory' instead, since it
provides more 'true' round-robin call delivery. For the Asterisk 1.6 release,
'rrmemory' will be renamed 'roundrobin'.
* The app_queue application option called 'monitor-join' has been deprecated
for this release. Users are encouraged to use 'monitor-type=mixmonitor' instead,
since it provides the same functionality but is not dependent on soxmix or some
other external program in order to mix the audio.
* app_meetme: The 'm' option (monitor) is renamed to 'l' (listen only), and
the 'm' option now provides the functionality of "initially muted".
In practice, most existing dialplans using the 'm' flag should not notice
any difference, unless the keypad menu is enabled, allowing the user
to unmute themsleves.
* ast_play_and_record would attempt to cancel the recording if a DTMF
'0' was received. This behavior was not documented in most of the
applications that used ast_play_and_record and the return codes from
ast_play_and_record weren't checked for properly.
ast_play_and_record has been changed so that '0' no longer cancels a
recording. If you want to allow DTMF digits to cancel an
in-progress recording use ast_play_and_record_full which allows you
to specify which DTMF digits can be used to accept a recording and
which digits can be used to cancel a recording.
* ast_app_messagecount has been renamed to ast_app_inboxcount. There is now a
new ast_app_messagecount function which takes a single context/mailbox/folder
mailbox specification and returns the message count for that folder only.
This addresses the deficiency of not being able to count the number of
messages in folders other than INBOX and Old.
* The exit behavior of the AGI applications has changed. Previously, when
a connection to an AGI server failed, the application would cause the channel
to immediately stop dialplan execution and hangup. Now, the only time that
the AGI applications will cause the channel to stop dialplan execution is
when the channel itself requests hangup. The AGI applications now set an
AGISTATUS variable which will allow you to find out whether running the AGI
was successful or not.
Previously, there was no way to handle the case where Asterisk was unable to
locally execute an AGI script for some reason. In this case, dialplan
execution will continue as it did before, but the AGISTATUS variable will be
set to "FAILURE".
A locally executed AGI script can now exit with a non-zero exit code and this
failure will be detected by Asterisk. If an AGI script exits with a non-zero
exit code, the AGISTATUS variable will be set to "FAILURE" as opposed to
"SUCCESS".
* app_voicemail: The ODBC_STORAGE capability now requires the extended table format
previously used only by EXTENDED_ODBC_STORAGE. This means that you will need to update
your table format using the schema provided in doc/odbcstorage.txt
* app_waitforsilence: Fixes have been made to this application which changes the
default behavior with how quickly it returns. You can maintain "old-style" behavior
with the addition/use of a third "timeout" parameter.
Please consult the application documentation and make changes to your dialplan
if appropriate.
Manager:
* After executing the 'status' manager action, the "Status" manager events
included the header "CallerID:" which was actually only the CallerID number,
and not the full CallerID string. This header has been renamed to
"CallerIDNum". For compatibility purposes, the CallerID parameter will remain
until after the release of 1.4, when it will be removed. Please use the time
during the 1.4 release to make this transition.
* The AgentConnect event now has an additional field called "BridgedChannel"
which contains the unique ID of the queue member channel that is taking the
call. This is useful when trying to link recording filenames back to
a particular call from the queue.
* app_userevent has been modified to always send Event: UserEvent with the
additional header UserEvent: <userspec>. Also, the Channel and UniqueID
headers are not automatically sent, unless you specify them as separate
arguments. Please see the application help for the new syntax.
* app_meetme: Mute and Unmute events are now reported via the Manager API.
Native Manager API commands MeetMeMute and MeetMeUnmute are provided, which
are easier to use than "Action Command:". The MeetMeStopTalking event has
also been deprecated in favor of the already existing MeetmeTalking event
with a "Status" of "on" or "off" added.
* OriginateFailure and OriginateSuccess events were replaced by event
OriginateResponse with a header named "Response" to indicate success or
failure
Variables:
* The builtin variables ${CALLERID}, ${CALLERIDNAME}, ${CALLERIDNUM},
${CALLERANI}, ${DNID}, ${RDNIS}, ${DATETIME}, ${TIMESTAMP}, ${ACCOUNTCODE},
and ${LANGUAGE} have all been deprecated in favor of their related dialplan
functions. You are encouraged to move towards the associated dialplan
function, as these variables will be removed in a future release.
* The CDR-CSV variables uniqueid, userfield, and basing time on GMT are now
adjustable from cdr.conf, instead of recompiling.
* OSP applications exports several new variables, ${OSPINHANDLE},
${OSPOUTHANDLE}, ${OSPINTOKEN}, ${OSPOUTTOKEN}, ${OSPCALLING},
${OSPINTIMELIMIT}, and ${OSPOUTTIMELIMIT}
* Builtin transfer functionality sets the variable ${TRANSFERERNAME} in the new
created channel. This variables holds the channel name of the transferer.
* The dial plan variable PRI_CAUSE will be removed from future versions
of Asterisk.
It is replaced by adding a cause value to the hangup() application.
Functions:
* The function ${CHECK_MD5()} has been deprecated in favor of using an
expression: $[${MD5(<string>)} = ${saved_md5}].
* The 'builtin' functions that used to be combined in pbx_functions.so are
now built as separate modules. If you are not using 'autoload=yes' in your
modules.conf file then you will need to explicitly load the modules that
contain the functions you want to use.
* The ENUMLOOKUP() function with the 'c' option (for counting the number of
records), but the lookup fails to match any records, the returned value will
now be "0" instead of blank.
* The REALTIME() function is now available in version 1.4 and app_realtime has
been deprecated in favor of the new function. app_realtime will be removed
completely with the version 1.6 release so please take the time between
releases to make any necessary changes
* The QUEUEAGENTCOUNT() function has been deprecated in favor of
QUEUE_MEMBER_COUNT().
The IAX2 channel:
* It is possible that previous configurations depended on the order in which
peers and users were specified in iax.conf for forcing the order in which
chan_iax2 matched against them. This behavior is going away and is considered
deprecated in this version. Avoid having ambiguous peer and user entries and
to make things easy on yourself, always set the "username" option for users
so that the remote end can match on that exactly instead of trying to infer
which user you want based on host.
If you would like to go ahead and use the new behavior which doesn't use the
order in the config file to influence matching order, then change the
MAX_PEER_BUCKETS define in chan_iax2.c to a value greater than one. An
example is provided there. By changing this, you will get *much* better
performance on systems that do a lot of peer and user lookups as they will be
stored in memory in a much more efficient manner.
* The "mailboxdetail" option has been deprecated. Previously, if this option
was not enabled, the 2 byte MSGCOUNT information element would be set to all
1's to indicate there there is some number of messages waiting. With this
option enabled, the number of new messages were placed in one byte and the
number of old messages are placed in the other. This is now the default
(and the only) behavior.
The SIP channel:
* The "incominglimit" setting is replaced by the "call-limit" setting in
sip.conf.
* OSP support code is removed from SIP channel to OSP applications. ospauth
option in sip.conf is removed to osp.conf as authpolicy. allowguest option
in sip.conf cannot be set as osp anymore.
* The Asterisk RTP stack has been changed in regards to RFC2833 reception
and transmission. Packets will now be sent with proper duration instead of all
at once. If you are receiving calls from a pre-1.4 Asterisk installation you
will want to turn on the rfc2833compensate option. Without this option your
DTMF reception may act poorly.
* The $SIPUSERAGENT dialplan variable is deprecated and will be removed
in coming versions of Asterisk. Please use the dialplan function
SIPCHANINFO(useragent) instead.
* The ALERT_INFO dialplan variable is deprecated and will be removed
in coming versions of Asterisk. Please use the dialplan application
sipaddheader() to add the "Alert-Info" header to the outbound invite.
* The "canreinvite" option has changed. canreinvite=yes used to disable
re-invites if you had NAT=yes. In 1.4, you need to set canreinvite=nonat
to disable re-invites when NAT=yes. This is propably what you want.
The settings are now: "yes", "no", "nonat", "update". Please consult
sip.conf.sample for detailed information.
The Zap channel:
* Support for MFC/R2 has been removed, as it has not been functional for some
time and it has no maintainer.
The Agent channel:
* Callback mode (AgentCallbackLogin) is now deprecated, since the entire function
it provided can be done using dialplan logic, without requiring additional
channel and module locks (which frequently caused deadlocks). An example of
how to do this using AEL dialplan is in doc/queues-with-callback-members.txt.
The G726-32 codec:
* It has been determined that previous versions of Asterisk used the wrong codeword
packing order for G726-32 data. This version supports both available packing orders,
and can transcode between them. It also now selects the proper order when
negotiating with a SIP peer based on the codec name supplied in the SDP. However,
there are existing devices that improperly request one order and then use another;
Sipura and Grandstream ATAs are known to do this, and there may be others. To
be able to continue to use these devices with this version of Asterisk and the
G726-32 codec, a configuration parameter called 'g726nonstandard' has been added
to sip.conf, so that Asterisk can use the packing order expected by the device (even
though it requested a different order). In addition, the internal format number for
G726-32 has been changed, and the old number is now assigned to AAL2-G726-32. The
result of this is that this version of Asterisk will be able to interoperate over
IAX2 with older versions of Asterisk, as long as this version is told to allow
'g726aal2' instead of 'g726' as the codec for the call.
Installation:
* On BSD systems, the installation directories have changed to more "FreeBSDish"
directories. On startup, Asterisk will look for the main configuration in
/usr/local/etc/asterisk/asterisk.conf
If you have an old installation, you might want to remove the binaries and
move the configuration files to the new locations. The following directories
are now default:
ASTLIBDIR /usr/local/lib/asterisk
ASTVARLIBDIR /usr/local/share/asterisk
ASTETCDIR /usr/local/etc/asterisk
ASTBINDIR /usr/local/bin/asterisk
ASTSBINDIR /usr/local/sbin/asterisk
Music on Hold:
* The music on hold handling has been changed in some significant ways in hopes
to make it work in a way that is much less confusing to users. Behavior will
not change if the same configuration is used from older versions of Asterisk.
However, there are some new configuration options that will make things work
in a way that makes more sense.
Previously, many of the channel drivers had an option called "musicclass" or
something similar. This option set what music on hold class this channel
would *hear* when put on hold. Some people expected (with good reason) that
this option was to configure what music on hold class to play when putting
the bridged channel on hold. This option has now been deprecated.
Two new music on hold related configuration options for channel drivers have
been introduced. Some channel drivers support both options, some just one,
and some support neither of them. Check the sample configuration files to see
which options apply to which channel driver.
The "mohsuggest" option specifies which music on hold class to suggest to the
bridged channel when putting them on hold. The only way that this class can
be overridden is if the bridged channel has a specific music class set that
was done in the dialplan using Set(CHANNEL(musicclass)=something).
The "mohinterpret" option is similar to the old "musicclass" option. It
specifies which music on hold class this channel would like to listen to when
put on hold. This music class is only effective if this channel has no music
class set on it from the dialplan and the bridged channel putting this one on
hold had no "mohsuggest" setting.
The IAX2 and Zap channel drivers have an additional feature for the
"mohinterpret" option. If this option is set to "passthrough", then these
channel drivers will pass through the HOLD message in signalling instead of
starting music on hold on the channel. An example for how this would be
useful is in an enterprise network of Asterisk servers. When one phone on one
server puts a phone on a different server on hold, the remote server will be
responsible for playing the hold music to its local phone that was put on
hold instead of the far end server across the network playing the music.
CDR Records:
* The behavior of the "clid" field of the CDR has always been that it will
contain the callerid ANI if it is set, or the callerid number if ANI was not
set. When using the "callerid" option for various channel drivers, some
would set ANI and some would not. This has been cleared up so that all
channel drivers set ANI. If you would like to change the callerid number
on the channel from the dialplan and have that change also show up in the
CDR, then you *must* set CALLERID(ANI) as well as CALLERID(num).
API:
* There are some API functions that were not previously prefixed with the 'ast_'
prefix but now are; these include the ADSI, ODBC and AGI interfaces. If you
have a module that uses the services provided by res_adsi, res_odbc, or
res_agi, you will need to add ast_ prefixes to the functions that you call
from those modules.
Formats:
* format_wav: The GAIN preprocessor definition has been changed from 2 to 0
in Asterisk 1.4. This change was made in response to user complaints of
choppiness or the clipping of loud signal peaks. The GAIN preprocessor
definition will be retained in Asterisk 1.4, but will be removed in a
future release. The use of GAIN for the increasing of voicemail message
volume should use the 'volgain' option in voicemail.conf

View File

@@ -1,271 +0,0 @@
=========================================================
===
=== Information for upgrading from Asterisk 1.4 to 1.6
===
=== These files document all the changes that MUST be taken
=== into account when upgrading between the Asterisk
=== versions listed below. These changes may require that
=== you modify your configuration files, dialplan or (in
=== some cases) source code if you have your own Asterisk
=== modules or patches. These files also includes advance
=== notice of any functionality that has been marked as
=== 'deprecated' and may be removed in a future release,
=== along with the suggested replacement functionality.
===
=== UPGRADE-1.2.txt -- Upgrade info for 1.0 to 1.2
=== UPGRADE-1.4.txt -- Upgrade info for 1.2 to 1.4
===
=========================================================
AEL:
* Macros are now implemented underneath with the Gosub() application.
Heaven Help You if you wrote code depending on any aspect of this!
Previous to 1.6, macros were implemented with the Macro() app, which
provided a nice feature of auto-returning. The compiler will do its
best to insert a Return() app call at the end of your macro if you did
not include it, but really, you should make sure that all execution
paths within your macros end in "return;".
* The conf2ael program is 'introduced' in this release; it is in a rather
crude state, but deemed useful for making a first pass at converting
extensions.conf code into AEL. More intelligence will come with time.
Core:
* The 'languageprefix' option in asterisk.conf is now deprecated, and
the default sound file layout for non-English sounds is the 'new
style' layout introduced in Asterisk 1.4 (and used by the automatic
sound file installer in the Makefile).
* The ast_expr2 stuff has been modified to handle floating-point numbers.
Numbers of the format D.D are now acceptable input for the expr parser,
Where D is a string of base-10 digits. All math is now done in "long double",
if it is available on your compiler/architecture. This was half-way between
a bug-fix (because the MATH func returns fp by default), and an enhancement.
Also, for those counting on, or needing, integer operations, a series of
'functions' were also added to the expr language, to allow several styles
of rounding/truncation, along with a set of common floating point operations,
like sin, cos, tan, log, pow, etc. The ability to call external functions
like CDR(), etc. was also added, without having to use the ${...} notation.
* The delimiter passed to applications has been changed to the comma (','), as
that is what people are used to using within extensions.conf. If you are
using realtime extensions, you will need to translate your existing dialplan
to use this separator. To use a literal comma, you need merely to escape it
with a backslash ('\'). Another possible side effect is that you may need to
remove the obscene level of backslashing that was necessary for the dialplan
to work correctly in 1.4 and previous versions. This should make writing
dialplans less painful in the future, albeit with the pain of a one-time
conversion. If you would like to avoid this conversion immediately, set
pbx_realtime=1.4 in the [compat] section of asterisk.conf. After
transitioning, set pbx_realtime=1.6 in the same section.
* For the same purpose as above, you may set res_agi=1.4 in the [compat]
section of asterisk.conf to continue to use the '|' delimiter in the EXEC
arguments of AGI applications. After converting to use the ',' delimiter,
change this option to res_agi=1.6.
* As a side effect of the application delimiter change, many places that used
to need quotes in order to get the proper meaning are no longer required.
You now only need to quote strings in configuration files if you literally
want quotation marks within a string.
* Any applications run that contain the pipe symbol but not a comma symbol will
get a warning printed to the effect that the application delimiter has changed.
However, there are legitimate reasons why this might be useful in certain
situations, so this warning can be turned off with the dontwarn option in
asterisk.conf.
* The logger.conf option 'rotatetimestamp' has been deprecated in favor of
'rotatestrategy'. This new option supports a 'rotate' strategy that more
closely mimics the system logger in terms of file rotation.
* The concise versions of various CLI commands are now deprecated. We recommend
using the manager interface (AMI) for application integration with Asterisk.
Voicemail:
* The voicemail configuration values 'maxmessage' and 'minmessage' have
been changed to 'maxsecs' and 'minsecs' to clarify their purpose and
to make them more distinguishable from 'maxmsgs', which sets folder
size. The old variables will continue to work in this version, albeit
with a deprecation warning.
* If you use any interface for modifying voicemail aside from the built in
dialplan applications, then the option "pollmailboxes" *must* be set in
voicemail.conf for message waiting indication (MWI) to work properly. This
is because Voicemail notification is now event based instead of polling
based. The channel drivers are no longer responsible for constantly manually
checking mailboxes for changes so that they can send MWI information to users.
Examples of situations that would require this option are web interfaces to
voicemail or an email client in the case of using IMAP storage.
Applications:
* ChanIsAvail() now has a 't' option, which allows the specified device
to be queried for state without consulting the channel drivers. This
performs mostly a 'ChanExists' sort of function.
* ChannelRedirect() will not terminate the channel that fails to do a
channelredirect as it has done previously. Instead CHANNELREDIRECT_STATUS
will reflect if the attempt was successful of not.
* SetCallerPres() has been replaced with the CALLERPRES() dialplan function
and is now deprecated.
* DISA()'s fifth argument is now an options argument. If you have previously
used 'NOANSWER' in this argument, you'll need to convert that to the new
option 'n'.
* Macro() is now deprecated. If you need subroutines, you should use the
Gosub()/Return() applications. To replace MacroExclusive(), we have
introduced dialplan functions LOCK(), TRYLOCK(), and UNLOCK(). You may use
these functions in any location where you desire to ensure that only one
channel is executing that path at any one time. The Macro() applications
are deprecated for performance reasons. However, since Macro() has been
around for a long time and so many dialplans depend heavily on it, for the
sake of backwards compatibility it will not be removed . It is also worth
noting that using both Macro() and GoSub() at the same time is _heavily_
discouraged.
* Read() now sets a READSTATUS variable on exit. It does NOT automatically
return -1 (and hangup) anymore on error. If you want to hangup on error,
you need to do so explicitly in your dialplan.
* Privacy() no longer uses privacy.conf, so any options must be specified
directly in the application arguments.
* MusicOnHold application now has duration parameter which allows specifying
timeout in seconds.
* WaitMusicOnHold application is now deprecated in favor of extended MusicOnHold.
* SetMusicOnHold is now deprecated. You should use Set(CHANNEL(musicclass)=...)
instead.
* The arguments in ExecIf changed a bit, to be more like other applications.
The syntax is now ExecIf(<cond>?appiftrue(args):appiffalse(args)).
* The behavior of the Set application now depends upon a compatibility option,
set in asterisk.conf. To use the old 1.4 behavior, which allowed Set to take
multiple key/value pairs, set app_set=1.4 in [compat] in asterisk.conf. To
use the new behavior, which permits variables to be set with embedded commas,
set app_set=1.6 in [compat] in asterisk.conf. Note that you can have both
behaviors at the same time, if you switch to using MSet if you want the old
behavior.
Dialplan Functions:
* QUEUE_MEMBER_COUNT() has been deprecated in favor of the QUEUE_MEMBER() function. For
more information, issue a "show function QUEUE_MEMBER" from the CLI.
CDR:
* The cdr_sqlite module has been marked as deprecated in favor of
cdr_sqlite3_custom. It will potentially be removed from the tree
after Asterisk 1.6 is released.
* The cdr_odbc module now uses res_odbc to manage its connections. The
username and password parameters in cdr_odbc.conf, therefore, are no
longer used. The dsn parameter now points to an entry in res_odbc.conf.
* The uniqueid field in the core Asterisk structure has been changed from a
maximum 31 character field to a 149 character field, to account for all
possible values the systemname prefix could be. In the past, if the
systemname was too long, the uniqueid would have been truncated.
* The cdr_tds module now supports all versions of FreeTDS that contain
the db-lib frontend. It will also now log the userfield variable if
the target database table contains a column for it.
Formats:
* format_wav: The GAIN preprocessor definition and source code that used it
is removed. This change was made in response to user complaints of
choppiness or the clipping of loud signal peaks. To increase the volume
of voicemail messages, use the 'volgain' option in voicemail.conf
Channel Drivers:
* SIP: a small upgrade to support the "Record" button on the SNOM360,
which sends a sip INFO message with a "Record: on" or "Record: off"
header. If Asterisk is set up (via features.conf) to accept "One Touch Monitor"
requests (by default, via '*1'), then the user-configured dialpad sequence
is generated, and recording can be started and stopped via this button. The
file names and formats are all controlled via the normal mechanisms. If the
user has not configured the automon feature, the normal "415 Unsupported media type"
is returned, and nothing is done.
* SIP: The "call-limit" option is marked as deprecated. It still works in this version of
Asterisk, but will be removed in the following version. Please use the groupcount functions
in the dialplan to enforce call limits. The "limitonpeer" configuration option is
now renamed to "counteronpeer".
* SIP: The "username" option is now renamed to "defaultuser" to match "defaultip".
These are used only before registration to call a peer with the uri
sip:defaultuser@defaultip
The "username" setting still work, but is deprecated and will not work in
the next version of Asterisk.
* chan_local.c: the comma delimiter inside the channel name has been changed to a
semicolon, in order to make the Local channel driver compatible with the comma
delimiter change in applications.
* H323: The "tos" setting has changed name to "tos_audio" and "cos" to "cos_audio"
to be compatible with settings in sip.conf. The "tos" and "cos" configuration
is deprecated and will stop working in the next release of Asterisk.
* Console: A new console channel driver, chan_console, has been added to Asterisk.
This new module can not be loaded at the same time as chan_alsa or chan_oss. The
default modules.conf only loads one of them (chan_oss by default). So, unless you
have modified your modules.conf to not use the autoload option, then you will need
to modify modules.conf to add another "noload" line to ensure that only one of
these three modules gets loaded.
* DAHDI: The chan_zap module that supported PSTN interfaces using
Zaptel has been renamed to chan_dahdi, and only supports the DAHDI
telephony driver package for PSTN interfaces. See the
Zaptel-to-DAHDI.txt file for more details on this transition.
* DAHDI: The "msdstrip" option has been deprecated, as it provides no value over
the method of stripping digits in the dialplan using variable substring syntax.
Configuration:
* pbx_dundi.c: tos parameter changed to use new values. Old values like lowdelay,
lowcost and other is not acceptable now. Look into qos.tex for description of
this parameter.
* queues.conf: the queue-lessthan sound file option is no longer available, and the
queue-round-seconds option no longer takes '1' as a valid parameter.
Manager:
* Manager has been upgraded to version 1.1 with a lot of changes.
Please check doc/manager_1_1.txt for information
* The IAXpeers command output has been changed to more closely resemble the
output of the SIPpeers command.
* cdr_manager now reports at the "cdr" level, not at "call" You may need to
change your manager.conf to add the level to existing AMI users, if they
want to see the CDR events generated.
* The Originate command now requires the Originate write permission. For
Originate with the Application parameter, you need the additional System
privilege if you want to do anything that calls out to a subshell.
iLBC Codec:
* Previously, the Asterisk source code distribution included the iLBC
encoder/decoder source code, from Global IP Solutions
(http://www.gipscorp.com). This code is not licensed for
distribution, and thus has been removed from the Asterisk source
code distribution. If you wish to use codec_ilbc to support iLBC
channels in Asterisk, you can run the contrib/scripts/get_ilbc_source.sh
script to download the source and put it in the proper place in
the Asterisk build tree. Once that is done you can follow your normal
steps of building Asterisk. You will need to run 'menuselect' and enable
the iLBC codec in the 'Codec Translators' category.

View File

@@ -1,88 +1,205 @@
===========================================================
===
=== Information for upgrading between Asterisk 1.6 versions
===
=== These files document all the changes that MUST be taken
=== into account when upgrading between the Asterisk
=== versions listed below. These changes may require that
=== you modify your configuration files, dialplan or (in
=== some cases) source code if you have your own Asterisk
=== modules or patches. These files also includes advance
=== notice of any functionality that has been marked as
=== 'deprecated' and may be removed in a future release,
=== along with the suggested replacement functionality.
===
=== UPGRADE-1.2.txt -- Upgrade info for 1.0 to 1.2
=== UPGRADE-1.4.txt -- Upgrade info for 1.2 to 1.4
=== UPGRADE-1.6.txt -- Upgrade info for 1.4 to 1.6
===
===========================================================
Information for Upgrading From Previous Asterisk Releases
=========================================================
As of 1.6.0.16:
Compiling:
* The firmware for the IAXy has been removed from Asterisk. It can be
downloaded from http://downloads.digium.com/pub/iaxy/. To have Asterisk
install the firmware into its proper location, place the firmware in the
contrib/firmware/iax/ directory in the Asterisk source tree before running
"make install".
* The Asterisk 1.2 source code now uses C language features
supported only by 'modern' C compilers. Generally, this means GCC
version 3.0 or higher, although some GCC 2.96 releases will also
work. Some non-GCC compilers that support C99 and the common GCC
extensions (including anonymous structures and unions) will also
work. All releases of GCC 2.95 do _not_ have the requisite feature
support; systems using that compiler will need to be upgraded to
a more recent compiler release.
* T.38 FAX error correction mode can no longer be configured in udptl.conf;
instead, it is configured on a per-peer (or global) basis in sip.conf, with
the same default as was present in udptl.conf.sample.
Dialplan Expressions:
* T.38 FAX maximum datagram size can no longer be configured in updtl.conf;
instead, it is either supplied by the application servicing the T.38 channel
(for a FAX send or receive) or calculated from the bridged endpoint's
maximum datagram size (for a T.38 FAX passthrough call). In addition, sip.conf
allows for overriding the value supplied by a remote endpoint, which is useful
when T.38 connections are made to gateways that supply incorrectly-calculated
maximum datagram sizes.
* The dialplan expression parser (which handles $[ ... ] constructs)
has gone through a major upgrade, but has one incompatible change:
spaces are no longer required around expression operators, including
string comparisons. However, you can now use quoting to keep strings
together for comparison. For more details, please read the
doc/README.variables file, and check over your dialplan for possible
problems.
As of 1.6.0.15:
Agents:
* There have been some changes to the IAX2 protocol to address the security
concerns documented in the security advisory AST-2009-006. Please see the
IAX2 security document, doc/IAX2-security.pdf, for information regarding
backwards compatibility with versions of Asterisk that do not contain these
changes to IAX2.
* The default for ackcall has been changed to "no" instead of "yes"
because of a bug which caused the "yes" behavior to generally act like
"no". You may need to adjust the value if your agents behave
differently than you expect with respect to acknowledgement.
From 1.6.0.10 to 1.6.0.11:
* The AgentCallBackLogin application now requires a second '|' before
specifying an extension@context. This is to distinguish the options
string from the extension, so that they do not conflict. See
'show application AgentCallbackLogin' for more details.
* Beginning with this release, Asterisk's internal methods of
negotiating T.38 (FAX over IP) sessions changed in
non-backwards-compatible ways. Any applications that previously used
AST_CONTROL_T38 control frames will have to be upgraded to use
AST_CONTROL_T38_PARAMETERS control frames instead; app_fax.c is a good
example of how to generate and respond to these frames. These changes
were made to solve significant T.38 interoperability problems between
Asterisk and various SIP/T.38 endpoints identified by many users of
Asterisk.
Parking:
From 1.6.0.9 to 1.6.0.10:
* Parking behavior has changed slightly; when a parked call times out,
Asterisk will attempt to deliver the call back to the extension that
parked it, rather than the 's' extension. If that extension is busy
or unavailable, the parked call will be lost.
* Support for Taiwanese was incorrectly supported with the "tw" language code.
In reality, the "tw" language code is reserved for the Twi language, native
to Ghana. If you were previously using the "tw" language code, you should
switch to using either "zh" (for Mandarin Chinese) or "zh_TW" for Taiwan
specific localizations. Additionally, "mx" should be changed to "es_MX",
Georgian was incorrectly specified as "ge" but should be "ka", and Czech is
"cs", not "cz".
Dialing:
From 1.6.0.1 to 1.6.0.2:
* The Caller*ID of the outbound leg is now the extension that was
called, rather than the Caller*ID of the inbound leg of the call. The
"o" flag for Dial can be used to restore the original behavior if
desired. Note that if you are looking for the originating callerid
from the manager event, there is a new manager event "Dial" which
provides the source and destination channels and callerid.
* The ast_agi_register_multiple() and ast_agi_unregister_multiple()
API calls were added in 1.6.0, so that modules that provide multiple
AGI commands could register/unregister them all with a single
step. However, these API calls were not implemented properly, and did
not allow the caller to know whether registration or unregistration
succeeded or failed. They have been redefined to now return success
or failure, but this means any code using these functions will need
be recompiled after upgrading to a version of Asterisk containing
these changes. In addition, the source code using these functions
should be reviewed to ensure it can properly react to failure
of registration or unregistration of its API commands.
IAX:
* The ast_agi_fdprintf() API call has been renamed to ast_agi_send()
to better match what it really does, and the argument order has been
changed to be consistent with other API calls that perform similar
operations.
* The naming convention for IAX channels has changed in two ways:
1. The call number follows a "-" rather than a "/" character.
2. The name of the channel has been simplified to IAX2/peer-callno,
rather than IAX2/peer@peer-callno or even IAX2/peer@peer/callno.
SIP:
* The global option "port" in 1.0.X that is used to set which port to
bind to has been changed to "bindport" to be more consistent with
the other channel drivers and to avoid confusion with the "port"
option for users/peers.
* The "Registry" event now uses "Username" rather than "User" for
consistency with IAX.
Applications:
* With the addition of dialplan functions (which operate similarly
to variables), the SetVar application has been renamed to Set.
* The CallerPres application has been removed. Use SetCallerPres
instead. It accepts both numeric and symbolic names.
* The applications GetGroupCount, GetGroupMatchCount, SetGroup, and
CheckGroup have been deprecated in favor of functions. Here is a
table of their replacements:
GetGroupCount([groupname][@category] GROUP_COUNT([groupname][@category]) Set(GROUPCOUNT=${GROUP_COUNT()})
GroupMatchCount(groupmatch[@category]) GROUP_MATCH_COUNT(groupmatch[@category]) Set(GROUPCOUNT=${GROUP_MATCH_COUNT(SIP/.*)})
SetGroup(groupname[@category]) GROUP([category])=groupname Set(GROUP()=test)
CheckGroup(max[@category]) N/A GotoIf($[ ${GROUP_COUNT()} > 5 ]?103)
Note that CheckGroup does not have a direct replacement. There is
also a new function called GROUP_LIST() which will return a space
separated list of all of the groups set on a channel. The GROUP()
function can also return the name of the group set on a channel when
used in a read environment.
* The applications DBGet and DBPut have been deprecated in favor of
functions. Here is a table of their replacements:
DBGet(foo=family/key) Set(foo=${DB(family/key)})
DBPut(family/key=${foo}) Set(DB(family/key)=${foo})
* The application SetLanguage has been deprecated in favor of the
function LANGUAGE().
SetLanguage(fr) Set(LANGUAGE()=fr)
The LANGUAGE function can also return the currently set language:
Set(MYLANG=${LANGUAGE()})
* The applications AbsoluteTimeout, DigitTimeout, and ResponseTimeout
have been deprecated in favor of the function TIMEOUT(timeouttype):
AbsoluteTimeout(300) Set(TIMEOUT(absolute)=300)
DigitTimeout(15) Set(TIMEOUT(digit)=15)
ResponseTimeout(15) Set(TIMEOUT(response)=15)
The TIMEOUT() function can also return the currently set timeouts:
Set(DTIMEOUT=${TIMEOUT(digit)})
* The applications SetCIDName, SetCIDNum, and SetRDNIS have been
deprecated in favor of the CALLERID(datatype) function:
SetCIDName(Joe Cool) Set(CALLERID(name)=Joe Cool)
SetCIDNum(2025551212) Set(CALLERID(number)=2025551212)
SetRDNIS(2024561414) Set(CALLERID(RDNIS)=2024561414)
* The application Record now uses the period to separate the filename
from the format, rather than the colon.
* The application VoiceMail now supports a 'temporary' greeting for each
mailbox. This greeting can be recorded by using option 4 in the
'mailbox options' menu, and 'change your password' option has been
moved to option 5.
* The application VoiceMailMain now only matches the 'default' context if
none is specified in the arguments. (This was the previously
documented behavior, however, we didn't follow that behavior.) The old
behavior can be restored by setting searchcontexts=yes in voicemail.conf.
Queues:
* A queue is now considered empty not only if there are no members but if
none of the members are available (e.g. agents not logged on). To
restore the original behavior, use "leavewhenempty=strict" or
"joinwhenempty=strict" instead of "=yes" for those options.
* It is now possible to use multi-digit extensions in the exit context
for a queue (although you should not have overlapping extensions,
as there is no digit timeout). This means that the EXITWITHKEY event
in queue_log can now contain a key field with more than a single
character in it.
Extensions:
* By default, there is a new option called "autofallthrough" in
extensions.conf that is set to yes. Asterisk 1.0 (and earlier)
behavior was to wait for an extension to be dialed after there were no
more extensions to execute. "autofallthrough" changes this behavior
so that the call will immediately be terminated with BUSY,
CONGESTION, or HANGUP based on Asterisk's best guess. If you are
writing an extension for IVR, you must use the WaitExten application
if "autofallthrough" is set to yes.
AGI:
* AGI scripts did not always get SIGHUP at the end, previously. That
behavior has been fixed. If you do not want your script to terminate
at the end of AGI being called (e.g. on a hangup) then set SIGHUP to
be ignored within your application.
* CallerID is reported with agi_callerid and agi_calleridname instead
of a single parameter holding both.
Music On Hold:
* The preferred format for musiconhold.conf has changed; please see the
sample configuration file for the new format. The existing format
is still supported but will generate warnings when the module is loaded.
chan_modem:
* All the chan_modem channel drivers (aopen, bestdata and i4l) are deprecated
in this release, and will be removed in the next major Asterisk release.
Please migrate to chan_misdn for ISDN interfaces; there is no upgrade
path for aopen and bestdata modem users.
MeetMe:
* The conference application now allows users to increase/decrease their
speaking volume and listening volume (independently of each other and
other users); the 'admin' and 'user' menus have changed, and new sound
files are included with this release. However, if a user calling in
over a Zaptel channel that does NOT have hardware DTMF detection
increases their speaking volume, it is likely they will no longer be
able to enter/exit the menu or make any further adjustments, as the
software DTMF detector will not be able to recognize the DTMF coming
from their device.
GetVar Manager Action:
* Previously, the behavior of the GetVar manager action reported the value
of a variable in the following manner:
> name: value
This has been changed to a manner similar to the SetVar action and is now
> Variable: name
> Value: value

View File

@@ -1,53 +0,0 @@
=========================================================
=== Information for upgrading from Zaptel to DAHDI ===
=========================================================
As announced in early 2008, Digium is renaming the Zaptel telephony
interface project to DAHDI (Digium Asterisk Hardware Device Interface)
to accommodate the desires of the owner of the Zaptel trademark for
telephony purposes.
This version of Asterisk can only be built using DAHDI, and as a
result there are number of changes that will be visible to previous
users of Asterisk with Zaptel.
First, the modules that directly use services from DAHDI have been
renamed; the new names are:
chan_zap.so -> chan_dahdi.so
app_zapbarge.so -> app_dahdibarge.so
app_zapras.so -> app_dahdiras.so
app_zapscan.so -> app_dahdiscan.so
codec_zap.so -> codec_dahdi.so
Second, the behavior of many modules has changed due to the switch to
DAHDI; the changes are listed below.
chan_dahdi.so:
Incoming and outgoing channels managed by this module will be
'DAHDI' channels instead of 'Zap' channels.
All CLI commands that began with 'zap' have been renamed to 'dahdi'
commands.
All Asterisk Manager Interface (AMI) actions that began with 'Zap'
have changed to 'DAHDI' prefixes.
The ZapSendKeypadFacility dialplan application has been renamed to
DAHDISendKeypadFacility.
The configuration for the channel driver will be read from
/etc/asterisk/chan_dahdi.conf instead of /etc/asterisk/zapata.conf.
app_dahdibarge.so:
The ZapBarge application has been renamed to DAHDIBarge.
app_dahdiras.so:
The ZapRAS application has been renamed to DAHDIRAS.
app_dahdiscan.so:
The ZapScan application has been renamed to DAHDIScan.

355
acl.c Normal file
View File

@@ -0,0 +1,355 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Various sorts of access control
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <sys/ioctl.h>
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
#include <fcntl.h>
#include <net/route.h>
#endif
#if defined(SOLARIS)
#include <sys/sockio.h>
#endif
/* netinet/ip.h may not define the following (See RFCs 791 and 1349) */
#if !defined(IPTOS_LOWCOST)
#define IPTOS_LOWCOST 0x02
#endif
#if !defined(IPTOS_MINCOST)
#define IPTOS_MINCOST IPTOS_LOWCOST
#endif
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/acl.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/srv.h"
#include "asterisk/compat.h"
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
AST_MUTEX_DEFINE_STATIC(routeseq_lock);
#endif
struct ast_ha {
/* Host access rule */
struct in_addr netaddr;
struct in_addr netmask;
int sense;
struct ast_ha *next;
};
/* Default IP - if not otherwise set, don't breathe garbage */
static struct in_addr __ourip = { 0x00000000 };
struct my_ifreq {
char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "eth0", "ppp0", etc. */
struct sockaddr_in ifru_addr;
};
/* Free HA structure */
void ast_free_ha(struct ast_ha *ha)
{
struct ast_ha *hal;
while(ha) {
hal = ha;
ha = ha->next;
free(hal);
}
}
/* Copy HA structure */
static void ast_copy_ha(struct ast_ha *from, struct ast_ha *to)
{
memcpy(&to->netaddr, &from->netaddr, sizeof(from->netaddr));
memcpy(&to->netmask, &from->netmask, sizeof(from->netmask));
to->sense = from->sense;
}
/* Create duplicate of ha structure */
static struct ast_ha *ast_duplicate_ha(struct ast_ha *original)
{
struct ast_ha *new_ha = malloc(sizeof(struct ast_ha));
/* Copy from original to new object */
ast_copy_ha(original, new_ha);
return new_ha;
}
/* Create duplicate HA link list */
/* Used in chan_sip2 templates */
struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original)
{
struct ast_ha *start=original;
struct ast_ha *ret = NULL;
struct ast_ha *link,*prev=NULL;
while (start) {
link = ast_duplicate_ha(start); /* Create copy of this object */
if (prev)
prev->next = link; /* Link previous to this object */
if (!ret)
ret = link; /* Save starting point */
start = start->next; /* Go to next object */
prev = link; /* Save pointer to this object */
}
return ret; /* Return start of list */
}
struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
{
struct ast_ha *ha = malloc(sizeof(struct ast_ha));
char *nm = "255.255.255.255";
char tmp[256];
struct ast_ha *prev = NULL;
struct ast_ha *ret;
int x, z;
unsigned int y;
ret = path;
while (path) {
prev = path;
path = path->next;
}
if (ha) {
ast_copy_string(tmp, stuff, sizeof(tmp));
nm = strchr(tmp, '/');
if (!nm) {
nm = "255.255.255.255";
} else {
*nm = '\0';
nm++;
}
if (!strchr(nm, '.')) {
if ((sscanf(nm, "%d", &x) == 1) && (x >= 0) && (x <= 32)) {
y = 0;
for (z=0;z<x;z++) {
y >>= 1;
y |= 0x80000000;
}
ha->netmask.s_addr = htonl(y);
}
} else if (!inet_aton(nm, &ha->netmask)) {
ast_log(LOG_WARNING, "%s is not a valid netmask\n", nm);
free(ha);
return ret;
}
if (!inet_aton(tmp, &ha->netaddr)) {
ast_log(LOG_WARNING, "%s is not a valid IP\n", tmp);
free(ha);
return ret;
}
ha->netaddr.s_addr &= ha->netmask.s_addr;
if (!strncasecmp(sense, "p", 1)) {
ha->sense = AST_SENSE_ALLOW;
} else {
ha->sense = AST_SENSE_DENY;
}
ha->next = NULL;
if (prev) {
prev->next = ha;
} else {
ret = ha;
}
}
ast_log(LOG_DEBUG, "%s/%s appended to acl for peer\n", stuff, nm);
return ret;
}
int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
{
/* Start optimistic */
int res = AST_SENSE_ALLOW;
while (ha) {
char iabuf[INET_ADDRSTRLEN];
char iabuf2[INET_ADDRSTRLEN];
/* DEBUG */
ast_log(LOG_DEBUG,
"##### Testing %s with %s\n",
ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr),
ast_inet_ntoa(iabuf2, sizeof(iabuf2), ha->netaddr));
/* For each rule, if this address and the netmask = the net address
apply the current rule */
if ((sin->sin_addr.s_addr & ha->netmask.s_addr) == ha->netaddr.s_addr)
res = ha->sense;
ha = ha->next;
}
return res;
}
int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *service)
{
struct hostent *hp;
struct ast_hostent ahp;
char srv[256];
char host[256];
int tportno = ntohs(sin->sin_port);
if (inet_aton(value, &sin->sin_addr))
return 0;
if (service) {
snprintf(srv, sizeof(srv), "%s.%s", service, value);
if (ast_get_srv(NULL, host, sizeof(host), &tportno, srv) > 0) {
sin->sin_port = htons(tportno);
value = host;
}
}
hp = ast_gethostbyname(value, &ahp);
if (hp) {
memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
} else {
ast_log(LOG_WARNING, "Unable to lookup '%s'\n", value);
return -1;
}
return 0;
}
int ast_str2tos(const char *value, int *tos)
{
int fval;
if (sscanf(value, "%i", &fval) == 1)
*tos = fval & 0xff;
else if (!strcasecmp(value, "lowdelay"))
*tos = IPTOS_LOWDELAY;
else if (!strcasecmp(value, "throughput"))
*tos = IPTOS_THROUGHPUT;
else if (!strcasecmp(value, "reliability"))
*tos = IPTOS_RELIABILITY;
else if (!strcasecmp(value, "mincost"))
*tos = IPTOS_MINCOST;
else if (!strcasecmp(value, "none"))
*tos = 0;
else
return -1;
return 0;
}
int ast_get_ip(struct sockaddr_in *sin, const char *value)
{
return ast_get_ip_or_srv(sin, value, NULL);
}
/* iface is the interface (e.g. eth0); address is the return value */
int ast_lookup_iface(char *iface, struct in_addr *address)
{
int mysock, res = 0;
struct my_ifreq ifreq;
memset(&ifreq, 0, sizeof(ifreq));
ast_copy_string(ifreq.ifrn_name, iface, sizeof(ifreq.ifrn_name));
mysock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
res = ioctl(mysock, SIOCGIFADDR, &ifreq);
close(mysock);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno));
memcpy((char *)address, (char *)&__ourip, sizeof(__ourip));
return -1;
} else {
memcpy((char *)address, (char *)&ifreq.ifru_addr.sin_addr, sizeof(ifreq.ifru_addr.sin_addr));
return 0;
}
}
int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
{
int s;
struct sockaddr_in sin;
socklen_t slen;
s = socket(PF_INET, SOCK_DGRAM, 0);
if (s < 0) {
ast_log(LOG_WARNING, "Cannot create socket\n");
return -1;
}
sin.sin_family = AF_INET;
sin.sin_port = 5060;
sin.sin_addr = *them;
if (connect(s, (struct sockaddr *)&sin, sizeof(sin))) {
ast_log(LOG_WARNING, "Cannot connect\n");
close(s);
return -1;
}
slen = sizeof(sin);
if (getsockname(s, (struct sockaddr *)&sin, &slen)) {
ast_log(LOG_WARNING, "Cannot get socket name\n");
close(s);
return -1;
}
close(s);
*us = sin.sin_addr;
return 0;
}
int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr)
{
char ourhost[MAXHOSTNAMELEN] = "";
struct ast_hostent ahp;
struct hostent *hp;
struct in_addr saddr;
/* just use the bind address if it is nonzero */
if (ntohl(bindaddr.sin_addr.s_addr)) {
memcpy(ourip, &bindaddr.sin_addr, sizeof(*ourip));
return 0;
}
/* try to use our hostname */
if (gethostname(ourhost, sizeof(ourhost) - 1)) {
ast_log(LOG_WARNING, "Unable to get hostname\n");
} else {
hp = ast_gethostbyname(ourhost, &ahp);
if (hp) {
memcpy(ourip, hp->h_addr, sizeof(*ourip));
return 0;
}
}
/* A.ROOT-SERVERS.NET. */
if (inet_aton("198.41.0.4", &saddr) && !ast_ouraddrfor(&saddr, ourip))
return 0;
return -1;
}

View File

@@ -31,26 +31,20 @@
Issue Date: 26/08/2003
*/
/*! \file
*
* \brief This file contains the code for implementing encryption and decryption
* for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It
* can optionally be replaced by code written in assembler using NASM. For
* further details see the file aesopt.h
*
* \author Dr Brian Gladman <brg@gladman.me.uk>
*/
\brief This file contains the code for implementing encryption and decryption
for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It
can optionally be replaced by code written in assembler using NASM. For
further details see the file aesopt.h
*/
#include "aesopt.h"
#if defined(__cplusplus)
extern "C"
{
#endif
#ifndef HAVE_CRYPTO
#include "aesopt.h"
#define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c])
#define so(y,x,c) word_out(y, c, s(x,c))
@@ -314,8 +308,6 @@ aes_rval aes_decrypt(const void *in_blk, void *out_blk, const aes_decrypt_ctx cx
#endif
#endif /* !HAVE_CRYPTO */
#if defined(__cplusplus)
}
#endif

View File

@@ -31,25 +31,19 @@
Issue Date: 26/08/2003
*/
/*! \file
*
* \brief This file contains the code for implementing the key schedule for AES
* (Rijndael) for block and key sizes of 16, 24, and 32 bytes. See aesopt.h
* for further details including optimisation.
*
* \author Dr Brian Gladman <brg@gladman.me.uk>
*/
\brief This file contains the code for implementing the key schedule for AES
(Rijndael) for block and key sizes of 16, 24, and 32 bytes. See aesopt.h
for further details including optimisation.
*/
#include "aesopt.h"
#if defined(__cplusplus)
extern "C"
{
#endif
#ifndef HAVE_CRYPTO
#include "aesopt.h"
/* Initialise the key schedule from the user supplied key. The key
length can be specified in bytes, with legal values of 16, 24
and 32, or in bits, with legal values of 128, 192 and 256. These
@@ -466,8 +460,6 @@ aes_rval aes_decrypt_key(const void *in_key, int key_len, aes_decrypt_ctx cx[1])
#endif
#endif /* !HAVE_CRYPTO */
#if defined(__cplusplus)
}
#endif

View File

@@ -37,8 +37,6 @@ extern "C"
{
#endif
#ifndef HAVE_CRYPTO
#define DO_TABLES
#include "aesopt.h"
@@ -228,8 +226,6 @@ void gen_tabs(void)
#endif
#endif /* !HAVE_CRYPTO */
#if defined(__cplusplus)
}
#endif

View File

@@ -3,7 +3,7 @@
#
# Makefile for AGI-related stuff
#
# Copyright (C) 1999-2006, Digium
# Copyright (C) 1999-2005, Digium
#
# Mark Spencer <markster@digium.com>
#
@@ -11,43 +11,42 @@
# the GNU General Public License
#
.PHONY: clean all uninstall
AGIS=agi-test.agi eagi-test eagi-sphinx-test
AGIS=agi-test.agi eagi-test eagi-sphinx-test jukebox.agi
CFLAGS+=-DNO_AST_MM
LIBS=
ifeq ($(OSARCH),SunOS)
LIBS+=-lsocket -lnsl
LIBS=-lsocket -lnsl ../strcompat.o
endif
ifeq ($(OSARCH),mingw32)
AGIS:=
ifeq ($(findstring BSD,${OSARCH}),BSD)
CFLAGS+=-I$(CROSS_COMPILE_TARGET)/usr/local/include -L$(CROSS_COMPILE_TARGET)/usr/local/lib
endif
include $(ASTTOPDIR)/Makefile.rules
_ASTCFLAGS+=-DSTANDALONE
all: $(AGIS)
strcompat.c: ../main/strcompat.c
@cp $< $@
eagi-test: eagi-test.o strcompat.o
eagi-sphinx-test: eagi-sphinx-test.o
all: depend $(AGIS)
install: all
mkdir -p $(DESTDIR)$(AGI_DIR)
for x in $(AGIS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(AGI_DIR) ; done
uninstall:
for x in $(AGIS); do rm -f $(DESTDIR)$(AGI_DIR)/$$x ; done
eagi-test: eagi-test.o
$(CC) $(CFLAGS) -o eagi-test eagi-test.o $(LIBS)
eagi-sphinx-test: eagi-sphinx-test.o
$(CC) $(CFLAGS) -o eagi-sphinx-test eagi-sphinx-test.o $(LIBS)
clean:
rm -f *.so *.o look eagi-test eagi-sphinx-test
rm -f .*.d *.s *.i
rm -f strcompat.c
rm -f *.so *.o look .depend eagi-test eagi-sphinx-test
ifneq ($(wildcard .*.d),)
include .*.d
%.so : %.o
$(CC) -shared -Xlinker -x -o $@ $<
ifneq ($(wildcard .depend),)
include .depend
endif
depend: .depend
.depend:
../build_tools/mkdep $(CFLAGS) `ls *.c`

View File

@@ -6,15 +6,6 @@
*
*/
/*! \file
* Extended AGI test application
*
* This code is released into public domain
* without any warranty of any kind.
*
* \ingroup agi
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@@ -26,10 +17,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "asterisk.h"
#include "asterisk/compat.h"
#include <asterisk/compat.h>
#define AUDIO_FILENO (STDERR_FILENO + 1)
@@ -79,9 +67,7 @@ static int read_environment(void)
char *val;
/* Read environment */
for(;;) {
if (!fgets(buf, sizeof(buf), stdin)) {
return -1;
}
fgets(buf, sizeof(buf), stdin);
if (feof(stdin))
return -1;
buf[strlen(buf) - 1] = '\0';
@@ -132,9 +118,7 @@ static char *wait_result(void)
return NULL;
}
if (FD_ISSET(STDIN_FILENO, &fds)) {
if (!fgets(astresp, sizeof(astresp), stdin)) {
return NULL;
}
fgets(astresp, sizeof(astresp), stdin);
if (feof(stdin)) {
fprintf(stderr, "Got hungup on apparently\n");
return NULL;
@@ -145,10 +129,9 @@ static char *wait_result(void)
}
if (FD_ISSET(AUDIO_FILENO, &fds)) {
res = read(AUDIO_FILENO, audiobuf, sizeof(audiobuf));
if ((res > 0) && (sphinx_sock > -1)) {
if (write(sphinx_sock, audiobuf, res) < 0) {
fprintf(stderr, "write() failed: %s\n", strerror(errno));
}
if (res > 0) {
if (sphinx_sock > -1)
write(sphinx_sock, audiobuf, res);
}
}
if ((sphinx_sock > -1) && FD_ISSET(sphinx_sock, &fds)) {
@@ -223,7 +206,7 @@ int main(int argc, char *argv[])
connect_sphinx();
tmp = getenv("agi_enhanced");
if (tmp) {
if (sscanf(tmp, "%30d.%30d", &ver, &subver) != 2)
if (sscanf(tmp, "%d.%d", &ver, &subver) != 2)
ver = 0;
}
if (ver < 1) {

View File

@@ -5,28 +5,23 @@
* with no warranty of any kind
*/
#include "asterisk.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/select.h>
#include <asterisk/compat.h>
#define AUDIO_FILENO (STDERR_FILENO + 1)
/*! \file
* Extended AGI test application
*
* This code is released into the public domain
* with no warranty of any kind
*
* \ingroup agi
*/
static int read_environment(void)
{
char buf[256];
char *val;
/* Read environment */
for(;;) {
if (!fgets(buf, sizeof(buf), stdin)) {
return -1;
}
fgets(buf, sizeof(buf), stdin);
if (feof(stdin))
return -1;
buf[strlen(buf) - 1] = '\0';
@@ -70,9 +65,7 @@ static char *wait_result(void)
return NULL;
}
if (FD_ISSET(STDIN_FILENO, &fds)) {
if (!fgets(astresp, sizeof(astresp), stdin)) {
return NULL;
}
fgets(astresp, sizeof(astresp), stdin);
if (feof(stdin)) {
fprintf(stderr, "Got hungup on apparently\n");
return NULL;
@@ -156,7 +149,7 @@ int main(int argc, char *argv[])
}
tmp = getenv("agi_enhanced");
if (tmp) {
if (sscanf(tmp, "%30d.%30d", &ver, &subver) != 2)
if (sscanf(tmp, "%d.%d", &ver, &subver) != 2)
ver = 0;
}
if (ver < 1) {

View File

@@ -1,488 +0,0 @@
#!/usr/bin/perl
#
# Jukebox 0.2
#
# A music manager for Asterisk.
#
# Copyright (C) 2005-2006, Justin Tunney
#
# Justin Tunney <jesuscyborg@gmail.com>
#
# This program is free software, distributed under the terms of the
# GNU General Public License v2.
#
# Keep it open source pigs
#
# --------------------------------------------------------------------
#
# Uses festival to list off all your MP3 music files over a channel in
# a hierarchical fashion. Put this file in your agi-bin folder which
# is located at: /var/lib/asterisk/agi-bin Be sure to chmod +x it!
#
# Invocation Example:
# exten => 68742,1,Answer()
# exten => 68742,2,agi,jukebox.agi|/home/justin/Music
# exten => 68742,3,Hangup()
#
# exten => 68742,1,Answer()
# exten => 68742,2,agi,jukebox.agi|/home/justin/Music|pm
# exten => 68742,3,Hangup()
#
# Options:
# p - Precache text2wave outputs for every possible filename.
# It is much better to set this option because if a caller
# presses a key during a cache operation, it will be ignored.
# m - Go back to menu after playing song
# g - Do not play the greeting message
#
# Usage Instructions:
# - Press '*' to go up a directory. If you are in the root music
# folder you will be exitted from the script.
# - If you have a really long list of files, you can filter the list
# at any time by pressing '#' and spelling out a few letters you
# expect the files to start with. For example, if you wanted to
# know what extension 'Requiem For A Dream' was, you'd type:
# '#737'. Note, phone keypads don't include Q and Z. Q is 7 and
# Z is 9.
#
# Notes:
# - This AGI script uses the MP3Player command which uses the
# mpg123 Program. Grab yourself a copy of this program by
# going to http://www.mpg123.de/cgi-bin/sitexplorer.cgi?/mpg123/
# Be sure to download mpg123-0.59r.tar.gz because it is known to
# work with Asterisk and hopefully isn't the release with that
# awful security problem. If you're using Fedora Core 3 with
# Alsa like me, make linux-alsa isn't going to work. Do make
# linux-devel and you're peachy keen.
#
# - You won't get nifty STDERR debug messages if you're using a
# remote asterisk shell.
#
# - For some reason, caching certain files will generate the
# error: 'using default diphone ax-ax for y-pau'. Example:
# # echo "Depeche Mode - CUW - 05 - The Meaning of Love" | text2wave -o /var/jukeboxcache/jukeboxcache/Depeche_Mode/Depeche_Mode_-_CUW_-_05_-_The_Meaning_of_Love.mp3.ul -otype ulaw -
# The temporary work around is to just touch these files.
#
# - The background app doesn't like to get more than 2031 chars
# of input.
#
use strict;
$|=1;
# Setup some variables
my %AGI; my $tests = 0; my $fail = 0; my $pass = 0;
my @masterCacheList = ();
my $maxNumber = 10;
while (<STDIN>) {
chomp;
last unless length($_);
if (/^agi_(\w+)\:\s+(.*)$/) {
$AGI{$1} = $2;
}
}
# setup options
my $SHOWGREET = 1;
my $PRECACHE = 0;
my $MENUAFTERSONG = 0;
$PRECACHE = 1 if $ARGV[1] =~ /p/;
$MENUAFTERSONG = 1 if $ARGV[1] =~ /m/;
$SHOWGREET = 0 if $ARGV[1] =~ /g/;
# setup folders
my $MUSIC = $ARGV[0];
$MUSIC = &rmts($MUSIC);
my $FESTIVALCACHE = "/var/jukeboxcache";
if (! -e $FESTIVALCACHE) {
`mkdir -p -m0776 $FESTIVALCACHE`;
}
# make sure we have some essential files
if (! -e "$FESTIVALCACHE/jukebox_greet.ul") {
`echo "Welcome to the Asterisk Jukebox" | text2wave -o $FESTIVALCACHE/jukebox_greet.ul -otype ulaw -`;
}
if (! -e "$FESTIVALCACHE/jukebox_press.ul") {
`echo "Press" | text2wave -o $FESTIVALCACHE/jukebox_press.ul -otype ulaw -`;
}
if (! -e "$FESTIVALCACHE/jukebox_for.ul") {
`echo "For" | text2wave -o $FESTIVALCACHE/jukebox_for.ul -otype ulaw -`;
}
if (! -e "$FESTIVALCACHE/jukebox_toplay.ul") {
`echo "To play" | text2wave -o $FESTIVALCACHE/jukebox_toplay.ul -otype ulaw -`;
}
if (! -e "$FESTIVALCACHE/jukebox_nonefound.ul") {
`echo "There were no music files found in this folder" | text2wave -o $FESTIVALCACHE/jukebox_nonefound.ul -otype ulaw -`;
}
if (! -e "$FESTIVALCACHE/jukebox_percent.ul") {
`echo "Percent" | text2wave -o $FESTIVALCACHE/jukebox_percent.ul -otype ulaw -`;
}
if (! -e "$FESTIVALCACHE/jukebox_generate.ul") {
`echo "Please wait while Astrisk Jukebox cashes the files of your music collection" | text2wave -o $FESTIVALCACHE/jukebox_generate.ul -otype ulaw -`;
}
if (! -e "$FESTIVALCACHE/jukebox_invalid.ul") {
`echo "You have entered an invalid selection" | text2wave -o $FESTIVALCACHE/jukebox_invalid.ul -otype ulaw -`;
}
if (! -e "$FESTIVALCACHE/jukebox_thankyou.ul") {
`echo "Thank you for using Astrisk Jukebox, Goodbye" | text2wave -o $FESTIVALCACHE/jukebox_thankyou.ul -otype ulaw -`;
}
# greet the user
if ($SHOWGREET) {
print "EXEC Playback \"$FESTIVALCACHE/jukebox_greet\"\n";
my $result = <STDIN>; &check_result($result);
}
# go through the directories
music_dir_cache() if $PRECACHE;
music_dir_menu('/');
exit 0;
##########################################################################
sub music_dir_menu {
my $dir = shift;
# generate a list of mp3's and directories and assign each one it's
# own selection number. Then make sure that we've got a sound clip
# for the file name
if (!opendir(THEDIR, rmts($MUSIC.$dir))) {
print STDERR "Failed to open music directory: $dir\n";
exit 1;
}
my @files = sort readdir THEDIR;
my $cnt = 1;
my @masterBgList = ();
foreach my $file (@files) {
chomp($file);
if ($file ne '.' && $file ne '..' && $file ne 'festivalcache') { # ignore special files
my $real_version = &rmts($MUSIC.$dir).'/'.$file;
my $cache_version = &rmts($FESTIVALCACHE.$dir).'/'.$file.'.ul';
my $cache_version2 = &rmts($FESTIVALCACHE.$dir).'/'.$file;
my $cache_version_esc = &clean_file($cache_version);
my $cache_version2_esc = &clean_file($cache_version2);
if (-d $real_version) {
# 0:id 1:type 2:text2wav-file 3:for-filtering 4:the-directory 5:text2wav echo
push(@masterBgList, [$cnt++, 1, $cache_version2_esc, &remove_special_chars($file), $file, "for the $file folder"]);
} elsif ($real_version =~ /\.mp3$/) {
# 0:id 1:type 2:text2wav-file 3:for-filtering 4:the-mp3
push(@masterBgList, [$cnt++, 2, $cache_version2_esc, &remove_special_chars($file), $real_version, "to play $file"]);
}
}
}
close(THEDIR);
my @filterList = @masterBgList;
if (@filterList == 0) {
print "EXEC Playback \"$FESTIVALCACHE/jukebox_nonefound\"\n";
my $result = <STDIN>; &check_result($result);
return 0;
}
for (;;) {
MYCONTINUE:
# play bg selections and figure out their selection
my $digit = '';
my $digitstr = '';
for (my $n=0; $n<@filterList; $n++) {
&cache_speech(&remove_file_extension($filterList[$n][5]), "$filterList[$n][2].ul") if ! -e "$filterList[$n][2].ul";
&cache_speech("Press $filterList[$n][0]", "$FESTIVALCACHE/jukebox_$filterList[$n][0].ul") if ! -e "$FESTIVALCACHE/jukebox_$filterList[$n][0].ul";
print "EXEC Background \"$filterList[$n][2]&$FESTIVALCACHE/jukebox_$filterList[$n][0]\"\n";
my $result = <STDIN>;
$digit = &check_result($result);
if ($digit > 0) {
$digitstr .= chr($digit);
last;
}
}
for (;;) {
print "WAIT FOR DIGIT 3000\n";
my $result = <STDIN>;
$digit = &check_result($result);
last if $digit <= 0;
$digitstr .= chr($digit);
}
# see if it's a valid selection
print STDERR "Digits Entered: '$digitstr'\n";
exit 0 if $digitstr eq '';
my $found = 0;
goto EXITSUB if $digitstr =~ /\*/;
# filter the list
if ($digitstr =~ /^\#\d+/) {
my $regexp = '';
for (my $n=1; $n<length($digitstr); $n++) {
my $d = substr($digitstr, $n, 1);
if ($d == 2) {
$regexp .= '[abc]';
} elsif ($d == 3) {
$regexp .= '[def]';
} elsif ($d == 4) {
$regexp .= '[ghi]';
} elsif ($d == 5) {
$regexp .= '[jkl]';
} elsif ($d == 6) {
$regexp .= '[mno]';
} elsif ($d == 7) {
$regexp .= '[pqrs]';
} elsif ($d == 8) {
$regexp .= '[tuv]';
} elsif ($d == 9) {
$regexp .= '[wxyz]';
}
}
@filterList = ();
for (my $n=1; $n<@masterBgList; $n++) {
push(@filterList, $masterBgList[$n]) if $masterBgList[$n][3] =~ /^$regexp/i;
}
goto MYCONTINUE;
}
for (my $n=0; $n<@masterBgList; $n++) {
if ($digitstr == $masterBgList[$n][0]) {
if ($masterBgList[$n][1] == 1) { # a folder
&music_dir_menu(rmts($dir).'/'.$masterBgList[$n][4]);
@filterList = @masterBgList;
goto MYCONTINUE;
} elsif ($masterBgList[$n][1] == 2) { # a file
# because *'s scripting language is crunk and won't allow us to escape
# funny filenames, we need to create a temporary symlink to the mp3
# file
my $mp3 = &escape_file($masterBgList[$n][4]);
my $link = `mktemp`;
chomp($link);
$link .= '.mp3';
print STDERR "ln -s $mp3 $link\n";
my $cmdr = `ln -s $mp3 $link`;
chomp($cmdr);
print "Failed to create symlink to mp3: $cmdr\n" if $cmdr ne '';
print "EXEC MP3Player \"$link\"\n";
my $result = <STDIN>; &check_result($result);
`rm $link`;
if (!$MENUAFTERSONG) {
print "EXEC Playback \"$FESTIVALCACHE/jukebox_thankyou\"\n";
my $result = <STDIN>; &check_result($result);
exit 0;
} else {
goto MYCONTINUE;
}
}
}
}
print "EXEC Playback \"$FESTIVALCACHE/jukebox_invalid\"\n";
my $result = <STDIN>; &check_result($result);
}
EXITSUB:
}
sub cache_speech {
my $speech = shift;
my $file = shift;
my $theDir = extract_file_dir($file);
`mkdir -p -m0776 $theDir`;
print STDERR "echo \"$speech\" | text2wave -o $file -otype ulaw -\n";
my $cmdr = `echo "$speech" | text2wave -o $file -otype ulaw -`;
chomp($cmdr);
if ($cmdr =~ /using default diphone/) {
# temporary bug work around....
`touch $file`;
} elsif ($cmdr ne '') {
print STDERR "Command Failed\n";
exit 1;
}
}
sub music_dir_cache {
# generate list of text2speech files to generate
if (!music_dir_cache_genlist('/')) {
print STDERR "Horrible Dreadful Error: No Music Found in $MUSIC!";
exit 1;
}
# add to list how many 'number' files we have to generate. We can't
# use the SayNumber app in Asterisk because we want to chain all
# talking in one Background command. We also want a consistent
# voice...
for (my $n=1; $n<=$maxNumber; $n++) {
push(@masterCacheList, [3, "Press $n", "$FESTIVALCACHE/jukebox_$n.ul"]) if ! -e "$FESTIVALCACHE/jukebox_$n.ul";
}
# now generate all these darn text2speech files
if (@masterCacheList > 5) {
print "EXEC Playback \"$FESTIVALCACHE/jukebox_generate\"\n";
my $result = <STDIN>; &check_result($result);
}
my $theTime = time();
for (my $n=0; $n < @masterCacheList; $n++) {
my $cmdr = '';
if ($masterCacheList[$n][0] == 1) { # directory
&cache_speech("for folder $masterCacheList[$n][1]", $masterCacheList[$n][2]);
} elsif ($masterCacheList[$n][0] == 2) { # file
&cache_speech("to play $masterCacheList[$n][1]", $masterCacheList[$n][2]);
} elsif ($masterCacheList[$n][0] == 3) { # number
&cache_speech($masterCacheList[$n][1], $masterCacheList[$n][2]);
}
if (time() >= $theTime + 30) {
my $percent = int($n / @masterCacheList * 100);
print "SAY NUMBER $percent \"\"\n";
my $result = <STDIN>; &check_result($result);
print "EXEC Playback \"$FESTIVALCACHE/jukebox_percent\"\n";
my $result = <STDIN>; &check_result($result);
$theTime = time();
}
}
}
# this function will fill the @masterCacheList of all the files that
# need to have text2speeced ulaw files of their names generated
sub music_dir_cache_genlist {
my $dir = shift;
if (!opendir(THEDIR, rmts($MUSIC.$dir))) {
print STDERR "Failed to open music directory: $dir\n";
exit 1;
}
my @files = sort readdir THEDIR;
my $foundFiles = 0;
my $tmpMaxNum = 0;
foreach my $file (@files) {
chomp;
if ($file ne '.' && $file ne '..' && $file ne 'festivalcache') { # ignore special files
my $real_version = &rmts($MUSIC.$dir).'/'.$file;
my $cache_version = &rmts($FESTIVALCACHE.$dir).'/'.$file.'.ul';
my $cache_version2 = &rmts($FESTIVALCACHE.$dir).'/'.$file;
my $cache_version_esc = &clean_file($cache_version);
my $cache_version2_esc = &clean_file($cache_version2);
if (-d $real_version) {
if (music_dir_cache_genlist(rmts($dir).'/'.$file)) {
$tmpMaxNum++;
$maxNumber = $tmpMaxNum if $tmpMaxNum > $maxNumber;
push(@masterCacheList, [1, $file, $cache_version_esc]) if ! -e $cache_version_esc;
$foundFiles = 1;
}
} elsif ($real_version =~ /\.mp3$/) {
$tmpMaxNum++;
$maxNumber = $tmpMaxNum if $tmpMaxNum > $maxNumber;
push(@masterCacheList, [2, &remove_file_extension($file), $cache_version_esc]) if ! -e $cache_version_esc;
$foundFiles = 1;
}
}
}
close(THEDIR);
return $foundFiles;
}
sub rmts { # remove trailing slash
my $hog = shift;
$hog =~ s/\/$//;
return $hog;
}
sub extract_file_name {
my $hog = shift;
$hog =~ /\/?([^\/]+)$/;
return $1;
}
sub extract_file_dir {
my $hog = shift;
return $hog if ! ($hog =~ /\//);
$hog =~ /(.*)\/[^\/]*$/;
return $1;
}
sub remove_file_extension {
my $hog = shift;
return $hog if ! ($hog =~ /\./);
$hog =~ /(.*)\.[^.]*$/;
return $1;
}
sub clean_file {
my $hog = shift;
$hog =~ s/\\/_/g;
$hog =~ s/ /_/g;
$hog =~ s/\t/_/g;
$hog =~ s/\'/_/g;
$hog =~ s/\"/_/g;
$hog =~ s/\(/_/g;
$hog =~ s/\)/_/g;
$hog =~ s/&/_/g;
$hog =~ s/\[/_/g;
$hog =~ s/\]/_/g;
$hog =~ s/\$/_/g;
$hog =~ s/\|/_/g;
$hog =~ s/\^/_/g;
return $hog;
}
sub remove_special_chars {
my $hog = shift;
$hog =~ s/\\//g;
$hog =~ s/ //g;
$hog =~ s/\t//g;
$hog =~ s/\'//g;
$hog =~ s/\"//g;
$hog =~ s/\(//g;
$hog =~ s/\)//g;
$hog =~ s/&//g;
$hog =~ s/\[//g;
$hog =~ s/\]//g;
$hog =~ s/\$//g;
$hog =~ s/\|//g;
$hog =~ s/\^//g;
return $hog;
}
sub escape_file {
my $hog = shift;
$hog =~ s/\\/\\\\/g;
$hog =~ s/ /\\ /g;
$hog =~ s/\t/\\\t/g;
$hog =~ s/\'/\\\'/g;
$hog =~ s/\"/\\\"/g;
$hog =~ s/\(/\\\(/g;
$hog =~ s/\)/\\\)/g;
$hog =~ s/&/\\&/g;
$hog =~ s/\[/\\\[/g;
$hog =~ s/\]/\\\]/g;
$hog =~ s/\$/\\\$/g;
$hog =~ s/\|/\\\|/g;
$hog =~ s/\^/\\\^/g;
return $hog;
}
sub check_result {
my ($res) = @_;
my $retval;
$tests++;
chomp $res;
if ($res =~ /^200/) {
$res =~ /result=(-?\d+)/;
if (!length($1)) {
print STDERR "FAIL ($res)\n";
$fail++;
exit 1;
} else {
print STDERR "PASS ($1)\n";
return $1;
}
} else {
print STDERR "FAIL (unexpected result '$res')\n";
exit 1;
}
}

100
alaw.c Normal file
View File

@@ -0,0 +1,100 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief u-Law to Signed linear conversion
*
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/alaw.h"
#define AMI_MASK 0x55
static inline unsigned char linear2alaw (short int linear)
{
int mask;
int seg;
int pcm_val;
static int seg_end[8] =
{
0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
};
pcm_val = linear;
if (pcm_val >= 0)
{
/* Sign (7th) bit = 1 */
mask = AMI_MASK | 0x80;
}
else
{
/* Sign bit = 0 */
mask = AMI_MASK;
pcm_val = -pcm_val;
}
/* Convert the scaled magnitude to segment number. */
for (seg = 0; seg < 8; seg++)
{
if (pcm_val <= seg_end[seg])
break;
}
/* Combine the sign, segment, and quantization bits. */
return ((seg << 4) | ((pcm_val >> ((seg) ? (seg + 3) : 4)) & 0x0F)) ^ mask;
}
/*- End of function --------------------------------------------------------*/
static inline short int alaw2linear (unsigned char alaw)
{
int i;
int seg;
alaw ^= AMI_MASK;
i = ((alaw & 0x0F) << 4);
seg = (((int) alaw & 0x70) >> 4);
if (seg)
i = (i + 0x100) << (seg - 1);
return (short int) ((alaw & 0x80) ? i : -i);
}
unsigned char __ast_lin2a[8192];
short __ast_alaw[256];
void ast_alaw_init(void)
{
int i;
/*
* Set up mu-law conversion table
*/
for(i = 0;i < 256;i++)
{
__ast_alaw[i] = alaw2linear(i);
}
/* set up the reverse (mu-law) conversion table */
for(i = -32768; i < 32768; i++)
{
__ast_lin2a[((unsigned short)i) >> 3] = linear2alaw(i);
}
}

1633
app.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -3,33 +3,128 @@
#
# Makefile for PBX applications
#
# Copyright (C) 1999-2006, Digium, Inc.
# Copyright (C) 1999-2005, Digium
#
# Mark Spencer <markster@digium.com>
#
# This program is free software, distributed under the terms of
# the GNU General Public License
#
-include $(ASTTOPDIR)/menuselect.makeopts $(ASTTOPDIR)/menuselect.makedeps
APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_mp3.so\
app_system.so app_echo.so app_record.so app_image.so app_url.so app_disa.so \
app_adsiprog.so app_getcpeid.so app_milliwatt.so \
app_zapateller.so app_setcallerid.so app_festival.so \
app_queue.so app_senddtmf.so app_parkandannounce.so \
app_setcidname.so app_lookupcidname.so app_macro.so \
app_authenticate.so app_softhangup.so app_lookupblacklist.so \
app_waitforring.so app_privacy.so app_db.so app_chanisavail.so \
app_enumlookup.so app_transfer.so app_setcidnum.so app_cdr.so \
app_hasnewvoicemail.so app_sayunixtime.so app_cut.so app_read.so \
app_setcdruserfield.so app_random.so app_ices.so app_eval.so \
app_nbscat.so app_sendtext.so app_exec.so \
app_groupcount.so app_txtcidname.so app_controlplayback.so \
app_talkdetect.so app_alarmreceiver.so app_userevent.so app_verbose.so \
app_test.so app_forkcdr.so app_math.so app_realtime.so \
app_dumpchan.so app_waitforsilence.so app_while.so app_setrdnis.so \
app_md5.so app_readfile.so app_chanspy.so app_settransfercapability.so \
app_dictate.so app_externalivr.so app_directed_pickup.so \
app_mixmonitor.so app_stack.so
MODULE_PREFIX=app
MENUSELECT_CATEGORY=APPS
MENUSELECT_DESCRIPTION=Applications
#
# Obsolete things...
#
#APPS+=app_sql_postgres.so
#APPS+=app_sql_odbc.so
MENUSELECT_OPTS_app_directory:=$(MENUSELECT_OPTS_app_voicemail)
ifneq ($(findstring ODBC_STORAGE,$(MENUSELECT_OPTS_app_voicemail)),)
MENUSELECT_DEPENDS_app_voicemail+=$(MENUSELECT_DEPENDS_ODBC_STORAGE)
MENUSELECT_DEPENDS_app_directory+=$(MENUSELECT_DEPENDS_ODBC_STORAGE)
#
# Experimental things
#
#APPS+=app_ivrdemo.so
#APPS+=app_skel.so
#APPS+=app_rpt.so
ifndef WITHOUT_ZAPTEL
ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/linux/zaptel.h)$(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/zaptel.h),)
APPS+=app_zapras.so app_meetme.so app_flash.so app_zapbarge.so app_zapscan.so app_page.so
endif
ifneq ($(findstring IMAP_STORAGE,$(MENUSELECT_OPTS_app_voicemail)),)
MENUSELECT_DEPENDS_app_voicemail+=$(MENUSELECT_DEPENDS_IMAP_STORAGE)
endif # WITHOUT_ZAPTEL
ifneq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/local/include/osp/osp.h $(CROSS_COMPILE_TARGET)/usr/include/osp/osp.h),)
APPS+=app_osplookup.so
endif
all: _all
include $(ASTTOPDIR)/Makefile.moddir_rules
ifneq ($(findstring $(OSARCH), mingw32 cygwin ),)
LIBS+= -lres_features.so -lres_ael_share.so -lres_monitor.so -lres_speech.so
LIBS+= -lres_smdi.so
ifeq ($(findstring BSD,${OSARCH}),BSD)
CFLAGS+=-I$(CROSS_COMPILE_TARGET)/usr/local/include -L$(CROSS_COMPILE_TARGET)/usr/local/lib
endif
CURLLIBS=$(shell $(CROSS_COMPILE_BIN)curl-config --libs)
ifneq ($(shell if [[ 0x`$(CROSS_COMPILE_BIN)curl-config --vernum` -ge 0x70907 ]]; then echo "OK" ; fi),)
ifneq (${CURLLIBS},)
APPS+=app_curl.so
endif
endif
ifeq (${OSARCH},CYGWIN)
CYGSOLINK=-Wl,--out-implib=lib$@.a -Wl,--export-all-symbols
CYGSOLIB=-L.. -L. -L../res -lasterisk.dll -lres_features.so -lres_adsi.so -lres_monitor.so
else
CFLAGS+=-fPIC
APPS+=app_sms.so
endif
#
# If you have UnixODBC you can use ODBC voicemail
# storage
#
# Uncomment to use ODBC storage
#CFLAGS+=-DUSE_ODBC_STORAGE
# Uncomment for extended ODBC voicemail storage
#CFLAGS+=-DEXTENDED_ODBC_STORAGE
# See doc/README.odbcstorage for more information
all: $(APPS)
clean:
rm -f *.so *.o .depend
%.so : %.o
$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB}
app_rpt.so : app_rpt.o
$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} -ltonezone
install: all
for x in $(APPS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
rm -f $(DESTDIR)$(MODULES_DIR)/app_datetime.so
rm -f $(DESTDIR)$(MODULES_DIR)/app_qcall.so
app_curl.so: app_curl.o
$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} $(CURLLIBS)
app_sql_postgres.o: app_sql_postgres.c
$(CC) -pipe -I$(CROSS_COMPILE_TARGET)/usr/local/pgsql/include -I$(CROSS_COMPILE_TARGET)/usr/include/postgresql $(CFLAGS) -c -o app_sql_postgres.o app_sql_postgres.c
app_sql_postgres.so: app_sql_postgres.o
$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} -L/usr/local/pgsql/lib -lpq
app_sql_odbc.so: app_sql_odbc.o
$(CC) $(SOLINK) -o $@ ${CYGSOLINK} $< ${CYGSOLIB} -lodbc
ifeq (SunOS,$(shell uname))
app_chanspy.so: app_chanspy.o
$(CC) $(SOLINK) -o $@ $< -lrt
endif
ifneq ($(wildcard .depend),)
include .depend
endif
depend: .depend
.depend:
../build_tools/mkdep $(CFLAGS) `ls *.c`
env:
env

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,451 +0,0 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2003 - 2006, Aheeva Technology.
*
* Claude Klimos (claude.klimos@aheeva.com)
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*
* A license has been granted to Digium (via disclaimer) for the use of
* this code.
*/
/*! \file
*
* \brief Answering machine detection
*
* \author Claude Klimos (claude.klimos@aheeva.com)
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/app.h"
static char *app = "AMD";
static char *synopsis = "Attempts to detect answering machines";
static char *descrip =
" AMD([initialSilence],[greeting],[afterGreetingSilence],[totalAnalysisTime]\n"
" ,[minimumWordLength],[betweenWordsSilence],[maximumNumberOfWords]\n"
" ,[silenceThreshold],[|maximumWordLength])\n"
" This application attempts to detect answering machines at the beginning\n"
" of outbound calls. Simply call this application after the call\n"
" has been answered (outbound only, of course).\n"
" When loaded, AMD reads amd.conf and uses the parameters specified as\n"
" default values. Those default values get overwritten when calling AMD\n"
" with parameters.\n"
"- 'initialSilence' is the maximum silence duration before the greeting. If\n"
" exceeded then MACHINE.\n"
"- 'greeting' is the maximum length of a greeting. If exceeded then MACHINE.\n"
"- 'afterGreetingSilence' is the silence after detecting a greeting.\n"
" If exceeded then HUMAN.\n"
"- 'totalAnalysisTime' is the maximum time allowed for the algorithm to decide\n"
" on a HUMAN or MACHINE.\n"
"- 'minimumWordLength'is the minimum duration of Voice to considered as a word.\n"
"- 'betweenWordsSilence' is the minimum duration of silence after a word to \n"
" consider the audio that follows as a new word.\n"
"- 'maximumNumberOfWords'is the maximum number of words in the greeting. \n"
" If exceeded then MACHINE.\n"
"- 'silenceThreshold' is the silence threshold.\n"
"- 'maximumWordLength' is the maximum duration of a word to accept. If exceeded then MACHINE\n"
"This application sets the following channel variables upon completion:\n"
" AMDSTATUS - This is the status of the answering machine detection.\n"
" Possible values are:\n"
" MACHINE | HUMAN | NOTSURE | HANGUP\n"
" AMDCAUSE - Indicates the cause that led to the conclusion.\n"
" Possible values are:\n"
" TOOLONG-<%d total_time>\n"
" INITIALSILENCE-<%d silenceDuration>-<%d initialSilence>\n"
" HUMAN-<%d silenceDuration>-<%d afterGreetingSilence>\n"
" MAXWORDS-<%d wordsCount>-<%d maximumNumberOfWords>\n"
" LONGGREETING-<%d voiceDuration>-<%d greeting>\n"
" MAXWORDLENGTH-<%d consecutiveVoiceDuration>\n";
#define STATE_IN_WORD 1
#define STATE_IN_SILENCE 2
/* Some default values for the algorithm parameters. These defaults will be overwritten from amd.conf */
static int dfltInitialSilence = 2500;
static int dfltGreeting = 1500;
static int dfltAfterGreetingSilence = 800;
static int dfltTotalAnalysisTime = 5000;
static int dfltMinimumWordLength = 100;
static int dfltBetweenWordsSilence = 50;
static int dfltMaximumNumberOfWords = 3;
static int dfltSilenceThreshold = 256;
static int dfltMaximumWordLength = 5000; /* Setting this to a large default so it is not used unless specify it in the configs or command line */
/* Set to the lowest ms value provided in amd.conf or application parameters */
static int dfltMaxWaitTimeForFrame = 50;
static void isAnsweringMachine(struct ast_channel *chan, void *data)
{
int res = 0;
struct ast_frame *f = NULL;
struct ast_dsp *silenceDetector = NULL;
int dspsilence = 0, readFormat, framelength = 0;
int inInitialSilence = 1;
int inGreeting = 0;
int voiceDuration = 0;
int silenceDuration = 0;
int iTotalTime = 0;
int iWordsCount = 0;
int currentState = STATE_IN_WORD;
int previousState = STATE_IN_SILENCE;
int consecutiveVoiceDuration = 0;
char amdCause[256] = "", amdStatus[256] = "";
char *parse = ast_strdupa(data);
/* Lets set the initial values of the variables that will control the algorithm.
The initial values are the default ones. If they are passed as arguments
when invoking the application, then the default values will be overwritten
by the ones passed as parameters. */
int initialSilence = dfltInitialSilence;
int greeting = dfltGreeting;
int afterGreetingSilence = dfltAfterGreetingSilence;
int totalAnalysisTime = dfltTotalAnalysisTime;
int minimumWordLength = dfltMinimumWordLength;
int betweenWordsSilence = dfltBetweenWordsSilence;
int maximumNumberOfWords = dfltMaximumNumberOfWords;
int silenceThreshold = dfltSilenceThreshold;
int maximumWordLength = dfltMaximumWordLength;
int maxWaitTimeForFrame = dfltMaxWaitTimeForFrame;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(argInitialSilence);
AST_APP_ARG(argGreeting);
AST_APP_ARG(argAfterGreetingSilence);
AST_APP_ARG(argTotalAnalysisTime);
AST_APP_ARG(argMinimumWordLength);
AST_APP_ARG(argBetweenWordsSilence);
AST_APP_ARG(argMaximumNumberOfWords);
AST_APP_ARG(argSilenceThreshold);
AST_APP_ARG(argMaximumWordLength);
);
ast_verb(3, "AMD: %s %s %s (Fmt: %d)\n", chan->name ,chan->cid.cid_ani, chan->cid.cid_rdnis, chan->readformat);
/* Lets parse the arguments. */
if (!ast_strlen_zero(parse)) {
/* Some arguments have been passed. Lets parse them and overwrite the defaults. */
AST_STANDARD_APP_ARGS(args, parse);
if (!ast_strlen_zero(args.argInitialSilence))
initialSilence = atoi(args.argInitialSilence);
if (!ast_strlen_zero(args.argGreeting))
greeting = atoi(args.argGreeting);
if (!ast_strlen_zero(args.argAfterGreetingSilence))
afterGreetingSilence = atoi(args.argAfterGreetingSilence);
if (!ast_strlen_zero(args.argTotalAnalysisTime))
totalAnalysisTime = atoi(args.argTotalAnalysisTime);
if (!ast_strlen_zero(args.argMinimumWordLength))
minimumWordLength = atoi(args.argMinimumWordLength);
if (!ast_strlen_zero(args.argBetweenWordsSilence))
betweenWordsSilence = atoi(args.argBetweenWordsSilence);
if (!ast_strlen_zero(args.argMaximumNumberOfWords))
maximumNumberOfWords = atoi(args.argMaximumNumberOfWords);
if (!ast_strlen_zero(args.argSilenceThreshold))
silenceThreshold = atoi(args.argSilenceThreshold);
if (!ast_strlen_zero(args.argMaximumWordLength))
maximumWordLength = atoi(args.argMaximumWordLength);
} else {
ast_debug(1, "AMD using the default parameters.\n");
}
/* Find lowest ms value, that will be max wait time for a frame */
if (maxWaitTimeForFrame > initialSilence)
maxWaitTimeForFrame = initialSilence;
if (maxWaitTimeForFrame > greeting)
maxWaitTimeForFrame = greeting;
if (maxWaitTimeForFrame > afterGreetingSilence)
maxWaitTimeForFrame = afterGreetingSilence;
if (maxWaitTimeForFrame > totalAnalysisTime)
maxWaitTimeForFrame = totalAnalysisTime;
if (maxWaitTimeForFrame > minimumWordLength)
maxWaitTimeForFrame = minimumWordLength;
if (maxWaitTimeForFrame > betweenWordsSilence)
maxWaitTimeForFrame = betweenWordsSilence;
/* Now we're ready to roll! */
ast_verb(3, "AMD: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] "
"totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] maximumWordLength [%d] \n",
initialSilence, greeting, afterGreetingSilence, totalAnalysisTime,
minimumWordLength, betweenWordsSilence, maximumNumberOfWords, silenceThreshold, maximumWordLength);
/* Set read format to signed linear so we get signed linear frames in */
readFormat = chan->readformat;
if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0 ) {
ast_log(LOG_WARNING, "AMD: Channel [%s]. Unable to set to linear mode, giving up\n", chan->name );
pbx_builtin_setvar_helper(chan , "AMDSTATUS", "");
pbx_builtin_setvar_helper(chan , "AMDCAUSE", "");
return;
}
/* Create a new DSP that will detect the silence */
if (!(silenceDetector = ast_dsp_new())) {
ast_log(LOG_WARNING, "AMD: Channel [%s]. Unable to create silence detector :(\n", chan->name );
pbx_builtin_setvar_helper(chan , "AMDSTATUS", "");
pbx_builtin_setvar_helper(chan , "AMDCAUSE", "");
return;
}
/* Set silence threshold to specified value */
ast_dsp_set_threshold(silenceDetector, silenceThreshold);
/* Now we go into a loop waiting for frames from the channel */
while ((res = ast_waitfor(chan, 2 * maxWaitTimeForFrame)) > -1) {
/* If we fail to read in a frame, that means they hung up */
if (!(f = ast_read(chan))) {
ast_verb(3, "AMD: Channel [%s]. HANGUP\n", chan->name);
ast_debug(1, "Got hangup\n");
strcpy(amdStatus, "HANGUP");
res = 1;
break;
}
if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_NULL || f->frametype == AST_FRAME_CNG) {
/* If the total time exceeds the analysis time then give up as we are not too sure */
if (f->frametype == AST_FRAME_VOICE)
framelength = (ast_codec_get_samples(f) / DEFAULT_SAMPLES_PER_MS);
else
framelength += 2 * maxWaitTimeForFrame;
iTotalTime += framelength;
if (iTotalTime >= totalAnalysisTime) {
ast_verb(3, "AMD: Channel [%s]. Too long...\n", chan->name );
ast_frfree(f);
strcpy(amdStatus , "NOTSURE");
sprintf(amdCause , "TOOLONG-%d", iTotalTime);
break;
}
/* Feed the frame of audio into the silence detector and see if we get a result */
if (f->frametype != AST_FRAME_VOICE)
dspsilence += 2 * maxWaitTimeForFrame;
else {
dspsilence = 0;
ast_dsp_silence(silenceDetector, f, &dspsilence);
}
if (dspsilence > 0) {
silenceDuration = dspsilence;
if (silenceDuration >= betweenWordsSilence) {
if (currentState != STATE_IN_SILENCE ) {
previousState = currentState;
ast_verb(3, "AMD: Channel [%s]. Changed state to STATE_IN_SILENCE\n", chan->name);
}
/* Find words less than word duration */
if (consecutiveVoiceDuration < minimumWordLength && consecutiveVoiceDuration > 0){
ast_verb(3, "AMD: Channel [%s]. Short Word Duration: %d\n", chan->name, consecutiveVoiceDuration);
}
currentState = STATE_IN_SILENCE;
consecutiveVoiceDuration = 0;
}
if (inInitialSilence == 1 && silenceDuration >= initialSilence) {
ast_verb(3, "AMD: Channel [%s]. ANSWERING MACHINE: silenceDuration:%d initialSilence:%d\n",
chan->name, silenceDuration, initialSilence);
ast_frfree(f);
strcpy(amdStatus , "MACHINE");
sprintf(amdCause , "INITIALSILENCE-%d-%d", silenceDuration, initialSilence);
res = 1;
break;
}
if (silenceDuration >= afterGreetingSilence && inGreeting == 1) {
ast_verb(3, "AMD: Channel [%s]. HUMAN: silenceDuration:%d afterGreetingSilence:%d\n",
chan->name, silenceDuration, afterGreetingSilence);
ast_frfree(f);
strcpy(amdStatus , "HUMAN");
sprintf(amdCause , "HUMAN-%d-%d", silenceDuration, afterGreetingSilence);
res = 1;
break;
}
} else {
consecutiveVoiceDuration += framelength;
voiceDuration += framelength;
/* If I have enough consecutive voice to say that I am in a Word, I can only increment the
number of words if my previous state was Silence, which means that I moved into a word. */
if (consecutiveVoiceDuration >= minimumWordLength && currentState == STATE_IN_SILENCE) {
iWordsCount++;
ast_verb(3, "AMD: Channel [%s]. Word detected. iWordsCount:%d\n", chan->name, iWordsCount);
previousState = currentState;
currentState = STATE_IN_WORD;
}
if (consecutiveVoiceDuration >= maximumWordLength){
ast_verb(3, "AMD: Channel [%s]. Maximum Word Length detected. [%d]\n", chan->name, consecutiveVoiceDuration);
ast_frfree(f);
strcpy(amdStatus , "MACHINE");
sprintf(amdCause , "MAXWORDLENGTH-%d", consecutiveVoiceDuration);
break;
}
if (iWordsCount >= maximumNumberOfWords) {
ast_verb(3, "AMD: Channel [%s]. ANSWERING MACHINE: iWordsCount:%d\n", chan->name, iWordsCount);
ast_frfree(f);
strcpy(amdStatus , "MACHINE");
sprintf(amdCause , "MAXWORDS-%d-%d", iWordsCount, maximumNumberOfWords);
res = 1;
break;
}
if (inGreeting == 1 && voiceDuration >= greeting) {
ast_verb(3, "AMD: Channel [%s]. ANSWERING MACHINE: voiceDuration:%d greeting:%d\n", chan->name, voiceDuration, greeting);
ast_frfree(f);
strcpy(amdStatus , "MACHINE");
sprintf(amdCause , "LONGGREETING-%d-%d", voiceDuration, greeting);
res = 1;
break;
}
if (voiceDuration >= minimumWordLength ) {
if (silenceDuration > 0)
ast_verb(3, "AMD: Channel [%s]. Detected Talk, previous silence duration: %d\n", chan->name, silenceDuration);
silenceDuration = 0;
}
if (consecutiveVoiceDuration >= minimumWordLength && inGreeting == 0) {
/* Only go in here once to change the greeting flag when we detect the 1st word */
if (silenceDuration > 0)
ast_verb(3, "AMD: Channel [%s]. Before Greeting Time: silenceDuration: %d voiceDuration: %d\n", chan->name, silenceDuration, voiceDuration);
inInitialSilence = 0;
inGreeting = 1;
}
}
}
ast_frfree(f);
}
if (!res) {
/* It took too long to get a frame back. Giving up. */
ast_verb(3, "AMD: Channel [%s]. Too long...\n", chan->name);
strcpy(amdStatus , "NOTSURE");
sprintf(amdCause , "TOOLONG-%d", iTotalTime);
}
/* Set the status and cause on the channel */
pbx_builtin_setvar_helper(chan , "AMDSTATUS" , amdStatus);
pbx_builtin_setvar_helper(chan , "AMDCAUSE" , amdCause);
/* Restore channel read format */
if (readFormat && ast_set_read_format(chan, readFormat))
ast_log(LOG_WARNING, "AMD: Unable to restore read format on '%s'\n", chan->name);
/* Free the DSP used to detect silence */
ast_dsp_free(silenceDetector);
return;
}
static int amd_exec(struct ast_channel *chan, void *data)
{
isAnsweringMachine(chan, data);
return 0;
}
static int load_config(int reload)
{
struct ast_config *cfg = NULL;
char *cat = NULL;
struct ast_variable *var = NULL;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
if (!(cfg = ast_config_load("amd.conf", config_flags))) {
ast_log(LOG_ERROR, "Configuration file amd.conf missing.\n");
return -1;
} else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
return 0;
cat = ast_category_browse(cfg, NULL);
while (cat) {
if (!strcasecmp(cat, "general") ) {
var = ast_variable_browse(cfg, cat);
while (var) {
if (!strcasecmp(var->name, "initial_silence")) {
dfltInitialSilence = atoi(var->value);
} else if (!strcasecmp(var->name, "greeting")) {
dfltGreeting = atoi(var->value);
} else if (!strcasecmp(var->name, "after_greeting_silence")) {
dfltAfterGreetingSilence = atoi(var->value);
} else if (!strcasecmp(var->name, "silence_threshold")) {
dfltSilenceThreshold = atoi(var->value);
} else if (!strcasecmp(var->name, "total_analysis_time")) {
dfltTotalAnalysisTime = atoi(var->value);
} else if (!strcasecmp(var->name, "min_word_length")) {
dfltMinimumWordLength = atoi(var->value);
} else if (!strcasecmp(var->name, "between_words_silence")) {
dfltBetweenWordsSilence = atoi(var->value);
} else if (!strcasecmp(var->name, "maximum_number_of_words")) {
dfltMaximumNumberOfWords = atoi(var->value);
} else if (!strcasecmp(var->name, "maximum_word_length")) {
dfltMaximumWordLength = atoi(var->value);
} else {
ast_log(LOG_WARNING, "%s: Cat:%s. Unknown keyword %s at line %d of amd.conf\n",
app, cat, var->name, var->lineno);
}
var = var->next;
}
}
cat = ast_category_browse(cfg, cat);
}
ast_config_destroy(cfg);
ast_verb(3, "AMD defaults: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] "
"totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] maximumWordLength [%d]\n",
dfltInitialSilence, dfltGreeting, dfltAfterGreetingSilence, dfltTotalAnalysisTime,
dfltMinimumWordLength, dfltBetweenWordsSilence, dfltMaximumNumberOfWords, dfltSilenceThreshold, dfltMaximumWordLength);
return 0;
}
static int unload_module(void)
{
return ast_unregister_application(app);
}
static int load_module(void)
{
if (load_config(0))
return AST_MODULE_LOAD_DECLINE;
if (ast_register_application(app, amd_exec, synopsis, descrip))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
}
static int reload(void)
{
if (load_config(1))
return AST_MODULE_LOAD_DECLINE;
return AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Answering Machine Detection Application",
.load = load_module,
.unload = unload_module,
.reload = reload,
);

View File

@@ -17,20 +17,24 @@
*/
/*! \file
*
* \brief Execute arbitrary authenticate commands
*
* \author Mark Spencer <markster@digium.com>
*
*
* \ingroup applications
*/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
@@ -38,189 +42,191 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/astdb.h"
#include "asterisk/utils.h"
enum {
OPT_ACCOUNT = (1 << 0),
OPT_DATABASE = (1 << 1),
OPT_MULTIPLE = (1 << 3),
OPT_REMOVE = (1 << 4),
} auth_option_flags;
AST_APP_OPTIONS(auth_app_options, {
AST_APP_OPTION('a', OPT_ACCOUNT),
AST_APP_OPTION('d', OPT_DATABASE),
AST_APP_OPTION('m', OPT_MULTIPLE),
AST_APP_OPTION('r', OPT_REMOVE),
});
static char *tdesc = "Authentication Application";
static char *app = "Authenticate";
static char *synopsis = "Authenticate a user";
static char *descrip =
" Authenticate(password[,options[,maxdigits]]): This application asks the caller\n"
"to enter a given password in order to continue dialplan execution. If the password\n"
"begins with the '/' character, it is interpreted as a file which contains a list of\n"
" Authenticate(password[|options]): This application asks the caller to enter a\n"
"given password in order to continue dialplan execution. If the password begins\n"
"with the '/' character, it is interpreted as a file which contains a list of\n"
"valid passwords, listed 1 password per line in the file.\n"
" When using a database key, the value associated with the key can be anything.\n"
"Users have three attempts to authenticate before the channel is hung up.\n"
"Users have three attempts to authenticate before the channel is hung up. If the\n"
"passsword is invalid, the 'j' option is specified, and priority n+101 exists,\n"
"dialplan execution will continnue at this location.\n"
" Options:\n"
" a - Set the channels' account code to the password that is entered\n"
" d - Interpret the given path as database key, not a literal file\n"
" j - Support jumping to n+101 if authentication fails\n"
" m - Interpret the given path as a file which contains a list of account\n"
" codes and password hashes delimited with ':', listed one per line in\n"
" the file. When one of the passwords is matched, the channel will have\n"
" its account code set to the corresponding account code in the file.\n"
" r - Remove the database key upon successful entry (valid with 'd' only)\n"
" maxdigits - maximum acceptable number of digits. Stops reading after\n"
" maxdigits have been entered (without requiring the user to\n"
" press the '#' key).\n"
" Defaults to 0 - no limit - wait for the user press the '#' key.\n"
;
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int auth_exec(struct ast_channel *chan, void *data)
{
int res = 0, retries, maxdigits;
char passwd[256], *prompt = "agent-pass", *argcopy = NULL;
struct ast_flags flags = {0};
AST_DECLARE_APP_ARGS(arglist,
AST_APP_ARG(password);
AST_APP_ARG(options);
AST_APP_ARG(maxdigits);
);
int res=0;
int jump = 0;
int retries;
struct localuser *u;
char password[256]="";
char passwd[256];
char *opts;
char *prompt;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Authenticate requires an argument(password)\n");
return -1;
}
LOCAL_USER_ADD(u);
if (chan->_state != AST_STATE_UP) {
if ((res = ast_answer(chan)))
res = ast_answer(chan);
if (res) {
LOCAL_USER_REMOVE(u);
return -1;
}
}
argcopy = ast_strdupa(data);
AST_STANDARD_APP_ARGS(arglist, argcopy);
if (!ast_strlen_zero(arglist.options))
ast_app_parse_options(auth_app_options, &flags, NULL, arglist.options);
if (!ast_strlen_zero(arglist.maxdigits)) {
maxdigits = atoi(arglist.maxdigits);
if ((maxdigits<1) || (maxdigits>sizeof(passwd)-2))
maxdigits = sizeof(passwd) - 2;
} else {
maxdigits = sizeof(passwd) - 2;
}
strncpy(password, data, sizeof(password) - 1);
opts=strchr(password, '|');
if (opts) {
*opts = 0;
opts++;
} else
opts = "";
if (strchr(opts, 'j'))
jump = 1;
/* Start asking for password */
prompt = "agent-pass";
for (retries = 0; retries < 3; retries++) {
if ((res = ast_app_getdata(chan, prompt, passwd, maxdigits, 0)) < 0)
res = ast_app_getdata(chan, prompt, passwd, sizeof(passwd) - 2, 0);
if (res < 0)
break;
res = 0;
if (password[0] == '/') {
if (strchr(opts, 'd')) {
char tmp[256];
/* Compare against a database key */
if (!ast_db_get(password + 1, passwd, tmp, sizeof(tmp))) {
/* It's a good password */
if (strchr(opts, 'r')) {
ast_db_del(password + 1, passwd);
}
break;
}
} else {
/* Compare against a file */
FILE *f;
f = fopen(password, "r");
if (f) {
char buf[256] = "";
char md5passwd[33] = "";
char *md5secret = NULL;
if (arglist.password[0] != '/') {
/* Compare against a fixed password */
if (!strcmp(passwd, arglist.password))
break;
} else if (ast_test_flag(&flags,OPT_DATABASE)) {
char tmp[256];
/* Compare against a database key */
if (!ast_db_get(arglist.password + 1, passwd, tmp, sizeof(tmp))) {
/* It's a good password */
if (ast_test_flag(&flags,OPT_REMOVE))
ast_db_del(arglist.password + 1, passwd);
break;
while (!feof(f)) {
fgets(buf, sizeof(buf), f);
if (!feof(f) && !ast_strlen_zero(buf)) {
buf[strlen(buf) - 1] = '\0';
if (strchr(opts, 'm')) {
md5secret = strchr(buf, ':');
if (md5secret == NULL)
continue;
*md5secret = '\0';
md5secret++;
ast_md5_hash(md5passwd, passwd);
if (!strcmp(md5passwd, md5secret)) {
if (strchr(opts, 'a'))
ast_cdr_setaccount(chan, buf);
break;
}
} else {
if (!strcmp(passwd, buf)) {
if (strchr(opts, 'a'))
ast_cdr_setaccount(chan, buf);
break;
}
}
}
}
fclose(f);
if (!ast_strlen_zero(buf)) {
if (strchr(opts, 'm')) {
if (md5secret && !strcmp(md5passwd, md5secret))
break;
} else {
if (!strcmp(passwd, buf))
break;
}
}
} else
ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", password, strerror(errno));
}
} else {
/* Compare against a file */
FILE *f;
char buf[256] = "", md5passwd[33] = "", *md5secret = NULL;
if (!(f = fopen(arglist.password, "r"))) {
ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", arglist.password, strerror(errno));
continue;
}
for (;;) {
size_t len;
if (feof(f))
break;
if (!fgets(buf, sizeof(buf), f)) {
continue;
}
if (ast_strlen_zero(buf))
continue;
len = strlen(buf) - 1;
if (buf[len] == '\n')
buf[len] = '\0';
if (ast_test_flag(&flags, OPT_MULTIPLE)) {
md5secret = buf;
strsep(&md5secret, ":");
if (!md5secret)
continue;
ast_md5_hash(md5passwd, passwd);
if (!strcmp(md5passwd, md5secret)) {
if (ast_test_flag(&flags,OPT_ACCOUNT))
ast_cdr_setaccount(chan, buf);
break;
}
} else {
if (!strcmp(passwd, buf)) {
if (ast_test_flag(&flags, OPT_ACCOUNT))
ast_cdr_setaccount(chan, buf);
break;
}
}
}
fclose(f);
if (!ast_strlen_zero(buf)) {
if (ast_test_flag(&flags, OPT_MULTIPLE)) {
if (md5secret && !strcmp(md5passwd, md5secret))
break;
} else {
if (!strcmp(passwd, buf))
break;
}
}
/* Compare against a fixed password */
if (!strcmp(passwd, password))
break;
}
prompt = "auth-incorrect";
prompt="auth-incorrect";
}
if ((retries < 3) && !res) {
if (ast_test_flag(&flags,OPT_ACCOUNT) && !ast_test_flag(&flags,OPT_MULTIPLE))
if (strchr(opts, 'a') && !strchr(opts, 'm'))
ast_cdr_setaccount(chan, passwd);
if (!(res = ast_streamfile(chan, "auth-thankyou", chan->language)))
res = ast_streamfile(chan, "auth-thankyou", chan->language);
if (!res)
res = ast_waitstream(chan, "");
} else {
if (!ast_streamfile(chan, "vm-goodbye", chan->language))
res = ast_waitstream(chan, "");
res = -1;
if (jump && ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0) {
res = 0;
} else {
if (!ast_streamfile(chan, "vm-goodbye", chan->language))
res = ast_waitstream(chan, "");
res = -1;
}
}
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app);
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
if (ast_register_application(app, auth_exec, synopsis, descrip))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
return ast_register_application(app, auth_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Authentication Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -17,47 +17,81 @@
*/
/*! \file
*
* \brief Applications connected with CDR engine
*
* \author Martin Pycko <martinp@digium.com>
*
* \ingroup applications
*/
#include <sys/types.h>
#include <stdlib.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/channel.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
static char *nocdr_descrip =
static char *tdesc = "Tell Asterisk to not maintain a CDR for the current call";
static char *nocdr_descrip =
" NoCDR(): This application will tell Asterisk not to maintain a CDR for the\n"
"current call.\n";
static char *nocdr_app = "NoCDR";
static char *nocdr_synopsis = "Tell Asterisk to not maintain a CDR for the current call";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int nocdr_exec(struct ast_channel *chan, void *data)
{
if (chan->cdr)
ast_set_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED);
struct localuser *u;
LOCAL_USER_ADD(u);
if (chan->cdr) {
ast_cdr_free(chan->cdr);
chan->cdr = NULL;
}
LOCAL_USER_REMOVE(u);
return 0;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(nocdr_app);
int res;
res = ast_unregister_application(nocdr_app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
if (ast_register_application(nocdr_app, nocdr_exec, nocdr_synopsis, nocdr_descrip))
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
return ast_register_application(nocdr_app, nocdr_exec, nocdr_synopsis, nocdr_descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Tell Asterisk to not maintain a CDR for the current call");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -18,79 +18,79 @@
*/
/*! \file
*
* \brief Check if Channel is Available
*
* \author Mark Spencer <markster@digium.com>
* \author James Golovich <james@gnuinter.net>
* \brief Check if Channel is Available
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <sys/ioctl.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
#include "asterisk/devicestate.h"
#include "asterisk/options.h"
static char *tdesc = "Check channel availability";
static char *app = "ChanIsAvail";
static char *synopsis = "Check channel availability";
static char *descrip =
" ChanIsAvail(Technology/resource[&Technology2/resource2...][,options]): \n"
static char *descrip =
" ChanIsAvail(Technology/resource[&Technology2/resource2...][|options]): \n"
"This application will check to see if any of the specified channels are\n"
"available.\n"
"available. The following variables will be set by this application:\n"
" ${AVAILCHAN} - the name of the available channel, if one exists\n"
" ${AVAILORIGCHAN} - the canonical channel name that was used to create the channel\n"
" ${AVAILSTATUS} - the status code for the available channel\n"
" Options:\n"
" s - Consider the channel unavailable if the channel is in use at all.\n"
" t - Simply checks if specified channels exist in the channel list\n"
" (implies option s).\n"
"Note that the AVAILSTATUS variable is used for both device state\n"
"and cause code. It is therefore possible for it to give a value that may\n"
"indicate a device is available when it is not. It is suggested that the\n"
"AVAILORIGCHAN variable is used instead to see whether a device is available\n"
"or not.\n"
"This application sets the following channel variable upon completion:\n"
" AVAILCHAN - the name of the available channel, if one exists\n"
" AVAILORIGCHAN - the canonical channel name that was used to create the channel\n"
" AVAILSTATUS - the status code for the available channel\n";
" s - Consider the channel unavailable if the channel is in use at all\n"
" j - Support jumping to priority n+101 if no channel is available\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int chanavail_exec(struct ast_channel *chan, void *data)
{
int res=-1, inuse=-1, option_state=0, string_compare=0;
int res=-1, inuse=-1, option_state=0, priority_jump=0;
int status;
char *info, tmp[512], trychan[512], *peers, *tech, *number, *rest, *cur;
struct localuser *u;
char *info, tmp[512], trychan[512], *peers, *tech, *number, *rest, *cur, *options, *stringp;
struct ast_channel *tempchan;
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");
ast_log(LOG_WARNING, "ChanIsAvail requires an argument (Zap/1&Zap/2)\n");
return -1;
}
info = ast_strdupa(data);
LOCAL_USER_ADD(u);
AST_STANDARD_APP_ARGS(args, info);
if (args.options) {
if (strchr(args.options, 's'))
info = ast_strdupa(data);
stringp = info;
strsep(&stringp, "|");
options = strsep(&stringp, "|");
if (options) {
if (strchr(options, 's'))
option_state = 1;
if (strchr(args.options, 't'))
string_compare = 1;
if (strchr(options, 'j'))
priority_jump = 1;
}
peers = args.reqchans;
peers = info;
if (peers) {
cur = peers;
do {
@@ -104,22 +104,17 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
number = strchr(tech, '/');
if (!number) {
ast_log(LOG_WARNING, "ChanIsAvail argument takes format ([technology]/[device])\n");
LOCAL_USER_REMOVE(u);
return -1;
}
*number = '\0';
number++;
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 (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). */
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);
}
@@ -144,19 +139,47 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
if (res < 1) {
pbx_builtin_setvar_helper(chan, "AVAILCHAN", "");
pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", "");
if (priority_jump || option_priority_jumping) {
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) {
LOCAL_USER_REMOVE(u);
return -1;
}
}
}
LOCAL_USER_REMOVE(u);
return 0;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app);
int res = 0;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, chanavail_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Check channel availability");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,98 +0,0 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2006, Sergey Basmanov
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief ChannelRedirect application
*
* \author Sergey Basmanov <sergey_basmanov@mail.ru>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
#include "asterisk/features.h"
static char *app = "ChannelRedirect";
static char *synopsis = "Redirects given channel to a dialplan target.";
static char *descrip =
"ChannelRedirect(channel,[[context,]extension,]priority)\n"
" Sends the specified channel to the specified extension priority\n"
"This application sets the following channel variables upon completion:\n"
" CHANNELREDIRECT_STATUS - Are set to the result of the redirection\n"
" either NOCHANNEL or SUCCESS\n";
static int asyncgoto_exec(struct ast_channel *chan, void *data)
{
int res = -1;
char *info;
struct ast_channel *chan2 = NULL;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(channel);
AST_APP_ARG(label);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "%s requires an argument (channel,[[context,]exten,]priority)\n", app);
return -1;
}
info = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, info);
if (ast_strlen_zero(args.channel) || ast_strlen_zero(args.label)) {
ast_log(LOG_WARNING, "%s requires an argument (channel,[[context,]exten,]priority)\n", app);
return -1;
}
chan2 = ast_get_channel_by_name_locked(args.channel);
if (!chan2) {
ast_log(LOG_WARNING, "No such channel: %s\n", args.channel);
pbx_builtin_setvar_helper(chan, "CHANNELREDIRECT_STATUS", "NOCHANNEL");
return 0;
}
if (chan2->pbx) {
ast_set_flag(chan2, AST_FLAG_BRIDGE_HANGUP_DONT); /* don't let the after-bridge code run the h-exten */
}
res = ast_async_parseable_goto(chan2, args.label);
pbx_builtin_setvar_helper(chan, "CHANNELREDIRECT_STATUS", "SUCCESS");
ast_channel_unlock(chan2);
return res;
}
static int unload_module(void)
{
return ast_unregister_application(app);
}
static int load_module(void)
{
return ast_register_application(app, asyncgoto_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Redirects a given channel to a dialplan target");

File diff suppressed because it is too large Load Diff

View File

@@ -17,28 +17,38 @@
*/
/*! \file
*
* \brief Trivial application to control playback of a sound file
*
* \author Mark Spencer <markster@digium.com>
*
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
static const char *tdesc = "Control Playback Application";
static const char *app = "ControlPlayback";
static const char *synopsis = "Play a file with fast forward and rewind";
static const char *descrip =
" ControlPlayback(file[,skipms[,ff[,rew[,stop[,pause[,restart,options]]]]]]]):\n"
static const char *descrip =
" ControlPlayback(file[|skipms[|ff[|rew[|stop[|pause[|restart|options]]]]]]]):\n"
"This application will play back the given filename. By default, the '*' key\n"
"can be used to rewind, and the '#' key can be used to fast-forward.\n"
"Parameters:\n"
@@ -50,142 +60,131 @@ static const char *descrip =
" pause - Pause playback when this DTMF digit is received.\n"
" restart - Restart playback when this DTMF digit is received.\n"
"Options:\n"
" o(#) - Start at # ms from the beginning of the file.\n"
"This application sets the following channel variables upon completion:\n"
" j - Jump to priority n+101 if the requested file is not found.\n"
"This application sets the following channel variable upon completion:\n"
" CPLAYBACKSTATUS - This variable contains the status of the attempt as a text\n"
" string, one of: SUCCESS | USERSTOPPED | ERROR\n"
" CPLAYBACKOFFSET - This contains the offset in ms into the file where\n"
" playback was at when it stopped. -1 is end of file.\n"
" CPLAYBACKSTOPKEY - If the playback is stopped by the user this variable contains\n"
" the key that was pressed.\n";
" string, one of: SUCCESS | USERSTOPPED | ERROR\n";
enum {
OPT_OFFSET = (1 << 1),
};
STANDARD_LOCAL_USER;
enum {
OPT_ARG_OFFSET = 0,
/* must stay as the last entry ... */
OPT_ARG_ARRAY_LEN,
};
AST_APP_OPTIONS(cpb_opts, BEGIN_OPTIONS
AST_APP_OPTION_ARG('o', OPT_OFFSET, OPT_ARG_OFFSET),
END_OPTIONS
);
LOCAL_USER_DECL;
static int is_on_phonepad(char key)
{
return key == 35 || key == 42 || (key >= 48 && key <= 57);
}
static int is_argument(const char *haystack, int needle)
{
if (ast_strlen_zero(haystack))
return 0;
if (strchr(haystack, needle))
return -1;
return 0;
}
static int controlplayback_exec(struct ast_channel *chan, void *data)
{
int res = 0;
int res = 0, priority_jump = 0;
int skipms = 0;
long offsetms = 0;
char offsetbuf[20];
char stopkeybuf[2];
struct localuser *u;
char *tmp;
struct ast_flags opts = { 0, };
char *opt_args[OPT_ARG_ARRAY_LEN];
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(filename);
AST_APP_ARG(skip);
AST_APP_ARG(fwd);
AST_APP_ARG(rev);
AST_APP_ARG(stop);
AST_APP_ARG(pause);
AST_APP_ARG(restart);
AST_APP_ARG(options);
);
int argc;
char *argv[8];
enum arg_ids {
arg_file = 0,
arg_skip = 1,
arg_fwd = 2,
arg_rev = 3,
arg_stop = 4,
arg_pause = 5,
arg_restart = 6,
options = 7,
};
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "ControlPlayback requires an argument (filename)\n");
return -1;
}
LOCAL_USER_ADD(u);
tmp = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, tmp);
memset(argv, 0, sizeof(argv));
if (args.argc < 1) {
argc = ast_app_separate_args(tmp, '|', argv, sizeof(argv) / sizeof(argv[0]));
if (argc < 1) {
ast_log(LOG_WARNING, "ControlPlayback requires an argument (filename)\n");
LOCAL_USER_REMOVE(u);
return -1;
}
skipms = args.skip ? (atoi(args.skip) ? atoi(args.skip) : 3000) : 3000;
skipms = argv[arg_skip] ? atoi(argv[arg_skip]) : 3000;
if (!skipms)
skipms = 3000;
if (!args.fwd || !is_on_phonepad(*args.fwd)) {
char *digit = "#";
if (!is_argument(args.rev, *digit) && !is_argument(args.stop, *digit) && !is_argument(args.pause, *digit) && !is_argument(args.restart, *digit))
args.fwd = digit;
else
args.fwd = NULL;
}
if (!args.rev || !is_on_phonepad(*args.rev)) {
char *digit = "*";
if (!is_argument(args.fwd, *digit) && !is_argument(args.stop, *digit) && !is_argument(args.pause, *digit) && !is_argument(args.restart, *digit))
args.rev = digit;
else
args.rev = NULL;
}
ast_debug(1, "Forward key = %s, Rewind key = %s\n", args.fwd, args.rev);
if (args.stop && !is_on_phonepad(*args.stop))
args.stop = NULL;
if (args.pause && !is_on_phonepad(*args.pause))
args.pause = NULL;
if (args.restart && !is_on_phonepad(*args.restart))
args.restart = NULL;
if (!argv[arg_fwd] || !is_on_phonepad(*argv[arg_fwd]))
argv[arg_fwd] = "#";
if (!argv[arg_rev] || !is_on_phonepad(*argv[arg_rev]))
argv[arg_rev] = "*";
if (argv[arg_stop] && !is_on_phonepad(*argv[arg_stop]))
argv[arg_stop] = NULL;
if (argv[arg_pause] && !is_on_phonepad(*argv[arg_pause]))
argv[arg_pause] = NULL;
if (argv[arg_restart] && !is_on_phonepad(*argv[arg_restart]))
argv[arg_restart] = NULL;
if (args.options) {
ast_app_parse_options(cpb_opts, &opts, opt_args, args.options);
if (ast_test_flag(&opts, OPT_OFFSET))
offsetms = atol(opt_args[OPT_ARG_OFFSET]);
if (argv[options]) {
if (strchr(argv[options], 'j'))
priority_jump = 1;
}
res = ast_control_streamfile(chan, args.filename, args.fwd, args.rev, args.stop, args.pause, args.restart, skipms, &offsetms);
res = ast_control_streamfile(chan, argv[arg_file], argv[arg_fwd], argv[arg_rev], argv[arg_stop], argv[arg_pause], argv[arg_restart], skipms);
/* If we stopped on one of our stop keys, return 0 */
if (res > 0 && args.stop && strchr(args.stop, res)) {
pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "USERSTOPPED");
snprintf(stopkeybuf, sizeof(stopkeybuf), "%c", res);
pbx_builtin_setvar_helper(chan, "CPLAYBACKSTOPKEY", stopkeybuf);
if (argv[arg_stop] && strchr(argv[arg_stop], res)) {
res = 0;
pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "USERSTOPPED");
} else {
if (res < 0) {
if (priority_jump || option_priority_jumping) {
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) {
ast_log(LOG_WARNING, "ControlPlayback tried to jump to priority n+101 as requested, but priority didn't exist\n");
}
}
res = 0;
pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "ERROR");
} else
pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "SUCCESS");
}
snprintf(offsetbuf, sizeof(offsetbuf), "%ld", offsetms);
pbx_builtin_setvar_helper(chan, "CPLAYBACKOFFSET", offsetbuf);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, controlplayback_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Control Playback Application");
char *description(void)
{
return (char *) tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

257
apps/app_curl.c Normal file
View File

@@ -0,0 +1,257 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2004 - 2005, Tilghman Lesher
*
* Tilghman Lesher <curl-20050919@the-tilghman.com>
* and Brian Wilkins <bwilkins@cfl.rr.com> (Added POST option)
*
* app_curl.c is distributed with no restrictions on usage or
* redistribution.
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
*/
/*! \file
* \brief Curl - App to load a URL
*
* \ingroup applications
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/cli.h"
#include "asterisk/options.h"
#include "asterisk/module.h"
static char *tdesc = "Load external URL";
static char *app = "Curl";
static char *synopsis = "Load an external URL";
static char *descrip =
" Curl(URL[|postdata]): This application will request the specified URL.\n"
"It is mainly used for signalling external applications of an event.\n"
"Parameters:\n"
" URL - This is the external URL to request.\n"
" postdata - This information will be treated as POST data.\n"
"This application will set the following variable:\n"
" CURL - This variable will contain the resulting page.\n"
"This application has been deprecated in favor of the CURL function.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
struct MemoryStruct {
char *memory;
size_t size;
};
static void *myrealloc(void *ptr, size_t size)
{
/* There might be a realloc() out there that doesn't like reallocing
NULL pointers, so we take care of it here */
if (ptr)
return realloc(ptr, size);
else
return malloc(size);
}
static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
register int realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)data;
mem->memory = (char *)myrealloc(mem->memory, mem->size + realsize + 1);
if (mem->memory) {
memcpy(&(mem->memory[mem->size]), ptr, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
}
return realsize;
}
static int curl_internal(struct MemoryStruct *chunk, char *url, char *post)
{
CURL *curl;
curl = curl_easy_init();
if (!curl) {
return -1;
}
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)chunk);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "asterisk-libcurl-agent/1.0");
if (post) {
curl_easy_setopt(curl, CURLOPT_POST, 1);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post);
}
curl_easy_perform(curl);
curl_easy_cleanup(curl);
return 0;
}
static int curl_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct localuser *u;
char *info, *post_data=NULL, *url;
struct MemoryStruct chunk = { NULL, 0 };
static int dep_warning = 0;
if (!dep_warning) {
ast_log(LOG_WARNING, "The application Curl is deprecated. Please use the CURL() function instead.\n");
dep_warning = 1;
}
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Curl requires an argument (URL)\n");
return -1;
}
LOCAL_USER_ADD(u);
if ((info = ast_strdupa(data))) {
url = strsep(&info, "|");
post_data = info;
} else {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
if (! curl_internal(&chunk, url, post_data)) {
if (chunk.memory) {
chunk.memory[chunk.size] = '\0';
if (chunk.memory[chunk.size - 1] == 10)
chunk.memory[chunk.size - 1] = '\0';
pbx_builtin_setvar_helper(chan, "CURL", chunk.memory);
free(chunk.memory);
}
} else {
ast_log(LOG_ERROR, "Cannot allocate curl structure\n");
res = -1;
}
LOCAL_USER_REMOVE(u);
return res;
}
static char *acf_curl_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
{
struct localuser *u;
char *info, *post_data=NULL, *url;
struct MemoryStruct chunk = { NULL, 0 };
*buf = '\0';
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "CURL requires an argument (URL)\n");
return buf;
}
LOCAL_USER_ACF_ADD(u);
info = ast_strdupa(data);
if (!info) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return buf;
}
url = strsep(&info, "|");
post_data = info;
if (! curl_internal(&chunk, url, post_data)) {
if (chunk.memory) {
chunk.memory[chunk.size] = '\0';
if (chunk.memory[chunk.size - 1] == 10)
chunk.memory[chunk.size - 1] = '\0';
ast_copy_string(buf, chunk.memory, len);
free(chunk.memory);
}
} else {
ast_log(LOG_ERROR, "Cannot allocate curl structure\n");
}
LOCAL_USER_REMOVE(u);
return buf;
}
struct ast_custom_function acf_curl = {
.name = "CURL",
.synopsis = "Retrieves the contents of a URL",
.syntax = "CURL(url[|post-data])",
.desc =
" url - URL to retrieve\n"
" post-data - Optional data to send as a POST (GET is default action)\n",
.read = acf_curl_exec,
};
int unload_module(void)
{
int res;
res = ast_custom_function_unregister(&acf_curl);
res |= ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
curl_global_cleanup();
return res;
}
int load_module(void)
{
int res;
curl_global_init(CURL_GLOBAL_ALL);
res = ast_custom_function_register(&acf_curl);
res |= ast_register_application(app, curl_exec, synopsis, descrip);
return res;
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

473
apps/app_cut.c Normal file
View File

@@ -0,0 +1,473 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <app_cut__v003@the-tilghman.com>
*
* This code is released by the author with no restrictions on usage.
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
*/
/*! \file
* \brief Cut application
*
* \ingroup applications
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
/* Maximum length of any variable */
#define MAXRESULT 1024
static char *tdesc = "Cut out information from a string";
static char *app_cut = "Cut";
static char *cut_synopsis = "Splits a variable's contents using the specified delimiter";
static char *cut_descrip =
" Cut(newvar=varname,delimiter,fieldspec): This application will split the\n"
"contents of a variable based on the given delimeter and store the result in\n"
"a new variable.\n"
"Parameters:\n"
" newvar - new variable created from result string\n"
" varname - variable you want cut\n"
" delimiter - defaults to '-'\n"
" fieldspec - number of the field you want (1-based offset)\n"
" may also be specified as a range (with -)\n"
" or group of ranges and fields (with &)\n"
"This application has been deprecated in favor of the CUT function.\n";
static char *app_sort = "Sort";
static char *app_sort_synopsis = "Sorts a list of keywords and values";
static char *app_sort_descrip =
" Sort(newvar=key1:val1[,key2:val2[[...],keyN:valN]]): This application will\n"
"sort the list provided in ascending order. The result will be stored in the\n"
"specified variable name.\n"
" This application has been deprecated in favor of the SORT function.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
struct sortable_keys {
char *key;
float value;
};
static int sort_subroutine(const void *arg1, const void *arg2)
{
const struct sortable_keys *one=arg1, *two=arg2;
if (one->value < two->value) {
return -1;
} else if (one->value == two->value) {
return 0;
} else {
return 1;
}
}
#define ERROR_NOARG (-1)
#define ERROR_NOMEM (-2)
#define ERROR_USAGE (-3)
static int sort_internal(struct ast_channel *chan, char *data, char *buffer, size_t buflen)
{
char *strings, *ptrkey, *ptrvalue;
int count=1, count2, element_count=0;
struct sortable_keys *sortable_keys;
memset(buffer, 0, buflen);
if (!data) {
return ERROR_NOARG;
}
strings = ast_strdupa((char *)data);
if (!strings) {
return ERROR_NOMEM;
}
for (ptrkey = strings; *ptrkey; ptrkey++) {
if (*ptrkey == '|') {
count++;
}
}
sortable_keys = alloca(count * sizeof(struct sortable_keys));
if (!sortable_keys) {
return ERROR_NOMEM;
}
memset(sortable_keys, 0, count * sizeof(struct sortable_keys));
/* Parse each into a struct */
count2 = 0;
while ((ptrkey = strsep(&strings, "|"))) {
ptrvalue = index(ptrkey, ':');
if (!ptrvalue) {
count--;
continue;
}
*ptrvalue = '\0';
ptrvalue++;
sortable_keys[count2].key = ptrkey;
sscanf(ptrvalue, "%f", &sortable_keys[count2].value);
count2++;
}
/* Sort the structs */
qsort(sortable_keys, count, sizeof(struct sortable_keys), sort_subroutine);
for (count2 = 0; count2 < count; count2++) {
int blen = strlen(buffer);
if (element_count++) {
strncat(buffer + blen, ",", buflen - blen - 1);
blen++;
}
strncat(buffer + blen, sortable_keys[count2].key, buflen - blen - 1);
}
return 0;
}
static int cut_internal(struct ast_channel *chan, char *data, char *buffer, size_t buflen)
{
char *s, *args[3], *varname=NULL, *delimiter=NULL, *field=NULL;
int args_okay = 0;
memset(buffer, 0, buflen);
/* Check and parse arguments */
if (data) {
s = ast_strdupa((char *)data);
if (s) {
ast_app_separate_args(s, '|', args, 3);
varname = args[0];
delimiter = args[1];
field = args[2];
if (field) {
args_okay = 1;
}
} else {
return ERROR_NOMEM;
}
}
if (args_okay) {
char d, ds[2];
char *tmp = alloca(strlen(varname) + 4);
char varvalue[MAXRESULT], *tmp2=varvalue;
if (tmp) {
snprintf(tmp, strlen(varname) + 4, "${%s}", varname);
memset(varvalue, 0, sizeof(varvalue));
} else {
return ERROR_NOMEM;
}
if (delimiter[0])
d = delimiter[0];
else
d = '-';
/* String form of the delimiter, for use with strsep(3) */
snprintf(ds, sizeof(ds), "%c", d);
pbx_substitute_variables_helper(chan, tmp, tmp2, MAXRESULT - 1);
if (tmp2) {
int curfieldnum = 1;
while ((tmp2 != NULL) && (field != NULL)) {
char *nextgroup = strsep(&field, "&");
int num1 = 0, num2 = MAXRESULT;
char trashchar;
if (sscanf(nextgroup, "%d-%d", &num1, &num2) == 2) {
/* range with both start and end */
} else if (sscanf(nextgroup, "-%d", &num2) == 1) {
/* range with end */
num1 = 0;
} else if ((sscanf(nextgroup, "%d%c", &num1, &trashchar) == 2) && (trashchar == '-')) {
/* range with start */
num2 = MAXRESULT;
} else if (sscanf(nextgroup, "%d", &num1) == 1) {
/* single number */
num2 = num1;
} else {
return ERROR_USAGE;
}
/* Get to start, if any */
if (num1 > 0) {
while ((tmp2 != (char *)NULL + 1) && (curfieldnum < num1)) {
tmp2 = index(tmp2, d) + 1;
curfieldnum++;
}
}
/* Most frequent problem is the expectation of reordering fields */
if ((num1 > 0) && (curfieldnum > num1)) {
ast_log(LOG_WARNING, "We're already past the field you wanted?\n");
}
/* Re-null tmp2 if we added 1 to NULL */
if (tmp2 == (char *)NULL + 1)
tmp2 = NULL;
/* Output fields until we either run out of fields or num2 is reached */
while ((tmp2 != NULL) && (curfieldnum <= num2)) {
char *tmp3 = strsep(&tmp2, ds);
int curlen = strlen(buffer);
if (curlen) {
snprintf(buffer + curlen, buflen - curlen, "%c%s", d, tmp3);
} else {
snprintf(buffer, buflen, "%s", tmp3);
}
curfieldnum++;
}
}
}
} else {
return ERROR_NOARG;
}
return 0;
}
static int sort_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *varname, *strings, result[512] = "";
static int dep_warning=0;
if (!dep_warning) {
ast_log(LOG_WARNING, "The application Sort is deprecated. Please use the SORT() function instead.\n");
dep_warning=1;
}
if (!data) {
ast_log(LOG_ERROR, "Sort() requires an argument\n");
return 0;
}
LOCAL_USER_ADD(u);
strings = ast_strdupa((char *)data);
if (!strings) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return 0;
}
varname = strsep(&strings, "=");
switch (sort_internal(chan, strings, result, sizeof(result))) {
case ERROR_NOARG:
ast_log(LOG_ERROR, "Sort() requires an argument\n");
res = 0;
break;
case ERROR_NOMEM:
ast_log(LOG_ERROR, "Out of memory\n");
res = -1;
break;
case 0:
pbx_builtin_setvar_helper(chan, varname, result);
res = 0;
break;
default:
ast_log(LOG_ERROR, "Unknown internal error\n");
res = -1;
}
LOCAL_USER_REMOVE(u);
return res;
}
static int cut_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *s, *newvar=NULL, result[512];
static int dep_warning = 0;
LOCAL_USER_ADD(u);
if (!dep_warning) {
ast_log(LOG_WARNING, "The application Cut is deprecated. Please use the CUT() function instead.\n");
dep_warning=1;
}
/* Check and parse arguments */
if (data) {
s = ast_strdupa((char *)data);
if (s) {
newvar = strsep(&s, "=");
} else {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
}
switch (cut_internal(chan, s, result, sizeof(result))) {
case ERROR_NOARG:
ast_log(LOG_ERROR, "Cut() requires an argument\n");
res = 0;
break;
case ERROR_NOMEM:
ast_log(LOG_ERROR, "Out of memory\n");
res = -1;
break;
case ERROR_USAGE:
ast_log(LOG_ERROR, "Usage: %s\n", cut_synopsis);
res = 0;
break;
case 0:
pbx_builtin_setvar_helper(chan, newvar, result);
res = 0;
break;
default:
ast_log(LOG_ERROR, "Unknown internal error\n");
res = -1;
}
LOCAL_USER_REMOVE(u);
return res;
}
static char *acf_sort_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
{
struct localuser *u;
LOCAL_USER_ACF_ADD(u);
switch (sort_internal(chan, data, buf, len)) {
case ERROR_NOARG:
ast_log(LOG_ERROR, "SORT() requires an argument\n");
break;
case ERROR_NOMEM:
ast_log(LOG_ERROR, "Out of memory\n");
break;
case 0:
break;
default:
ast_log(LOG_ERROR, "Unknown internal error\n");
}
LOCAL_USER_REMOVE(u);
return buf;
}
static char *acf_cut_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
{
struct localuser *u;
LOCAL_USER_ACF_ADD(u);
switch (cut_internal(chan, data, buf, len)) {
case ERROR_NOARG:
ast_log(LOG_ERROR, "CUT() requires an argument\n");
break;
case ERROR_NOMEM:
ast_log(LOG_ERROR, "Out of memory\n");
break;
case ERROR_USAGE:
ast_log(LOG_ERROR, "Usage: %s\n", cut_synopsis);
break;
case 0:
break;
default:
ast_log(LOG_ERROR, "Unknown internal error\n");
}
LOCAL_USER_REMOVE(u);
return buf;
}
struct ast_custom_function acf_sort = {
.name = "SORT",
.synopsis = "Sorts a list of key/vals into a list of keys, based upon the vals",
.syntax = "SORT(key1:val1[...][,keyN:valN])",
.desc =
"Takes a comma-separated list of keys and values, each separated by a colon, and returns a\n"
"comma-separated list of the keys, sorted by their values. Values will be evaluated as\n"
"floating-point numbers.\n",
.read = acf_sort_exec,
};
struct ast_custom_function acf_cut = {
.name = "CUT",
.synopsis = "Slices and dices strings, based upon a named delimiter.",
.syntax = "CUT(<varname>,<char-delim>,<range-spec>)",
.desc =
" varname - variable you want cut\n"
" char-delim - defaults to '-'\n"
" range-spec - number of the field you want (1-based offset)\n"
" may also be specified as a range (with -)\n"
" or group of ranges and fields (with &)\n",
.read = acf_cut_exec,
};
int unload_module(void)
{
int res;
res = ast_custom_function_unregister(&acf_cut);
res |= ast_custom_function_unregister(&acf_sort);
res |= ast_unregister_application(app_sort);
res |= ast_unregister_application(app_cut);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
int res;
res = ast_custom_function_register(&acf_cut);
res |= ast_custom_function_register(&acf_sort);
res |= ast_register_application(app_sort, sort_exec, app_sort_synopsis, app_sort_descrip);
res |= ast_register_application(app_cut, cut_exec, cut_synopsis, cut_descrip);
return res;
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

101
apps/app_datetime.c Normal file
View File

@@ -0,0 +1,101 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
* \brief Time of day - Report the time of day
*
* \ingroup applications
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/say.h"
static char *tdesc = "Date and Time";
static char *app = "DateTime";
static char *synopsis = "Say the date and time";
static char *descrip =
" DateTime(): This application will say the current date and time.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int datetime_exec(struct ast_channel *chan, void *data)
{
int res=0;
time_t t;
struct localuser *u;
LOCAL_USER_ADD(u);
time(&t);
if (chan->_state != AST_STATE_UP)
res = ast_answer(chan);
if (!res)
res = ast_say_datetime(chan, t, "", chan->language);
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
return ast_register_application(app, datetime_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -22,53 +22,90 @@
*
* \brief Database access functions
*
* \author Mark Spencer <markster@digium.com>
* \author Jefferson Noxon <jeff@debian.org>
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/options.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/astdb.h"
#include "asterisk/lock.h"
#include "asterisk/options.h"
static char *tdesc = "Database Access Functions";
static char *g_descrip =
" DBget(varname=family/key[|options]): This application will retrieve a value\n"
"from the Asterisk database and store it in the given variable.\n"
" Options:\n"
" j - Jump to priority n+101 if the requested family/key isn't found.\n"
" This application sets the following channel variable upon completion:\n"
" DBGETSTATUS - This variable will contain the status of the attempt\n"
" FOUND | NOTFOUND \n"
" This application has been deprecated in favor of the DB function.\n";
static char *p_descrip =
" DBput(family/key=value): This application will store the given value in the\n"
"specified location in the Asterisk database.\n"
" This application has been deprecated in favor of the DB function.\n";
/*! \todo XXX Remove this application after 1.4 is relased */
static char *d_descrip =
" DBdel(family/key): This application will delete a key from the Asterisk\n"
"database.\n"
" This application has been DEPRECATED in favor of the DB_DELETE function.\n";
"database.\n";
static char *dt_descrip =
" DBdeltree(family[/keytree]): This application will delete a family or keytree\n"
"from the Asterisk database\n";
static char *g_app = "DBget";
static char *p_app = "DBput";
static char *d_app = "DBdel";
static char *dt_app = "DBdeltree";
static char *g_synopsis = "Retrieve a value from the database";
static char *p_synopsis = "Store a value in the database";
static char *d_synopsis = "Delete a key from the database";
static char *dt_synopsis = "Delete a family or keytree from the database";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int deltree_exec(struct ast_channel *chan, void *data)
{
char *argv, *family, *keytree;
struct localuser *u;
LOCAL_USER_ADD(u);
argv = ast_strdupa(data);
if (!argv) {
ast_log(LOG_ERROR, "Memory allocation failed\n");
LOCAL_USER_REMOVE(u);
return 0;
}
if (strchr(argv, '/')) {
family = strsep(&argv, "/");
keytree = strsep(&argv, "\0");
if (!family || !keytree) {
ast_debug(1, "Ignoring; Syntax error in argument\n");
return 0;
}
if (!family || !keytree) {
ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
LOCAL_USER_REMOVE(u);
return 0;
}
if (ast_strlen_zero(keytree))
keytree = 0;
} else {
@@ -76,13 +113,19 @@ static int deltree_exec(struct ast_channel *chan, void *data)
keytree = 0;
}
if (keytree)
ast_verb(3, "DBdeltree: family=%s, keytree=%s\n", family, keytree);
else
ast_verb(3, "DBdeltree: family=%s\n", family);
if (option_verbose > 2) {
if (keytree)
ast_verbose(VERBOSE_PREFIX_3 "DBdeltree: family=%s, keytree=%s\n", family, keytree);
else
ast_verbose(VERBOSE_PREFIX_3 "DBdeltree: family=%s\n", family);
}
if (ast_db_deltree(family, keytree))
ast_verb(3, "DBdeltree: Error deleting key from database.\n");
if (ast_db_deltree(family, keytree)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "DBdeltree: Error deleting key from database.\n");
}
LOCAL_USER_REMOVE(u);
return 0;
}
@@ -90,50 +133,191 @@ static int deltree_exec(struct ast_channel *chan, void *data)
static int del_exec(struct ast_channel *chan, void *data)
{
char *argv, *family, *key;
static int deprecation_warning = 0;
struct localuser *u;
if (!deprecation_warning) {
deprecation_warning = 1;
ast_log(LOG_WARNING, "The DBdel application has been deprecated in favor of the DB_DELETE dialplan function!\n");
}
LOCAL_USER_ADD(u);
argv = ast_strdupa(data);
if (!argv) {
ast_log (LOG_ERROR, "Memory allocation failed\n");
LOCAL_USER_REMOVE(u);
return 0;
}
if (strchr(argv, '/')) {
family = strsep(&argv, "/");
key = strsep(&argv, "\0");
if (!family || !key) {
ast_debug(1, "Ignoring; Syntax error in argument\n");
ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
LOCAL_USER_REMOVE(u);
return 0;
}
ast_verb(3, "DBdel: family=%s, key=%s\n", family, key);
if (ast_db_del(family, key))
ast_verb(3, "DBdel: Error deleting key from database.\n");
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "DBdel: family=%s, key=%s\n", family, key);
if (ast_db_del(family, key)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "DBdel: Error deleting key from database.\n");
}
} else {
ast_debug(1, "Ignoring, no parameters\n");
ast_log(LOG_DEBUG, "Ignoring, no parameters\n");
}
LOCAL_USER_REMOVE(u);
return 0;
}
static int put_exec(struct ast_channel *chan, void *data)
{
char *argv, *value, *family, *key;
static int dep_warning = 0;
struct localuser *u;
LOCAL_USER_ADD(u);
if (!dep_warning) {
ast_log(LOG_WARNING, "This application has been deprecated, please use the ${DB(family/key)} function instead.\n");
dep_warning = 1;
}
argv = ast_strdupa(data);
if (!argv) {
ast_log(LOG_ERROR, "Memory allocation failed\n");
LOCAL_USER_REMOVE(u);
return 0;
}
if (strchr(argv, '/') && strchr(argv, '=')) {
family = strsep(&argv, "/");
key = strsep(&argv, "=");
value = strsep(&argv, "\0");
if (!value || !family || !key) {
ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
LOCAL_USER_REMOVE(u);
return 0;
}
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "DBput: family=%s, key=%s, value=%s\n", family, key, value);
if (ast_db_put(family, key, value)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "DBput: Error writing value to database.\n");
}
} else {
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
}
LOCAL_USER_REMOVE(u);
return 0;
}
static int unload_module(void)
static int get_exec(struct ast_channel *chan, void *data)
{
char *argv, *varname, *family, *key, *options = NULL;
char dbresult[256];
static int dep_warning = 0;
int priority_jump = 0;
struct localuser *u;
LOCAL_USER_ADD(u);
if (!dep_warning) {
ast_log(LOG_WARNING, "This application has been deprecated, please use the ${DB(family/key)} function instead.\n");
dep_warning = 1;
}
argv = ast_strdupa(data);
if (!argv) {
ast_log(LOG_ERROR, "Memory allocation failed\n");
LOCAL_USER_REMOVE(u);
return 0;
}
if (strchr(argv, '=') && strchr(argv, '/')) {
varname = strsep(&argv, "=");
family = strsep(&argv, "/");
if (strchr((void *)&argv, '|')) {
key = strsep(&argv, "|");
options = strsep(&argv, "\0");
} else
key = strsep(&argv, "\0");
if (!varname || !family || !key) {
ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
LOCAL_USER_REMOVE(u);
return 0;
}
if (options) {
if (strchr(options, 'j'))
priority_jump = 1;
}
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "DBget: varname=%s, family=%s, key=%s\n", varname, family, key);
if (!ast_db_get(family, key, dbresult, sizeof (dbresult) - 1)) {
pbx_builtin_setvar_helper(chan, varname, dbresult);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "DBget: set variable %s to %s\n", varname, dbresult);
pbx_builtin_setvar_helper(chan, "DBGETSTATUS", "FOUND");
} else {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "DBget: Value not found in database.\n");
if (priority_jump || option_priority_jumping) {
/* Send the call to n+101 priority, where n is the current priority */
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
}
pbx_builtin_setvar_helper(chan, "DBGETSTATUS", "NOTFOUND");
}
} else {
ast_log(LOG_DEBUG, "Ignoring, no parameters\n");
}
LOCAL_USER_REMOVE(u);
return 0;
}
int unload_module(void)
{
int retval;
retval = ast_unregister_application(dt_app);
retval |= ast_unregister_application(d_app);
retval |= ast_unregister_application(p_app);
retval |= ast_unregister_application(g_app);
STANDARD_HANGUP_LOCALUSERS;
return retval;
}
static int load_module(void)
int load_module(void)
{
int retval;
retval = ast_register_application(d_app, del_exec, d_synopsis, d_descrip);
retval = ast_register_application(g_app, get_exec, g_synopsis, g_descrip);
retval |= ast_register_application(p_app, put_exec, p_synopsis, p_descrip);
retval |= ast_register_application(d_app, del_exec, d_synopsis, d_descrip);
retval |= ast_register_application(dt_app, deltree_exec, dt_synopsis, dt_descrip);
return retval;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Database Access Functions");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

File diff suppressed because it is too large Load Diff

View File

@@ -22,30 +22,38 @@
*
* \brief Virtual Dictation Machine Application For Asterisk
*
* \author Anthony Minessale II <anthmct@yahoo.com>
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h> /* for mkdir */
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <sys/stat.h>
#include "asterisk/paths.h" /* use ast_config_AST_SPOOL_DIR */
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/say.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
static char *tdesc = "Virtual Dictation Machine";
static char *app = "Dictate";
static char *synopsis = "Virtual Dictation Machine";
static char *desc = " Dictate([<base_dir>[,<filename>]])\n"
static char *desc = " Dictate([<base_dir>])\n"
"Start dictation machine using optional base dir for files.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
typedef enum {
DFLAG_RECORD = (1 << 0),
DFLAG_PLAY = (1 << 1),
@@ -61,7 +69,7 @@ typedef enum {
#define ast_toggle_flag(it,flag) if(ast_test_flag(it, flag)) ast_clear_flag(it, flag); else ast_set_flag(it, flag)
static int play_and_wait(struct ast_channel *chan, char *file, char *digits)
static int play_and_wait(struct ast_channel *chan, char *file, char *digits)
{
int res = -1;
if (!ast_streamfile(chan, file, chan->language)) {
@@ -72,19 +80,16 @@ static int play_and_wait(struct ast_channel *chan, char *file, char *digits)
static int dictate_exec(struct ast_channel *chan, void *data)
{
char *path = NULL, filein[256], *filename = "";
char *parse;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(base);
AST_APP_ARG(filename);
);
char *mydata, *argv[2], *path = NULL, filein[256];
char dftbase[256];
char *base;
struct ast_flags flags = {0};
struct ast_filestream *fs;
struct ast_frame *f = NULL;
struct localuser *u;
int ffactor = 320 * 80,
res = 0,
argc = 0,
done = 0,
oldr = 0,
lastop = 0,
@@ -94,44 +99,37 @@ static int dictate_exec(struct ast_channel *chan, void *data)
len = 0,
maxlen = 0,
mode = 0;
LOCAL_USER_ADD(u);
snprintf(dftbase, sizeof(dftbase), "%s/dictate", ast_config_AST_SPOOL_DIR);
if (!ast_strlen_zero(data)) {
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
} else
args.argc = 0;
if (args.argc && !ast_strlen_zero(args.base)) {
base = args.base;
if (!ast_strlen_zero(data) && (mydata = ast_strdupa(data))) {
argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
}
if (argc) {
base = argv[0];
} else {
base = dftbase;
}
if (args.argc > 1 && args.filename) {
filename = args.filename;
}
oldr = chan->readformat;
if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)) < 0) {
ast_log(LOG_WARNING, "Unable to set to linear mode.\n");
LOCAL_USER_REMOVE(u);
return -1;
}
if (chan->_state != AST_STATE_UP) {
ast_answer(chan);
}
ast_answer(chan);
ast_safe_sleep(chan, 200);
for (res = 0; !res;) {
if (ast_strlen_zero(filename)) {
if (ast_app_getdata(chan, "dictate/enter_filename", filein, sizeof(filein), 0) ||
ast_strlen_zero(filein)) {
res = -1;
break;
}
} else {
ast_copy_string(filein, filename, sizeof(filein));
filename = "";
for(res = 0; !res;) {
if (ast_app_getdata(chan, "dictate/enter_filename", filein, sizeof(filein), 0) ||
ast_strlen_zero(filein)) {
res = -1;
break;
}
ast_mkdir(base, 0755);
mkdir(base, 0755);
len = strlen(base) + strlen(filein) + 2;
if (!path || len > maxlen) {
path = alloca(len);
@@ -142,7 +140,7 @@ static int dictate_exec(struct ast_channel *chan, void *data)
}
snprintf(path, len, "%s/%s", base, filein);
fs = ast_writefile(path, "raw", NULL, O_CREAT|O_APPEND, 0, AST_FILE_MODE);
fs = ast_writefile(path, "raw", NULL, O_CREAT|O_APPEND, 0, 0700);
mode = DMODE_PLAY;
memset(&flags, 0, sizeof(flags));
ast_set_flag(&flags, DFLAG_PAUSE);
@@ -172,7 +170,7 @@ static int dictate_exec(struct ast_channel *chan, void *data)
if (speed > 4) {
speed = 1;
}
res = ast_say_number(chan, speed, AST_DIGIT_ANY, chan->language, NULL);
res = ast_say_number(chan, speed, AST_DIGIT_ANY, chan->language, (char *) NULL);
break;
case '7':
samples -= ffactor;
@@ -284,7 +282,7 @@ static int dictate_exec(struct ast_channel *chan, void *data)
case DMODE_RECORD:
if (lastop != DMODE_RECORD) {
int oflags = O_CREAT | O_WRONLY;
if (ast_test_flag(&flags, DFLAG_PAUSE)) {
if (ast_test_flag(&flags, DFLAG_PAUSE)) {
digit = play_and_wait(chan, "dictate/record_mode", AST_DIGIT_ANY);
if (digit == 0) {
digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY);
@@ -300,7 +298,7 @@ static int dictate_exec(struct ast_channel *chan, void *data)
} else {
oflags |= O_APPEND;
}
fs = ast_writefile(path, "raw", NULL, oflags, 0, AST_FILE_MODE);
fs = ast_writefile(path, "raw", NULL, oflags, 0, 0700);
if (ast_test_flag(&flags, DFLAG_TRUNC)) {
ast_seekstream(fs, 0, SEEK_SET);
ast_clear_flag(&flags, DFLAG_TRUNC);
@@ -322,19 +320,40 @@ static int dictate_exec(struct ast_channel *chan, void *data)
if (oldr) {
ast_set_read_format(chan, oldr);
}
LOCAL_USER_REMOVE(u);
return 0;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, dictate_exec, synopsis, desc);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Virtual Dictation Machine");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -20,153 +20,150 @@
*
* \brief Directed Call Pickup Support
*
* \author Joshua Colp <jcolp@digium.com>
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
#include "asterisk/features.h"
#define PICKUPMARK "PICKUPMARK"
static const char *tdesc = "Directed Call Pickup Application";
static const char *app = "Pickup";
static const char *synopsis = "Directed Call Pickup";
static const char *descrip =
" Pickup([extension[@context][&extension2@[context]...]]): This application can\n"
"pickup any ringing channel that is calling the specified extension. If no\n"
"context is specified, the current context will be used. If you use the special\n"
"string \"PICKUPMARK\" for the context parameter, for example 10@PICKUPMARK,\n"
"this application tries to find a channel which has defined a ${PICKUPMARK}\n"
"channel variable with the same value as \"extension\" (in this example, \"10\").\n"
"When no parameter is specified, the application will pickup a channel matching\n"
"the pickup group of the active channel.";
" Pickup(extension[@context]): This application can pickup any ringing channel\n"
"that is calling the specified extension. If no context is specified, the current\n"
"context will be used.\n";
/* Perform actual pickup between two channels */
static int pickup_do(struct ast_channel *chan, struct ast_channel *target)
{
int res = 0;
STANDARD_LOCAL_USER;
ast_debug(1, "Call pickup on '%s' by '%s'\n", target->name, chan->name);
LOCAL_USER_DECL;
if ((res = ast_answer(chan))) {
ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
return -1;
}
if ((res = ast_queue_control(chan, AST_CONTROL_ANSWER))) {
ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
return -1;
}
if ((res = ast_channel_masquerade(target, chan))) {
ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
return -1;
}
return res;
}
/* Helper function that determines whether a channel is capable of being picked up */
static int can_pickup(struct ast_channel *chan)
{
if (!chan->pbx && (chan->_state == AST_STATE_RINGING || chan->_state == AST_STATE_RING || chan->_state == AST_STATE_DOWN))
return 1;
else
return 0;
}
/* Attempt to pick up specified extension with context */
static int pickup_by_exten(struct ast_channel *chan, const char *exten, const char *context)
{
int res = -1;
struct ast_channel *target = NULL;
while ((target = ast_channel_walk_locked(target))) {
if ((!strcasecmp(target->macroexten, exten) || !strcasecmp(target->exten, exten)) &&
!strcasecmp(target->dialcontext, context) &&
(chan != target) && can_pickup(target)) {
res = pickup_do(chan, target);
ast_channel_unlock(target);
break;
}
ast_channel_unlock(target);
}
return res;
}
/* Attempt to pick up specified mark */
static int pickup_by_mark(struct ast_channel *chan, const char *mark)
{
int res = -1;
const char *tmp = NULL;
struct ast_channel *target = NULL;
while ((target = ast_channel_walk_locked(target))) {
if ((tmp = pbx_builtin_getvar_helper(target, PICKUPMARK)) &&
!strcasecmp(tmp, mark) &&
can_pickup(target)) {
res = pickup_do(chan, target);
ast_channel_unlock(target);
break;
}
ast_channel_unlock(target);
}
return res;
}
/* Main application entry point */
static int pickup_exec(struct ast_channel *chan, void *data)
{
int res = 0;
char *tmp = ast_strdupa(data);
char *exten = NULL, *context = NULL;
struct localuser *u = NULL;
struct ast_channel *origin = NULL, *target = NULL;
char *tmp = NULL, *exten = NULL, *context = NULL;
char workspace[256] = "";
if (ast_strlen_zero(data)) {
res = ast_pickup_call(chan);
return res;
ast_log(LOG_WARNING, "Pickup requires an argument (extension) !\n");
return -1;
}
LOCAL_USER_ADD(u);
/* Get the extension and context if present */
exten = data;
context = strchr(data, '@');
if (context) {
*context = '\0';
context++;
}
/* Find a channel to pickup */
origin = ast_get_channel_by_exten_locked(exten, context);
if (origin && origin->cdr) {
ast_cdr_getvar(origin->cdr, "dstchannel", &tmp, workspace,
sizeof(workspace), 0);
if (tmp) {
/* We have a possible channel... now we need to find it! */
target = ast_get_channel_by_name_locked(tmp);
} else {
ast_log(LOG_DEBUG, "No target channel found.\n");
res = -1;
}
ast_mutex_unlock(&origin->lock);
} else {
if (origin)
ast_mutex_unlock(&origin->lock);
ast_log(LOG_DEBUG, "No originating channel found.\n");
}
/* Parse extension (and context if there) */
while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) {
if ((context = strchr(exten, '@')))
*context++ = '\0';
if (!ast_strlen_zero(context) && !strcasecmp(context, PICKUPMARK)) {
if (!pickup_by_mark(chan, exten))
break;
} else {
if (!pickup_by_exten(chan, exten, !ast_strlen_zero(context) ? context : chan->context))
break;
if (res)
goto out;
if (target && (!target->pbx) && ((target->_state == AST_STATE_RINGING) || (target->_state == AST_STATE_RING))) {
ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n", target->name,
chan->name);
res = ast_answer(chan);
if (res) {
ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
res = -1;
goto out;
}
ast_log(LOG_NOTICE, "No target channel found for %s.\n", exten);
res = ast_queue_control(chan, AST_CONTROL_ANSWER);
if (res) {
ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n",
chan->name);
res = -1;
goto out;
}
res = ast_channel_masquerade(target, chan);
if (res) {
ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
res = -1;
goto out;
}
} else {
ast_log(LOG_DEBUG, "No call pickup possible...\n");
res = -1;
}
/* Done */
out:
if (target)
ast_mutex_unlock(&target->lock);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, pickup_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Directed Call Pickup Application");
char *description(void)
{
return (char *) tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

File diff suppressed because it is too large Load Diff

View File

@@ -22,19 +22,23 @@
* \brief DISA -- Direct Inward System Access Application
*
* \author Jim Dixon <jim@lambdatel.com>
*
*
* \ingroup applications
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <math.h>
#include <sys/time.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/app.h"
#include "asterisk/indications.h"
@@ -43,62 +47,57 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/translate.h"
#include "asterisk/ulaw.h"
#include "asterisk/callerid.h"
#include "asterisk/stringfields.h"
static char *tdesc = "DISA (Direct Inward System Access) Application";
static char *app = "DISA";
static char *synopsis = "DISA (Direct Inward System Access)";
static char *descrip =
"DISA(<numeric passcode>[,<context>[,<cid>[,mailbox[,options]]]]) or\n"
"DISA(<filename>[,,,,options])\n"
"The DISA, Direct Inward System Access, application allows someone from \n"
"outside the telephone switch (PBX) to obtain an \"internal\" system \n"
"dialtone and to place calls from it as if they were placing a call from \n"
"within the switch.\n"
"DISA plays a dialtone. The user enters their numeric passcode, followed by\n"
"the pound sign (#). If the passcode is correct, the user is then given\n"
"system dialtone within <context> on which a call may be placed. If the user\n"
"enters an invalid extension and extension \"i\" exists in the specified\n"
"context, it will be used.\n"
"\n"
"If you need to present a DISA dialtone without entering a password, simply\n"
"set <passcode> to \"no-password\".\n"
"\n"
"Be aware that using this may compromise the security of your PBX.\n"
"\n"
"The arguments to this application (in extensions.conf) allow either\n"
"specification of a single global passcode (that everyone uses), or\n"
"individual passcodes contained in a file.\n"
"\n"
"The file that contains the passcodes (if used) allows a complete\n"
"specification of all of the same arguments available on the command\n"
"line, with the sole exception of the options. The file may contain blank\n"
"lines, or comments starting with \"#\" or \";\".\n"
"\n"
"<context> specifies the dialplan context in which the user-entered extension\n"
"will be matched. If no context is specified, the DISA application defaults\n"
"the context to \"disa\". Presumably a normal system will have a special\n"
"context set up for DISA use with some or a lot of restrictions.\n"
"\n"
"<cid> specifies a new (different) callerid to be used for this call.\n"
"\n"
"<mailbox[@context]> will cause a stutter-dialtone (indication \"dialrecall\")\n"
"to be used, if the specified mailbox contains any new messages.\n"
"\n"
"The following options are available:\n"
" n - the DISA application will not answer initially.\n"
" p - the extension entered will be considered complete when a '#' is entered.\n";
static char *descrip =
"DISA(<numeric passcode>[|<context>]) or disa(<filename>)\n"
"The DISA, Direct Inward System Access, application allows someone from \n"
"outside the telephone switch (PBX) to obtain an \"internal\" system \n"
"dialtone and to place calls from it as if they were placing a call from \n"
"within the switch.\n"
"DISA plays a dialtone. The user enters their numeric passcode, followed by\n"
"the pound sign (#). If the passcode is correct, the user is then given\n"
"system dialtone on which a call may be placed. Obviously, this type\n"
"of access has SERIOUS security implications, and GREAT care must be\n"
"taken NOT to compromise your security.\n\n"
"There is a possibility of accessing DISA without password. Simply\n"
"exchange your password with \"no-password\".\n\n"
" Example: exten => s,1,DISA(no-password|local)\n\n"
"Be aware that using this compromises the security of your PBX.\n\n"
"The arguments to this application (in extensions.conf) allow either\n"
"specification of a single global passcode (that everyone uses), or\n"
"individual passcodes contained in a file. It also allow specification\n"
"of the context on which the user will be dialing. If no context is\n"
"specified, the DISA application defaults the context to \"disa\".\n"
"Presumably a normal system will have a special context set up\n"
"for DISA use with some or a lot of restrictions. \n\n"
"The file that contains the passcodes (if used) allows specification\n"
"of either just a passcode (defaulting to the \"disa\" context, or\n"
"passcode|context on each line of the file. The file may contain blank\n"
"lines, or comments starting with \"#\" or \";\". In addition, the\n"
"above arguments may have |new-callerid-string appended to them, to\n"
"specify a new (different) callerid to be used for this call, for\n"
"example: numeric-passcode|context|\"My Phone\" <(234) 123-4567> or \n"
"full-pathname-of-passcode-file|\"My Phone\" <(234) 123-4567>. Last\n"
"but not least, |mailbox[@context] may be appended, which will cause\n"
"a stutter-dialtone (indication \"dialrecall\") to be used, if the\n"
"specified mailbox contains any new messages, for example:\n"
"numeric-passcode|context||1234 (w/a changing callerid). Note that\n"
"in the case of specifying the numeric-passcode, the context must be\n"
"specified if the callerid is specified also.\n\n"
"If login is successful, the application looks up the dialed number in\n"
"the specified (or default) context, and executes it if found.\n"
"If the user enters an invalid extension and extension \"i\" (invalid) \n"
"exists in the context, it will be used.\n";
enum {
NOANSWER_FLAG = (1 << 0),
POUND_TO_END_FLAG = (1 << 1),
} option_flags;
STANDARD_LOCAL_USER;
AST_APP_OPTIONS(app_opts, {
AST_APP_OPTION('n', NOANSWER_FLAG),
AST_APP_OPTION('p', POUND_TO_END_FLAG),
});
LOCAL_USER_DECL;
static void play_dialtone(struct ast_channel *chan, char *mailbox)
{
@@ -115,140 +114,168 @@ static void play_dialtone(struct ast_channel *chan, char *mailbox)
static int disa_exec(struct ast_channel *chan, void *data)
{
int i = 0, j, k = 0, did_ignore = 0, special_noanswer = 0;
int firstdigittimeout = (chan->pbx ? chan->pbx->rtimeout * 1000 : 20000);
int digittimeout = (chan->pbx ? chan->pbx->dtimeout * 1000 : 10000);
struct ast_flags flags;
char *tmp, exten[AST_MAX_EXTENSION] = "", acctcode[20]="";
int i,j,k,x,did_ignore;
int firstdigittimeout = 20000;
int digittimeout = 10000;
struct localuser *u;
char *tmp, exten[AST_MAX_EXTENSION],acctcode[20]="";
char pwline[256];
char ourcidname[256],ourcidnum[256];
struct ast_frame *f;
struct timeval lastdigittime;
int res;
time_t rstart;
FILE *fp;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(passcode);
AST_APP_ARG(context);
AST_APP_ARG(cid);
AST_APP_ARG(mailbox);
AST_APP_ARG(options);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "DISA requires an argument (passcode/passcode file)\n");
ast_log(LOG_WARNING, "disa requires an argument (passcode/passcode file)\n");
return -1;
}
ast_debug(1, "Digittimeout: %d\n", digittimeout);
ast_debug(1, "Responsetimeout: %d\n", firstdigittimeout);
LOCAL_USER_ADD(u);
if (chan->pbx) {
firstdigittimeout = chan->pbx->rtimeout*1000;
digittimeout = chan->pbx->dtimeout*1000;
}
if (ast_set_write_format(chan,AST_FORMAT_ULAW)) {
ast_log(LOG_WARNING, "Unable to set write format to Mu-law on %s\n",chan->name);
LOCAL_USER_REMOVE(u);
return -1;
}
if (ast_set_read_format(chan,AST_FORMAT_ULAW)) {
ast_log(LOG_WARNING, "Unable to set read format to Mu-law on %s\n",chan->name);
LOCAL_USER_REMOVE(u);
return -1;
}
ast_log(LOG_DEBUG, "Digittimeout: %d\n", digittimeout);
ast_log(LOG_DEBUG, "Responsetimeout: %d\n", firstdigittimeout);
tmp = ast_strdupa(data);
if (!tmp) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
AST_STANDARD_APP_ARGS(args, tmp);
if (ast_strlen_zero(args.context))
args.context = "disa";
if (ast_strlen_zero(args.context))
args.context = "disa";
if (ast_strlen_zero(args.mailbox))
args.mailbox = "";
if (!ast_strlen_zero(args.options))
ast_app_parse_options(app_opts, &flags, NULL, args.options);
ast_debug(1, "Mailbox: %s\n",args.mailbox);
ast_log(LOG_DEBUG, "Mailbox: %s\n",args.mailbox);
if (chan->_state != AST_STATE_UP) {
/* answer */
ast_answer(chan);
}
i = k = x = 0; /* k is 0 for pswd entry, 1 for ext entry */
did_ignore = 0;
exten[0] = 0;
acctcode[0] = 0;
/* can we access DISA without password? */
if (!ast_test_flag(&flags, NOANSWER_FLAG)) {
if (chan->_state != AST_STATE_UP) {
/* answer */
ast_answer(chan);
}
} else special_noanswer = 1;
ast_debug(1, "Context: %s\n",args.context);
ast_log(LOG_DEBUG, "Context: %s\n",args.context);
if (!strcasecmp(args.passcode, "no-password")) {
k |= 1; /* We have the password */
ast_debug(1, "DISA no-password login success\n");
ast_log(LOG_DEBUG, "DISA no-password login success\n");
}
lastdigittime = ast_tvnow();
play_dialtone(chan, args.mailbox);
ast_set_flag(chan, AST_FLAG_END_DTMF_ONLY);
for (;;) {
/* if outa time, give em reorder */
if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) > ((k&2) ? digittimeout : firstdigittimeout)) {
ast_debug(1,"DISA %s entry timeout on chan %s\n",
if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) >
((k&2) ? digittimeout : firstdigittimeout))
{
ast_log(LOG_DEBUG,"DISA %s entry timeout on chan %s\n",
((k&1) ? "extension" : "password"),chan->name);
break;
}
if ((res = ast_waitfor(chan, -1) < 0)) {
ast_debug(1, "Waitfor returned %d\n", res);
ast_log(LOG_DEBUG, "Waitfor returned %d\n", res);
continue;
}
if (!(f = ast_read(chan))) {
ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
f = ast_read(chan);
if (f == NULL)
{
LOCAL_USER_REMOVE(u);
return -1;
}
if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
if ((f->frametype == AST_FRAME_CONTROL) &&
(f->subclass == AST_CONTROL_HANGUP))
{
ast_frfree(f);
ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
LOCAL_USER_REMOVE(u);
return -1;
}
/* If the frame coming in is not DTMF, just drop it and continue */
if (f->frametype != AST_FRAME_DTMF) {
if (f->frametype == AST_FRAME_VOICE) {
ast_frfree(f);
continue;
}
/* if not DTMF, just do it again */
if (f->frametype != AST_FRAME_DTMF)
{
ast_frfree(f);
continue;
}
j = f->subclass; /* save digit */
ast_frfree(f);
if (!i) {
k |= 2; /* We have the first digit */
if (i == 0)
{
k|=2; /* We have the first digit */
ast_playtones_stop(chan);
}
lastdigittime = ast_tvnow();
/* got a DTMF tone */
if (i < AST_MAX_EXTENSION) { /* if still valid number of digits */
if (!(k&1)) { /* if in password state */
if (j == '#') { /* end of password */
/* got a DTMF tone */
if (i < AST_MAX_EXTENSION) /* if still valid number of digits */
{
if (!(k&1)) /* if in password state */
{
if (j == '#') /* end of password */
{
/* see if this is an integer */
if (sscanf(args.passcode,"%30d",&j) < 1) { /* nope, it must be a filename */
if (sscanf(args.passcode,"%d",&j) < 1)
{ /* nope, it must be a filename */
fp = fopen(args.passcode,"r");
if (!fp) {
if (!fp)
{
ast_log(LOG_WARNING,"DISA password file %s not found on chan %s\n",args.passcode,chan->name);
ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
LOCAL_USER_REMOVE(u);
return -1;
}
}
pwline[0] = 0;
while(fgets(pwline,sizeof(pwline) - 1,fp)) {
if (!pwline[0])
continue;
if (pwline[strlen(pwline) - 1] == '\n')
while(fgets(pwline,sizeof(pwline) - 1,fp))
{
if (!pwline[0]) continue;
if (pwline[strlen(pwline) - 1] == '\n')
pwline[strlen(pwline) - 1] = 0;
if (!pwline[0])
continue;
/* skip comments */
if (pwline[0] == '#')
continue;
if (pwline[0] == ';')
continue;
if (!pwline[0]) continue;
/* skip comments */
if (pwline[0] == '#') continue;
if (pwline[0] == ';') continue;
AST_STANDARD_APP_ARGS(args, pwline);
ast_log(LOG_DEBUG, "Mailbox: %s\n",args.mailbox);
ast_debug(1, "Mailbox: %s\n",args.mailbox);
/* password must be in valid format (numeric) */
if (sscanf(args.passcode,"%30d", &j) < 1)
continue;
/* if we got it */
/* password must be in valid format (numeric) */
if (sscanf(args.passcode,"%d",&j) < 1) continue;
/* if we got it */
if (!strcmp(exten,args.passcode)) {
if (ast_strlen_zero(args.context))
args.context = "disa";
@@ -256,17 +283,18 @@ static int disa_exec(struct ast_channel *chan, void *data)
args.mailbox = "";
break;
}
}
}
fclose(fp);
}
/* compare the two */
if (strcmp(exten,args.passcode)) {
}
/* compare the two */
if (strcmp(exten,args.passcode))
{
ast_log(LOG_WARNING,"DISA on chan %s got bad password %s\n",chan->name,exten);
goto reorder;
}
/* password good, set to dial state */
ast_debug(1,"DISA on chan %s password is good\n",chan->name);
ast_log(LOG_DEBUG,"DISA on chan %s password is good\n",chan->name);
play_dialtone(chan, args.mailbox);
k|=1; /* In number mode */
@@ -274,32 +302,15 @@ static int disa_exec(struct ast_channel *chan, void *data)
exten[sizeof(acctcode)] = 0;
ast_copy_string(acctcode, exten, sizeof(acctcode));
exten[0] = 0;
ast_debug(1,"Successful DISA log-in on chan %s\n", chan->name);
ast_log(LOG_DEBUG,"Successful DISA log-in on chan %s\n",chan->name);
continue;
}
} else {
if (j == '#') { /* end of extension .. maybe */
if (i == 0 &&
(ast_matchmore_extension(chan, args.context, "#", 1, chan->cid.cid_num) ||
ast_exists_extension(chan, args.context, "#", 1, chan->cid.cid_num)) ) {
/* Let the # be the part of, or the entire extension */
} else {
break;
}
}
}
exten[i++] = j; /* save digit */
exten[i] = 0;
if (!(k&1))
continue; /* if getting password, continue doing it */
/* if this exists */
/* user wants end of number, remove # */
if (ast_test_flag(&flags, POUND_TO_END_FLAG) && j == '#') {
exten[--i] = 0;
break;
}
if (!(k&1)) continue; /* if getting password, continue doing it */
/* if this exists */
if (ast_ignore_pattern(args.context, exten)) {
play_dialtone(chan, "");
@@ -310,15 +321,13 @@ static int disa_exec(struct ast_channel *chan, void *data)
did_ignore = 0;
}
/* if can do some more, do it */
/* if can do some more, do it */
if (!ast_matchmore_extension(chan,args.context,exten,1, chan->cid.cid_num)) {
break;
}
}
}
ast_clear_flag(chan, AST_FLAG_END_DTMF_ONLY);
if (k == 3) {
int recheck = 0;
struct ast_flags flags = { AST_CDR_FLAG_POSTED };
@@ -332,17 +341,18 @@ static int disa_exec(struct ast_channel *chan, void *data)
if (!recheck || ast_exists_extension(chan, args.context, exten, 1, chan->cid.cid_num)) {
ast_playtones_stop(chan);
/* We're authenticated and have a target extension */
if (!ast_strlen_zero(args.cid)) {
if (!ast_strlen_zero(args.cid))
{
ast_callerid_split(args.cid, ourcidname, sizeof(ourcidname), ourcidnum, sizeof(ourcidnum));
ast_set_callerid(chan, ourcidnum, ourcidname, ourcidnum);
}
if (!ast_strlen_zero(acctcode))
ast_string_field_set(chan, accountcode, acctcode);
ast_copy_string(chan->accountcode, acctcode, sizeof(chan->accountcode));
if (special_noanswer) flags.flags = 0;
ast_cdr_reset(chan->cdr, &flags);
ast_explicit_goto(chan, args.context, exten, 1);
LOCAL_USER_REMOVE(u);
return 0;
}
}
@@ -350,23 +360,53 @@ static int disa_exec(struct ast_channel *chan, void *data)
/* Received invalid, but no "i" extension exists in the given context */
reorder:
/* Play congestion for a bit */
ast_indicate(chan, AST_CONTROL_CONGESTION);
ast_safe_sleep(chan, 10*1000);
ast_indicate(chan,AST_CONTROL_CONGESTION);
/* something is invalid, give em reorder for several seconds */
time(&rstart);
while(time(NULL) < rstart + 10)
{
if (ast_waitfor(chan, -1) < 0)
break;
f = ast_read(chan);
if (!f)
break;
ast_frfree(f);
}
ast_playtones_stop(chan);
LOCAL_USER_REMOVE(u);
return -1;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app);
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, disa_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "DISA (Direct Inward System Access) Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key(void)
{
return ASTERISK_GPL_KEY;
}

View File

@@ -22,41 +22,53 @@
/*! \file
*
* \brief Application to dump channel variables
*
* \author Anthony Minessale <anthmct@yahoo.com>
*
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
static char *tdesc = "Dump Info About The Calling Channel";
static char *app = "DumpChan";
static char *synopsis = "Dump Info About The Calling Channel";
static char *desc =
" DumpChan([<min_verbose_level>])\n"
"Displays information on channel and listing of all channel\n"
"variables. If min_verbose_level is specified, output is only\n"
"displayed when the verbose level is currently set to that number\n"
"or greater. \n";
static char *desc =
" DumpChan([<min_verbose_level>])\n"
"Displays information on channel and listing of all channel\n"
"variables. If min_verbose_level is specified, output is only\n"
"displayed when the verbose level is currently set to that number\n"
"or greater. \n";
STANDARD_LOCAL_USER;
static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
LOCAL_USER_DECL;
static int ast_serialize_showchan(struct ast_channel *c, char *buf, size_t size)
{
struct timeval now;
long elapsed_seconds = 0;
int hour = 0, min = 0, sec = 0;
char cgrp[BUFSIZ/2];
char pgrp[BUFSIZ/2];
char formatbuf[BUFSIZ/2];
long elapsed_seconds=0;
int hour=0, min=0, sec=0;
char cgrp[256];
char pgrp[256];
now = ast_tvnow();
memset(buf, 0, size);
memset(buf,0,size);
if (!c)
return 0;
@@ -67,94 +79,115 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
sec = elapsed_seconds % 60;
}
snprintf(buf,size,
"Name= %s\n"
"Type= %s\n"
"UniqueID= %s\n"
"CallerIDNum= %s\n"
"CallerIDName= %s\n"
"DNIDDigits= %s\n"
"RDNIS= %s\n"
"Language= %s\n"
"State= %s (%d)\n"
"Rings= %d\n"
"NativeFormat= %s\n"
"WriteFormat= %s\n"
"ReadFormat= %s\n"
"RawWriteFormat= %s\n"
"RawReadFormat= %s\n"
"1stFileDescriptor= %d\n"
"Framesin= %d %s\n"
"Framesout= %d %s\n"
"TimetoHangup= %ld\n"
"ElapsedTime= %dh%dm%ds\n"
"Context= %s\n"
"Extension= %s\n"
"Priority= %d\n"
"CallGroup= %s\n"
"PickupGroup= %s\n"
"Application= %s\n"
"Data= %s\n"
"Blocking_in= %s\n",
c->name,
c->tech->type,
c->uniqueid,
S_OR(c->cid.cid_num, "(N/A)"),
S_OR(c->cid.cid_name, "(N/A)"),
S_OR(c->cid.cid_dnid, "(N/A)"),
S_OR(c->cid.cid_rdnis, "(N/A)"),
c->language,
ast_state2str(c->_state),
c->_state,
c->rings,
ast_getformatname_multiple(formatbuf, sizeof(formatbuf), c->nativeformats),
ast_getformatname_multiple(formatbuf, sizeof(formatbuf), c->writeformat),
ast_getformatname_multiple(formatbuf, sizeof(formatbuf), c->readformat),
ast_getformatname_multiple(formatbuf, sizeof(formatbuf), c->rawwriteformat),
ast_getformatname_multiple(formatbuf, sizeof(formatbuf), c->rawreadformat),
c->fds[0], c->fin & ~DEBUGCHAN_FLAG, (c->fin & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
c->fout & ~DEBUGCHAN_FLAG, (c->fout & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "", (long)c->whentohangup,
hour,
min,
sec,
c->context,
c->exten,
c->priority,
ast_print_group(cgrp, sizeof(cgrp), c->callgroup),
ast_print_group(pgrp, sizeof(pgrp), c->pickupgroup),
( c->appl ? c->appl : "(N/A)" ),
( c-> data ? S_OR(c->data, "(Empty)") : "(None)"),
(ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)"));
snprintf(buf,size,
"Name= %s\n"
"Type= %s\n"
"UniqueID= %s\n"
"CallerID= %s\n"
"CallerIDName= %s\n"
"DNIDDigits= %s\n"
"State= %s (%d)\n"
"Rings= %d\n"
"NativeFormat= %d\n"
"WriteFormat= %d\n"
"ReadFormat= %d\n"
"1stFileDescriptor= %d\n"
"Framesin= %d %s\n"
"Framesout= %d %s\n"
"TimetoHangup= %ld\n"
"ElapsedTime= %dh%dm%ds\n"
"Context= %s\n"
"Extension= %s\n"
"Priority= %d\n"
"CallGroup= %s\n"
"PickupGroup= %s\n"
"Application= %s\n"
"Data= %s\n"
"Blocking_in= %s\n",
c->name,
c->type,
c->uniqueid,
(c->cid.cid_num ? c->cid.cid_num : "(N/A)"),
(c->cid.cid_name ? c->cid.cid_name : "(N/A)"),
(c->cid.cid_dnid ? c->cid.cid_dnid : "(N/A)" ),
ast_state2str(c->_state),
c->_state,
c->rings,
c->nativeformats,
c->writeformat,
c->readformat,
c->fds[0], c->fin & 0x7fffffff, (c->fin & 0x80000000) ? " (DEBUGGED)" : "",
c->fout & 0x7fffffff, (c->fout & 0x80000000) ? " (DEBUGGED)" : "", (long)c->whentohangup,
hour,
min,
sec,
c->context,
c->exten,
c->priority,
ast_print_group(cgrp, sizeof(cgrp), c->callgroup),
ast_print_group(pgrp, sizeof(pgrp), c->pickupgroup),
( c->appl ? c->appl : "(N/A)" ),
( c-> data ? (!ast_strlen_zero(c->data) ? c->data : "(Empty)") : "(None)"),
(ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)"));
return 0;
}
static int dumpchan_exec(struct ast_channel *chan, void *data)
{
struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX very large! */
int res=0;
struct localuser *u;
char vars[1024];
char info[1024];
int level = 0;
static char *line = "================================================================================";
LOCAL_USER_ADD(u);
if (!ast_strlen_zero(data))
if (!ast_strlen_zero(data)) {
level = atoi(data);
}
pbx_builtin_serialize_variables(chan, &vars);
serialize_showchan(chan, info, sizeof(info));
pbx_builtin_serialize_variables(chan, vars, sizeof(vars));
ast_serialize_showchan(chan, info, sizeof(info));
if (option_verbose >= level)
ast_verbose("\nDumping Info For Channel: %s:\n%s\nInfo:\n%s\nVariables:\n%s%s\n", chan->name, line, info, vars->str, line);
ast_verbose("\nDumping Info For Channel: %s:\n%s\nInfo:\n%s\nVariables:\n%s%s\n",chan->name, line, info, vars, line);
return 0;
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app);
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, dumpchan_exec, synopsis, desc);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dump Info About The Calling Channel");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,69 +19,105 @@
/*! \file
*
* \brief Echo application -- play back what you hear to evaluate latency
*
* \author Mark Spencer <markster@digium.com>
*
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
static char *tdesc = "Simple Echo Application";
static char *app = "Echo";
static char *synopsis = "Echo audio, video, or DTMF back to the calling party";
static char *synopsis = "Echo audio read back to the user";
static char *descrip =
" Echo(): This application will echo any audio, video, or DTMF frames read from\n"
"the calling channel back to itself. If the DTMF digit '#' is received, the\n"
"application will exit.\n";
static char *descrip =
" Echo(): Echo audio read from channel back to the channel. \n"
"User can exit the application by either pressing the '#' key, \n"
"or hanging up.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int echo_exec(struct ast_channel *chan, void *data)
{
int res = -1;
int format;
format = ast_best_codec(chan->nativeformats);
ast_set_write_format(chan, format);
ast_set_read_format(chan, format);
while (ast_waitfor(chan, -1) > -1) {
struct ast_frame *f = ast_read(chan);
if (!f) {
int res=-1;
struct localuser *u;
struct ast_frame *f;
LOCAL_USER_ADD(u);
ast_set_write_format(chan, ast_best_codec(chan->nativeformats));
ast_set_read_format(chan, ast_best_codec(chan->nativeformats));
/* Do our thing here */
while(ast_waitfor(chan, -1) > -1) {
f = ast_read(chan);
if (!f)
break;
}
f->delivery.tv_sec = 0;
f->delivery.tv_usec = 0;
if (ast_write(chan, f)) {
ast_frfree(f);
goto end;
}
if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
res = 0;
ast_frfree(f);
goto end;
if (f->frametype == AST_FRAME_VOICE) {
if (ast_write(chan, f))
break;
} else if (f->frametype == AST_FRAME_VIDEO) {
if (ast_write(chan, f))
break;
} else if (f->frametype == AST_FRAME_DTMF) {
if (f->subclass == '#') {
res = 0;
break;
} else
if (ast_write(chan, f))
break;
}
ast_frfree(f);
}
end:
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app);
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, echo_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Simple Echo Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

270
apps/app_enumlookup.c Normal file
View File

@@ -0,0 +1,270 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Enumlookup - lookup entry in ENUM
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/enum.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/options.h"
static char *tdesc = "ENUM Lookup";
static char *app = "EnumLookup";
static char *synopsis = "Lookup number in ENUM";
static char *descrip =
" EnumLookup(exten[|option]): Looks up an extension via ENUM and sets\n"
"the variable 'ENUM'. For VoIP URIs this variable will \n"
"look like 'TECHNOLOGY/URI' with the appropriate technology.\n"
"Currently, the enumservices SIP, H323, IAX, IAX2 and TEL are recognized. \n"
"\nReturns status in the ENUMSTATUS channel variable:\n"
" ERROR Failed to do a lookup\n"
" <tech> Technology of the successful lookup: SIP, H323, IAX, IAX2 or TEL\n"
" BADURI Got URI Asterisk does not understand.\n"
" The option string may contain zero or the following character:\n"
" 'j' -- jump to +101 priority if the lookup isn't successful.\n"
" and jump to +51 priority on a TEL entry.\n";
#define ENUM_CONFIG "enum.conf"
static char h323driver[80] = "";
#define H323DRIVERDEFAULT "H323"
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
/*--- enumlookup_exec: Look up number in ENUM and return result */
static int enumlookup_exec(struct ast_channel *chan, void *data)
{
int res=0,priority_jump=0;
char tech[80];
char dest[80];
char tmp[256];
char *c,*t = NULL;
static int dep_warning=0;
struct localuser *u;
char *parse;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(d);
AST_APP_ARG(o);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "EnumLookup requires an argument (extension)\n");
return -1;
}
if (!dep_warning) {
ast_log(LOG_WARNING, "The application EnumLookup is deprecated. Please use the ENUMLOOKUP() function instead.\n");
dep_warning = 1;
}
LOCAL_USER_ADD(u);
parse = ast_strdupa(data);
if (!parse) {
ast_log(LOG_ERROR, "Out of memory!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
AST_STANDARD_APP_ARGS(args, parse);
tech[0] = '\0';
dest[0] = '\0';
if (args.o) {
if (strchr(args.o, 'j'))
priority_jump = 1;
}
res = ast_get_enum(chan, args.d, dest, sizeof(dest), tech, sizeof(tech), NULL, NULL);
if (!res) { /* Failed to do a lookup */
if (priority_jump || option_priority_jumping) {
/* Look for a "busy" place */
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
}
pbx_builtin_setvar_helper(chan, "ENUMSTATUS", "ERROR");
LOCAL_USER_REMOVE(u);
return 0;
}
pbx_builtin_setvar_helper(chan, "ENUMSTATUS", tech);
/* Parse it out */
if (res > 0) {
if (!strcasecmp(tech, "SIP")) {
c = dest;
if (!strncmp(c, "sip:", 4))
c += 4;
snprintf(tmp, sizeof(tmp), "SIP/%s", c);
pbx_builtin_setvar_helper(chan, "ENUM", tmp);
} else if (!strcasecmp(tech, "h323")) {
c = dest;
if (!strncmp(c, "h323:", 5))
c += 5;
snprintf(tmp, sizeof(tmp), "%s/%s", h323driver, c);
/* do a s!;.*!! on the H323 URI */
t = strchr(c,';');
if (t)
*t = 0;
pbx_builtin_setvar_helper(chan, "ENUM", tmp);
} else if (!strcasecmp(tech, "iax")) {
c = dest;
if (!strncmp(c, "iax:", 4))
c += 4;
snprintf(tmp, sizeof(tmp), "IAX/%s", c);
pbx_builtin_setvar_helper(chan, "ENUM", tmp);
} else if (!strcasecmp(tech, "iax2")) {
c = dest;
if (!strncmp(c, "iax2:", 5))
c += 5;
snprintf(tmp, sizeof(tmp), "IAX2/%s", c);
pbx_builtin_setvar_helper(chan, "ENUM", tmp);
} else if (!strcasecmp(tech, "tel")) {
c = dest;
if (!strncmp(c, "tel:", 4))
c += 4;
if (c[0] != '+') {
ast_log(LOG_NOTICE, "tel: uri must start with a \"+\" (got '%s')\n", c);
res = 0;
} else {
/* now copy over the number, skipping all non-digits and stop at ; or NULL */
t = tmp;
while( *c && (*c != ';') && (t - tmp < (sizeof(tmp) - 1))) {
if (isdigit(*c))
*t++ = *c;
c++;
}
*t = 0;
pbx_builtin_setvar_helper(chan, "ENUM", tmp);
ast_log(LOG_NOTICE, "tel: ENUM set to \"%s\"\n", tmp);
if (priority_jump || option_priority_jumping) {
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 51))
res = 0;
}
}
} else if (!ast_strlen_zero(tech)) {
ast_log(LOG_NOTICE, "Don't know how to handle technology '%s'\n", tech);
pbx_builtin_setvar_helper(chan, "ENUMSTATUS", "BADURI");
res = 0;
}
}
LOCAL_USER_REMOVE(u);
return 0;
}
/*--- load_config: Load enum.conf and find out how to handle H.323 */
static int load_config(void)
{
struct ast_config *cfg;
char *s;
cfg = ast_config_load(ENUM_CONFIG);
if (cfg) {
if (!(s=ast_variable_retrieve(cfg, "general", "h323driver"))) {
strncpy(h323driver, H323DRIVERDEFAULT, sizeof(h323driver) - 1);
} else {
strncpy(h323driver, s, sizeof(h323driver) - 1);
}
ast_config_destroy(cfg);
return 0;
}
ast_log(LOG_NOTICE, "No ENUM Config file, using defaults\n");
return 0;
}
/*--- unload_module: Unload this application from PBX */
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
/*--- load_module: Load this application into PBX */
int load_module(void)
{
int res;
res = ast_register_application(app, enumlookup_exec, synopsis, descrip);
if (!res)
res = load_config();
return res;
}
/*--- reload: Reload configuration file */
int reload(void)
{
return load_config();
}
/*--- description: Describe module */
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

127
apps/app_eval.c Normal file
View File

@@ -0,0 +1,127 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (c) 2004 - 2005, Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <app_eval__v001@the-tilghman.com>
*
* This code is released by the author with no restrictions on usage.
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
*/
/*! \file
* \brief Eval application
*
* \author Tilghman Lesher <app_eval__v001@the-tilghman.com>
*
* \ingroup applications
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
/* Maximum length of any variable */
#define MAXRESULT 1024
static char *tdesc = "Reevaluates strings";
static char *app_eval = "Eval";
static char *eval_synopsis = "Evaluates a string";
static char *eval_descrip =
"Usage: Eval(newvar=somestring)\n"
" Normally Asterisk evaluates variables inline. But what if you want to\n"
"store variable offsets in a database, to be evaluated later? Eval is\n"
"the answer, by allowing a string to be evaluated twice in the dialplan,\n"
"the first time as part of the normal dialplan, and the second using Eval.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int eval_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *s, *newvar=NULL, tmp[MAXRESULT];
static int dep_warning = 0;
LOCAL_USER_ADD(u);
if (!dep_warning) {
ast_log(LOG_WARNING, "This application has been deprecated in favor of the dialplan function, EVAL\n");
dep_warning = 1;
}
/* Check and parse arguments */
if (data) {
s = ast_strdupa((char *)data);
if (s) {
newvar = strsep(&s, "=");
if (newvar && (newvar[0] != '\0')) {
memset(tmp, 0, MAXRESULT);
pbx_substitute_variables_helper(chan, s, tmp, MAXRESULT - 1);
pbx_builtin_setvar_helper(chan, newvar, tmp);
}
} else {
ast_log(LOG_ERROR, "Out of memory\n");
res = -1;
}
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
int res;
res = ast_unregister_application(app_eval);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
return ast_register_application(app_eval, eval_exec, eval_synopsis, eval_descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -2,9 +2,8 @@
* Asterisk -- An open source telephony toolkit.
*
* Copyright (c) 2004 - 2005, Tilghman Lesher. All rights reserved.
* Portions copyright (c) 2006, Philipp Dunkel.
*
* Tilghman Lesher <app_exec__v002@the-tilghman.com>
* Tilghman Lesher <app_exec__v001@the-tilghman.com>
*
* This code is released by the author with no restrictions on usage.
*
@@ -20,227 +19,117 @@
*
* \brief Exec application
*
* \author Tilghman Lesher <app_exec__v002@the-tilghman.com>
* \author Philipp Dunkel <philipp.dunkel@ebox.at>
* \author Tilghman Lesher <app_exec__v001@the-tilghman.com>
*
* \ingroup applications
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
/* Maximum length of any variable */
#define MAXRESULT 1024
#define MAXRESULT 1024
/*! Note
*
* The key difference between these two apps is exit status. In a
* nutshell, Exec tries to be transparent as possible, behaving
* in exactly the same way as if the application it calls was
* directly invoked from the dialplan.
*
* TryExec, on the other hand, provides a way to execute applications
* and catch any possible fatal error without actually fatally
* affecting the dialplan.
*/
static char *tdesc = "Executes applications";
static char *app_exec = "Exec";
static char *exec_synopsis = "Executes dialplan application";
static char *exec_synopsis = "Executes internal application";
static char *exec_descrip =
" Exec(appname(arguments)):\n"
"Allows an arbitrary application to be invoked even when not\n"
"hardcoded into the dialplan. If the underlying application\n"
"terminates the dialplan, or if the application cannot be found,\n"
"Exec will terminate the dialplan.\n"
" To invoke external applications, see the application System.\n"
" If you would like to catch any error instead, see TryExec.\n";
static char *app_tryexec = "TryExec";
static char *tryexec_synopsis = "Executes dialplan application, always returning";
static char *tryexec_descrip =
" TryExec(appname(arguments)):\n"
"Allows an arbitrary application to be invoked even when not\n"
"Usage: Exec(appname(arguments))\n"
" Allows an arbitrary application to be invoked even when not\n"
"hardcoded into the dialplan. To invoke external applications\n"
"see the application System. Always returns to the dialplan.\n"
"The channel variable TRYSTATUS will be set to one of:\n"
" SUCCESS if the application returned zero\n"
" FAILED if the application returned non-zero\n"
" NOAPP if the application was not found or was not specified\n";
"see the application System. Returns whatever value the\n"
"app returns or a non-zero value if the app cannot be found.\n";
static char *app_execif = "ExecIf";
static char *execif_synopsis = "Executes dialplan application, conditionally";
static char *execif_descrip =
" ExecIF (<expr>?<appiftrue>(<args>)[:<appiffalse>(<args>)])\n"
"If <expr> is true, execute and return the result of <appiftrue>(<args>).\n"
"If <expr> is true, but <appiftrue> is not found, then the application\n"
"will return a non-zero value.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int exec_exec(struct ast_channel *chan, void *data)
{
int res = 0;
int res=0;
struct localuser *u;
char *s, *appname, *endargs, args[MAXRESULT];
struct ast_app *app;
if (ast_strlen_zero(data))
return 0;
LOCAL_USER_ADD(u);
s = ast_strdupa(data);
args[0] = 0;
appname = strsep(&s, "(");
if (s) {
endargs = strrchr(s, ')');
if (endargs)
*endargs = '\0';
pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
}
if (appname) {
app = pbx_findapp(appname);
if (app) {
res = pbx_exec(chan, app, args);
memset(args, 0, MAXRESULT);
/* Check and parse arguments */
if (data) {
s = ast_strdupa((char *)data);
if (s) {
appname = strsep(&s, "(");
if (s) {
endargs = strrchr(s, ')');
if (endargs)
*endargs = '\0';
pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
}
if (appname) {
app = pbx_findapp(appname);
if (app) {
res = pbx_exec(chan, app, args, 1);
} else {
ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
res = -1;
}
}
} else {
ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
ast_log(LOG_ERROR, "Out of memory\n");
res = -1;
}
}
LOCAL_USER_REMOVE(u);
return res;
}
static int tryexec_exec(struct ast_channel *chan, void *data)
{
int res = 0;
char *s, *appname, *endargs, args[MAXRESULT];
struct ast_app *app;
if (ast_strlen_zero(data))
return 0;
s = ast_strdupa(data);
args[0] = 0;
appname = strsep(&s, "(");
if (s) {
endargs = strrchr(s, ')');
if (endargs)
*endargs = '\0';
pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
}
if (appname) {
app = pbx_findapp(appname);
if (app) {
res = pbx_exec(chan, app, args);
pbx_builtin_setvar_helper(chan, "TRYSTATUS", res ? "FAILED" : "SUCCESS");
} else {
ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
pbx_builtin_setvar_helper(chan, "TRYSTATUS", "NOAPP");
}
}
return 0;
}
static int execif_exec(struct ast_channel *chan, void *data)
{
int res = 0;
char *truedata = NULL, *falsedata = NULL, *end, *firstcomma, *firstquestion;
struct ast_app *app = NULL;
AST_DECLARE_APP_ARGS(expr,
AST_APP_ARG(expr);
AST_APP_ARG(remainder);
);
AST_DECLARE_APP_ARGS(apps,
AST_APP_ARG(t);
AST_APP_ARG(f);
);
char *parse = ast_strdupa(data);
firstcomma = strchr(parse, ',');
firstquestion = strchr(parse, '?');
if ((firstcomma != NULL && firstquestion != NULL && firstcomma < firstquestion) || (firstquestion == NULL)) {
/* Deprecated syntax */
AST_DECLARE_APP_ARGS(depr,
AST_APP_ARG(expr);
AST_APP_ARG(appname);
AST_APP_ARG(appargs);
);
AST_STANDARD_APP_ARGS(depr, parse);
ast_log(LOG_WARNING, "Deprecated syntax found. Please upgrade to using ExecIf(<expr>?%s(%s))\n", depr.appname, depr.appargs);
/* Make the two syntaxes look the same */
expr.expr = depr.expr;
apps.t = depr.appname;
apps.f = NULL;
truedata = depr.appargs;
} else {
/* Preferred syntax */
AST_NONSTANDARD_RAW_ARGS(expr, parse, '?');
if (ast_strlen_zero(expr.remainder)) {
ast_log(LOG_ERROR, "Usage: ExecIf(<expr>?<appiftrue>(<args>)[:<appiffalse>(<args)])\n");
return -1;
}
AST_NONSTANDARD_RAW_ARGS(apps, expr.remainder, ':');
if (apps.t && (truedata = strchr(apps.t, '('))) {
*truedata++ = '\0';
if ((end = strrchr(truedata, ')'))) {
*end = '\0';
}
}
if (apps.f && (falsedata = strchr(apps.f, '('))) {
*falsedata++ = '\0';
if ((end = strrchr(falsedata, ')'))) {
*end = '\0';
}
}
}
if (pbx_checkcondition(expr.expr)) {
if (!ast_strlen_zero(apps.t) && (app = pbx_findapp(apps.t))) {
res = pbx_exec(chan, app, S_OR(truedata, ""));
} else {
ast_log(LOG_WARNING, "Could not find application! (%s)\n", apps.t);
res = -1;
}
} else if (!ast_strlen_zero(apps.f)) {
if ((app = pbx_findapp(apps.f))) {
res = pbx_exec(chan, app, S_OR(falsedata, ""));
} else {
ast_log(LOG_WARNING, "Could not find application! (%s)\n", apps.f);
res = -1;
}
}
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app_exec);
res |= ast_unregister_application(app_tryexec);
res |= ast_unregister_application(app_execif);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
int res = ast_register_application(app_exec, exec_exec, exec_synopsis, exec_descrip);
res |= ast_register_application(app_tryexec, tryexec_exec, tryexec_synopsis, tryexec_descrip);
res |= ast_register_application(app_execif, execif_exec, execif_synopsis, execif_descrip);
return ast_register_application(app_exec, exec_exec, exec_synopsis, exec_descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Executes dialplan applications");
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -22,50 +22,46 @@
/*! \file
*
* \brief External IVR application interface
*
* \author Kevin P. Fleming <kpfleming@digium.com>
*
* \note Portions taken from the file-based music-on-hold work
* created by Anthony Minessale II in res_musiconhold.c
*
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>working_fork</depend>
***/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <signal.h>
#ifdef HAVE_CAP
#include <sys/capability.h>
#endif /* HAVE_CAP */
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/linkedlists.h"
#include "asterisk/app.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
static const char *tdesc = "External IVR Interface Application";
static const char *app = "ExternalIVR";
static const char *synopsis = "Interfaces with an external IVR application";
static const char *descrip =
" ExternalIVR(command[,arg[,arg...]]): Forks a process to run the supplied command,\n"
static const char *descrip =
" ExternalIVR(command[|arg[|arg...]]): Forks an process to run the supplied command,\n"
"and starts a generator on the channel. The generator's play list is\n"
"controlled by the external application, which can add and clear entries\n"
"via simple commands issued over its stdout. The external application\n"
"will receive all DTMF events received on the channel, and notification\n"
"if the channel is hung up. The application will not be forcibly terminated\n"
"when the channel is hung up.\n"
"See doc/externalivr.txt for a protocol specification.\n";
"See doc/README.externalivr for a protocol specification.\n";
/* XXX the parser in gcc 2.95 gets confused if you don't put a space between 'name' and the comma */
#define ast_chan_log(level, channel, format, ...) ast_log(level, "%s: " format, channel->name , ## __VA_ARGS__)
@@ -75,8 +71,9 @@ struct playlist_entry {
char filename[1];
};
struct ivr_localuser {
struct localuser {
struct ast_channel *chan;
struct localuser *next;
AST_LIST_HEAD(playlist, playlist_entry) playlist;
AST_LIST_HEAD(finishlist, playlist_entry) finishlist;
int abort_current_sound;
@@ -84,20 +81,17 @@ struct ivr_localuser {
int option_autoclear;
};
LOCAL_USER_DECL;
struct gen_state {
struct ivr_localuser *u;
struct localuser *u;
struct ast_filestream *stream;
struct playlist_entry *current;
int sample_queue;
};
static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u,
int *eivr_events_fd, int *eivr_commands_fd, int *eivr_errors_fd,
const char *args);
static void send_eivr_event(FILE *handle, const char event, const char *data,
const struct ast_channel *chan)
static void send_child_event(FILE *handle, const char event, const char *data,
const struct ast_channel *chan)
{
char tmp[256];
@@ -108,16 +102,17 @@ static void send_eivr_event(FILE *handle, const char event, const char *data,
}
fprintf(handle, "%s\n", tmp);
if (option_debug)
ast_chan_log(LOG_DEBUG, chan, "sent '%s'\n", tmp);
ast_chan_log(LOG_DEBUG, chan, "sent '%s'\n", tmp);
}
static void *gen_alloc(struct ast_channel *chan, void *params)
{
struct ivr_localuser *u = params;
struct localuser *u = params;
struct gen_state *state;
if (!(state = ast_calloc(1, sizeof(*state))))
state = calloc(1, sizeof(*state));
if (!state)
return NULL;
state->u = u;
@@ -140,15 +135,15 @@ static void gen_release(struct ast_channel *chan, void *data)
struct gen_state *state = data;
gen_closestream(state);
ast_free(data);
free(data);
}
/* caller has the playlist locked */
static int gen_nextfile(struct gen_state *state)
{
struct ivr_localuser *u = state->u;
struct localuser *u = state->u;
char *file_to_stream;
u->abort_current_sound = 0;
u->playing_silence = 0;
gen_closestream(state);
@@ -166,7 +161,7 @@ static int gen_nextfile(struct gen_state *state)
ast_chan_log(LOG_WARNING, u->chan, "File '%s' could not be opened: %s\n", file_to_stream, strerror(errno));
if (!u->playing_silence) {
continue;
} else {
} else {
break;
}
}
@@ -178,10 +173,10 @@ static int gen_nextfile(struct gen_state *state)
static struct ast_frame *gen_readframe(struct gen_state *state)
{
struct ast_frame *f = NULL;
struct ivr_localuser *u = state->u;
struct localuser *u = state->u;
if (u->abort_current_sound ||
(u->playing_silence && AST_LIST_FIRST(&u->playlist))) {
(u->playing_silence && AST_LIST_FIRST(&u->playlist))) {
gen_closestream(state);
AST_LIST_LOCK(&u->playlist);
gen_nextfile(state);
@@ -233,60 +228,13 @@ static struct ast_generator gen =
generate: gen_generate,
};
static void ast_eivr_getvariable(struct ast_channel *chan, char *data, char *outbuf, int outbuflen)
{
/* original input data: "G,var1,var2," */
/* data passed as "data": "var1,var2" */
char *inbuf, *variable;
const char *value;
int j;
struct ast_str *newstring = ast_str_alloca(outbuflen);
outbuf[0] = '\0';
for (j = 1, inbuf = data; ; j++) {
variable = strsep(&inbuf, ",");
if (variable == NULL) {
int outstrlen = strlen(outbuf);
if(outstrlen && outbuf[outstrlen - 1] == ',') {
outbuf[outstrlen - 1] = 0;
}
break;
}
value = pbx_builtin_getvar_helper(chan, variable);
if(!value)
value = "";
ast_str_append(&newstring, 0, "%s=%s,", variable, value);
ast_copy_string(outbuf, newstring->str, outbuflen);
}
};
static void ast_eivr_setvariable(struct ast_channel *chan, char *data)
{
char *value;
char *inbuf = ast_strdupa(data), *variable;
for (variable = strsep(&inbuf, ","); variable; variable = strsep(&inbuf, ",")) {
ast_debug(1, "Setting up a variable: %s\n", variable);
/* variable contains "varname=value" */
value = strchr(variable, '=');
if (!value) {
value = "";
} else {
*value++ = '\0';
}
pbx_builtin_setvar_helper(chan, variable, value);
}
};
static struct playlist_entry *make_entry(const char *filename)
{
struct playlist_entry *entry;
if (!(entry = ast_calloc(1, sizeof(*entry) + strlen(filename) + 10))) /* XXX why 10 ? */
entry = calloc(1, sizeof(*entry) + strlen(filename) + 10);
if (!entry)
return NULL;
strcpy(entry->filename, filename);
@@ -296,56 +244,65 @@ static struct playlist_entry *make_entry(const char *filename)
static int app_exec(struct ast_channel *chan, void *data)
{
struct localuser *u = NULL;
struct playlist_entry *entry;
int child_stdin[2] = { -1, -1 };
int child_stdout[2] = { -1, -1 };
int child_stderr[2] = { -1, -1 };
const char *args = data;
int child_stdin[2] = { 0,0 };
int child_stdout[2] = { 0,0 };
int child_stderr[2] = { 0,0 };
int res = -1;
int gen_active = 0;
int pid;
char *buf, *comma_delim_argbuf;
struct ivr_localuser foo = {
.playlist = AST_LIST_HEAD_INIT_VALUE,
.finishlist = AST_LIST_HEAD_INIT_VALUE,
};
struct ivr_localuser *u = &foo;
char *argv[32];
int argc = 1;
char *buf, *command;
FILE *child_commands = NULL;
FILE *child_errors = NULL;
FILE *child_events = NULL;
sigset_t fullset, oldset;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(cmd)[32];
);
LOCAL_USER_ADD(u);
sigfillset(&fullset);
pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
AST_LIST_HEAD_INIT(&u->playlist);
AST_LIST_HEAD_INIT(&u->finishlist);
u->abort_current_sound = 0;
u->chan = chan;
if (ast_strlen_zero(data)) {
if (ast_strlen_zero(args)) {
ast_log(LOG_WARNING, "ExternalIVR requires a command to execute\n");
return -1;
goto exit;
}
buf = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, buf);
if (!buf) {
ast_log(LOG_ERROR, "Out of memory!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
argc = ast_app_separate_args(buf, '|', argv, sizeof(argv) / sizeof(argv[0]));
/* copy args and replace commas with pipes */
comma_delim_argbuf = ast_strdupa(data);
if (pipe(child_stdin)) {
ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child input: %s\n", strerror(errno));
goto exit;
}
if (pipe(child_stdout)) {
ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child output: %s\n", strerror(errno));
goto exit;
}
if (pipe(child_stderr)) {
ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child errors: %s\n", strerror(errno));
goto exit;
}
if (chan->_state != AST_STATE_UP) {
ast_answer(chan);
}
if (ast_activate_generator(chan, &gen, u) < 0) {
ast_chan_log(LOG_WARNING, chan, "Failed to activate generator\n");
goto exit;
@@ -361,20 +318,11 @@ static int app_exec(struct ast_channel *chan, void *data)
if (!pid) {
/* child process */
int i;
#ifdef HAVE_CAP
cap_t cap = cap_from_text("cap_net_admin-eip");
if (cap_set_proc(cap)) {
/* Careful with order! Logging cannot happen after we close FDs */
ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
}
cap_free(cap);
#endif
signal(SIGPIPE, SIG_DFL);
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
if (ast_opt_high_priority)
if (option_highpriority)
ast_set_priority(0);
dup2(child_stdin[0], STDIN_FILENO);
@@ -382,290 +330,268 @@ static int app_exec(struct ast_channel *chan, void *data)
dup2(child_stderr[1], STDERR_FILENO);
for (i = STDERR_FILENO + 1; i < 1024; i++)
close(i);
execv(args.cmd[0], args.cmd);
fprintf(stderr, "Failed to execute '%s': %s\n", args.cmd[0], strerror(errno));
execv(argv[0], argv);
fprintf(stderr, "Failed to execute '%s': %s\n", argv[0], strerror(errno));
_exit(1);
} else {
/* parent process */
int child_events_fd = child_stdin[1];
int child_commands_fd = child_stdout[0];
int child_errors_fd = child_stderr[0];
struct ast_frame *f;
int ms;
int exception;
int ready_fd;
int waitfds[2] = { child_errors_fd, child_commands_fd };
struct ast_channel *rchan;
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
close(child_stdin[0]);
child_stdin[0] = -1;
child_stdin[0] = 0;
close(child_stdout[1]);
child_stdout[1] = -1;
child_stdout[1] = 0;
close(child_stderr[1]);
child_stderr[1] = -1;
res = eivr_comm(chan, u, &child_stdin[1], &child_stdout[0], &child_stderr[0], comma_delim_argbuf);
child_stderr[1] = 0;
if (!(child_events = fdopen(child_events_fd, "w"))) {
ast_chan_log(LOG_WARNING, chan, "Could not open stream for child events\n");
goto exit;
}
if (!(child_commands = fdopen(child_commands_fd, "r"))) {
ast_chan_log(LOG_WARNING, chan, "Could not open stream for child commands\n");
goto exit;
}
if (!(child_errors = fdopen(child_errors_fd, "r"))) {
ast_chan_log(LOG_WARNING, chan, "Could not open stream for child errors\n");
goto exit;
}
setvbuf(child_events, NULL, _IONBF, 0);
setvbuf(child_commands, NULL, _IONBF, 0);
setvbuf(child_errors, NULL, _IONBF, 0);
res = 0;
while (1) {
if (ast_test_flag(chan, AST_FLAG_ZOMBIE)) {
ast_chan_log(LOG_NOTICE, chan, "Is a zombie\n");
res = -1;
break;
}
if (ast_check_hangup(chan)) {
ast_chan_log(LOG_NOTICE, chan, "Got check_hangup\n");
send_child_event(child_events, 'H', NULL, chan);
res = -1;
break;
}
ready_fd = 0;
ms = 100;
errno = 0;
exception = 0;
rchan = ast_waitfor_nandfds(&chan, 1, waitfds, 2, &exception, &ready_fd, &ms);
if (!AST_LIST_EMPTY(&u->finishlist)) {
AST_LIST_LOCK(&u->finishlist);
while ((entry = AST_LIST_REMOVE_HEAD(&u->finishlist, list))) {
send_child_event(child_events, 'F', entry->filename, chan);
free(entry);
}
AST_LIST_UNLOCK(&u->finishlist);
}
if (rchan) {
/* the channel has something */
f = ast_read(chan);
if (!f) {
ast_chan_log(LOG_NOTICE, chan, "Returned no frame\n");
send_child_event(child_events, 'H', NULL, chan);
res = -1;
break;
}
if (f->frametype == AST_FRAME_DTMF) {
send_child_event(child_events, f->subclass, NULL, chan);
if (u->option_autoclear) {
if (!u->abort_current_sound && !u->playing_silence)
send_child_event(child_events, 'T', NULL, chan);
AST_LIST_LOCK(&u->playlist);
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
send_child_event(child_events, 'D', entry->filename, chan);
free(entry);
}
if (!u->playing_silence)
u->abort_current_sound = 1;
AST_LIST_UNLOCK(&u->playlist);
}
} else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
ast_chan_log(LOG_NOTICE, chan, "Got AST_CONTROL_HANGUP\n");
send_child_event(child_events, 'H', NULL, chan);
ast_frfree(f);
res = -1;
break;
}
ast_frfree(f);
} else if (ready_fd == child_commands_fd) {
char input[1024];
if (exception || feof(child_commands)) {
ast_chan_log(LOG_WARNING, chan, "Child process went away\n");
res = -1;
break;
}
if (!fgets(input, sizeof(input), child_commands))
continue;
command = ast_strip(input);
ast_chan_log(LOG_DEBUG, chan, "got command '%s'\n", input);
if (strlen(input) < 4)
continue;
if (input[0] == 'S') {
if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) {
ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
send_child_event(child_events, 'Z', NULL, chan);
strcpy(&input[2], "exception");
}
if (!u->abort_current_sound && !u->playing_silence)
send_child_event(child_events, 'T', NULL, chan);
AST_LIST_LOCK(&u->playlist);
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
send_child_event(child_events, 'D', entry->filename, chan);
free(entry);
}
if (!u->playing_silence)
u->abort_current_sound = 1;
entry = make_entry(&input[2]);
if (entry)
AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
AST_LIST_UNLOCK(&u->playlist);
} else if (input[0] == 'A') {
if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) {
ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
send_child_event(child_events, 'Z', NULL, chan);
strcpy(&input[2], "exception");
}
entry = make_entry(&input[2]);
if (entry) {
AST_LIST_LOCK(&u->playlist);
AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
AST_LIST_UNLOCK(&u->playlist);
}
} else if (input[0] == 'H') {
ast_chan_log(LOG_NOTICE, chan, "Hanging up: %s\n", &input[2]);
send_child_event(child_events, 'H', NULL, chan);
break;
} else if (input[0] == 'O') {
if (!strcasecmp(&input[2], "autoclear"))
u->option_autoclear = 1;
else if (!strcasecmp(&input[2], "noautoclear"))
u->option_autoclear = 0;
else
ast_chan_log(LOG_WARNING, chan, "Unknown option requested '%s'\n", &input[2]);
}
} else if (ready_fd == child_errors_fd) {
char input[1024];
if (exception || feof(child_errors)) {
ast_chan_log(LOG_WARNING, chan, "Child process went away\n");
res = -1;
break;
}
if (fgets(input, sizeof(input), child_errors)) {
command = ast_strip(input);
ast_chan_log(LOG_NOTICE, chan, "stderr: %s\n", command);
}
} else if ((ready_fd < 0) && ms) {
if (errno == 0 || errno == EINTR)
continue;
ast_chan_log(LOG_WARNING, chan, "Wait failed (%s)\n", strerror(errno));
break;
}
}
}
exit:
if (gen_active) {
exit:
if (gen_active)
ast_deactivate_generator(chan);
}
if (child_stdin[0] > -1) {
if (child_events)
fclose(child_events);
if (child_commands)
fclose(child_commands);
if (child_errors)
fclose(child_errors);
if (child_stdin[0])
close(child_stdin[0]);
}
if (child_stdin[1] > -1) {
if (child_stdin[1])
close(child_stdin[1]);
}
if (child_stdout[0] > -1) {
if (child_stdout[0])
close(child_stdout[0]);
}
if (child_stdout[1] > -1) {
if (child_stdout[1])
close(child_stdout[1]);
}
if (child_stderr[0] > -1) {
if (child_stderr[0])
close(child_stderr[0]);
}
if (child_stderr[1] > -1) {
if (child_stderr[1])
close(child_stderr[1]);
}
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
ast_free(entry);
}
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list)))
free(entry);
LOCAL_USER_REMOVE(u);
return res;
}
static int eivr_comm(struct ast_channel *chan, struct ivr_localuser *u,
int *eivr_events_fd, int *eivr_commands_fd, int *eivr_errors_fd,
const char *args)
int unload_module(void)
{
struct playlist_entry *entry;
struct ast_frame *f;
int ms;
int exception;
int ready_fd;
int waitfds[2] = { *eivr_commands_fd, (eivr_errors_fd) ? *eivr_errors_fd : -1 };
struct ast_channel *rchan;
char *command;
int res = -1;
int test_available_fd = -1;
FILE *eivr_commands = NULL;
FILE *eivr_errors = NULL;
FILE *eivr_events = NULL;
if (!(eivr_events = fdopen(*eivr_events_fd, "w"))) {
ast_chan_log(LOG_WARNING, chan, "Could not open stream to send events\n");
goto exit;
}
if (!(eivr_commands = fdopen(*eivr_commands_fd, "r"))) {
ast_chan_log(LOG_WARNING, chan, "Could not open stream to receive commands\n");
goto exit;
}
if (eivr_errors_fd) { /*if opening a socket connection, error stream will not be used*/
if (!(eivr_errors = fdopen(*eivr_errors_fd, "r"))) {
ast_chan_log(LOG_WARNING, chan, "Could not open stream to receive errors\n");
goto exit;
}
}
int res;
test_available_fd = open("/dev/null", O_RDONLY);
setvbuf(eivr_events, NULL, _IONBF, 0);
setvbuf(eivr_commands, NULL, _IONBF, 0);
if(eivr_errors)
setvbuf(eivr_errors, NULL, _IONBF, 0);
res = ast_unregister_application(app);
res = 0;
while (1) {
if (ast_test_flag(chan, AST_FLAG_ZOMBIE)) {
ast_chan_log(LOG_NOTICE, chan, "Is a zombie\n");
res = -1;
break;
}
if (ast_check_hangup(chan)) {
ast_chan_log(LOG_NOTICE, chan, "Got check_hangup\n");
send_eivr_event(eivr_events, 'H', NULL, chan);
res = -1;
break;
}
ready_fd = 0;
ms = 100;
errno = 0;
exception = 0;
rchan = ast_waitfor_nandfds(&chan, 1, waitfds, (eivr_errors_fd) ? 2 : 1, &exception, &ready_fd, &ms);
if (!AST_LIST_EMPTY(&u->finishlist)) {
AST_LIST_LOCK(&u->finishlist);
while ((entry = AST_LIST_REMOVE_HEAD(&u->finishlist, list))) {
send_eivr_event(eivr_events, 'F', entry->filename, chan);
ast_free(entry);
}
AST_LIST_UNLOCK(&u->finishlist);
}
if (rchan) {
/* the channel has something */
f = ast_read(chan);
if (!f) {
ast_chan_log(LOG_NOTICE, chan, "Returned no frame\n");
send_eivr_event(eivr_events, 'H', NULL, chan);
res = -1;
break;
}
if (f->frametype == AST_FRAME_DTMF) {
send_eivr_event(eivr_events, f->subclass, NULL, chan);
if (u->option_autoclear) {
if (!u->abort_current_sound && !u->playing_silence)
send_eivr_event(eivr_events, 'T', NULL, chan);
AST_LIST_LOCK(&u->playlist);
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
send_eivr_event(eivr_events, 'D', entry->filename, chan);
ast_free(entry);
}
if (!u->playing_silence)
u->abort_current_sound = 1;
AST_LIST_UNLOCK(&u->playlist);
}
} else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
ast_chan_log(LOG_NOTICE, chan, "Got AST_CONTROL_HANGUP\n");
send_eivr_event(eivr_events, 'H', NULL, chan);
ast_frfree(f);
res = -1;
break;
}
ast_frfree(f);
} else if (ready_fd == *eivr_commands_fd) {
char input[1024];
if (exception || (dup2(*eivr_commands_fd, test_available_fd) == -1) || feof(eivr_commands)) {
ast_chan_log(LOG_WARNING, chan, "Child process went away\n");
res = -1;
break;
}
if (!fgets(input, sizeof(input), eivr_commands))
continue;
command = ast_strip(input);
if (option_debug)
ast_chan_log(LOG_DEBUG, chan, "got command '%s'\n", input);
if (strlen(input) < 4)
continue;
if (input[0] == 'P') {
send_eivr_event(eivr_events, 'P', args, chan);
} else if (input[0] == 'S') {
if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) {
ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
send_eivr_event(eivr_events, 'Z', NULL, chan);
strcpy(&input[2], "exception");
}
if (!u->abort_current_sound && !u->playing_silence)
send_eivr_event(eivr_events, 'T', NULL, chan);
AST_LIST_LOCK(&u->playlist);
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
send_eivr_event(eivr_events, 'D', entry->filename, chan);
ast_free(entry);
}
if (!u->playing_silence)
u->abort_current_sound = 1;
entry = make_entry(&input[2]);
if (entry)
AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
AST_LIST_UNLOCK(&u->playlist);
} else if (input[0] == 'A') {
if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) {
ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
send_eivr_event(eivr_events, 'Z', NULL, chan);
strcpy(&input[2], "exception");
}
entry = make_entry(&input[2]);
if (entry) {
AST_LIST_LOCK(&u->playlist);
AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
AST_LIST_UNLOCK(&u->playlist);
}
} else if (input[0] == 'G') {
/* A get variable message: "G,variable1,variable2,..." */
char response[2048];
STANDARD_HANGUP_LOCALUSERS;
ast_chan_log(LOG_NOTICE, chan, "Getting a Variable out of the channel: %s\n", &input[2]);
ast_eivr_getvariable(chan, &input[2], response, sizeof(response));
send_eivr_event(eivr_events, 'G', response, chan);
} else if (input[0] == 'V') {
/* A set variable message: "V,variablename=foo" */
ast_chan_log(LOG_NOTICE, chan, "Setting a Variable up: %s\n", &input[2]);
ast_eivr_setvariable(chan, &input[2]);
} else if (input[0] == 'L') {
ast_chan_log(LOG_NOTICE, chan, "Log message from EIVR: %s\n", &input[2]);
} else if (input[0] == 'X') {
ast_chan_log(LOG_NOTICE, chan, "Exiting ExternalIVR: %s\n", &input[2]);
/*! \todo add deprecation debug message for X command here */
res = 0;
break;
} else if (input[0] == 'E') {
ast_chan_log(LOG_NOTICE, chan, "Exiting: %s\n", &input[2]);
send_eivr_event(eivr_events, 'E', NULL, chan);
res = 0;
break;
} else if (input[0] == 'H') {
ast_chan_log(LOG_NOTICE, chan, "Hanging up: %s\n", &input[2]);
send_eivr_event(eivr_events, 'H', NULL, chan);
res = -1;
break;
} else if (input[0] == 'O') {
if (!strcasecmp(&input[2], "autoclear"))
u->option_autoclear = 1;
else if (!strcasecmp(&input[2], "noautoclear"))
u->option_autoclear = 0;
else
ast_chan_log(LOG_WARNING, chan, "Unknown option requested '%s'\n", &input[2]);
}
} else if (eivr_errors_fd && (ready_fd == *eivr_errors_fd)) {
char input[1024];
if (exception || feof(eivr_errors)) {
ast_chan_log(LOG_WARNING, chan, "Child process went away\n");
res = -1;
break;
}
if (fgets(input, sizeof(input), eivr_errors)) {
command = ast_strip(input);
ast_chan_log(LOG_NOTICE, chan, "stderr: %s\n", command);
}
} else if ((ready_fd < 0) && ms) {
if (errno == 0 || errno == EINTR)
continue;
ast_chan_log(LOG_WARNING, chan, "Wait failed (%s)\n", strerror(errno));
break;
}
}
exit:
if (test_available_fd > -1) {
close(test_available_fd);
}
if (eivr_events) {
fclose(eivr_events);
*eivr_events_fd = -1;
}
if (eivr_commands) {
fclose(eivr_commands);
*eivr_commands_fd = -1;
}
if (eivr_errors) {
fclose(eivr_errors);
*eivr_errors_fd = -1;
}
return res;
}
static int unload_module(void)
{
return ast_unregister_application(app);
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, app_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "External IVR Interface Application");
char *description(void)
{
return (char *) tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,899 +0,0 @@
/*
* Asterisk -- A telephony toolkit for Linux.
*
* Simple fax applications
*
* 2007-2008, Dmitry Andrianov <asterisk@dima.spb.ru>
*
* Code based on original implementation by Steve Underwood <steveu@coppice.org>
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*
*/
/*** MODULEINFO
<depend>spandsp</depend>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <pthread.h>
#include <errno.h>
#include <tiffio.h>
#include <spandsp.h>
#ifdef HAVE_SPANDSP_EXPOSE_H
#include <spandsp/expose.h>
#endif
#include <spandsp/version.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/module.h"
#include "asterisk/manager.h"
static char *app_sndfax_name = "SendFAX";
static char *app_sndfax_synopsis = "Send a FAX";
static char *app_sndfax_desc =
" SendFAX(filename[|options]):\n"
"Send a given TIFF file to the channel as a FAX.\n"
"The option string may contain zero or more of the following characters:\n"
" 'a' - makes the application behave as an answering machine\n"
" The default behaviour is to behave as a calling machine.\n"
"\n"
"This application uses following variables:\n"
" LOCALSTATIONID to identify itself to the remote end.\n"
" LOCALHEADERINFO to generate a header line on each page.\n"
"\n"
"This application sets the following channel variables upon completion:\n"
" FAXSTATUS - status of operation:\n"
" SUCCESS | FAILED\n"
" FAXERROR - Error when FAILED\n"
" FAXMODE - Mode used:\n"
" audio | T38\n"
" REMOTESTATIONID - CSID of the remote side.\n"
" FAXPAGES - number of pages sent.\n"
" FAXBITRATE - transmition rate.\n"
" FAXRESOLUTION - resolution.\n"
"\n"
"Returns -1 in case of user hang up or any channel error.\n"
"Returns 0 on success.\n";
static char *app_rcvfax_name = "ReceiveFAX";
static char *app_rcvfax_synopsis = "Receive a FAX";
static char *app_rcvfax_desc =
" ReceiveFAX(filename[|options]):\n"
"Receives a fax from the channel into the given filename overwriting\n"
"the file if it already exists. File created will have TIFF format.\n"
"The option string may contain zero or more of the following characters:\n"
" 'c' -- makes the application behave as a calling machine\n"
" The default behaviour is to behave as an answering machine.\n"
"\n"
"This application uses following variables:\n"
" LOCALSTATIONID to identify itself to the remote end.\n"
" LOCALHEADERINFO to generate a header line on each page.\n"
"\n"
"This application sets the following channel variables upon completion:\n"
" FAXSTATUS - status of operation:\n"
" SUCCESS | FAILED\n"
" FAXERROR - Error when FAILED\n"
" FAXMODE - Mode used:\n"
" audio | T38\n"
" REMOTESTATIONID - CSID of the remote side.\n"
" FAXPAGES - number of pages sent.\n"
" FAXBITRATE - transmition rate.\n"
" FAXRESOLUTION - resolution.\n"
"\n"
"Returns -1 in case of user hang up or any channel error.\n"
"Returns 0 on success.\n";
#define MAX_SAMPLES 240
/* Watchdog. I have seen situations when remote fax disconnects (because of poor line
quality) while SpanDSP continues staying in T30_STATE_IV_CTC state forever.
To avoid this, we terminate when we see that T30 state does not change for 5 minutes.
We also terminate application when more than 30 minutes passed regardless of
state changes. This is just a precaution measure - no fax should take that long */
#define WATCHDOG_TOTAL_TIMEOUT 30 * 60
#define WATCHDOG_STATE_TIMEOUT 5 * 60
typedef struct {
struct ast_channel *chan;
enum ast_t38_state t38state; /* T38 state of the channel */
int direction; /* Fax direction: 0 - receiving, 1 - sending */
int caller_mode;
char *file_name;
struct ast_control_t38_parameters t38parameters;
volatile int finished;
} fax_session;
static void span_message(int level, const char *msg)
{
if (level == SPAN_LOG_ERROR) {
ast_log(LOG_ERROR, "%s", msg);
} else if (level == SPAN_LOG_WARNING) {
ast_log(LOG_WARNING, "%s", msg);
} else {
ast_log(LOG_DEBUG, "%s", msg);
}
}
static int t38_tx_packet_handler(t38_core_state_t *s, void *user_data, const uint8_t *buf, int len, int count)
{
struct ast_channel *chan = (struct ast_channel *) user_data;
struct ast_frame outf = {
.frametype = AST_FRAME_MODEM,
.subclass = AST_MODEM_T38,
.src = __FUNCTION__,
};
/* TODO: Asterisk does not provide means of resending the same packet multiple
times so count is ignored at the moment */
AST_FRAME_SET_BUFFER(&outf, buf, 0, len);
if (ast_write(chan, &outf) < 0) {
ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
return -1;
}
return 0;
}
static void phase_e_handler(t30_state_t *f, void *user_data, int result)
{
const char *local_ident;
const char *far_ident;
char buf[20];
fax_session *s = (fax_session *) user_data;
t30_stats_t stat;
int pages_transferred;
ast_debug(1, "Fax phase E handler. result=%d\n", result);
t30_get_transfer_statistics(f, &stat);
s = (fax_session *) user_data;
if (result != T30_ERR_OK) {
s->finished = -1;
/* FAXSTATUS is already set to FAILED */
pbx_builtin_setvar_helper(s->chan, "FAXERROR", t30_completion_code_to_str(result));
ast_log(LOG_WARNING, "Error transmitting fax. result=%d: %s.\n", result, t30_completion_code_to_str(result));
return;
}
s->finished = 1;
local_ident = t30_get_tx_ident(f);
far_ident = t30_get_rx_ident(f);
pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "SUCCESS");
pbx_builtin_setvar_helper(s->chan, "FAXERROR", NULL);
pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", far_ident);
#if SPANDSP_RELEASE_DATE >= 20090220
pages_transferred = (s->direction) ? stat.pages_tx : stat.pages_rx;
#else
pages_transferred = stat.pages_transferred;
#endif
snprintf(buf, sizeof(buf), "%d", pages_transferred);
pbx_builtin_setvar_helper(s->chan, "FAXPAGES", buf);
snprintf(buf, sizeof(buf), "%d", stat.y_resolution);
pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", buf);
snprintf(buf, sizeof(buf), "%d", stat.bit_rate);
pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", buf);
ast_debug(1, "Fax transmitted successfully.\n");
ast_debug(1, " Remote station ID: %s\n", far_ident);
ast_debug(1, " Pages transferred: %d\n", pages_transferred);
ast_debug(1, " Image resolution: %d x %d\n", stat.x_resolution, stat.y_resolution);
ast_debug(1, " Transfer Rate: %d\n", stat.bit_rate);
manager_event(EVENT_FLAG_CALL,
s->direction ? "FaxSent" : "FaxReceived",
"Channel: %s\r\n"
"Exten: %s\r\n"
"CallerID: %s\r\n"
"RemoteStationID: %s\r\n"
"LocalStationID: %s\r\n"
"PagesTransferred: %d\r\n"
"Resolution: %d\r\n"
"TransferRate: %d\r\n"
"FileName: %s\r\n",
s->chan->name,
s->chan->exten,
S_OR(s->chan->cid.cid_num, ""),
far_ident,
local_ident,
pages_transferred,
stat.y_resolution,
stat.bit_rate,
s->file_name);
}
/* === Helper functions to configure fax === */
/* Setup SPAN logging according to Asterisk debug level */
static int set_logging(logging_state_t *state)
{
int level = SPAN_LOG_WARNING + option_debug;
span_log_set_message_handler(state, span_message);
span_log_set_level(state, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | level);
return 0;
}
static void set_local_info(t30_state_t *state, fax_session *s)
{
const char *x;
x = pbx_builtin_getvar_helper(s->chan, "LOCALSTATIONID");
if (!ast_strlen_zero(x))
t30_set_tx_ident(state, x);
x = pbx_builtin_getvar_helper(s->chan, "LOCALHEADERINFO");
if (!ast_strlen_zero(x))
t30_set_tx_page_header_info(state, x);
}
static void set_file(t30_state_t *state, fax_session *s)
{
if (s->direction)
t30_set_tx_file(state, s->file_name, -1, -1);
else
t30_set_rx_file(state, s->file_name, -1);
}
static void set_ecm(t30_state_t *state, int ecm)
{
t30_set_ecm_capability(state, ecm);
t30_set_supported_compressions(state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
}
/* === Generator === */
/* This function is only needed to return passed params so
generator_activate will save it to channel's generatordata */
static void *fax_generator_alloc(struct ast_channel *chan, void *params)
{
return params;
}
static int fax_generator_generate(struct ast_channel *chan, void *data, int len, int samples)
{
fax_state_t *fax = (fax_state_t*) data;
uint8_t buffer[AST_FRIENDLY_OFFSET + MAX_SAMPLES * sizeof(uint16_t)];
int16_t *buf = (int16_t *) (buffer + AST_FRIENDLY_OFFSET);
struct ast_frame outf = {
.frametype = AST_FRAME_VOICE,
.subclass = AST_FORMAT_SLINEAR,
.src = __FUNCTION__,
};
if (samples > MAX_SAMPLES) {
ast_log(LOG_WARNING, "Only generating %d samples, where %d requested\n", MAX_SAMPLES, samples);
samples = MAX_SAMPLES;
}
if ((len = fax_tx(fax, buf, samples)) > 0) {
outf.samples = len;
AST_FRAME_SET_BUFFER(&outf, buffer, AST_FRIENDLY_OFFSET, len * sizeof(int16_t));
if (ast_write(chan, &outf) < 0) {
ast_log(LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
return -1;
}
}
return 0;
}
struct ast_generator generator = {
alloc: fax_generator_alloc,
generate: fax_generator_generate,
};
/* === Transmission === */
static int transmit_audio(fax_session *s)
{
int res = -1;
int original_read_fmt = AST_FORMAT_SLINEAR;
int original_write_fmt = AST_FORMAT_SLINEAR;
fax_state_t fax;
t30_state_t *t30state;
struct ast_frame *inf = NULL;
int last_state = 0;
struct timeval now, start, state_change;
enum ast_t38_state t38_state;
struct ast_control_t38_parameters t38_parameters = { .version = 0,
.max_ifp = 800,
.rate = AST_T38_RATE_14400,
.rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF,
.fill_bit_removal = 1,
/*
* spandsp has API calls to support MMR and JBIG transcoding, but they aren't
* implemented quite yet... so don't offer them to the remote endpoint
* .transcoding_mmr = 1,
* .transcoding_jbig = 1,
*/
};
/* if in called party mode, try to use T.38 */
if (s->caller_mode == FALSE) {
/* check if we are already in T.38 mode (unlikely), or if we can request
* a switch... if so, request it now and wait for the result, rather
* than starting an audio FAX session that will have to be cancelled
*/
if ((t38_state = ast_channel_get_t38_state(s->chan)) == T38_STATE_NEGOTIATED) {
return 1;
} else if ((t38_state != T38_STATE_UNAVAILABLE) &&
(t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE,
(ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0))) {
/* wait up to five seconds for negotiation to complete */
unsigned int timeout = 5000;
int ms;
ast_debug(1, "Negotiating T.38 for receive on %s\n", s->chan->name);
while (timeout > 0) {
ms = ast_waitfor(s->chan, 1000);
if (ms < 0) {
ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", s->chan->name);
return -1;
}
if (!ms) {
/* nothing happened */
if (timeout > 0) {
timeout -= 1000;
continue;
} else {
ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", s->chan->name);
break;
}
}
if (!(inf = ast_read(s->chan))) {
return -1;
}
if ((inf->frametype == AST_FRAME_CONTROL) &&
(inf->subclass == AST_CONTROL_T38_PARAMETERS) &&
(inf->datalen == sizeof(t38_parameters))) {
struct ast_control_t38_parameters *parameters = inf->data;
switch (parameters->request_response) {
case AST_T38_NEGOTIATED:
ast_debug(1, "Negotiated T.38 for receive on %s\n", s->chan->name);
res = 1;
break;
case AST_T38_REFUSED:
ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", s->chan->name);
break;
default:
ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", s->chan->name);
break;
}
ast_frfree(inf);
if (res == 1) {
return 1;
} else {
break;
}
}
ast_frfree(inf);
}
}
}
#if SPANDSP_RELEASE_DATE >= 20080725
/* for spandsp shaphots 0.0.6 and higher */
t30state = &fax.t30;
#else
/* for spandsp release 0.0.5 */
t30state = &fax.t30_state;
#endif
original_read_fmt = s->chan->readformat;
if (original_read_fmt != AST_FORMAT_SLINEAR) {
res = ast_set_read_format(s->chan, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
goto done;
}
}
original_write_fmt = s->chan->writeformat;
if (original_write_fmt != AST_FORMAT_SLINEAR) {
res = ast_set_write_format(s->chan, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
goto done;
}
}
/* Initialize T30 terminal */
fax_init(&fax, s->caller_mode);
/* Setup logging */
set_logging(&fax.logging);
set_logging(&t30state->logging);
/* Configure terminal */
set_local_info(t30state, s);
set_file(t30state, s);
set_ecm(t30state, TRUE);
fax_set_transmit_on_idle(&fax, TRUE);
t30_set_phase_e_handler(t30state, phase_e_handler, s);
start = state_change = ast_tvnow();
ast_activate_generator(s->chan, &generator, &fax);
while (!s->finished) {
inf = NULL;
if ((res = ast_waitfor(s->chan, 25)) < 0) {
ast_debug(1, "Error waiting for a frame\n");
break;
}
/* Watchdog */
now = ast_tvnow();
if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {
ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
res = -1;
break;
}
if (!res) {
/* There was timeout waiting for a frame. Loop around and wait again */
continue;
}
/* There is a frame available. Get it */
res = 0;
if (!(inf = ast_read(s->chan))) {
ast_debug(1, "Channel hangup\n");
res = -1;
break;
}
ast_debug(10, "frame %d/%d, len=%d\n", inf->frametype, inf->subclass, inf->datalen);
/* Check the frame type. Format also must be checked because there is a chance
that a frame in old format was already queued before we set channel format
to slinear so it will still be received by ast_read */
if (inf->frametype == AST_FRAME_VOICE && inf->subclass == AST_FORMAT_SLINEAR) {
if (fax_rx(&fax, inf->data, inf->samples) < 0) {
/* I know fax_rx never returns errors. The check here is for good style only */
ast_log(LOG_WARNING, "fax_rx returned error\n");
res = -1;
break;
}
if (last_state != t30state->state) {
state_change = ast_tvnow();
last_state = t30state->state;
}
} else if ((inf->frametype == AST_FRAME_CONTROL) &&
(inf->subclass == AST_CONTROL_T38_PARAMETERS)) {
struct ast_control_t38_parameters *parameters = inf->data;
if (parameters->request_response == AST_T38_NEGOTIATED) {
/* T38 switchover completed */
s->t38parameters = *parameters;
ast_debug(1, "T38 negotiated, finishing audio loop\n");
res = 1;
break;
} else if (parameters->request_response == AST_T38_REQUEST_NEGOTIATE) {
t38_parameters.request_response = AST_T38_NEGOTIATED;
ast_debug(1, "T38 request received, accepting\n");
/* Complete T38 switchover */
ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
/* Do not break audio loop, wait until channel driver finally acks switchover
* with AST_T38_NEGOTIATED
*/
}
}
ast_frfree(inf);
inf = NULL;
}
ast_debug(1, "Loop finished, res=%d\n", res);
if (inf)
ast_frfree(inf);
ast_deactivate_generator(s->chan);
/* If we are switching to T38, remove phase E handler. Otherwise it will be executed
by t30_terminate, display diagnostics and set status variables although no transmittion
has taken place yet. */
if (res > 0) {
t30_set_phase_e_handler(t30state, NULL, NULL);
}
t30_terminate(t30state);
fax_release(&fax);
done:
if (original_write_fmt != AST_FORMAT_SLINEAR) {
if (ast_set_write_format(s->chan, original_write_fmt) < 0)
ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", s->chan->name);
}
if (original_read_fmt != AST_FORMAT_SLINEAR) {
if (ast_set_read_format(s->chan, original_read_fmt) < 0)
ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", s->chan->name);
}
return res;
}
static int transmit_t38(fax_session *s)
{
int res = 0;
t38_terminal_state_t t38;
struct ast_frame *inf = NULL;
int last_state = 0;
struct timeval now, start, state_change, last_frame;
t30_state_t *t30state;
t38_core_state_t *t38state;
#if SPANDSP_RELEASE_DATE >= 20080725
/* for spandsp shaphots 0.0.6 and higher */
t30state = &t38.t30;
t38state = &t38.t38_fe.t38;
#else
/* for spandsp releases 0.0.5 */
t30state = &t38.t30_state;
t38state = &t38.t38;
#endif
/* Initialize terminal */
memset(&t38, 0, sizeof(t38));
if (t38_terminal_init(&t38, s->caller_mode, t38_tx_packet_handler, s->chan) == NULL) {
ast_log(LOG_WARNING, "Unable to start T.38 termination.\n");
res = -1;
goto disable_t38;
}
t38_set_max_datagram_size(t38state, s->t38parameters.max_ifp);
if (s->t38parameters.fill_bit_removal) {
t38_set_fill_bit_removal(t38state, TRUE);
}
if (s->t38parameters.transcoding_mmr) {
t38_set_mmr_transcoding(t38state, TRUE);
}
if (s->t38parameters.transcoding_jbig) {
t38_set_jbig_transcoding(t38state, TRUE);
}
/* Setup logging */
set_logging(&t38.logging);
set_logging(&t30state->logging);
set_logging(&t38state->logging);
/* Configure terminal */
set_local_info(t30state, s);
set_file(t30state, s);
set_ecm(t30state, TRUE);
t30_set_phase_e_handler(t30state, phase_e_handler, s);
now = start = state_change = ast_tvnow();
while (!s->finished) {
res = ast_waitfor(s->chan, 20);
if (res < 0)
break;
else if (res > 0)
res = 0;
last_frame = now;
now = ast_tvnow();
t38_terminal_send_timeout(&t38, ast_tvdiff_us(now, last_frame) / (1000000 / 8000));
inf = ast_read(s->chan);
if (inf == NULL) {
ast_debug(1, "Channel hangup\n");
res = -1;
break;
}
ast_debug(10, "frame %d/%d, len=%d\n", inf->frametype, inf->subclass, inf->datalen);
if (inf->frametype == AST_FRAME_MODEM && inf->subclass == AST_MODEM_T38) {
t38_core_rx_ifp_packet(t38state, inf->data, inf->datalen, inf->seqno);
/* Watchdog */
if (last_state != t30state->state) {
state_change = ast_tvnow();
last_state = t30state->state;
}
} else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass == AST_CONTROL_T38_PARAMETERS) {
struct ast_control_t38_parameters *parameters = inf->data;
if (parameters->request_response == AST_T38_TERMINATED) {
ast_debug(1, "T38 down, finishing\n");
break;
}
}
ast_frfree(inf);
inf = NULL;
/* Watchdog */
if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {
ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
res = -1;
break;
}
}
ast_debug(1, "Loop finished, res=%d\n", res);
if (inf)
ast_frfree(inf);
t30_terminate(t30state);
t38_terminal_release(&t38);
disable_t38:
/* if we are not the caller, it's our job to shut down the T.38
* session when the FAX transmisson is complete.
*/
if ((s->caller_mode == FALSE) &&
(ast_channel_get_t38_state(s->chan) == T38_STATE_NEGOTIATED)) {
struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, };
if (ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0) {
/* wait up to five seconds for negotiation to complete */
unsigned int timeout = 5000;
int ms;
ast_debug(1, "Shutting down T.38 on %s\n", s->chan->name);
while (timeout > 0) {
ms = ast_waitfor(s->chan, 1000);
if (ms < 0) {
ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", s->chan->name);
return -1;
}
if (!ms) {
/* nothing happened */
if (timeout > 0) {
timeout -= 1000;
continue;
} else {
ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 shutdown.\n", s->chan->name);
break;
}
}
if (!(inf = ast_read(s->chan))) {
return -1;
}
if ((inf->frametype == AST_FRAME_CONTROL) &&
(inf->subclass == AST_CONTROL_T38_PARAMETERS) &&
(inf->datalen == sizeof(t38_parameters))) {
struct ast_control_t38_parameters *parameters = inf->data;
switch (parameters->request_response) {
case AST_T38_TERMINATED:
ast_debug(1, "Shut down T.38 on %s\n", s->chan->name);
break;
case AST_T38_REFUSED:
ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", s->chan->name);
break;
default:
ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", s->chan->name);
break;
}
ast_frfree(inf);
break;
}
ast_frfree(inf);
}
}
}
return res;
}
static int transmit(fax_session *s)
{
int res = 0;
/* Clear all channel variables which to be set by the application.
Pre-set status to error so in case of any problems we can just leave */
pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "FAILED");
pbx_builtin_setvar_helper(s->chan, "FAXERROR", "Channel problems");
pbx_builtin_setvar_helper(s->chan, "FAXMODE", NULL);
pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", NULL);
pbx_builtin_setvar_helper(s->chan, "FAXPAGES", NULL);
pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", NULL);
pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", NULL);
if (s->chan->_state != AST_STATE_UP) {
/* Shouldn't need this, but checking to see if channel is already answered
* Theoretically asterisk should already have answered before running the app */
res = ast_answer(s->chan);
if (res) {
ast_log(LOG_WARNING, "Could not answer channel '%s'\n", s->chan->name);
return res;
}
}
s->t38state = ast_channel_get_t38_state(s->chan);
if (s->t38state != T38_STATE_NEGOTIATED) {
/* T38 is not negotiated on the channel yet. First start regular transmission. If it switches to T38, follow */
pbx_builtin_setvar_helper(s->chan, "FAXMODE", "audio");
res = transmit_audio(s);
if (res > 0) {
/* transmit_audio reports switchover to T38. Update t38state */
s->t38state = ast_channel_get_t38_state(s->chan);
if (s->t38state != T38_STATE_NEGOTIATED) {
ast_log(LOG_ERROR, "Audio loop reports T38 switchover but t38state != T38_STATE_NEGOTIATED\n");
}
}
}
if (s->t38state == T38_STATE_NEGOTIATED) {
pbx_builtin_setvar_helper(s->chan, "FAXMODE", "T38");
res = transmit_t38(s);
}
if (res) {
ast_log(LOG_WARNING, "Transmission error\n");
res = -1;
} else if (s->finished < 0) {
ast_log(LOG_WARNING, "Transmission failed\n");
} else if (s->finished > 0) {
ast_debug(1, "Transmission finished Ok\n");
}
return res;
}
/* === Application functions === */
static int sndfax_exec(struct ast_channel *chan, void *data)
{
int res = 0;
char *parse;
fax_session session = { 0, };
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(file_name);
AST_APP_ARG(options);
);
if (chan == NULL) {
ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
return -1;
}
/* The next few lines of code parse out the filename and header from the input string */
if (ast_strlen_zero(data)) {
/* No data implies no filename or anything is present */
ast_log(LOG_ERROR, "SendFAX requires an argument (filename)\n");
return -1;
}
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
session.caller_mode = TRUE;
if (args.options) {
if (strchr(args.options, 'a'))
session.caller_mode = FALSE;
}
/* Done parsing */
session.direction = 1;
session.file_name = args.file_name;
session.chan = chan;
session.finished = 0;
res = transmit(&session);
return res;
}
static int rcvfax_exec(struct ast_channel *chan, void *data)
{
int res = 0;
char *parse;
fax_session session;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(file_name);
AST_APP_ARG(options);
);
if (chan == NULL) {
ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
return -1;
}
/* The next few lines of code parse out the filename and header from the input string */
if (ast_strlen_zero(data)) {
/* No data implies no filename or anything is present */
ast_log(LOG_ERROR, "ReceiveFAX requires an argument (filename)\n");
return -1;
}
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
session.caller_mode = FALSE;
if (args.options) {
if (strchr(args.options, 'c'))
session.caller_mode = TRUE;
}
/* Done parsing */
session.direction = 0;
session.file_name = args.file_name;
session.chan = chan;
session.finished = 0;
res = transmit(&session);
return res;
}
static int unload_module(void)
{
int res;
res = ast_unregister_application(app_sndfax_name);
res |= ast_unregister_application(app_rcvfax_name);
return res;
}
static int load_module(void)
{
int res ;
res = ast_register_application(app_sndfax_name, sndfax_exec, app_sndfax_synopsis, app_sndfax_desc);
res |= ast_register_application(app_rcvfax_name, rcvfax_exec, app_rcvfax_synopsis, app_rcvfax_desc);
/* The default SPAN message handler prints to stderr. It is something we do not want */
span_set_message_handler(NULL);
return res;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Simple FAX Application",
.load = load_module,
.unload = unload_module,
);

View File

@@ -19,35 +19,33 @@
/*! \file
*
* \brief Connect to festival
*
* \author Christos Ricudis <ricudis@itc.auth.gr>
*
* \extref The Festival Speech Synthesis System - http://www.cstr.ed.ac.uk/projects/festival/
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>working_fork</depend>
***/
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <errno.h>
#ifdef HAVE_CAP
#include <sys/capability.h>
#endif /* HAVE_CAP */
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
@@ -55,132 +53,120 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/config.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
#include "asterisk/options.h"
#define FESTIVAL_CONFIG "festival.conf"
#define MAXLEN 180
#define MAXFESTLEN 2048
static char *tdesc = "Simple Festival Interface";
static char *app = "Festival";
static char *synopsis = "Say text to the user";
static char *descrip =
" Festival(text[,intkeys]): Connect to Festival, send the argument, get back the waveform,\n"
" Festival(text[|intkeys]): Connect to Festival, send the argument, get back the waveform,"
"play it to the user, allowing any given interrupt keys to immediately terminate and return\n"
"the value, or 'any' to allow any number back (useful in dialplan)\n";
STANDARD_LOCAL_USER;
static char *socket_receive_file_to_buff(int fd, int *size)
LOCAL_USER_DECL;
static char *socket_receive_file_to_buff(int fd,int *size)
{
/* Receive file (probably a waveform file) from socket using
* Festival key stuff technique, but long winded I know, sorry
* but will receive any file without closing the stream or
* using OOB data
*/
static char *file_stuff_key = "ft_StUfF_key"; /* must == Festival's key */
char *buff, *tmp;
int bufflen;
int n,k,i;
char c;
/* Receive file (probably a waveform file) from socket using */
/* Festival key stuff technique, but long winded I know, sorry */
/* but will receive any file without closeing the stream or */
/* using OOB data */
static char *file_stuff_key = "ft_StUfF_key"; /* must == Festival's key */
char *buff;
int bufflen;
int n,k,i;
char c;
bufflen = 1024;
if (!(buff = ast_malloc(bufflen)))
return NULL;
*size = 0;
bufflen = 1024;
buff = (char *)malloc(bufflen);
*size=0;
for (k = 0; file_stuff_key[k] != '\0';) {
n = read(fd, &c, 1);
if (n == 0)
break; /* hit stream eof before end of file */
if ((*size) + k + 1 >= bufflen) {
/* +1 so you can add a terminating NULL if you want */
bufflen += bufflen / 4;
if (!(tmp = ast_realloc(buff, bufflen))) {
ast_free(buff);
return NULL;
}
buff = tmp;
}
if (file_stuff_key[k] == c)
k++;
else if ((c == 'X') && (file_stuff_key[k+1] == '\0')) {
/* It looked like the key but wasn't */
for (i = 0; i < k; i++, (*size)++)
buff[*size] = file_stuff_key[i];
k = 0;
/* omit the stuffed 'X' */
} else {
for (i = 0; i < k; i++, (*size)++)
buff[*size] = file_stuff_key[i];
k = 0;
buff[*size] = c;
(*size)++;
}
}
for (k=0; file_stuff_key[k] != '\0';)
{
n = read(fd,&c,1);
if (n==0) break; /* hit stream eof before end of file */
if ((*size)+k+1 >= bufflen)
{ /* +1 so you can add a NULL if you want */
bufflen += bufflen/4;
buff = (char *)realloc(buff,bufflen);
}
if (file_stuff_key[k] == c)
k++;
else if ((c == 'X') && (file_stuff_key[k+1] == '\0'))
{ /* It looked like the key but wasn't */
for (i=0; i < k; i++,(*size)++)
buff[*size] = file_stuff_key[i];
k=0;
/* omit the stuffed 'X' */
}
else
{
for (i=0; i < k; i++,(*size)++)
buff[*size] = file_stuff_key[i];
k=0;
buff[*size] = c;
(*size)++;
}
return buff;
}
return buff;
}
static int send_waveform_to_fd(char *waveform, int length, int fd)
{
int res;
int x;
static int send_waveform_to_fd(char *waveform, int length, int fd) {
int res;
int x;
#ifdef __PPC__
char c;
#endif
sigset_t fullset, oldset;
#ifdef HAVE_CAP
cap_t cap;
#endif
sigfillset(&fullset);
pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
res = fork();
if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n");
if (res) {
res = fork();
if (res < 0)
ast_log(LOG_WARNING, "Fork failed\n");
if (res) {
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
return res;
return res;
}
#ifdef HAVE_CAP
cap = cap_from_text("cap_net_admin-eip");
if (cap_set_proc(cap)) {
/* Careful with order! Logging cannot happen after we close FDs */
ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
}
cap_free(cap);
#endif
for (x = 0; x < 256; x++) {
if (x != fd)
close(x);
}
if (ast_opt_high_priority)
for (x=0;x<256;x++) {
if (x != fd)
close(x);
}
if (option_highpriority)
ast_set_priority(0);
signal(SIGPIPE, SIG_DFL);
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
/*IAS */
#ifdef __PPC__
for (x = 0; x < length; x += 2) {
c = *(waveform + x + 1);
*(waveform + x + 1) = *(waveform + x);
*(waveform + x) = c;
for( x=0; x<length; x+=2)
{
c = *(waveform+x+1);
*(waveform+x+1)=*(waveform+x);
*(waveform+x)=c;
}
#endif
if (write(fd, waveform, length) < 0) {
ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
}
write(fd,waveform,length);
close(fd);
exit(0);
}
static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, int length, char *intkeys)
{
int res = 0;
static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, int length, char *intkeys) {
int res=0;
int fds[2];
int ms = -1;
int pid = -1;
int needed = 0;
int owriteformat;
@@ -189,15 +175,13 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
struct ast_frame f;
char offset[AST_FRIENDLY_OFFSET];
char frdata[2048];
} myf = {
.f = { 0, },
};
if (pipe(fds)) {
ast_log(LOG_WARNING, "Unable to create pipe\n");
return -1;
}
} myf;
if (pipe(fds)) {
ast_log(LOG_WARNING, "Unable to create pipe\n");
return -1;
}
/* Answer if it's not already going */
if (chan->_state != AST_STATE_UP)
ast_answer(chan);
@@ -211,13 +195,14 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
return -1;
}
res = send_waveform_to_fd(waveform, length, fds[1]);
res=send_waveform_to_fd(waveform,length,fds[1]);
if (res >= 0) {
pid = res;
/* Order is important -- there's almost always going to be mp3... we want to prioritize the
user */
for (;;) {
res = ast_waitfor(chan, 1000);
ms = 1000;
res = ast_waitfor(chan, ms);
if (res < 1) {
res = -1;
break;
@@ -229,7 +214,7 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
break;
}
if (f->frametype == AST_FRAME_DTMF) {
ast_debug(1, "User pressed a key\n");
ast_log(LOG_DEBUG, "User pressed a key\n");
if (intkeys && strchr(intkeys, f->subclass)) {
res = f->subclass;
ast_frfree(f);
@@ -250,6 +235,7 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
myf.f.subclass = AST_FORMAT_SLINEAR;
myf.f.datalen = res;
myf.f.samples = res / 2;
myf.f.mallocd = 0;
myf.f.offset = AST_FRIENDLY_OFFSET;
myf.f.src = __PRETTY_FUNCTION__;
myf.f.data = myf.frdata;
@@ -259,13 +245,13 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
break;
}
if (res < needed) { /* last frame */
ast_debug(1, "Last frame\n");
res = 0;
ast_log(LOG_DEBUG, "Last frame\n");
res=0;
ast_frfree(f);
break;
}
} else {
ast_debug(1, "No more waveform\n");
ast_log(LOG_DEBUG, "No more waveform\n");
res = 0;
}
}
@@ -275,29 +261,34 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
close(fds[0]);
close(fds[1]);
#if 0
if (pid > -1)
kill(pid, SIGKILL);
#endif
/* if (pid > -1) */
/* kill(pid, SIGKILL); */
if (!res && owriteformat)
ast_set_write_format(chan, owriteformat);
return res;
}
#define MAXLEN 180
#define MAXFESTLEN 2048
static int festival_exec(struct ast_channel *chan, void *vdata)
{
int usecache;
int res = 0;
struct sockaddr_in serv_addr;
int res=0;
struct localuser *u;
struct sockaddr_in serv_addr;
struct hostent *serverhost;
struct ast_hostent ahp;
int fd;
FILE *fs;
const char *host;
const char *cachedir;
const char *temp;
const char *festivalcommand;
int port = 1314;
char *host;
char *cachedir;
char *temp;
char *festivalcommand;
int port=1314;
int n;
char ack[4];
char *waveform;
@@ -310,29 +301,27 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
char MD5Hex[33] = "";
char koko[4] = "";
char cachefile[MAXFESTLEN]="";
int readcache = 0;
int writecache = 0;
int readcache=0;
int writecache=0;
int strln;
int fdesc = -1;
char buffer[16384];
int seekpos = 0;
char *data;
char *intstr;
struct ast_config *cfg;
char *newfestivalcommand;
struct ast_flags config_flags = { 0 };
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(text);
AST_APP_ARG(interrupt);
);
if (ast_strlen_zero(vdata)) {
ast_log(LOG_WARNING, "festival requires an argument (text)\n");
return -1;
}
cfg = ast_config_load(FESTIVAL_CONFIG, config_flags);
LOCAL_USER_ADD(u);
cfg = ast_config_load(FESTIVAL_CONFIG);
if (!cfg) {
ast_log(LOG_WARNING, "No such configuration file %s\n", FESTIVAL_CONFIG);
LOCAL_USER_REMOVE(u);
return -1;
}
if (!(host = ast_variable_retrieve(cfg, "general", "host"))) {
@@ -344,226 +333,216 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
port = atoi(temp);
}
if (!(temp = ast_variable_retrieve(cfg, "general", "usecache"))) {
usecache = 0;
usecache=0;
} else {
usecache = ast_true(temp);
}
if (!(cachedir = ast_variable_retrieve(cfg, "general", "cachedir"))) {
cachedir = "/tmp/";
}
data = ast_strdupa(vdata);
AST_STANDARD_APP_ARGS(args, data);
if (!(festivalcommand = ast_variable_retrieve(cfg, "general", "festivalcommand"))) {
const char *startcmd = "(tts_textasterisk \"";
const char *endcmd = "\" 'file)(quit)\n";
strln = strlen(startcmd) + strlen(args.text) + strlen(endcmd) + 1;
newfestivalcommand = alloca(strln);
snprintf(newfestivalcommand, strln, "%s%s%s", startcmd, args.text, endcmd);
festivalcommand = newfestivalcommand;
} else { /* This else parses the festivalcommand that we're sent from the config file for \n's, etc */
int i, j;
newfestivalcommand = alloca(strlen(festivalcommand) + strlen(args.text) + 1);
for (i = 0, j = 0; i < strlen(festivalcommand); i++) {
if (festivalcommand[i] == '\\' && festivalcommand[i + 1] == 'n') {
newfestivalcommand[j++] = '\n';
i++;
} else if (festivalcommand[i] == '\\') {
newfestivalcommand[j++] = festivalcommand[i + 1];
i++;
} else if (festivalcommand[i] == '%' && festivalcommand[i + 1] == 's') {
sprintf(&newfestivalcommand[j], "%s", args.text); /* we know it is big enough */
j += strlen(args.text);
i++;
} else
newfestivalcommand[j++] = festivalcommand[i];
}
newfestivalcommand[j] = '\0';
festivalcommand = newfestivalcommand;
festivalcommand = "(tts_textasterisk \"%s\" 'file)(quit)\n";
}
if (args.interrupt && !strcasecmp(args.interrupt, "any"))
args.interrupt = AST_DIGIT_ANY;
ast_debug(1, "Text passed to festival server : %s\n", args.text);
/* Connect to local festival server */
fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fd < 0) {
ast_log(LOG_WARNING, "festival_client: can't get socket\n");
data = ast_strdupa(vdata);
if (!data) {
ast_log(LOG_ERROR, "Out of memery\n");
ast_config_destroy(cfg);
LOCAL_USER_REMOVE(u);
return -1;
}
memset(&serv_addr, 0, sizeof(serv_addr));
if ((serv_addr.sin_addr.s_addr = inet_addr(host)) == -1) {
/* its a name rather than an ipnum */
serverhost = ast_gethostbyname(host, &ahp);
if (serverhost == NULL) {
ast_log(LOG_WARNING, "festival_client: gethostbyname failed\n");
ast_config_destroy(cfg);
return -1;
}
memmove(&serv_addr.sin_addr, serverhost->h_addr, serverhost->h_length);
intstr = strchr(data, '|');
if (intstr) {
*intstr = '\0';
intstr++;
if (!strcasecmp(intstr, "any"))
intstr = AST_DIGIT_ANY;
}
ast_log(LOG_DEBUG, "Text passed to festival server : %s\n",(char *)data);
/* Connect to local festival server */
fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fd < 0) {
ast_log(LOG_WARNING,"festival_client: can't get socket\n");
ast_config_destroy(cfg);
LOCAL_USER_REMOVE(u);
return -1;
}
memset(&serv_addr, 0, sizeof(serv_addr));
if ((serv_addr.sin_addr.s_addr = inet_addr(host)) == -1) {
/* its a name rather than an ipnum */
serverhost = ast_gethostbyname(host, &ahp);
if (serverhost == (struct hostent *)0) {
ast_log(LOG_WARNING,"festival_client: gethostbyname failed\n");
ast_config_destroy(cfg);
LOCAL_USER_REMOVE(u);
return -1;
}
memmove(&serv_addr.sin_addr,serverhost->h_addr, serverhost->h_length);
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
ast_log(LOG_WARNING, "festival_client: connect to server failed\n");
ast_log(LOG_WARNING,"festival_client: connect to server failed\n");
ast_config_destroy(cfg);
return -1;
LOCAL_USER_REMOVE(u);
return -1;
}
/* Compute MD5 sum of string */
MD5Init(&md5ctx);
MD5Update(&md5ctx,(unsigned char const *)data,strlen(data));
MD5Final(MD5Res,&md5ctx);
MD5Hex[0] = '\0';
/* Convert to HEX and look if there is any matching file in the cache
directory */
for (i=0;i<16;i++) {
snprintf(koko, sizeof(koko), "%X",MD5Res[i]);
strncat(MD5Hex, koko, sizeof(MD5Hex) - strlen(MD5Hex) - 1);
}
readcache=0;
writecache=0;
if (strlen(cachedir)+strlen(MD5Hex)+1<=MAXFESTLEN && (usecache==-1)) {
snprintf(cachefile, sizeof(cachefile), "%s/%s", cachedir, MD5Hex);
fdesc=open(cachefile,O_RDWR);
if (fdesc==-1) {
fdesc=open(cachefile,O_CREAT|O_RDWR,0777);
if (fdesc!=-1) {
writecache=1;
strln=strlen((char *)data);
ast_log(LOG_DEBUG,"line length : %d\n",strln);
write(fdesc,&strln,sizeof(int));
write(fdesc,data,strln);
seekpos=lseek(fdesc,0,SEEK_CUR);
ast_log(LOG_DEBUG,"Seek position : %d\n",seekpos);
}
} else {
read(fdesc,&strln,sizeof(int));
ast_log(LOG_DEBUG,"Cache file exists, strln=%d, strlen=%d\n",strln,(int)strlen((char *)data));
if (strlen((char *)data)==strln) {
ast_log(LOG_DEBUG,"Size OK\n");
read(fdesc,&bigstring,strln);
bigstring[strln] = 0;
if (strcmp(bigstring,data)==0) {
readcache=1;
} else {
ast_log(LOG_WARNING,"Strings do not match\n");
}
} else {
ast_log(LOG_WARNING,"Size mismatch\n");
}
}
}
/* Compute MD5 sum of string */
MD5Init(&md5ctx);
MD5Update(&md5ctx, (unsigned char *)args.text, strlen(args.text));
MD5Final(MD5Res, &md5ctx);
MD5Hex[0] = '\0';
/* Convert to HEX and look if there is any matching file in the cache
directory */
for (i = 0; i < 16; i++) {
snprintf(koko, sizeof(koko), "%X", MD5Res[i]);
strncat(MD5Hex, koko, sizeof(MD5Hex) - strlen(MD5Hex) - 1);
}
readcache = 0;
writecache = 0;
if (strlen(cachedir) + strlen(MD5Hex) + 1 <= MAXFESTLEN && (usecache == -1)) {
snprintf(cachefile, sizeof(cachefile), "%s/%s", cachedir, MD5Hex);
fdesc = open(cachefile, O_RDWR);
if (fdesc == -1) {
fdesc = open(cachefile, O_CREAT | O_RDWR, AST_FILE_MODE);
if (fdesc != -1) {
writecache = 1;
strln = strlen(args.text);
ast_debug(1, "line length : %d\n", strln);
if (write(fdesc,&strln,sizeof(int)) < 0) {
ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
}
if (write(fdesc,data,strln) < 0) {
ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
}
seekpos = lseek(fdesc, 0, SEEK_CUR);
ast_debug(1, "Seek position : %d\n", seekpos);
}
} else {
if (read(fdesc,&strln,sizeof(int)) != sizeof(int)) {
ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
}
ast_debug(1, "Cache file exists, strln=%d, strlen=%d\n", strln, (int)strlen(args.text));
if (strlen(args.text) == strln) {
ast_debug(1, "Size OK\n");
if (read(fdesc,&bigstring,strln) != strln) {
ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
}
bigstring[strln] = 0;
if (strcmp(bigstring, args.text) == 0) {
readcache = 1;
} else {
ast_log(LOG_WARNING, "Strings do not match\n");
}
} else {
ast_log(LOG_WARNING, "Size mismatch\n");
}
}
}
if (readcache == 1) {
if (readcache==1) {
close(fd);
fd = fdesc;
ast_debug(1, "Reading from cache...\n");
fd=fdesc;
ast_log(LOG_DEBUG,"Reading from cache...\n");
} else {
ast_debug(1, "Passing text to festival...\n");
fs = fdopen(dup(fd), "wb");
fprintf(fs, "%s", festivalcommand);
ast_log(LOG_DEBUG,"Passing text to festival...\n");
fs=fdopen(dup(fd),"wb");
fprintf(fs,festivalcommand,(char *)data);
fflush(fs);
fclose(fs);
}
/* Write to cache and then pass it down */
if (writecache == 1) {
ast_debug(1, "Writing result to cache...\n");
while ((strln = read(fd, buffer, 16384)) != 0) {
if (write(fdesc,buffer,strln) < 0) {
ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
}
if (writecache==1) {
ast_log(LOG_DEBUG,"Writing result to cache...\n");
while ((strln=read(fd,buffer,16384))!=0) {
write(fdesc,buffer,strln);
}
close(fd);
close(fdesc);
fd = open(cachefile, O_RDWR);
lseek(fd, seekpos, SEEK_SET);
fd=open(cachefile,O_RDWR);
lseek(fd,seekpos,SEEK_SET);
}
ast_debug(1, "Passing data to channel...\n");
ast_log(LOG_DEBUG,"Passing data to channel...\n");
/* Read back info from server */
/* This assumes only one waveform will come back, also LP is unlikely */
wave = 0;
do {
int read_data;
for (n = 0; n < 3; ) {
read_data = read(fd, ack + n, 3 - n);
/* this avoids falling in infinite loop
* in case that festival server goes down
*/
if (read_data == -1) {
ast_log(LOG_WARNING, "Unable to read from cache/festival fd\n");
close(fd);
ast_config_destroy(cfg);
return -1;
}
n += read_data;
}
int read_data;
for (n=0; n < 3; )
{
read_data = read(fd,ack+n,3-n);
/* this avoids falling in infinite loop
* in case that festival server goes down
* */
if ( read_data == -1 )
{
ast_log(LOG_WARNING,"Unable to read from cache/festival fd\n");
close(fd);
ast_config_destroy(cfg);
LOCAL_USER_REMOVE(u);
return -1;
}
n += read_data;
}
ack[3] = '\0';
if (strcmp(ack, "WV\n") == 0) { /* receive a waveform */
ast_debug(1, "Festival WV command\n");
if ((waveform = socket_receive_file_to_buff(fd, &filesize))) {
res = send_waveform_to_channel(chan, waveform, filesize, args.interrupt);
ast_free(waveform);
}
break;
} else if (strcmp(ack, "LP\n") == 0) { /* receive an s-expr */
ast_debug(1, "Festival LP command\n");
if ((waveform = socket_receive_file_to_buff(fd, &filesize))) {
waveform[filesize] = '\0';
ast_log(LOG_WARNING, "Festival returned LP : %s\n", waveform);
ast_free(waveform);
}
} else if (strcmp(ack, "ER\n") == 0) { /* server got an error */
ast_log(LOG_WARNING, "Festival returned ER\n");
res = -1;
if (strcmp(ack,"WV\n") == 0) { /* receive a waveform */
ast_log(LOG_DEBUG,"Festival WV command\n");
waveform = socket_receive_file_to_buff(fd,&filesize);
res = send_waveform_to_channel(chan,waveform,filesize, intstr);
free(waveform);
break;
}
} while (strcmp(ack, "OK\n") != 0);
else if (strcmp(ack,"LP\n") == 0) { /* receive an s-expr */
ast_log(LOG_DEBUG,"Festival LP command\n");
waveform = socket_receive_file_to_buff(fd,&filesize);
waveform[filesize]='\0';
ast_log(LOG_WARNING,"Festival returned LP : %s\n",waveform);
free(waveform);
} else if (strcmp(ack,"ER\n") == 0) { /* server got an error */
ast_log(LOG_WARNING,"Festival returned ER\n");
res=-1;
break;
}
} while (strcmp(ack,"OK\n") != 0);
close(fd);
ast_config_destroy(cfg);
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int unload_module(void)
int load_module(void)
{
return ast_unregister_application(app);
}
static int load_module(void)
{
struct ast_flags config_flags = { 0 };
struct ast_config *cfg = ast_config_load(FESTIVAL_CONFIG, config_flags);
if (!cfg) {
ast_log(LOG_WARNING, "No such configuration file %s\n", FESTIVAL_CONFIG);
return AST_MODULE_LOAD_DECLINE;
}
ast_config_destroy(cfg);
return ast_register_application(app, festival_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Simple Festival Interface");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -18,50 +18,58 @@
/*! \file
*
* \brief App to flash a DAHDI trunk
*
* \author Mark Spencer <markster@digium.com>
* \brief App to flash a zap trunk
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>dahdi</depend>
***/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#ifdef __linux__
#include <linux/zaptel.h>
#else
#include <zaptel.h>
#endif /* __linux__ */
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <sys/ioctl.h>
#include <dahdi/user.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/image.h"
#include "asterisk/options.h"
static char *tdesc = "Flash zap trunk application";
static char *app = "Flash";
static char *synopsis = "Flashes a DAHDI Trunk";
static char *synopsis = "Flashes a Zap Trunk";
static char *descrip =
"Performs a flash on a DAHDI trunk. This can be used\n"
"to access features provided on an incoming analogue circuit\n"
"such as conference and call waiting. Use with SendDTMF() to\n"
"perform external transfers\n";
" Flash(): Sends a flash on a zap trunk. This is only a hack for\n"
"people who want to perform transfers and such via AGI and is generally\n"
"quite useless oths application will only work on Zap trunks.\n";
STANDARD_LOCAL_USER;
static inline int dahdi_wait_event(int fd)
LOCAL_USER_DECL;
static inline int zt_wait_event(int fd)
{
/* Avoid the silly dahdi_waitevent which ignores a bunch of events */
/* Avoid the silly zt_waitevent which ignores a bunch of events */
int i,j=0;
i = DAHDI_IOMUX_SIGEVENT;
if (ioctl(fd, DAHDI_IOMUX, &i) == -1) return -1;
if (ioctl(fd, DAHDI_GETEVENT, &j) == -1) return -1;
i = ZT_IOMUX_SIGEVENT;
if (ioctl(fd, ZT_IOMUX, &i) == -1) return -1;
if (ioctl(fd, ZT_GETEVENT, &j) == -1) return -1;
return j;
}
@@ -69,45 +77,65 @@ static int flash_exec(struct ast_channel *chan, void *data)
{
int res = -1;
int x;
struct dahdi_params dahdip;
if (strcasecmp(chan->tech->type, "DAHDI")) {
ast_log(LOG_WARNING, "%s is not a DAHDI channel\n", chan->name);
return -1;
}
memset(&dahdip, 0, sizeof(dahdip));
res = ioctl(chan->fds[0], DAHDI_GET_PARAMS, &dahdip);
if (!res) {
if (dahdip.sigtype & __DAHDI_SIG_FXS) {
x = DAHDI_FLASH;
res = ioctl(chan->fds[0], DAHDI_HOOK, &x);
if (!res || (errno == EINPROGRESS)) {
if (res) {
/* Wait for the event to finish */
dahdi_wait_event(chan->fds[0]);
}
res = ast_safe_sleep(chan, 1000);
ast_verb(3, "Flashed channel %s\n", chan->name);
struct localuser *u;
struct zt_params ztp;
LOCAL_USER_ADD(u);
if (!strcasecmp(chan->type, "Zap")) {
memset(&ztp, 0, sizeof(ztp));
res = ioctl(chan->fds[0], ZT_GET_PARAMS, &ztp);
if (!res) {
if (ztp.sigtype & __ZT_SIG_FXS) {
x = ZT_FLASH;
res = ioctl(chan->fds[0], ZT_HOOK, &x);
if (!res || (errno == EINPROGRESS)) {
if (res) {
/* Wait for the event to finish */
zt_wait_event(chan->fds[0]);
}
res = ast_safe_sleep(chan, 1000);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Flashed channel %s\n", chan->name);
} else
ast_log(LOG_WARNING, "Unable to flash channel %s: %s\n", chan->name, strerror(errno));
} else
ast_log(LOG_WARNING, "Unable to flash channel %s: %s\n", chan->name, strerror(errno));
ast_log(LOG_WARNING, "%s is not an FXO Channel\n", chan->name);
} else
ast_log(LOG_WARNING, "%s is not an FXO Channel\n", chan->name);
ast_log(LOG_WARNING, "Unable to get parameters of %s: %s\n", chan->name, strerror(errno));
} else
ast_log(LOG_WARNING, "Unable to get parameters of %s: %s\n", chan->name, strerror(errno));
ast_log(LOG_WARNING, "%s is not a Zap channel\n", chan->name);
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int unload_module(void)
{
return ast_unregister_application(app);
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, flash_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Flash channel application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

File diff suppressed because it is too large Load Diff

View File

@@ -18,142 +18,42 @@
/*! \file
*
* \brief Fork CDR application
*
* \author Anthony Minessale anthmct@yahoo.com
*
* \note Development of this app Sponsored/Funded by TAAN Softworks Corp
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/cdr.h"
#include "asterisk/app.h"
#include "asterisk/module.h"
static char *tdesc = "Fork The CDR into 2 separate entities.";
static char *app = "ForkCDR";
static char *synopsis =
"Forks the Call Data Record";
static char *descrip =
" ForkCDR([options]): Causes the Call Data Record to fork an additional\n"
"cdr record starting from the time of the fork call. This new cdr record will\n"
"be linked to end of the list of cdr records attached to the channel. The original CDR\n"
"has a LOCKED flag set, which forces most cdr operations to skip it, except\n"
"for the functions that set the answer and end times, which ignore the LOCKED\n"
"flag. This allows all the cdr records in the channel to be 'ended' together\n"
"when the channel is closed.\n"
"The CDR() func (when setting CDR values) normally ignores the LOCKED flag also,\n"
"but has options to vary its behavior. The 'T' option (described below), can\n"
"override this behavior, but beware the risks.\n"
"\n"
"Detailed Behavior Description:\n"
"First, this app finds the last cdr record in the list, and makes\n"
"a copy of it. This new copy will be the newly forked cdr record.\n"
"Next, this new record is linked to the end of the cdr record list.\n"
"Next, The new cdr record is RESET (unless you use an option to prevent this)\n"
"This means that:\n"
" 1. All flags are unset on the cdr record\n"
" 2. the start, end, and answer times are all set to zero.\n"
" 3. the billsec and duration fields are set to zero.\n"
" 4. the start time is set to the current time.\n"
" 5. the disposition is set to NULL.\n"
"Next, unless you specified the 'v' option, all variables will be\n"
"removed from the original cdr record. Thus, the 'v' option allows\n"
"any CDR variables to be replicated to all new forked cdr records.\n"
"Without the 'v' option, the variables on the original are effectively\n"
"moved to the new forked cdr record.\n"
"Next, if the 's' option is set, the provided variable and value\n"
"are set on the original cdr record.\n"
"Next, if the 'a' option is given, and the original cdr record has an\n"
"answer time set, then the new forked cdr record will have its answer\n"
"time set to its start time. If the old answer time were carried forward,\n"
"the answer time would be earlier than the start time, giving strange\n"
"duration and billsec times.\n"
"Next, if the 'd' option was specified, the disposition is copied from\n"
"the original cdr record to the new forked cdr.\n"
"Next, if the 'D' option was specified, the destination channel field\n"
"in the new forked CDR is erased.\n"
"Next, if the 'e' option was specified, the 'end' time for the original\n"
"cdr record is set to the current time. Future hang-up or ending events\n"
"will not override this time stamp.\n"
"Next, If the 'A' option is specified, the original cdr record will have\n"
"it ANS_LOCKED flag set, which prevent future answer events\n"
"from updating the original cdr record's disposition. Normally, an\n"
"'ANSWERED' event would mark all cdr records in the chain as 'ANSWERED'.\n"
"Next, if the 'T' option is specified, the original cdr record will have\n"
"its 'DONT_TOUCH' flag set, which will force the cdr_answer, cdr_end, and\n"
"cdr_setvar functions to leave that cdr record alone.\n"
"And, last but not least, the original cdr record has its LOCKED flag\n"
"set. Almost all internal CDR functions (except for the funcs that set\n"
"the end, and answer times, and set a variable) will honor this flag\n"
"and leave a LOCKED cdr record alone.\n"
"This means that the newly created forked cdr record will be affected\n"
"by events transpiring within Asterisk, with the previously noted\n"
"exceptions.\n"
" Options:\n"
" a - update the answer time on the NEW CDR just after it's been inited.\n"
" The new CDR may have been answered already. The reset that forkcdr\n"
" does will erase the answer time. This will bring it back, but\n"
" the answer time will be a copy of the fork/start time. It will\n"
" only do this if the initial cdr was indeed already answered.\n"
" A - Lock the original CDR against the answer time being updated.\n"
" This will allow the disposition on the original CDR to remain the same.\n"
" d - Copy the disposition forward from the old cdr, after the \n"
" init.\n"
" D - Clear the dstchannel on the new CDR after reset.\n"
" e - end the original CDR. Do this after all the neccessary data\n"
" is copied from the original CDR to the new forked CDR.\n"
" R - do NOT reset the new cdr.\n"
" s(name=val) - Set the CDR var 'name' in the original CDR, with value\n"
" 'val'.\n"
" T - Mark the original CDR with a DONT_TOUCH flag. setvar, answer, and end\n"
" cdr funcs will obey this flag; normally they don't honor the LOCKED\n"
" flag set on the original CDR record.\n"
" Beware-- using this flag may cause CDR's not to have their end times\n"
" updated! It is suggested that if you specify this flag, you might\n"
" wish to use the 'e' flag as well!\n"
" v - When the new CDR is forked, it gets a copy of the vars attached\n"
" to the current CDR. The vars attached to the original CDR are removed\n"
" unless this option is specified.\n";
"cdr record starting from the time of the fork call\n"
"If the option 'v' is passed all cdr variables will be passed along also.\n"
"";
enum {
OPT_SETANS = (1 << 0),
OPT_SETDISP = (1 << 1),
OPT_RESETDEST = (1 << 2),
OPT_ENDCDR = (1 << 3),
OPT_NORESET = (1 << 4),
OPT_KEEPVARS = (1 << 5),
OPT_VARSET = (1 << 6),
OPT_ANSLOCK = (1 << 7),
OPT_DONTOUCH = (1 << 8),
};
STANDARD_LOCAL_USER;
enum {
OPT_ARG_VARSET = 0,
/* note: this entry _MUST_ be the last one in the enum */
OPT_ARG_ARRAY_SIZE,
};
LOCAL_USER_DECL;
AST_APP_OPTIONS(forkcdr_exec_options, {
AST_APP_OPTION('a', OPT_SETANS),
AST_APP_OPTION('A', OPT_ANSLOCK),
AST_APP_OPTION('d', OPT_SETDISP),
AST_APP_OPTION('D', OPT_RESETDEST),
AST_APP_OPTION('e', OPT_ENDCDR),
AST_APP_OPTION('R', OPT_NORESET),
AST_APP_OPTION_ARG('s', OPT_VARSET, OPT_ARG_VARSET),
AST_APP_OPTION('T', OPT_DONTOUCH),
AST_APP_OPTION('v', OPT_KEEPVARS),
});
static void ast_cdr_fork(struct ast_channel *chan, struct ast_flags optflags, char *set)
static void ast_cdr_fork(struct ast_channel *chan)
{
struct ast_cdr *cdr;
struct ast_cdr *newcdr;
@@ -168,84 +68,64 @@ static void ast_cdr_fork(struct ast_channel *chan, struct ast_flags optflags, ch
return;
ast_cdr_append(cdr, newcdr);
if (!ast_test_flag(&optflags, OPT_NORESET))
ast_cdr_reset(newcdr, &flags);
ast_cdr_reset(newcdr, &flags);
if (!ast_test_flag(cdr, AST_CDR_FLAG_KEEP_VARS))
ast_cdr_free_vars(cdr, 0);
if (!ast_strlen_zero(set)) {
char *varname = ast_strdupa(set), *varval;
varval = strchr(varname,'=');
if (varval) {
*varval = 0;
varval++;
ast_cdr_setvar(cdr, varname, varval, 0);
}
}
if (ast_test_flag(&optflags, OPT_SETANS) && !ast_tvzero(cdr->answer))
newcdr->answer = newcdr->start;
if (ast_test_flag(&optflags, OPT_SETDISP))
newcdr->disposition = cdr->disposition;
if (ast_test_flag(&optflags, OPT_RESETDEST))
newcdr->dstchannel[0] = 0;
if (ast_test_flag(&optflags, OPT_ENDCDR))
ast_cdr_end(cdr);
if (ast_test_flag(&optflags, OPT_ANSLOCK))
ast_set_flag(cdr, AST_CDR_FLAG_ANSLOCKED);
if (ast_test_flag(&optflags, OPT_DONTOUCH))
ast_set_flag(cdr, AST_CDR_FLAG_DONT_TOUCH);
ast_set_flag(cdr, AST_CDR_FLAG_CHILD | AST_CDR_FLAG_LOCKED);
}
static int forkcdr_exec(struct ast_channel *chan, void *data)
{
int res = 0;
char *argcopy = NULL;
struct ast_flags flags = {0};
char *opts[OPT_ARG_ARRAY_SIZE];
AST_DECLARE_APP_ARGS(arglist,
AST_APP_ARG(options);
);
struct localuser *u;
if (!chan->cdr) {
ast_log(LOG_WARNING, "Channel does not have a CDR\n");
return 0;
}
argcopy = ast_strdupa(data);
LOCAL_USER_ADD(u);
AST_STANDARD_APP_ARGS(arglist, argcopy);
opts[OPT_ARG_VARSET] = 0;
if (!ast_strlen_zero(arglist.options))
ast_app_parse_options(forkcdr_exec_options, &flags, opts, arglist.options);
if (!ast_strlen_zero(data))
ast_set2_flag(chan->cdr, ast_test_flag(&flags, OPT_KEEPVARS), AST_CDR_FLAG_KEEP_VARS);
ast_set2_flag(chan->cdr, strchr(data, 'v'), AST_CDR_FLAG_KEEP_VARS);
ast_cdr_fork(chan, flags, opts[OPT_ARG_VARSET]);
ast_cdr_fork(chan);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app);
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, forkcdr_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Fork The CDR into 2 separate entities");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,31 +19,41 @@
/*! \file
*
* \brief Get ADSI CPE ID
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/adsi.h"
#include "asterisk/options.h"
static char *tdesc = "Get ADSI CPE ID";
static char *app = "GetCPEID";
static char *synopsis = "Get ADSI CPE ID";
static char *descrip =
" GetCPEID(): Obtains and displays ADSI CPE ID and other information in order\n"
"to properly setup dahdi.conf for on-hook operations.\n";
" GetCPEID: Obtains and displays ADSI CPE ID and other information in order\n"
"to properly setup zapata.conf for on-hook operations.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int cpeid_setstatus(struct ast_channel *chan, char *stuff[], int voice)
{
@@ -53,54 +63,60 @@ static int cpeid_setstatus(struct ast_channel *chan, char *stuff[], int voice)
for (x=0;x<4;x++)
tmp[x] = stuff[x];
tmp[4] = NULL;
return ast_adsi_print(chan, tmp, justify, voice);
return adsi_print(chan, tmp, justify, voice);
}
static int cpeid_exec(struct ast_channel *chan, void *idata)
{
int res=0;
struct localuser *u;
unsigned char cpeid[4];
int gotgeometry = 0;
int gotcpeid = 0;
int width, height, buttons;
char *data[4];
unsigned int x;
char data[4][80];
char *stuff[4];
for (x = 0; x < 4; x++)
data[x] = alloca(80);
strcpy(data[0], "** CPE Info **");
strcpy(data[1], "Identifying CPE...");
strcpy(data[2], "Please wait...");
res = ast_adsi_load_session(chan, NULL, 0, 1);
LOCAL_USER_ADD(u);
stuff[0] = data[0];
stuff[1] = data[1];
stuff[2] = data[2];
stuff[3] = data[3];
memset(data, 0, sizeof(data));
strncpy(stuff[0], "** CPE Info **", sizeof(data[0]) - 1);
strncpy(stuff[1], "Identifying CPE...", sizeof(data[1]) - 1);
strncpy(stuff[2], "Please wait...", sizeof(data[2]) - 1);
res = adsi_load_session(chan, NULL, 0, 1);
if (res > 0) {
cpeid_setstatus(chan, data, 0);
res = ast_adsi_get_cpeid(chan, cpeid, 0);
cpeid_setstatus(chan, stuff, 0);
res = adsi_get_cpeid(chan, cpeid, 0);
if (res > 0) {
gotcpeid = 1;
ast_verb(3, "Got CPEID of '%02x:%02x:%02x:%02x' on '%s'\n", cpeid[0], cpeid[1], cpeid[2], cpeid[3], chan->name);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Got CPEID of '%02x:%02x:%02x:%02x' on '%s'\n", cpeid[0], cpeid[1], cpeid[2], cpeid[3], chan->name);
}
if (res > -1) {
strcpy(data[1], "Measuring CPE...");
strcpy(data[2], "Please wait...");
cpeid_setstatus(chan, data, 0);
res = ast_adsi_get_cpeinfo(chan, &width, &height, &buttons, 0);
strncpy(stuff[1], "Measuring CPE...", sizeof(data[1]) - 1);
strncpy(stuff[2], "Please wait...", sizeof(data[2]) - 1);
cpeid_setstatus(chan, stuff, 0);
res = adsi_get_cpeinfo(chan, &width, &height, &buttons, 0);
if (res > -1) {
ast_verb(3, "CPE has %d lines, %d columns, and %d buttons on '%s'\n", height, width, buttons, chan->name);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "CPE has %d lines, %d columns, and %d buttons on '%s'\n", height, width, buttons, chan->name);
gotgeometry = 1;
}
}
if (res > -1) {
if (gotcpeid)
snprintf(data[1], 80, "CPEID: %02x:%02x:%02x:%02x", cpeid[0], cpeid[1], cpeid[2], cpeid[3]);
snprintf(stuff[1], sizeof(data[1]), "CPEID: %02x:%02x:%02x:%02x", cpeid[0], cpeid[1], cpeid[2], cpeid[3]);
else
strcpy(data[1], "CPEID Unknown");
strncpy(stuff[1], "CPEID Unknown", sizeof(data[1]) - 1);
if (gotgeometry)
snprintf(data[2], 80, "Geom: %dx%d, %d buttons", width, height, buttons);
snprintf(stuff[2], sizeof(data[2]), "Geom: %dx%d, %d buttons", width, height, buttons);
else
strcpy(data[2], "Geometry unknown");
strcpy(data[3], "Press # to exit");
cpeid_setstatus(chan, data, 1);
strncpy(stuff[2], "Geometry unknown", sizeof(data[2]) - 1);
strncpy(stuff[3], "Press # to exit", sizeof(data[3]) - 1);
cpeid_setstatus(chan, stuff, 1);
for(;;) {
res = ast_waitfordigit(chan, 1000);
if (res < 0)
@@ -110,21 +126,42 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
break;
}
}
ast_adsi_unload_session(chan);
adsi_unload_session(chan);
}
}
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app);
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, cpeid_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Get ADSI CPE ID");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

338
apps/app_groupcount.c Normal file
View File

@@ -0,0 +1,338 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Group Manipulation Applications
*
* \ingroup applications
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <regex.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int group_count_exec(struct ast_channel *chan, void *data)
{
int res = 0;
int count;
struct localuser *u;
char group[80] = "";
char category[80] = "";
char ret[80] = "";
char *grp;
static int deprecation_warning = 0;
LOCAL_USER_ADD(u);
if (!deprecation_warning) {
ast_log(LOG_WARNING, "The GetGroupCount application has been deprecated, please use the GROUP_COUNT function.\n");
deprecation_warning = 1;
}
ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category));
if (ast_strlen_zero(group)) {
grp = pbx_builtin_getvar_helper(chan, category);
if (!ast_strlen_zero(grp))
ast_copy_string(group, grp, sizeof(group));
}
count = ast_app_group_get_count(group, category);
snprintf(ret, sizeof(ret), "%d", count);
pbx_builtin_setvar_helper(chan, "GROUPCOUNT", ret);
LOCAL_USER_REMOVE(u);
return res;
}
static int group_match_count_exec(struct ast_channel *chan, void *data)
{
int res = 0;
int count;
struct localuser *u;
char group[80] = "";
char category[80] = "";
char ret[80] = "";
static int deprecation_warning = 0;
LOCAL_USER_ADD(u);
if (!deprecation_warning) {
ast_log(LOG_WARNING, "The GetGroupMatchCount application has been deprecated, please use the GROUP_MATCH_COUNT function.\n");
deprecation_warning = 1;
}
ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category));
if (!ast_strlen_zero(group)) {
count = ast_app_group_match_get_count(group, category);
snprintf(ret, sizeof(ret), "%d", count);
pbx_builtin_setvar_helper(chan, "GROUPCOUNT", ret);
}
LOCAL_USER_REMOVE(u);
return res;
}
static int group_set_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct localuser *u;
static int deprecation_warning = 0;
LOCAL_USER_ADD(u);
if (!deprecation_warning) {
ast_log(LOG_WARNING, "The SetGroup application has been deprecated, please use the GROUP() function.\n");
deprecation_warning = 1;
}
if (ast_app_group_set_channel(chan, data))
ast_log(LOG_WARNING, "SetGroup requires an argument (group name)\n");
LOCAL_USER_REMOVE(u);
return res;
}
static int group_check_exec(struct ast_channel *chan, void *data)
{
int res = 0;
int max, count;
struct localuser *u;
char limit[80]="";
char category[80]="";
static int deprecation_warning = 0;
char *parse;
int priority_jump = 0;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(max);
AST_APP_ARG(options);
);
LOCAL_USER_ADD(u);
if (!deprecation_warning) {
ast_log(LOG_WARNING, "The CheckGroup application has been deprecated, please use a combination of the GotoIf application and the GROUP_COUNT() function.\n");
deprecation_warning = 1;
}
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "CheckGroup requires an argument(max[@category][|options])\n");
return 0;
}
if (!(parse = ast_strdupa(data))) {
ast_log(LOG_WARNING, "Memory Error!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
AST_STANDARD_APP_ARGS(args, parse);
if (args.options) {
if (strchr(args.options, 'j'))
priority_jump = 1;
}
if (ast_strlen_zero(args.max)) {
ast_log(LOG_WARNING, "CheckGroup requires an argument(max[@category][|options])\n");
return res;
}
ast_app_group_split_group(args.max, limit, sizeof(limit), category, sizeof(category));
if ((sscanf(limit, "%d", &max) == 1) && (max > -1)) {
count = ast_app_group_get_count(pbx_builtin_getvar_helper(chan, category), category);
if (count > max) {
pbx_builtin_setvar_helper(chan, "CHECKGROUPSTATUS", "OVERMAX");
if (priority_jump || option_priority_jumping) {
if (!ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101))
res = -1;
}
} else
pbx_builtin_setvar_helper(chan, "CHECKGROUPSTATUS", "OK");
} else
ast_log(LOG_WARNING, "CheckGroup requires a positive integer argument (max)\n");
LOCAL_USER_REMOVE(u);
return res;
}
static int group_show_channels(int fd, int argc, char *argv[])
{
#define FORMAT_STRING "%-25s %-20s %-20s\n"
int numchans = 0;
struct ast_group_info *gi = NULL;
regex_t regexbuf;
int havepattern = 0;
if (argc < 3 || argc > 4)
return RESULT_SHOWUSAGE;
if (argc == 4) {
if (regcomp(&regexbuf, argv[3], REG_EXTENDED | REG_NOSUB))
return RESULT_SHOWUSAGE;
havepattern = 1;
}
ast_cli(fd, FORMAT_STRING, "Channel", "Group", "Category");
ast_app_group_list_lock();
gi = ast_app_group_list_head();
while (gi) {
if (!havepattern || !regexec(&regexbuf, gi->group, 0, NULL, 0)) {
ast_cli(fd, FORMAT_STRING, gi->chan->name, gi->group, (ast_strlen_zero(gi->category) ? "(default)" : gi->category));
numchans++;
}
gi = AST_LIST_NEXT(gi, list);
}
ast_app_group_list_unlock();
if (havepattern)
regfree(&regexbuf);
ast_cli(fd, "%d active channel%s\n", numchans, (numchans != 1) ? "s" : "");
return RESULT_SUCCESS;
#undef FORMAT_STRING
}
static char *tdesc = "Group Management Routines";
static char *app_group_count = "GetGroupCount";
static char *app_group_set = "SetGroup";
static char *app_group_check = "CheckGroup";
static char *app_group_match_count = "GetGroupMatchCount";
static char *group_count_synopsis = "Get the channel count of a group";
static char *group_set_synopsis = "Set the channel's group";
static char *group_check_synopsis = "Check the channel count of a group against a limit";
static char *group_match_count_synopsis = "Get the channel count of all groups that match a pattern";
static char *group_count_descrip =
"Usage: GetGroupCount([groupname][@category])\n"
" Calculates the group count for the specified group, or uses\n"
"the current channel's group if not specifed (and non-empty).\n"
"Stores result in GROUPCOUNT. \n"
"Note: This application has been deprecated, please use the function\n"
"GROUP_COUNT.\n";
static char *group_set_descrip =
"Usage: SetGroup(groupname[@category])\n"
" Sets the channel group to the specified value. Equivalent to\n"
"Set(GROUP=group). Always returns 0.\n";
static char *group_check_descrip =
"Usage: CheckGroup(max[@category][|options])\n"
" Checks that the current number of total channels in the\n"
"current channel's group does not exceed 'max'. If the number\n"
"does not exceed 'max', we continue to the next step. \n"
" The option string may contain zero of the following character:\n"
" 'j' -- jump to n+101 priority if the number does in fact exceed max,\n"
" and priority n+101 exists. Execuation then continues at that\n"
" step, otherwise -1 is returned.\n"
" This application sets the following channel variable upon successful completion:\n"
" CHECKGROUPSTATUS The status of the check that the current channel's\n"
" group does not exceed 'max'. It's value is one of\n"
" OK | OVERMAX \n";
static char *group_match_count_descrip =
"Usage: GetGroupMatchCount(groupmatch[@category])\n"
" Calculates the group count for all groups that match the specified\n"
"pattern. Uses standard regular expression matching (see regex(7)).\n"
"Stores result in GROUPCOUNT. Always returns 0.\n"
"Note: This application has been deprecated, please use the function\n"
"GROUP_MATCH_COUNT.\n";
static char show_channels_usage[] =
"Usage: group show channels [pattern]\n"
" Lists all currently active channels with channel group(s) specified.\n Optional regular expression pattern is matched to group names for each channel.\n";
static struct ast_cli_entry cli_show_channels =
{ { "group", "show", "channels", NULL }, group_show_channels, "Show active channels with group(s)", show_channels_usage};
int unload_module(void)
{
int res;
res = ast_cli_unregister(&cli_show_channels);
res |= ast_unregister_application(app_group_count);
res |= ast_unregister_application(app_group_set);
res |= ast_unregister_application(app_group_check);
res |= ast_unregister_application(app_group_match_count);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
int res;
res = ast_register_application(app_group_count, group_count_exec, group_count_synopsis, group_count_descrip);
res |= ast_register_application(app_group_set, group_set_exec, group_set_synopsis, group_set_descrip);
res |= ast_register_application(app_group_check, group_check_exec, group_check_synopsis, group_check_descrip);
res |= ast_register_application(app_group_match_count, group_match_count_exec, group_match_count_synopsis, group_match_count_descrip);
res |= ast_cli_register(&cli_show_channels);
return res;
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

363
apps/app_hasnewvoicemail.c Normal file
View File

@@ -0,0 +1,363 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Changes Copyright (c) 2004 - 2005 Todd Freeman <freeman@andrews.edu>
*
* 95% based on HasNewVoicemail by:
*
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <asterisk-hasnewvoicemail-app@the-tilghman.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief HasVoicemail application
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/options.h"
#ifdef USE_ODBC_STORAGE
#include "asterisk/res_odbc.h"
static char odbc_database[80];
static char odbc_table[80];
#endif
static char *tdesc = "Indicator for whether a voice mailbox has messages in a given folder.";
static char *app_hasvoicemail = "HasVoicemail";
static char *hasvoicemail_synopsis = "Conditionally branches to priority + 101 with the right options set";
static char *hasvoicemail_descrip =
"HasVoicemail(vmbox[/folder][@context][|varname[|options]])\n"
" Optionally sets <varname> to the number of messages in that folder."
" Assumes folder of INBOX if not specified.\n"
" The option string may contain zero or the following character:\n"
" 'j' -- jump to priority n+101, if there is voicemail in the folder indicated.\n"
" This application sets the following channel variable upon completion:\n"
" HASVMSTATUS The result of the voicemail check returned as a text string as follows\n"
" <# of messages in the folder, 0 for NONE>\n";
static char *app_hasnewvoicemail = "HasNewVoicemail";
static char *hasnewvoicemail_synopsis = "Conditionally branches to priority + 101 with the right options set";
static char *hasnewvoicemail_descrip =
"HasNewVoicemail(vmbox[/folder][@context][|varname[|options]])\n"
"Assumes folder 'INBOX' if folder is not specified. Optionally sets <varname> to the number of messages\n"
"in that folder.\n"
" The option string may contain zero of the following character:\n"
" 'j' -- jump to priority n+101, if there is new voicemail in folder 'folder' or INBOX\n"
" This application sets the following channel variable upon completion:\n"
" HASVMSTATUS The result of the new voicemail check returned as a text string as follows\n"
" <# of messages in the folder, 0 for NONE>\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
#ifdef USE_ODBC_STORAGE
static int hasvoicemail_internal(const char *context, const char *mailbox, const char *folder)
{
int nummsgs = 0;
int res;
SQLHSTMT stmt;
char sql[256];
char rowdata[20];
if (!folder)
folder = "INBOX";
/* If no mailbox, return immediately */
if (ast_strlen_zero(mailbox))
return 0;
if (ast_strlen_zero(context))
context = "default";
odbc_obj *obj;
obj = fetch_odbc_obj(odbc_database, 0);
if (obj) {
res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
goto yuck;
}
snprintf(sql, sizeof(sql), "SELECT COUNT(*) FROM %s WHERE dir = '%s/voicemail/%s/%s/%s'", odbc_table, ast_config_AST_SPOOL_DIR, context, mailbox, folder);
res = SQLPrepare(stmt, sql, SQL_NTS);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
goto yuck;
}
res = odbc_smart_execute(obj, stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
goto yuck;
}
res = SQLFetch(stmt);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
goto yuck;
}
res = SQLGetData(stmt, 1, SQL_CHAR, rowdata, sizeof(rowdata), NULL);
if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
goto yuck;
}
nummsgs = atoi(rowdata);
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
} else
ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
yuck:
return nummsgs;
}
#else
static int hasvoicemail_internal(const char *context, const char *mailbox, const char *folder)
{
DIR *dir;
struct dirent *de;
char fn[256];
int count = 0;
if (ast_strlen_zero(folder))
folder = "INBOX";
if (ast_strlen_zero(context))
context = "default";
/* If no mailbox, return immediately */
if (ast_strlen_zero(mailbox))
return 0;
snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/%s", ast_config_AST_SPOOL_DIR, context, mailbox, folder);
dir = opendir(fn);
if (!dir)
return 0;
while ((de = readdir(dir))) {
if (!strncasecmp(de->d_name, "msg", 3) && !strcasecmp(de->d_name + 8, "txt"))
count++;
}
closedir(dir);
return count;
}
#endif
static int hasvoicemail_exec(struct ast_channel *chan, void *data)
{
struct localuser *u;
char *input, *varname = NULL, *vmbox, *context = "default";
char *vmfolder;
int vmcount = 0;
static int dep_warning = 0;
int priority_jump = 0;
char tmp[12];
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(vmbox);
AST_APP_ARG(varname);
AST_APP_ARG(options);
);
if (!dep_warning) {
ast_log(LOG_WARNING, "The applications HasVoicemail and HasNewVoicemail have been deprecated. Please use the VMCOUNT() function instead.\n");
dep_warning = 1;
}
if (!data) {
ast_log(LOG_WARNING, "HasVoicemail requires an argument (vm-box[/folder][@context][|varname[|options]])\n");
return -1;
}
LOCAL_USER_ADD(u);
input = ast_strdupa((char *)data);
if (! input) {
ast_log(LOG_ERROR, "Out of memory error\n");
LOCAL_USER_REMOVE(u);
return -1;
}
AST_STANDARD_APP_ARGS(args, input);
if ((vmbox = strsep(&args.vmbox, "@")))
if (!ast_strlen_zero(args.vmbox))
context = args.vmbox;
if (!vmbox)
vmbox = args.vmbox;
vmfolder = strchr(vmbox, '/');
if (vmfolder) {
*vmfolder = '\0';
vmfolder++;
} else {
vmfolder = "INBOX";
}
if (args.options) {
if (strchr(args.options, 'j'))
priority_jump = 1;
}
vmcount = hasvoicemail_internal(context, vmbox, vmfolder);
/* Set the count in the channel variable */
if (varname) {
snprintf(tmp, sizeof(tmp), "%d", vmcount);
pbx_builtin_setvar_helper(chan, varname, tmp);
}
if (vmcount > 0) {
/* Branch to the next extension */
if (priority_jump || option_priority_jumping) {
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101))
ast_log(LOG_WARNING, "VM box %s@%s has new voicemail, but extension %s, priority %d doesn't exist\n", vmbox, context, chan->exten, chan->priority + 101);
}
}
snprintf(tmp, sizeof(tmp), "%d", vmcount);
pbx_builtin_setvar_helper(chan, "HASVMSTATUS", tmp);
LOCAL_USER_REMOVE(u);
return 0;
}
static char *acf_vmcount_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
{
struct localuser *u;
char *args, *context, *box, *folder;
LOCAL_USER_ACF_ADD(u);
buf[0] = '\0';
args = ast_strdupa(data);
if (!args) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return buf;
}
box = strsep(&args, "|");
if (strchr(box, '@')) {
context = box;
box = strsep(&context, "@");
} else {
context = "default";
}
if (args) {
folder = args;
} else {
folder = "INBOX";
}
snprintf(buf, len, "%d", hasvoicemail_internal(context, box, folder));
LOCAL_USER_REMOVE(u);
return buf;
}
struct ast_custom_function acf_vmcount = {
.name = "VMCOUNT",
.synopsis = "Counts the voicemail in a specified mailbox",
.syntax = "VMCOUNT(vmbox[@context][|folder])",
.desc =
" context - defaults to \"default\"\n"
" folder - defaults to \"INBOX\"\n",
.read = acf_vmcount_exec,
};
static int load_config(void)
{
#ifdef USE_ODBC_STORAGE
struct ast_config *cfg;
char *tmp;
cfg = ast_config_load("voicemail.conf");
if (cfg) {
if (! (tmp = ast_variable_retrieve(cfg, "general", "odbcstorage")))
tmp = "asterisk";
ast_copy_string(odbc_database, tmp, sizeof(odbc_database));
if (! (tmp = ast_variable_retrieve(cfg, "general", "odbctable")))
tmp = "voicemessages";
ast_copy_string(odbc_table, tmp, sizeof(odbc_table));
ast_config_destroy(cfg);
}
#endif
return 0;
}
int reload(void)
{
return load_config();
}
int unload_module(void)
{
int res;
res = ast_custom_function_unregister(&acf_vmcount);
res |= ast_unregister_application(app_hasvoicemail);
res |= ast_unregister_application(app_hasnewvoicemail);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
int res;
load_config();
res = ast_custom_function_register(&acf_vmcount);
res |= ast_register_application(app_hasvoicemail, hasvoicemail_exec, hasvoicemail_synopsis, hasvoicemail_descrip);
res |= ast_register_application(app_hasnewvoicemail, hasvoicemail_exec, hasnewvoicemail_synopsis, hasnewvoicemail_descrip);
return res;
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,40 +19,37 @@
/*! \file
*
* \brief Stream to an icecast server via ICES (see contrib/asterisk-ices.xml)
*
* \author Mark Spencer <markster@digium.com>
*
* \extref ICES - http://www.icecast.org/ices.php
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>working_fork</depend>
***/
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <errno.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <signal.h>
#include <fcntl.h>
#include <sys/time.h>
#ifdef HAVE_CAP
#include <sys/capability.h>
#endif /* HAVE_CAP */
#include "asterisk/paths.h" /* use ast_config_AST_CONFIG_DIR */
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/frame.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/options.h"
#define path_BIN "/usr/bin/"
#define path_LOCAL "/usr/local/bin/"
#define ICES "/usr/bin/ices"
#define LOCAL_ICES "/usr/local/bin/ices"
static char *tdesc = "Encode and Stream via icecast and ices";
static char *app = "ICES";
@@ -61,19 +58,17 @@ static char *synopsis = "Encode and stream using 'ices'";
static char *descrip =
" ICES(config.xml) Streams to an icecast server using ices\n"
"(available separately). A configuration file must be supplied\n"
"for ices (see contrib/asterisk-ices.xml). \n"
"\n"
"- ICES version 2 cient and server required.\n";
"for ices (see examples/asterisk-ices.conf). \n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int icesencode(char *filename, int fd)
{
int res;
int x;
sigset_t fullset, oldset;
#ifdef HAVE_CAP
cap_t cap;
#endif
sigfillset(&fullset);
pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
@@ -90,46 +85,27 @@ static int icesencode(char *filename, int fd)
signal(SIGPIPE, SIG_DFL);
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
#ifdef HAVE_CAP
cap = cap_from_text("cap_net_admin-eip");
if (cap_set_proc(cap)) {
/* Careful with order! Logging cannot happen after we close FDs */
ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
}
cap_free(cap);
#endif
if (ast_opt_high_priority)
if (option_highpriority)
ast_set_priority(0);
dup2(fd, STDIN_FILENO);
for (x=STDERR_FILENO + 1;x<1024;x++) {
if ((x != STDIN_FILENO) && (x != STDOUT_FILENO))
close(x);
}
/* Most commonly installed in /usr/local/bin
* But many places has it in /usr/bin
* As a last-ditch effort, try to use PATH
*/
execl(path_LOCAL "ices2", "ices", filename, (char *)NULL);
execl(path_BIN "ices2", "ices", filename, (char *)NULL);
execlp("ices2", "ices", filename, (char *)NULL);
ast_debug(1, "Couldn't find ices version 2, attempting to use ices version 1.");
execl(path_LOCAL "ices", "ices", filename, (char *)NULL);
execl(path_BIN "ices", "ices", filename, (char *)NULL);
/* Most commonly installed in /usr/local/bin */
execl(ICES, "ices", filename, (char *)NULL);
/* But many places has it in /usr/bin */
execl(LOCAL_ICES, "ices", filename, (char *)NULL);
/* As a last-ditch effort, try to use PATH */
execlp("ices", "ices", filename, (char *)NULL);
ast_log(LOG_WARNING, "Execute of ices failed, could not find command.\n");
close(fd);
ast_log(LOG_WARNING, "Execute of ices failed\n");
_exit(0);
}
static int ices_exec(struct ast_channel *chan, void *data)
{
int res = 0;
int res=0;
struct localuser *u;
int fds[2];
int ms = -1;
int pid = -1;
@@ -144,11 +120,14 @@ static int ices_exec(struct ast_channel *chan, void *data)
ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n");
return -1;
}
LOCAL_USER_ADD(u);
last = ast_tv(0, 0);
if (pipe(fds)) {
ast_log(LOG_WARNING, "Unable to create pipe\n");
LOCAL_USER_REMOVE(u);
return -1;
}
flags = fcntl(fds[1], F_GETFL);
@@ -163,6 +142,7 @@ static int ices_exec(struct ast_channel *chan, void *data)
close(fds[0]);
close(fds[1]);
ast_log(LOG_WARNING, "Answer failed!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -172,30 +152,32 @@ static int ices_exec(struct ast_channel *chan, void *data)
close(fds[0]);
close(fds[1]);
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
LOCAL_USER_REMOVE(u);
return -1;
}
if (((char *)data)[0] == '/')
ast_copy_string(filename, (char *) data, sizeof(filename));
strncpy(filename, (char *)data, sizeof(filename) - 1);
else
snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_CONFIG_DIR, (char *)data);
snprintf(filename, sizeof(filename), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, (char *)data);
/* Placeholder for options */
c = strchr(filename, '|');
if (c)
*c = '\0';
res = icesencode(filename, fds[0]);
close(fds[0]);
if (res >= 0) {
pid = res;
for (;;) {
/* Wait for audio, and stream */
ms = ast_waitfor(chan, -1);
if (ms < 0) {
ast_debug(1, "Hangup detected\n");
ast_log(LOG_DEBUG, "Hangup detected\n");
res = -1;
break;
}
f = ast_read(chan);
if (!f) {
ast_debug(1, "Null frame == hangup() detected\n");
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
res = -1;
break;
}
@@ -213,7 +195,6 @@ static int ices_exec(struct ast_channel *chan, void *data)
ast_frfree(f);
}
}
close(fds[0]);
close(fds[1]);
if (pid > -1)
@@ -221,17 +202,40 @@ static int ices_exec(struct ast_channel *chan, void *data)
if (!res && oreadformat)
ast_set_read_format(chan, oreadformat);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app);
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, ices_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Encode and Stream via icecast and ices");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,62 +19,129 @@
/*! \file
*
* \brief App to transmit an image
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/image.h"
#include "asterisk/app.h"
#include "asterisk/options.h"
static char *tdesc = "Image Transmission Application";
static char *app = "SendImage";
static char *synopsis = "Send an image file";
static char *descrip =
" SendImage(filename): Sends an image on a channel.\n"
"If the channel supports image transport but the image send fails, the channel\n"
"will be hung up. Otherwise, the dialplan continues execution. This\n"
"application sets the following channel variable upon completion:\n"
" SENDIMAGESTATUS The status is the result of the attempt, one of:\n"
" OK | NOSUPPORT \n";
" SendImage(filename): Sends an image on a channel. \n"
"If the channel supports image transport but the image send\n"
"fails, the channel will be hung up. Otherwise, the dialplan\n"
"continues execution.\n"
"The option string may contain the following character:\n"
" 'j' -- jump to priority n+101 if the channel doesn't support image transport\n"
"This application sets the following channel variable upon completion:\n"
" SENDIMAGESTATUS The status is the result of the attempt as a text string, one of\n"
" OK | NOSUPPORT \n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int sendimage_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct localuser *u;
char *parse;
int priority_jump = 0;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(filename);
AST_APP_ARG(options);
);
LOCAL_USER_ADD(u);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "SendImage requires an argument (filename)\n");
if (!(parse = ast_strdupa(data))) {
ast_log(LOG_WARNING, "Memory Error!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
AST_STANDARD_APP_ARGS(args, parse);
if (ast_strlen_zero(args.filename)) {
ast_log(LOG_WARNING, "SendImage requires an argument (filename[|options])\n");
return -1;
}
if (args.options) {
if (strchr(args.options, 'j'))
priority_jump = 1;
}
if (!ast_supports_images(chan)) {
/* Does not support transport */
if (priority_jump || option_priority_jumping)
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
pbx_builtin_setvar_helper(chan, "SENDIMAGESTATUS", "NOSUPPORT");
LOCAL_USER_REMOVE(u);
return 0;
}
if (!(res = ast_send_image(chan, data)))
res = ast_send_image(chan, args.filename);
if (!res)
pbx_builtin_setvar_helper(chan, "SENDIMAGESTATUS", "OK");
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app);
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, sendimage_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Image Transmission Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

234
apps/app_intercom.c Normal file
View File

@@ -0,0 +1,234 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Use /dev/dsp as an intercom.
*
* \ingroup applications
*/
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/time.h>
#include <netinet/in.h>
#if defined(__linux__)
#include <linux/soundcard.h>
#elif defined(__FreeBSD__)
#include <sys/soundcard.h>
#else
#include <soundcard.h>
#endif
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#ifdef __OpenBSD__
#define DEV_DSP "/dev/audio"
#else
#define DEV_DSP "/dev/dsp"
#endif
/* Number of 32 byte buffers -- each buffer is 2 ms */
#define BUFFER_SIZE 32
static char *tdesc = "Intercom using /dev/dsp for output";
static char *app = "Intercom";
static char *synopsis = "(Obsolete) Send to Intercom";
static char *descrip =
" Intercom(): Sends the user to the intercom (i.e. /dev/dsp). This program\n"
"is generally considered obselete by the chan_oss module. User can terminate\n"with a DTMF tone, or by hangup.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
AST_MUTEX_DEFINE_STATIC(sound_lock);
static int sound = -1;
static int write_audio(short *data, int len)
{
int res;
struct audio_buf_info info;
ast_mutex_lock(&sound_lock);
if (sound < 0) {
ast_log(LOG_WARNING, "Sound device closed?\n");
ast_mutex_unlock(&sound_lock);
return -1;
}
if (ioctl(sound, SNDCTL_DSP_GETOSPACE, &info)) {
ast_log(LOG_WARNING, "Unable to read output space\n");
ast_mutex_unlock(&sound_lock);
return -1;
}
res = write(sound, data, len);
ast_mutex_unlock(&sound_lock);
return res;
}
static int create_audio(void)
{
int fmt, desired, res, fd;
fd = open(DEV_DSP, O_WRONLY);
if (fd < 0) {
ast_log(LOG_WARNING, "Unable to open %s: %s\n", DEV_DSP, strerror(errno));
close(fd);
return -1;
}
fmt = AFMT_S16_LE;
res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n");
close(fd);
return -1;
}
fmt = 0;
res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt);
if (res < 0) {
ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
close(fd);
return -1;
}
/* 8000 Hz desired */
desired = 8000;
fmt = desired;
res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt);
if (res < 0) {
ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
close(fd);
return -1;
}
if (fmt != desired) {
ast_log(LOG_WARNING, "Requested %d Hz, got %d Hz -- sound may be choppy\n", desired, fmt);
}
#if 1
/* 2 bytes * 15 units of 2^5 = 32 bytes per buffer */
fmt = ((BUFFER_SIZE) << 16) | (0x0005);
res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set fragment size -- sound may be choppy\n");
}
#endif
sound = fd;
return 0;
}
static int intercom_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct localuser *u;
struct ast_frame *f;
int oreadformat;
LOCAL_USER_ADD(u);
/* Remember original read format */
oreadformat = chan->readformat;
/* Set mode to signed linear */
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set format to signed linear on channel %s\n", chan->name);
LOCAL_USER_REMOVE(u);
return -1;
}
/* Read packets from the channel */
while(!res) {
res = ast_waitfor(chan, -1);
if (res > 0) {
res = 0;
f = ast_read(chan);
if (f) {
if (f->frametype == AST_FRAME_DTMF) {
ast_frfree(f);
break;
} else {
if (f->frametype == AST_FRAME_VOICE) {
if (f->subclass == AST_FORMAT_SLINEAR) {
res = write_audio(f->data, f->datalen);
if (res > 0)
res = 0;
} else
ast_log(LOG_DEBUG, "Unable to handle non-signed linear frame (%d)\n", f->subclass);
}
}
ast_frfree(f);
} else
res = -1;
}
}
if (!res)
ast_set_read_format(chan, oreadformat);
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
int res;
if (sound > -1)
close(sound);
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
if (create_audio())
return -1;
return ast_register_application(app, intercom_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,21 +19,21 @@
/*! \file
*
* \brief IVR Demo application
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
/*** MODULEINFO
<defaultenabled>no</defaultenabled>
***/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
@@ -82,16 +82,22 @@ AST_IVR_DECLARE_MENU(ivr_demo, "IVR Demo Main Menu", 0,
{ NULL },
});
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int skel_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "skel requires an argument (filename)\n");
return -1;
}
LOCAL_USER_ADD(u);
/* Do our thing here */
if (chan->_state != AST_STATE_UP)
@@ -99,17 +105,40 @@ static int skel_exec(struct ast_channel *chan, void *data)
if (!res)
res = ast_ivr_menu_run(chan, &ivr_demo, data);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app);
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, skel_exec, tdesc, synopsis);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "IVR Demo Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,976 +0,0 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2007 - 2008, Russell Bryant
*
* Russell Bryant <russell@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*!
* \file
* \brief Jack Application
*
* \author Russell Bryant <russell@digium.com>
*
* This is an application to connect an Asterisk channel to an input
* and output jack port so that the audio can be processed through
* another application, or to play audio from another application.
*
* \arg http://www.jackaudio.org/
*
* \note To install libresample, check it out of the following repository:
* <code>$ svn co http://svn.digium.com/svn/thirdparty/libresample/trunk</code>
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>jack</depend>
<depend>resample</depend>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <limits.h>
#include <jack/jack.h>
#include <jack/ringbuffer.h>
#include <libresample.h>
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/strings.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/audiohook.h"
#define RESAMPLE_QUALITY 1
#define RINGBUFFER_SIZE 16384
/*! \brief Common options between the Jack() app and JACK_HOOK() function */
#define COMMON_OPTIONS \
" s(<name>) - Connect to the specified jack server name.\n" \
" i(<name>) - Connect the output port that gets created to the specified\n" \
" jack input port.\n" \
" o(<name>) - Connect the input port that gets created to the specified\n" \
" jack output port.\n" \
" n - Do not automatically start the JACK server if it is not already\n" \
" running.\n"
static char *jack_app = "JACK";
static char *jack_synopsis =
"JACK (Jack Audio Connection Kit) Application";
static char *jack_desc =
"JACK([options])\n"
" When this application is executed, two jack ports will be created; one input\n"
"and one output. Other applications can be hooked up to these ports to access\n"
"the audio coming from, or being sent to the channel.\n"
" Valid options:\n"
COMMON_OPTIONS
"";
struct jack_data {
AST_DECLARE_STRING_FIELDS(
AST_STRING_FIELD(server_name);
AST_STRING_FIELD(connect_input_port);
AST_STRING_FIELD(connect_output_port);
);
jack_client_t *client;
jack_port_t *input_port;
jack_port_t *output_port;
jack_ringbuffer_t *input_rb;
jack_ringbuffer_t *output_rb;
void *output_resampler;
double output_resample_factor;
void *input_resampler;
double input_resample_factor;
unsigned int stop:1;
unsigned int has_audiohook:1;
unsigned int no_start_server:1;
/*! Only used with JACK_HOOK */
struct ast_audiohook audiohook;
};
static const struct {
jack_status_t status;
const char *str;
} jack_status_table[] = {
{ JackFailure, "Failure" },
{ JackInvalidOption, "Invalid Option" },
{ JackNameNotUnique, "Name Not Unique" },
{ JackServerStarted, "Server Started" },
{ JackServerFailed, "Server Failed" },
{ JackServerError, "Server Error" },
{ JackNoSuchClient, "No Such Client" },
{ JackLoadFailure, "Load Failure" },
{ JackInitFailure, "Init Failure" },
{ JackShmFailure, "Shared Memory Access Failure" },
{ JackVersionError, "Version Mismatch" },
};
static const char *jack_status_to_str(jack_status_t status)
{
int i;
for (i = 0; i < ARRAY_LEN(jack_status_table); i++) {
if (jack_status_table[i].status == status)
return jack_status_table[i].str;
}
return "Unknown Error";
}
static void log_jack_status(const char *prefix, jack_status_t status)
{
struct ast_str *str = ast_str_alloca(512);
int i, first = 0;
for (i = 0; i < (sizeof(status) * 8); i++) {
if (!(status & (1 << i)))
continue;
if (!first) {
ast_str_set(&str, 0, "%s", jack_status_to_str((1 << i)));
first = 1;
} else
ast_str_append(&str, 0, ", %s", jack_status_to_str((1 << i)));
}
ast_log(LOG_NOTICE, "%s: %s\n", prefix, str->str);
}
static int alloc_resampler(struct jack_data *jack_data, int input)
{
double from_srate, to_srate, jack_srate;
void **resampler;
double *resample_factor;
if (input && jack_data->input_resampler)
return 0;
if (!input && jack_data->output_resampler)
return 0;
jack_srate = jack_get_sample_rate(jack_data->client);
/* XXX Hard coded 8 kHz */
to_srate = input ? 8000.0 : jack_srate;
from_srate = input ? jack_srate : 8000.0;
resample_factor = input ? &jack_data->input_resample_factor :
&jack_data->output_resample_factor;
if (from_srate == to_srate) {
/* Awesome! The jack sample rate is the same as ours.
* Resampling isn't needed. */
*resample_factor = 1.0;
return 0;
}
*resample_factor = to_srate / from_srate;
resampler = input ? &jack_data->input_resampler :
&jack_data->output_resampler;
if (!(*resampler = resample_open(RESAMPLE_QUALITY,
*resample_factor, *resample_factor))) {
ast_log(LOG_ERROR, "Failed to open %s resampler\n",
input ? "input" : "output");
return -1;
}
return 0;
}
/*!
* \brief Handle jack input port
*
* Read nframes number of samples from the input buffer, resample it
* if necessary, and write it into the appropriate ringbuffer.
*/
static void handle_input(void *buf, jack_nframes_t nframes,
struct jack_data *jack_data)
{
short s_buf[nframes];
float *in_buf = buf;
size_t res;
int i;
size_t write_len = sizeof(s_buf);
if (jack_data->input_resampler) {
int total_in_buf_used = 0;
int total_out_buf_used = 0;
float f_buf[nframes + 1];
memset(f_buf, 0, sizeof(f_buf));
while (total_in_buf_used < nframes) {
int in_buf_used;
int out_buf_used;
out_buf_used = resample_process(jack_data->input_resampler,
jack_data->input_resample_factor,
&in_buf[total_in_buf_used], nframes - total_in_buf_used,
0, &in_buf_used,
&f_buf[total_out_buf_used], ARRAY_LEN(f_buf) - total_out_buf_used);
if (out_buf_used < 0)
break;
total_out_buf_used += out_buf_used;
total_in_buf_used += in_buf_used;
if (total_out_buf_used == ARRAY_LEN(f_buf)) {
ast_log(LOG_ERROR, "Output buffer filled ... need to increase its size, "
"nframes '%d', total_out_buf_used '%d'\n", nframes, total_out_buf_used);
break;
}
}
for (i = 0; i < total_out_buf_used; i++)
s_buf[i] = f_buf[i] * (SHRT_MAX / 1.0);
write_len = total_out_buf_used * sizeof(int16_t);
} else {
/* No resampling needed */
for (i = 0; i < nframes; i++)
s_buf[i] = in_buf[i] * (SHRT_MAX / 1.0);
}
res = jack_ringbuffer_write(jack_data->input_rb, (const char *) s_buf, write_len);
if (res != write_len) {
ast_debug(2, "Tried to write %d bytes to the ringbuffer, but only wrote %d\n",
(int) sizeof(s_buf), (int) res);
}
}
/*!
* \brief Handle jack output port
*
* Read nframes number of samples from the ringbuffer and write it out to the
* output port buffer.
*/
static void handle_output(void *buf, jack_nframes_t nframes,
struct jack_data *jack_data)
{
size_t res, len;
len = nframes * sizeof(float);
res = jack_ringbuffer_read(jack_data->output_rb, buf, len);
if (len != res) {
ast_debug(2, "Wanted %d bytes to send to the output port, "
"but only got %d\n", (int) len, (int) res);
}
}
static int jack_process(jack_nframes_t nframes, void *arg)
{
struct jack_data *jack_data = arg;
void *input_port_buf, *output_port_buf;
if (!jack_data->input_resample_factor)
alloc_resampler(jack_data, 1);
input_port_buf = jack_port_get_buffer(jack_data->input_port, nframes);
handle_input(input_port_buf, nframes, jack_data);
output_port_buf = jack_port_get_buffer(jack_data->output_port, nframes);
handle_output(output_port_buf, nframes, jack_data);
return 0;
}
static void jack_shutdown(void *arg)
{
struct jack_data *jack_data = arg;
jack_data->stop = 1;
}
static struct jack_data *destroy_jack_data(struct jack_data *jack_data)
{
if (jack_data->input_port) {
jack_port_unregister(jack_data->client, jack_data->input_port);
jack_data->input_port = NULL;
}
if (jack_data->output_port) {
jack_port_unregister(jack_data->client, jack_data->output_port);
jack_data->output_port = NULL;
}
if (jack_data->client) {
jack_client_close(jack_data->client);
jack_data->client = NULL;
}
if (jack_data->input_rb) {
jack_ringbuffer_free(jack_data->input_rb);
jack_data->input_rb = NULL;
}
if (jack_data->output_rb) {
jack_ringbuffer_free(jack_data->output_rb);
jack_data->output_rb = NULL;
}
if (jack_data->output_resampler) {
resample_close(jack_data->output_resampler);
jack_data->output_resampler = NULL;
}
if (jack_data->input_resampler) {
resample_close(jack_data->input_resampler);
jack_data->input_resampler = NULL;
}
if (jack_data->has_audiohook)
ast_audiohook_destroy(&jack_data->audiohook);
ast_string_field_free_memory(jack_data);
ast_free(jack_data);
return NULL;
}
static int init_jack_data(struct ast_channel *chan, struct jack_data *jack_data)
{
const char *chan_name;
jack_status_t status = 0;
jack_options_t jack_options = JackNullOption;
ast_channel_lock(chan);
chan_name = ast_strdupa(chan->name);
ast_channel_unlock(chan);
if (!(jack_data->output_rb = jack_ringbuffer_create(RINGBUFFER_SIZE)))
return -1;
if (!(jack_data->input_rb = jack_ringbuffer_create(RINGBUFFER_SIZE)))
return -1;
if (jack_data->no_start_server)
jack_options |= JackNoStartServer;
if (!ast_strlen_zero(jack_data->server_name)) {
jack_options |= JackServerName;
jack_data->client = jack_client_open(chan_name, jack_options, &status,
jack_data->server_name);
} else {
jack_data->client = jack_client_open(chan_name, jack_options, &status);
}
if (status)
log_jack_status("Client Open Status", status);
if (!jack_data->client)
return -1;
jack_data->input_port = jack_port_register(jack_data->client, "input",
JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0);
if (!jack_data->input_port) {
ast_log(LOG_ERROR, "Failed to create input port for jack port\n");
return -1;
}
jack_data->output_port = jack_port_register(jack_data->client, "output",
JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0);
if (!jack_data->output_port) {
ast_log(LOG_ERROR, "Failed to create output port for jack port\n");
return -1;
}
if (jack_set_process_callback(jack_data->client, jack_process, jack_data)) {
ast_log(LOG_ERROR, "Failed to register process callback with jack client\n");
return -1;
}
jack_on_shutdown(jack_data->client, jack_shutdown, jack_data);
if (jack_activate(jack_data->client)) {
ast_log(LOG_ERROR, "Unable to activate jack client\n");
return -1;
}
while (!ast_strlen_zero(jack_data->connect_input_port)) {
const char **ports;
int i;
ports = jack_get_ports(jack_data->client, jack_data->connect_input_port,
NULL, JackPortIsInput);
if (!ports) {
ast_log(LOG_ERROR, "No input port matching '%s' was found\n",
jack_data->connect_input_port);
break;
}
for (i = 0; ports[i]; i++) {
ast_debug(1, "Found port '%s' that matched specified input port '%s'\n",
ports[i], jack_data->connect_input_port);
}
if (jack_connect(jack_data->client, jack_port_name(jack_data->output_port), ports[0])) {
ast_log(LOG_ERROR, "Failed to connect '%s' to '%s'\n", ports[0],
jack_port_name(jack_data->output_port));
} else {
ast_debug(1, "Connected '%s' to '%s'\n", ports[0],
jack_port_name(jack_data->output_port));
}
free((void *) ports);
break;
}
while (!ast_strlen_zero(jack_data->connect_output_port)) {
const char **ports;
int i;
ports = jack_get_ports(jack_data->client, jack_data->connect_output_port,
NULL, JackPortIsOutput);
if (!ports) {
ast_log(LOG_ERROR, "No output port matching '%s' was found\n",
jack_data->connect_output_port);
break;
}
for (i = 0; ports[i]; i++) {
ast_debug(1, "Found port '%s' that matched specified output port '%s'\n",
ports[i], jack_data->connect_output_port);
}
if (jack_connect(jack_data->client, ports[0], jack_port_name(jack_data->input_port))) {
ast_log(LOG_ERROR, "Failed to connect '%s' to '%s'\n", ports[0],
jack_port_name(jack_data->input_port));
} else {
ast_debug(1, "Connected '%s' to '%s'\n", ports[0],
jack_port_name(jack_data->input_port));
}
free((void *) ports);
break;
}
return 0;
}
static int queue_voice_frame(struct jack_data *jack_data, struct ast_frame *f)
{
float f_buf[f->samples * 8];
size_t f_buf_used = 0;
int i;
int16_t *s_buf = f->data;
size_t res;
memset(f_buf, 0, sizeof(f_buf));
if (!jack_data->output_resample_factor)
alloc_resampler(jack_data, 0);
if (jack_data->output_resampler) {
float in_buf[f->samples];
int total_in_buf_used = 0;
int total_out_buf_used = 0;
memset(in_buf, 0, sizeof(in_buf));
for (i = 0; i < f->samples; i++)
in_buf[i] = s_buf[i] * (1.0 / SHRT_MAX);
while (total_in_buf_used < ARRAY_LEN(in_buf)) {
int in_buf_used;
int out_buf_used;
out_buf_used = resample_process(jack_data->output_resampler,
jack_data->output_resample_factor,
&in_buf[total_in_buf_used], ARRAY_LEN(in_buf) - total_in_buf_used,
0, &in_buf_used,
&f_buf[total_out_buf_used], ARRAY_LEN(f_buf) - total_out_buf_used);
if (out_buf_used < 0)
break;
total_out_buf_used += out_buf_used;
total_in_buf_used += in_buf_used;
if (total_out_buf_used == ARRAY_LEN(f_buf)) {
ast_log(LOG_ERROR, "Output buffer filled ... need to increase its size\n");
break;
}
}
f_buf_used = total_out_buf_used;
if (f_buf_used > ARRAY_LEN(f_buf))
f_buf_used = ARRAY_LEN(f_buf);
} else {
/* No resampling needed */
for (i = 0; i < f->samples; i++)
f_buf[i] = s_buf[i] * (1.0 / SHRT_MAX);
f_buf_used = f->samples;
}
res = jack_ringbuffer_write(jack_data->output_rb, (const char *) f_buf, f_buf_used * sizeof(float));
if (res != (f_buf_used * sizeof(float))) {
ast_debug(2, "Tried to write %d bytes to the ringbuffer, but only wrote %d\n",
(int) (f_buf_used * sizeof(float)), (int) res);
}
return 0;
}
/*!
* \brief handle jack audio
*
* \param[in] chan The Asterisk channel to write the frames to if no output frame
* is provided.
* \param[in] jack_data This is the jack_data struct that contains the input
* ringbuffer that audio will be read from.
* \param[out] out_frame If this argument is non-NULL, then assuming there is
* enough data avilable in the ringbuffer, the audio in this frame
* will get replaced with audio from the input buffer. If there is
* not enough data available to read at this time, then the frame
* data gets zeroed out.
*
* Read data from the input ringbuffer, which is the properly resampled audio
* that was read from the jack input port. Write it to the channel in 20 ms frames,
* or fill up an output frame instead if one is provided.
*
* \return Nothing.
*/
static void handle_jack_audio(struct ast_channel *chan, struct jack_data *jack_data,
struct ast_frame *out_frame)
{
short buf[160];
struct ast_frame f = {
.frametype = AST_FRAME_VOICE,
.subclass = AST_FORMAT_SLINEAR,
.src = "JACK",
.data = buf,
.datalen = sizeof(buf),
.samples = ARRAY_LEN(buf),
};
for (;;) {
size_t res, read_len;
char *read_buf;
read_len = out_frame ? out_frame->datalen : sizeof(buf);
read_buf = out_frame ? out_frame->data : buf;
res = jack_ringbuffer_read_space(jack_data->input_rb);
if (res < read_len) {
/* Not enough data ready for another frame, move on ... */
if (out_frame) {
ast_debug(1, "Sending an empty frame for the JACK_HOOK\n");
memset(out_frame->data, 0, out_frame->datalen);
}
break;
}
res = jack_ringbuffer_read(jack_data->input_rb, (char *) read_buf, read_len);
if (res < read_len) {
ast_log(LOG_ERROR, "Error reading from ringbuffer, even though it said there was enough data\n");
break;
}
if (out_frame) {
/* If an output frame was provided, then we just want to fill up the
* buffer in that frame and return. */
break;
}
ast_write(chan, &f);
}
}
enum {
OPT_SERVER_NAME = (1 << 0),
OPT_INPUT_PORT = (1 << 1),
OPT_OUTPUT_PORT = (1 << 2),
OPT_NOSTART_SERVER = (1 << 3),
};
enum {
OPT_ARG_SERVER_NAME,
OPT_ARG_INPUT_PORT,
OPT_ARG_OUTPUT_PORT,
/* Must be the last element */
OPT_ARG_ARRAY_SIZE,
};
AST_APP_OPTIONS(jack_exec_options, BEGIN_OPTIONS
AST_APP_OPTION_ARG('s', OPT_SERVER_NAME, OPT_ARG_SERVER_NAME),
AST_APP_OPTION_ARG('i', OPT_INPUT_PORT, OPT_ARG_INPUT_PORT),
AST_APP_OPTION_ARG('o', OPT_OUTPUT_PORT, OPT_ARG_OUTPUT_PORT),
AST_APP_OPTION('n', OPT_NOSTART_SERVER),
END_OPTIONS );
static struct jack_data *jack_data_alloc(void)
{
struct jack_data *jack_data;
if (!(jack_data = ast_calloc(1, sizeof(*jack_data))))
return NULL;
if (ast_string_field_init(jack_data, 32)) {
ast_free(jack_data);
return NULL;
}
return jack_data;
}
/*!
* \note This must be done before calling init_jack_data().
*/
static int handle_options(struct jack_data *jack_data, const char *__options_str)
{
struct ast_flags options = { 0, };
char *option_args[OPT_ARG_ARRAY_SIZE];
char *options_str;
options_str = ast_strdupa(__options_str);
ast_app_parse_options(jack_exec_options, &options, option_args, options_str);
if (ast_test_flag(&options, OPT_SERVER_NAME)) {
if (!ast_strlen_zero(option_args[OPT_ARG_SERVER_NAME]))
ast_string_field_set(jack_data, server_name, option_args[OPT_ARG_SERVER_NAME]);
else {
ast_log(LOG_ERROR, "A server name must be provided with the s() option\n");
return -1;
}
}
if (ast_test_flag(&options, OPT_INPUT_PORT)) {
if (!ast_strlen_zero(option_args[OPT_ARG_INPUT_PORT]))
ast_string_field_set(jack_data, connect_input_port, option_args[OPT_ARG_INPUT_PORT]);
else {
ast_log(LOG_ERROR, "A name must be provided with the i() option\n");
return -1;
}
}
if (ast_test_flag(&options, OPT_OUTPUT_PORT)) {
if (!ast_strlen_zero(option_args[OPT_ARG_OUTPUT_PORT]))
ast_string_field_set(jack_data, connect_output_port, option_args[OPT_ARG_OUTPUT_PORT]);
else {
ast_log(LOG_ERROR, "A name must be provided with the o() option\n");
return -1;
}
}
jack_data->no_start_server = ast_test_flag(&options, OPT_NOSTART_SERVER) ? 1 : 0;
return 0;
}
static int jack_exec(struct ast_channel *chan, void *data)
{
struct jack_data *jack_data;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(options);
);
if (!(jack_data = jack_data_alloc()))
return -1;
args.options = data;
if (!ast_strlen_zero(args.options) && handle_options(jack_data, args.options)) {
destroy_jack_data(jack_data);
return -1;
}
if (init_jack_data(chan, jack_data)) {
destroy_jack_data(jack_data);
return -1;
}
if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
destroy_jack_data(jack_data);
return -1;
}
if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
destroy_jack_data(jack_data);
return -1;
}
while (!jack_data->stop) {
struct ast_frame *f;
ast_waitfor(chan, -1);
f = ast_read(chan);
if (!f) {
jack_data->stop = 1;
continue;
}
switch (f->frametype) {
case AST_FRAME_CONTROL:
if (f->subclass == AST_CONTROL_HANGUP)
jack_data->stop = 1;
break;
case AST_FRAME_VOICE:
queue_voice_frame(jack_data, f);
default:
break;
}
ast_frfree(f);
handle_jack_audio(chan, jack_data, NULL);
}
jack_data = destroy_jack_data(jack_data);
return 0;
}
static void jack_hook_ds_destroy(void *data)
{
struct jack_data *jack_data = data;
destroy_jack_data(jack_data);
}
static const struct ast_datastore_info jack_hook_ds_info = {
.type = "JACK_HOOK",
.destroy = jack_hook_ds_destroy,
};
static int jack_hook_callback(struct ast_audiohook *audiohook, struct ast_channel *chan,
struct ast_frame *frame, enum ast_audiohook_direction direction)
{
struct ast_datastore *datastore;
struct jack_data *jack_data;
if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE)
return 0;
if (direction != AST_AUDIOHOOK_DIRECTION_READ)
return 0;
if (frame->frametype != AST_FRAME_VOICE)
return 0;
if (frame->subclass != AST_FORMAT_SLINEAR) {
ast_log(LOG_WARNING, "Expected frame in SLINEAR for the audiohook, but got format %d\n",
frame->subclass);
return 0;
}
ast_channel_lock(chan);
if (!(datastore = ast_channel_datastore_find(chan, &jack_hook_ds_info, NULL))) {
ast_log(LOG_ERROR, "JACK_HOOK datastore not found for '%s'\n", chan->name);
ast_channel_unlock(chan);
return -1;
}
jack_data = datastore->data;
queue_voice_frame(jack_data, frame);
handle_jack_audio(chan, jack_data, frame);
ast_channel_unlock(chan);
return 0;
}
static int enable_jack_hook(struct ast_channel *chan, char *data)
{
struct ast_datastore *datastore;
struct jack_data *jack_data = NULL;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(mode);
AST_APP_ARG(options);
);
AST_STANDARD_APP_ARGS(args, data);
ast_channel_lock(chan);
if ((datastore = ast_channel_datastore_find(chan, &jack_hook_ds_info, NULL))) {
ast_log(LOG_ERROR, "JACK_HOOK already enabled for '%s'\n", chan->name);
goto return_error;
}
if (ast_strlen_zero(args.mode) || strcasecmp(args.mode, "manipulate")) {
ast_log(LOG_ERROR, "'%s' is not a supported mode. Only manipulate is supported.\n",
S_OR(args.mode, "<none>"));
goto return_error;
}
if (!(jack_data = jack_data_alloc()))
goto return_error;
if (!ast_strlen_zero(args.options) && handle_options(jack_data, args.options))
goto return_error;
if (init_jack_data(chan, jack_data))
goto return_error;
if (!(datastore = ast_channel_datastore_alloc(&jack_hook_ds_info, NULL)))
goto return_error;
jack_data->has_audiohook = 1;
ast_audiohook_init(&jack_data->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "JACK_HOOK");
jack_data->audiohook.manipulate_callback = jack_hook_callback;
datastore->data = jack_data;
if (ast_audiohook_attach(chan, &jack_data->audiohook))
goto return_error;
if (ast_channel_datastore_add(chan, datastore))
goto return_error;
ast_channel_unlock(chan);
return 0;
return_error:
ast_channel_unlock(chan);
if (jack_data)
destroy_jack_data(jack_data);
return -1;
}
static int disable_jack_hook(struct ast_channel *chan)
{
struct ast_datastore *datastore;
struct jack_data *jack_data;
ast_channel_lock(chan);
if (!(datastore = ast_channel_datastore_find(chan, &jack_hook_ds_info, NULL))) {
ast_channel_unlock(chan);
ast_log(LOG_WARNING, "No JACK_HOOK found to disable\n");
return -1;
}
ast_channel_datastore_remove(chan, datastore);
jack_data = datastore->data;
ast_audiohook_detach(&jack_data->audiohook);
/* Keep the channel locked while we destroy the datastore, so that we can
* ensure that all of the jack stuff is stopped just in case another frame
* tries to come through the audiohook callback. */
ast_channel_datastore_free(datastore);
ast_channel_unlock(chan);
return 0;
}
static int jack_hook_write(struct ast_channel *chan, const char *cmd, char *data,
const char *value)
{
int res;
if (!strcasecmp(value, "on"))
res = enable_jack_hook(chan, data);
else if (!strcasecmp(value, "off"))
res = disable_jack_hook(chan);
else {
ast_log(LOG_ERROR, "'%s' is not a valid value for JACK_HOOK()\n", value);
res = -1;
}
return res;
}
static struct ast_custom_function jack_hook_function = {
.name = "JACK_HOOK",
.synopsis = "Enable a jack hook on a channel",
.syntax = "JACK_HOOK(<mode>,[options])",
.desc =
" The JACK_HOOK allows turning on or off jack connectivity to this channel.\n"
"When the JACK_HOOK is turned on, jack ports will get created that allow\n"
"access to the audio stream for this channel. The mode specifies which mode\n"
"this hook should run in. A mode must be specified when turning the JACK_HOOK.\n"
"on. However, all arguments are optional when turning it off.\n"
"\n"
" Valid modes are:\n"
#if 0
/* XXX TODO */
" spy - Create a read-only audio hook. Only an output jack port will\n"
" get created.\n"
" whisper - Create a write-only audio hook. Only an input jack port will\n"
" get created.\n"
#endif
" manipulate - Create a read/write audio hook. Both an input and an output\n"
" jack port will get created. Audio from the channel will be\n"
" sent out the output port and will be replaced by the audio\n"
" coming in on the input port as it gets passed on.\n"
"\n"
" Valid options are:\n"
COMMON_OPTIONS
"\n"
" Examples:\n"
" To turn on the JACK_HOOK,\n"
" Set(JACK_HOOK(manipulate,i(pure_data_0:input0)o(pure_data_0:output0))=on)\n"
" To turn off the JACK_HOOK,\n"
" Set(JACK_HOOK()=off)\n"
"",
.write = jack_hook_write,
};
static int unload_module(void)
{
int res;
res = ast_unregister_application(jack_app);
res |= ast_custom_function_unregister(&jack_hook_function);
return res;
}
static int load_module(void)
{
if (ast_register_application(jack_app, jack_exec, jack_synopsis, jack_desc))
return AST_MODULE_LOAD_DECLINE;
if (ast_custom_function_register(&jack_hook_function)) {
ast_unregister_application(jack_app);
return AST_MODULE_LOAD_DECLINE;
}
return AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "JACK Interface");

141
apps/app_lookupblacklist.c Normal file
View File

@@ -0,0 +1,141 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief App to lookup the callerid number, and see if it is blacklisted
*
* \ingroup applications
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/image.h"
#include "asterisk/callerid.h"
#include "asterisk/astdb.h"
#include "asterisk/options.h"
static char *tdesc = "Look up Caller*ID name/number from blacklist database";
static char *app = "LookupBlacklist";
static char *synopsis = "Look up Caller*ID name/number from blacklist database";
static char *descrip =
" LookupBlacklist(options): Looks up the Caller*ID number on the active\n"
"channel in the Asterisk database (family 'blacklist'). \n"
"The option string may contain the following character:\n"
" 'j' -- jump to n+101 priority if the number/name is found in the blacklist\n"
"This application sets the following channel variable upon completion:\n"
" LOOKUPBLSTATUS The status of the Blacklist lookup as a text string, one of\n"
" FOUND | NOTFOUND\n"
"Example: exten => 1234,1,LookupBlacklist()\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int
lookupblacklist_exec (struct ast_channel *chan, void *data)
{
char blacklist[1];
struct localuser *u;
int bl = 0;
int priority_jump = 0;
LOCAL_USER_ADD(u);
if (!ast_strlen_zero(data)) {
if (strchr(data, 'j'))
priority_jump = 1;
}
if (chan->cid.cid_num) {
if (!ast_db_get("blacklist", chan->cid.cid_num, blacklist, sizeof (blacklist))) {
if (option_verbose > 2)
ast_log(LOG_NOTICE, "Blacklisted number %s found\n",chan->cid.cid_num);
bl = 1;
}
}
if (chan->cid.cid_name) {
if (!ast_db_get("blacklist", chan->cid.cid_name, blacklist, sizeof (blacklist))) {
if (option_verbose > 2)
ast_log (LOG_NOTICE,"Blacklisted name \"%s\" found\n",chan->cid.cid_name);
bl = 1;
}
}
if (bl) {
if (priority_jump || option_priority_jumping)
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
pbx_builtin_setvar_helper(chan, "LOOKUPBLSTATUS", "FOUND");
} else
pbx_builtin_setvar_helper(chan, "LOOKUPBLSTATUS", "NOTFOUND");
LOCAL_USER_REMOVE(u);
return 0;
}
int unload_module (void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module (void)
{
return ast_register_application (app, lookupblacklist_exec, synopsis,descrip);
}
char *description (void)
{
return tdesc;
}
int usecount (void)
{
int res;
STANDARD_USECOUNT (res);
return res;
}
char *key ()
{
return ASTERISK_GPL_KEY;
}

120
apps/app_lookupcidname.c Normal file
View File

@@ -0,0 +1,120 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief App to set callerid name from database, based on directory number
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/image.h"
#include "asterisk/callerid.h"
#include "asterisk/astdb.h"
static char *tdesc = "Look up CallerID Name from local database";
static char *app = "LookupCIDName";
static char *synopsis = "Look up CallerID Name from local database";
static char *descrip =
" LookupCIDName: Looks up the Caller*ID number on the active\n"
"channel in the Asterisk database (family 'cidname') and sets the\n"
"Caller*ID name. Does nothing if no Caller*ID was received on the\n"
"channel. This is useful if you do not subscribe to Caller*ID\n"
"name delivery, or if you want to change the names on some incoming\n"
"calls.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int
lookupcidname_exec (struct ast_channel *chan, void *data)
{
char dbname[64];
struct localuser *u;
LOCAL_USER_ADD (u);
if (chan->cid.cid_num) {
if (!ast_db_get ("cidname", chan->cid.cid_num, dbname, sizeof (dbname))) {
ast_set_callerid (chan, NULL, dbname, NULL);
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID name to %s\n",
dbname);
}
}
LOCAL_USER_REMOVE (u);
return 0;
}
int
unload_module (void)
{
int res;
res = ast_unregister_application (app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int
load_module (void)
{
return ast_register_application (app, lookupcidname_exec, synopsis,
descrip);
}
char *
description (void)
{
return tdesc;
}
int
usecount (void)
{
int res;
STANDARD_USECOUNT (res);
return res;
}
char *
key ()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,20 +19,26 @@
/*! \file
*
* \brief Dial plan macro Implementation
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
@@ -42,46 +48,36 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
/* special result value used to force macro exit */
#define MACRO_EXIT_RESULT 1024
#define WAITEXTENWARNING "Use of the application WaitExten within a macro will not function as expected.\n" \
"Please use the Read application in order to read DTMF from a channel currently\n" \
"executing a macro.\n"
static char *tdesc = "Extension Macros";
static char *descrip =
" Macro(macroname,arg1,arg2...): Executes a macro using the context\n"
" Macro(macroname|arg1|arg2...): Executes a macro using the context\n"
"'macro-<macroname>', jumping to the 's' extension of that context and\n"
"executing each step, then returning when the steps end. \n"
"The calling extension, context, and priority are stored in ${MACRO_EXTEN},\n"
"The calling extension, context, and priority are stored in ${MACRO_EXTEN}, \n"
"${MACRO_CONTEXT} and ${MACRO_PRIORITY} respectively. Arguments become\n"
"${ARG1}, ${ARG2}, etc in the macro context.\n"
"If you Goto out of the Macro context, the Macro will terminate and control\n"
"will be returned at the location of the Goto.\n"
"If ${MACRO_OFFSET} is set at termination, Macro will attempt to continue\n"
"at priority MACRO_OFFSET + N + 1 if such a step exists, and N + 1 otherwise.\n"
"Extensions: While a macro is being executed, it becomes the current context.\n"
" This means that if a hangup occurs, for instance, that the macro\n"
" will be searched for an 'h' extension, NOT the context from which\n"
" the macro was called. So, make sure to define all appropriate\n"
" extensions in your macro! (you can use 'catch' in AEL) \n"
"WARNING: Because of the way Macro is implemented (it executes the priorities\n"
" contained within it via sub-engine), and a fixed per-thread memory\n"
" stack allowance, macros are limited to 7 levels of nesting (macro\n"
" calling macro calling macro, etc.). It may be possible that\n"
" stack-intensive applications in deeply nested macros could cause\n"
" Asterisk to crash earlier than this limit. It is advised that if you\n"
" need to deeply nest macro calls, that you use the Gosub application\n"
" (now allows arguments like a Macro) with explict Return() calls\n"
" instead.\n"
WAITEXTENWARNING;
" contained within it via sub-engine), and a fixed per-thread\n"
" memory stack allowance, macros are limited to 7 levels\n"
" of nesting (macro calling macro calling macro, etc.); It\n"
" may be possible that stack-intensive applications in deeply nested\n"
" macros could cause asterisk to crash earlier than this limit.\n";
static char *if_descrip =
" MacroIf(<expr>?macroname_a[,arg1][:macroname_b[,arg1]])\n"
" MacroIf(<expr>?macroname_a[|arg1][:macroname_b[|arg1]])\n"
"Executes macro defined in <macroname_a> if <expr> is true\n"
"(otherwise <macroname_b> if provided)\n"
"Arguments and return values as in application Macro()\n"
WAITEXTENWARNING;
static char *exclusive_descrip =
" MacroExclusive(macroname,arg1,arg2...):\n"
"Executes macro defined in the context 'macro-macroname'\n"
"Only one call at a time may run the macro.\n"
"(we'll wait if another call is busy executing in the Macro)\n"
"Arguments and return values as in application Macro()\n"
WAITEXTENWARNING;
"Arguments and return values as in application macro()\n";
static char *exit_descrip =
" MacroExit():\n"
@@ -92,38 +88,15 @@ static char *exit_descrip =
static char *app = "Macro";
static char *if_app = "MacroIf";
static char *exclusive_app = "MacroExclusive";
static char *exit_app = "MacroExit";
static char *synopsis = "Macro Implementation";
static char *if_synopsis = "Conditional Macro Implementation";
static char *exclusive_synopsis = "Exclusive Macro Implementation";
static char *exit_synopsis = "Exit From Macro";
static void macro_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
STANDARD_LOCAL_USER;
struct ast_datastore_info macro_ds_info = {
.type = "MACRO",
.chan_fixup = macro_fixup,
};
static void macro_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
{
int i;
char varname[10];
pbx_builtin_setvar_helper(new_chan, "MACRO_DEPTH", "0");
pbx_builtin_setvar_helper(new_chan, "MACRO_CONTEXT", NULL);
pbx_builtin_setvar_helper(new_chan, "MACRO_EXTEN", NULL);
pbx_builtin_setvar_helper(new_chan, "MACRO_PRIORITY", NULL);
pbx_builtin_setvar_helper(new_chan, "MACRO_OFFSET", NULL);
for (i = 1; i < 100; i++) {
snprintf(varname, sizeof(varname), "ARG%d", i);
while (pbx_builtin_getvar_helper(new_chan, varname)) {
/* Kill all levels of arguments */
pbx_builtin_setvar_helper(new_chan, varname, NULL);
}
}
}
LOCAL_USER_DECL;
static struct ast_exten *find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid)
{
@@ -160,9 +133,8 @@ static struct ast_exten *find_matching_priority(struct ast_context *c, const cha
return NULL;
}
static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
static int macro_exec(struct ast_channel *chan, void *data)
{
const char *s;
char *tmp;
char *cur, *rest;
char *macro;
@@ -176,53 +148,47 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
int oldpriority, gosub_level = 0;
char pc[80], depthc[12];
char oldcontext[AST_MAX_CONTEXT] = "";
const char *inhangupc;
char *offsets, *s, *inhangupc;
int offset, depth = 0, maxdepth = 7;
int setmacrocontext=0;
int autoloopflag, inhangup = 0;
int autoloopflag, dead = 0, inhangup = 0;
char *save_macro_exten;
char *save_macro_context;
char *save_macro_priority;
char *save_macro_offset;
struct ast_datastore *macro_store = ast_channel_datastore_find(chan, &macro_ds_info, NULL);
struct localuser *u;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Macro() requires arguments. See \"core show application macro\" for help.\n");
ast_log(LOG_WARNING, "Macro() requires arguments. See \"show application macro\" for help.\n");
return -1;
}
do {
if (macro_store) {
break;
}
if (!(macro_store = ast_channel_datastore_alloc(&macro_ds_info, NULL))) {
ast_log(LOG_WARNING, "Unable to allocate new datastore.\n");
break;
}
/* Just the existence of this datastore is enough. */
macro_store->inheritance = DATASTORE_INHERIT_FOREVER;
ast_channel_datastore_add(chan, macro_store);
} while (0);
LOCAL_USER_ADD(u);
/* does the user want a deeper rabbit hole? */
s = pbx_builtin_getvar_helper(chan, "MACRO_RECURSION");
if (s)
sscanf(s, "%30d", &maxdepth);
sscanf(s, "%d", &maxdepth);
/* Count how many levels deep the rabbit hole goes */
s = pbx_builtin_getvar_helper(chan, "MACRO_DEPTH");
if (s)
sscanf(s, "%30d", &depth);
tmp = pbx_builtin_getvar_helper(chan, "MACRO_DEPTH");
if (tmp) {
sscanf(tmp, "%d", &depth);
} else {
depth = 0;
}
/* Used for detecting whether to return when a Macro is called from another Macro after hangup */
if (strcmp(chan->exten, "h") == 0)
pbx_builtin_setvar_helper(chan, "MACRO_IN_HANGUP", "1");
inhangupc = pbx_builtin_getvar_helper(chan, "MACRO_IN_HANGUP");
if (!ast_strlen_zero(inhangupc))
sscanf(inhangupc, "%30d", &inhangup);
sscanf(inhangupc, "%d", &inhangup);
if (depth >= maxdepth) {
ast_log(LOG_ERROR, "Macro(): possible infinite loop detected. Returning early.\n");
LOCAL_USER_REMOVE(u);
return 0;
}
snprintf(depthc, sizeof(depthc), "%d", depth + 1);
@@ -230,32 +196,21 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
tmp = ast_strdupa(data);
rest = tmp;
macro = strsep(&rest, ",");
macro = strsep(&rest, "|");
if (ast_strlen_zero(macro)) {
ast_log(LOG_WARNING, "Invalid macro name specified\n");
LOCAL_USER_REMOVE(u);
return 0;
}
snprintf(fullmacro, sizeof(fullmacro), "macro-%s", macro);
if (!ast_exists_extension(chan, fullmacro, "s", 1, chan->cid.cid_num)) {
if (!ast_context_find(fullmacro))
if (!ast_context_find(fullmacro))
ast_log(LOG_WARNING, "No such context '%s' for macro '%s'\n", fullmacro, macro);
else
ast_log(LOG_WARNING, "Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro);
ast_log(LOG_WARNING, "Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro);
LOCAL_USER_REMOVE(u);
return 0;
}
/* If we are to run the macro exclusively, take the mutex */
if (exclusive) {
ast_debug(1, "Locking macrolock for '%s'\n", fullmacro);
ast_autoservice_start(chan);
if (ast_context_lockmacro(fullmacro)) {
ast_log(LOG_WARNING, "Failed to lock macro '%s' as in-use\n", fullmacro);
ast_autoservice_stop(chan);
return 0;
}
ast_autoservice_stop(chan);
}
/* Save old info */
oldpriority = chan->priority;
@@ -269,17 +224,25 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
}
argc = 1;
/* Save old macro variables */
save_macro_exten = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_EXTEN"));
save_macro_exten = pbx_builtin_getvar_helper(chan, "MACRO_EXTEN");
if (save_macro_exten)
save_macro_exten = strdup(save_macro_exten);
pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", oldexten);
save_macro_context = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT"));
save_macro_context = pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT");
if (save_macro_context)
save_macro_context = strdup(save_macro_context);
pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", oldcontext);
save_macro_priority = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_PRIORITY"));
save_macro_priority = pbx_builtin_getvar_helper(chan, "MACRO_PRIORITY");
if (save_macro_priority)
save_macro_priority = strdup(save_macro_priority);
snprintf(pc, sizeof(pc), "%d", oldpriority);
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", pc);
save_macro_offset = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"));
save_macro_offset = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET");
if (save_macro_offset)
save_macro_offset = strdup(save_macro_offset);
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL);
/* Setup environment for new run */
@@ -288,14 +251,13 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
ast_copy_string(chan->context, fullmacro, sizeof(chan->context));
chan->priority = 1;
while((cur = strsep(&rest, ",")) && (argc < MAX_ARGS)) {
const char *s;
while((cur = strsep(&rest, "|")) && (argc < MAX_ARGS)) {
/* Save copy of old arguments if we're overwriting some, otherwise
let them pass through to the other macro */
snprintf(varname, sizeof(varname), "ARG%d", argc);
s = pbx_builtin_getvar_helper(chan, varname);
if (s)
oldargs[argc] = ast_strdup(s);
oldargs[argc] = pbx_builtin_getvar_helper(chan, varname);
if (oldargs[argc])
oldargs[argc] = strdup(oldargs[argc]);
pbx_builtin_setvar_helper(chan, varname, cur);
argc++;
}
@@ -304,17 +266,16 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
struct ast_context *c;
struct ast_exten *e;
int foundx;
runningapp[0] = '\0';
runningdata[0] = '\0';
/* What application will execute? */
if (ast_rdlock_contexts()) {
if (ast_lock_contexts()) {
ast_log(LOG_WARNING, "Failed to lock contexts list\n");
} else {
for (c = ast_walk_contexts(NULL), e = NULL; c; c = ast_walk_contexts(c)) {
if (!strcmp(ast_get_context_name(c), chan->context)) {
if (ast_rdlock_context(c)) {
if (ast_lock_context(c)) {
ast_log(LOG_WARNING, "Unable to lock context?\n");
} else {
e = find_matching_priority(c, chan->exten, chan->priority, chan->cid.cid_num);
@@ -333,55 +294,65 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
/* Reset the macro depth, if it was changed in the last iteration */
pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
if ((res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num, &foundx,1))) {
if ((res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num))) {
/* Something bad happened, or a hangup has been requested. */
if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
(res == '*') || (res == '#')) {
/* Just return result as to the previous application as if it had been dialed */
ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
break;
}
switch(res) {
case MACRO_EXIT_RESULT:
res = 0;
goto out;
case AST_PBX_KEEPALIVE:
if (option_debug)
ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE in macro %s on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name);
if (option_verbose > 1)
ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE in macro '%s' on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name);
goto out;
break;
default:
ast_debug(2, "Spawn extension (%s,%s,%d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
if (option_debug)
ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
if (option_verbose > 1)
ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro);
dead = 1;
goto out;
}
}
ast_debug(1, "Executed application: %s\n", runningapp);
ast_log(LOG_DEBUG, "Executed application: %s\n", runningapp);
if (!strcasecmp(runningapp, "GOSUB")) {
gosub_level++;
ast_debug(1, "Incrementing gosub_level\n");
ast_log(LOG_DEBUG, "Incrementing gosub_level\n");
} else if (!strcasecmp(runningapp, "GOSUBIF")) {
char tmp2[1024], *cond, *app, *app2 = tmp2;
char tmp2[1024] = "", *cond, *app, *app2 = tmp2;
pbx_substitute_variables_helper(chan, runningdata, tmp2, sizeof(tmp2) - 1);
cond = strsep(&app2, "?");
app = strsep(&app2, ":");
if (pbx_checkcondition(cond)) {
if (!ast_strlen_zero(app)) {
gosub_level++;
ast_debug(1, "Incrementing gosub_level\n");
ast_log(LOG_DEBUG, "Incrementing gosub_level\n");
}
} else {
if (!ast_strlen_zero(app2)) {
gosub_level++;
ast_debug(1, "Incrementing gosub_level\n");
ast_log(LOG_DEBUG, "Incrementing gosub_level\n");
}
}
} else if (!strcasecmp(runningapp, "RETURN")) {
gosub_level--;
ast_debug(1, "Decrementing gosub_level\n");
ast_log(LOG_DEBUG, "Decrementing gosub_level\n");
} else if (!strcasecmp(runningapp, "STACKPOP")) {
gosub_level--;
ast_debug(1, "Decrementing gosub_level\n");
ast_log(LOG_DEBUG, "Decrementing gosub_level\n");
} else if (!strncasecmp(runningapp, "EXEC", 4)) {
/* Must evaluate args to find actual app */
char tmp2[1024], *tmp3 = NULL;
char tmp2[1024] = "", *tmp3 = NULL;
pbx_substitute_variables_helper(chan, runningdata, tmp2, sizeof(tmp2) - 1);
if (!strcasecmp(runningapp, "EXECIF")) {
tmp3 = strchr(tmp2, '|');
@@ -393,82 +364,85 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
tmp3 = tmp2;
if (tmp3)
ast_debug(1, "Last app: %s\n", tmp3);
ast_log(LOG_DEBUG, "Last app: %s\n", tmp3);
if (tmp3 && !strncasecmp(tmp3, "GOSUB", 5)) {
gosub_level++;
ast_debug(1, "Incrementing gosub_level\n");
ast_log(LOG_DEBUG, "Incrementing gosub_level\n");
} else if (tmp3 && !strncasecmp(tmp3, "RETURN", 6)) {
gosub_level--;
ast_debug(1, "Decrementing gosub_level\n");
ast_log(LOG_DEBUG, "Decrementing gosub_level\n");
} else if (tmp3 && !strncasecmp(tmp3, "STACKPOP", 8)) {
gosub_level--;
ast_debug(1, "Decrementing gosub_level\n");
ast_log(LOG_DEBUG, "Decrementing gosub_level\n");
}
}
if (gosub_level == 0 && strcasecmp(chan->context, fullmacro)) {
ast_verb(2, "Channel '%s' jumping out of macro '%s'\n", chan->name, macro);
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Channel '%s' jumping out of macro '%s'\n", chan->name, macro);
break;
}
/* don't stop executing extensions when we're in "h" */
if (ast_check_hangup(chan) && !inhangup) {
ast_debug(1, "Extension %s, macroexten %s, priority %d returned normally even though call was hung up\n", chan->exten, chan->macroexten, chan->priority);
if (chan->_softhangup && !inhangup) {
ast_log(LOG_DEBUG, "Extension %s, macroexten %s, priority %d returned normally even though call was hung up\n",
chan->exten, chan->macroexten, chan->priority);
goto out;
}
chan->priority++;
}
out:
/* Don't let the channel change now. */
ast_channel_lock(chan);
/* Reset the depth back to what it was when the routine was entered (like if we called Macro recursively) */
snprintf(depthc, sizeof(depthc), "%d", depth);
pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
if (!dead) {
pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
}
for (x = 1; x < argc; x++) {
/* Restore old arguments and delete ours */
snprintf(varname, sizeof(varname), "ARG%d", x);
if (oldargs[x]) {
pbx_builtin_setvar_helper(chan, varname, oldargs[x]);
ast_free(oldargs[x]);
} else {
if (!dead)
pbx_builtin_setvar_helper(chan, varname, oldargs[x]);
free(oldargs[x]);
} else if (!dead) {
pbx_builtin_setvar_helper(chan, varname, NULL);
}
}
/* Restore macro variables */
pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten);
pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context);
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
if (!dead) {
pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten);
pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context);
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
}
if (save_macro_exten)
ast_free(save_macro_exten);
free(save_macro_exten);
if (save_macro_context)
ast_free(save_macro_context);
free(save_macro_context);
if (save_macro_priority)
ast_free(save_macro_priority);
free(save_macro_priority);
if (setmacrocontext) {
if (!dead && setmacrocontext) {
chan->macrocontext[0] = '\0';
chan->macroexten[0] = '\0';
chan->macropriority = 0;
}
if (!strcasecmp(chan->context, fullmacro)) {
if (!dead && !strcasecmp(chan->context, fullmacro)) {
/* If we're leaving the macro normally, restore original information */
chan->priority = oldpriority;
ast_copy_string(chan->context, oldcontext, sizeof(chan->context));
if (!(ast_check_hangup(chan) & AST_SOFTHANGUP_ASYNCGOTO)) {
if (!(chan->_softhangup & AST_SOFTHANGUP_ASYNCGOTO)) {
/* Copy the extension, so long as we're not in softhangup, where we could be given an asyncgoto */
const char *offsets;
ast_copy_string(chan->exten, oldexten, sizeof(chan->exten));
if ((offsets = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"))) {
/* Handle macro offset if it's set by checking the availability of step n + offset + 1, otherwise continue
normally if there is any problem */
if (sscanf(offsets, "%30d", &offset) == 1) {
if (sscanf(offsets, "%d", &offset) == 1) {
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + offset + 1, chan->cid.cid_num)) {
chan->priority += offset;
}
@@ -477,40 +451,28 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
}
}
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset);
if (!dead)
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset);
if (save_macro_offset)
ast_free(save_macro_offset);
/* Unlock the macro */
if (exclusive) {
ast_debug(1, "Unlocking macrolock for '%s'\n", fullmacro);
if (ast_context_unlockmacro(fullmacro)) {
ast_log(LOG_ERROR, "Failed to unlock macro '%s' - that isn't good\n", fullmacro);
res = 0;
}
}
ast_channel_unlock(chan);
free(save_macro_offset);
LOCAL_USER_REMOVE(u);
return res;
}
static int macro_exec(struct ast_channel *chan, void *data)
{
return _macro_exec(chan, data, 0);
}
static int macroexclusive_exec(struct ast_channel *chan, void *data)
{
return _macro_exec(chan, data, 1);
}
static int macroif_exec(struct ast_channel *chan, void *data)
{
char *expr = NULL, *label_a = NULL, *label_b = NULL;
int res = 0;
struct localuser *u;
if (!(expr = ast_strdupa(data)))
LOCAL_USER_ADD(u);
expr = ast_strdupa(data);
if (!expr) {
ast_log(LOG_ERROR, "Out of Memory!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
if ((label_a = strchr(expr, '?'))) {
*label_a = '\0';
@@ -526,6 +488,8 @@ static int macroif_exec(struct ast_channel *chan, void *data)
} else
ast_log(LOG_WARNING, "Invalid Syntax.\n");
LOCAL_USER_REMOVE(u);
return res;
}
@@ -534,28 +498,43 @@ static int macro_exit_exec(struct ast_channel *chan, void *data)
return MACRO_EXIT_RESULT;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(if_app);
res |= ast_unregister_application(exit_app);
res |= ast_unregister_application(app);
res |= ast_unregister_application(exclusive_app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
int res;
res = ast_register_application(exit_app, macro_exit_exec, exit_synopsis, exit_descrip);
res |= ast_register_application(if_app, macroif_exec, if_synopsis, if_descrip);
res |= ast_register_application(exclusive_app, macroexclusive_exec, exclusive_synopsis, exclusive_descrip);
res |= ast_register_application(app, macro_exec, synopsis, descrip);
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Extension Macros");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

298
apps/app_math.c Normal file
View File

@@ -0,0 +1,298 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2004 - 2005, Andy Powell
*
* Updated by Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief A simple math application
*
* \ingroup applications
*/
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <dirent.h>
#include <ctype.h>
#include <sys/file.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
#include "asterisk/say.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
#include "asterisk/manager.h"
#include "asterisk/localtime.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
static char *tdesc = "Basic Math Functions";
static char *app_math = "Math";
static char *math_synopsis = "Performs Mathematical Functions";
static char *math_descrip =
"Math(returnvar,<number1><op><number 2>\n\n"
"Perform floating point calculation on number 1 to number 2 and \n"
"store the result in returnvar. Valid ops are: \n"
" +,-,/,*,%,<,>,>=,<=,==\n"
"and behave as their C equivalents.\n"
" This application has been deprecated in favor of the MATH function.\n";
#define ADDFUNCTION 0
#define DIVIDEFUNCTION 1
#define MULTIPLYFUNCTION 2
#define SUBTRACTFUNCTION 3
#define MODULUSFUNCTION 4
#define GTFUNCTION 5
#define LTFUNCTION 6
#define GTEFUNCTION 7
#define LTEFUNCTION 8
#define EQFUNCTION 9
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int math_exec(struct ast_channel *chan, void *data)
{
float fnum1;
float fnum2;
float ftmp = 0;
char *op;
int iaction=-1;
static int deprecation_warning = 0;
/* dunno, big calulations :D */
char user_result[30];
char *s;
char *mvar, *mvalue1, *mvalue2=NULL;
struct localuser *u;
if (!deprecation_warning) {
ast_log(LOG_WARNING, "Math() is deprecated, please use Set(var=${MATH(...)} instead.\n");
deprecation_warning = 1;
}
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "No parameters passed. !\n");
return -1;
}
LOCAL_USER_ADD(u);
s = ast_strdupa(data);
if (!s) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
mvar = strsep(&s, "|");
mvalue1 = strsep(&s, "|");
if ((op = strchr(mvalue1, '+'))) {
iaction = ADDFUNCTION;
*op = '\0';
} else if ((op = strchr(mvalue1, '-'))) {
iaction = SUBTRACTFUNCTION;
*op = '\0';
} else if ((op = strchr(mvalue1, '*'))) {
iaction = MULTIPLYFUNCTION;
*op = '\0';
} else if ((op = strchr(mvalue1, '/'))) {
iaction = DIVIDEFUNCTION;
*op = '\0';
} else if ((op = strchr(mvalue1, '>'))) {
iaction = GTFUNCTION;
*op = '\0';
if (*(op+1) == '=') {
op++;
*op = '\0';
iaction = GTEFUNCTION;
}
} else if ((op = strchr(mvalue1, '<'))) {
iaction = LTFUNCTION;
*op = '\0';
if (*(op+1) == '=') {
op++;
*op = '\0';
iaction = LTEFUNCTION;
}
} else if ((op = strchr(mvalue1, '='))) {
iaction = GTFUNCTION;
*op = '\0';
if (*(op+1) == '=') {
op++;
*op = '\0';
iaction = EQFUNCTION;
} else
op = NULL;
}
if (op)
mvalue2 = op + 1;
if (!mvar || !mvalue1 || !mvalue2) {
ast_log(LOG_WARNING, "Supply all the parameters - just this once, please\n");
LOCAL_USER_REMOVE(u);
return -1;
}
if (!strcmp(mvar,"")) {
ast_log(LOG_WARNING, "No return variable set.\n");
LOCAL_USER_REMOVE(u);
return -1;
}
if (sscanf(mvalue1, "%f", &fnum1) != 1) {
ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue1);
LOCAL_USER_REMOVE(u);
return -1;
}
if (sscanf(mvalue2, "%f", &fnum2) != 1) {
ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue2);
LOCAL_USER_REMOVE(u);
return -1;
}
switch (iaction) {
case ADDFUNCTION :
ftmp = fnum1 + fnum2;
break;
case DIVIDEFUNCTION :
if (fnum2 <=0)
ftmp = 0; /* can't do a divide by 0 */
else
ftmp = (fnum1 / fnum2);
break;
case MULTIPLYFUNCTION :
ftmp = (fnum1 * fnum2);
break;
case SUBTRACTFUNCTION :
ftmp = (fnum1 - fnum2);
break;
case MODULUSFUNCTION : {
int inum1 = fnum1;
int inum2 = fnum2;
ftmp = (inum1 % inum2);
break;
}
case GTFUNCTION :
if (fnum1 > fnum2)
strcpy(user_result, "TRUE");
else
strcpy(user_result, "FALSE");
break;
case LTFUNCTION :
if (fnum1 < fnum2)
strcpy(user_result, "TRUE");
else
strcpy(user_result, "FALSE");
break;
case GTEFUNCTION :
if (fnum1 >= fnum2)
strcpy(user_result, "TRUE");
else
strcpy(user_result, "FALSE");
break;
case LTEFUNCTION :
if (fnum1 <= fnum2)
strcpy(user_result, "TRUE");
else
strcpy(user_result, "FALSE");
break;
case EQFUNCTION :
if (fnum1 == fnum2)
strcpy(user_result, "TRUE");
else
strcpy(user_result, "FALSE");
break;
default :
ast_log(LOG_WARNING, "Something happened that neither of us should be proud of %d\n", iaction);
LOCAL_USER_REMOVE(u);
return -1;
}
if (iaction < GTFUNCTION || iaction > EQFUNCTION)
snprintf(user_result,sizeof(user_result),"%f",ftmp);
pbx_builtin_setvar_helper(chan, mvar, user_result);
LOCAL_USER_REMOVE(u);
return 0;
}
int unload_module(void)
{
int res;
res = ast_unregister_application(app_math);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
return ast_register_application(app_math, math_exec, math_synopsis, math_descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}
/* Fading everything to black and blue... */

205
apps/app_md5.c Normal file
View File

@@ -0,0 +1,205 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2005, Olle E. Johansson, Edvina.net
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief MD5 checksum application
*
* \todo Remove this deprecated application in 1.3dev
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
static char *tdesc_md5 = "MD5 checksum applications";
static char *app_md5 = "MD5";
static char *desc_md5 = "Calculate MD5 checksum";
static char *synopsis_md5 =
" MD5(<var>=<string>): Calculates a MD5 checksum on <string>.\n"
"Returns hash value in a channel variable. \n";
static char *app_md5check = "MD5Check";
static char *desc_md5check = "Check MD5 checksum";
static char *synopsis_md5check =
" MD5Check(<md5hash>|<string>[|options]): Calculates a MD5 checksum on <string>\n"
"and compares it with the hash. Returns 0 if <md5hash> is correct for <string>.\n"
"The option string may contain zero or more of the following characters:\n"
" 'j' -- jump to priority n+101 if the hash and string do not match \n"
"This application sets the following channel variable upon completion:\n"
" CHECKMD5STATUS The status of the MD5 check, one of the following\n"
" MATCH | NOMATCH\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
/*--- md5_exec: Calculate MD5 checksum (hash) on given string and
return it in channel variable ---*/
static int md5_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *varname= NULL; /* Variable to set */
char *string = NULL; /* String to calculate on */
char retvar[50]; /* Return value */
static int dep_warning = 0;
if (!dep_warning) {
ast_log(LOG_WARNING, "This application has been deprecated, please use the MD5 function instead.\n");
dep_warning = 1;
}
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Syntax: md5(<varname>=<string>) - missing argument!\n");
return -1;
}
LOCAL_USER_ADD(u);
memset(retvar,0, sizeof(retvar));
string = ast_strdupa(data);
varname = strsep(&string,"=");
if (ast_strlen_zero(varname)) {
ast_log(LOG_WARNING, "Syntax: md5(<varname>=<string>) - missing argument!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
ast_md5_hash(retvar, string);
pbx_builtin_setvar_helper(chan, varname, retvar);
LOCAL_USER_REMOVE(u);
return res;
}
/*--- md5check_exec: Calculate MD5 checksum and compare it with
existing checksum. ---*/
static int md5check_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *string = NULL; /* String to calculate on */
char newhash[50]; /* Return value */
static int dep_warning = 0;
int priority_jump = 0;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(md5hash);
AST_APP_ARG(string);
AST_APP_ARG(options);
);
if (!dep_warning) {
ast_log(LOG_WARNING, "This application has been deprecated, please use the CHECK_MD5 function instead.\n");
dep_warning = 1;
}
LOCAL_USER_ADD(u);
if (!(string = ast_strdupa(data))) {
ast_log(LOG_WARNING, "Memory Error!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
AST_STANDARD_APP_ARGS(args, string);
if (args.options) {
if (strchr(args.options, 'j'))
priority_jump = 1;
}
if (ast_strlen_zero(args.md5hash) || ast_strlen_zero(args.string)) {
ast_log(LOG_WARNING, "Syntax: MD5Check(<md5hash>|<string>[|options]) - missing argument!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
memset(newhash,0, sizeof(newhash));
ast_md5_hash(newhash, args.string);
if (!strcmp(newhash, args.md5hash)) { /* Verification ok */
if (option_debug > 2)
ast_log(LOG_DEBUG, "MD5 verified ok: %s -- %s\n", args.md5hash, args.string);
pbx_builtin_setvar_helper(chan, "CHECKMD5STATUS", "MATCH");
LOCAL_USER_REMOVE(u);
return 0;
}
if (option_debug > 2)
ast_log(LOG_DEBUG, "ERROR: MD5 not verified: %s -- %s\n", args.md5hash, args.string);
pbx_builtin_setvar_helper(chan, "CHECKMD5STATUS", "NOMATCH");
if (priority_jump || option_priority_jumping) {
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101))
if (option_debug > 2)
ast_log(LOG_DEBUG, "Can't jump to exten+101 (e%s,p%d), sorry\n", chan->exten,chan->priority+101);
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
int res;
res = ast_unregister_application(app_md5);
res |= ast_unregister_application(app_md5check);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
int res;
res = ast_register_application(app_md5check, md5check_exec, desc_md5check, synopsis_md5check);
res |= ast_register_application(app_md5, md5_exec, desc_md5, synopsis_md5);
return res;
}
char *description(void)
{
return tdesc_md5;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

File diff suppressed because it is too large Load Diff

View File

@@ -19,144 +19,152 @@
/*! \file
*
* \brief Digital Milliwatt Test
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>res_indications</depend>
***/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/indications.h"
#include "asterisk/module.h"
static char *tdesc = "Digital Milliwatt (mu-law) Test Application";
static char *app = "Milliwatt";
static char *synopsis = "Generate a Constant 1004Hz tone at 0dbm (mu-law)";
static char *synopsis = "Generate a Constant 1000Hz tone at 0dbm (mu-law)";
static char *descrip =
" Milliwatt([options]): Generate a Constant 1004Hz tone at 0dbm.\n"
"Previous versions of this application generated the tone at 1000Hz. If for\n"
"some reason you would prefer that behavior, supply the 'o' option to get the\n"
"old behavior.\n"
"";
"Milliwatt(): Generate a Constant 1000Hz tone at 0dbm (mu-law)\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static char digital_milliwatt[] = {0x1e,0x0b,0x0b,0x1e,0x9e,0x8b,0x8b,0x9e} ;
static void *milliwatt_alloc(struct ast_channel *chan, void *params)
{
return ast_calloc(1, sizeof(int));
int *indexp;
indexp = malloc(sizeof(int));
if (indexp == NULL) return(NULL);
*indexp = 0;
return(indexp);
}
static void milliwatt_release(struct ast_channel *chan, void *data)
{
ast_free(data);
free(data);
return;
}
static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int samples)
{
struct ast_frame wf;
unsigned char buf[AST_FRIENDLY_OFFSET + 640];
const int maxsamples = ARRAY_LEN(buf);
int i, *indexp = (int *) data;
struct ast_frame wf = {
.frametype = AST_FRAME_VOICE,
.subclass = AST_FORMAT_ULAW,
.offset = AST_FRIENDLY_OFFSET,
.data = buf + AST_FRIENDLY_OFFSET,
.src = __FUNCTION__,
};
int i,*indexp = (int *) data;
/* Instead of len, use samples, because channel.c generator_force
* generate(chan, tmp, 0, 160) ignores len. In any case, len is
* a multiple of samples, given by number of samples times bytes per
* sample. In the case of ulaw, len = samples. for signed linear
* len = 2 * samples */
if (samples > maxsamples) {
ast_log(LOG_WARNING, "Only doing %d samples (%d requested)\n", maxsamples, samples);
samples = maxsamples;
if (len + AST_FRIENDLY_OFFSET > sizeof(buf))
{
ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",(int)(sizeof(buf) - AST_FRIENDLY_OFFSET),len);
len = sizeof(buf) - AST_FRIENDLY_OFFSET;
}
len = samples * sizeof (buf[0]);
wf.frametype = AST_FRAME_VOICE;
wf.subclass = AST_FORMAT_ULAW;
wf.offset = AST_FRIENDLY_OFFSET;
wf.mallocd = 0;
wf.data = buf + AST_FRIENDLY_OFFSET;
wf.datalen = len;
wf.samples = samples;
wf.samples = wf.datalen;
wf.src = "app_milliwatt";
wf.delivery.tv_sec = 0;
wf.delivery.tv_usec = 0;
wf.prev = wf.next = NULL;
/* create a buffer containing the digital milliwatt pattern */
for (i = 0; i < len; i++) {
for(i = 0; i < len; i++)
{
buf[AST_FRIENDLY_OFFSET + i] = digital_milliwatt[(*indexp)++];
*indexp &= 7;
}
if (ast_write(chan,&wf) < 0) {
if (ast_write(chan,&wf) < 0)
{
ast_log(LOG_WARNING,"Failed to write frame to '%s': %s\n",chan->name,strerror(errno));
return -1;
}
return 0;
}
static struct ast_generator milliwattgen = {
static struct ast_generator milliwattgen =
{
alloc: milliwatt_alloc,
release: milliwatt_release,
generate: milliwatt_generate,
};
static int old_milliwatt_exec(struct ast_channel *chan)
{
ast_set_write_format(chan, AST_FORMAT_ULAW);
ast_set_read_format(chan, AST_FORMAT_ULAW);
if (chan->_state != AST_STATE_UP) {
ast_answer(chan);
}
if (ast_activate_generator(chan,&milliwattgen,"milliwatt") < 0) {
ast_log(LOG_WARNING,"Failed to activate generator on '%s'\n",chan->name);
return -1;
}
while (!ast_safe_sleep(chan, 10000))
;
ast_deactivate_generator(chan);
return -1;
}
} ;
static int milliwatt_exec(struct ast_channel *chan, void *data)
{
const char *options = data;
int res = -1;
if (!ast_strlen_zero(options) && strchr(options, 'o')) {
return old_milliwatt_exec(chan);
struct localuser *u;
LOCAL_USER_ADD(u);
ast_set_write_format(chan, AST_FORMAT_ULAW);
ast_set_read_format(chan, AST_FORMAT_ULAW);
if (chan->_state != AST_STATE_UP)
{
ast_answer(chan);
}
res = ast_playtones_start(chan, 23255, "1004/1000", 0);
while (!res) {
res = ast_safe_sleep(chan, 10000);
if (ast_activate_generator(chan,&milliwattgen,"milliwatt") < 0)
{
ast_log(LOG_WARNING,"Failed to activate generator on '%s'\n",chan->name);
LOCAL_USER_REMOVE(u);
return -1;
}
while(!ast_safe_sleep(chan, 10000));
ast_deactivate_generator(chan);
LOCAL_USER_REMOVE(u);
return -1;
}
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int unload_module(void)
{
return ast_unregister_application(app);
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, milliwatt_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Digital Milliwatt (mu-law) Test Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2005, Anthony Minessale II
* Copyright (C) 2005 - 2006, Digium, Inc.
* Copyright (C) 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
* Kevin P. Fleming <kpfleming@digium.com>
@@ -22,50 +22,47 @@
*/
/*! \file
*
* \brief MixMonitor() - Record a call and mix the audio during the recording
* \ingroup applications
*
* \author Mark Spencer <markster@digium.com>
* \author Kevin P. Fleming <kpfleming@digium.com>
*
* \note Based on app_muxmon.c provided by
* Anthony Minessale II <anthmct@yahoo.com>
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/paths.h" /* use ast_config_AST_MONITOR_DIR */
#include "asterisk/file.h"
#include "asterisk/audiohook.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/chanspy.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/cli.h"
#include "asterisk/options.h"
#include "asterisk/app.h"
#include "asterisk/channel.h"
#include "asterisk/linkedlists.h"
#define get_volfactor(x) x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0
static const char *tdesc = "Mixed Audio Monitoring Application";
static const char *app = "MixMonitor";
static const char *synopsis = "Record a call and mix the audio during the recording";
static const char *desc = ""
" MixMonitor(<file>.<ext>[,<options>[,<command>]]):\n"
" MixMonitor(<file>.<ext>[|<options>[|<command>]])\n\n"
"Records the audio on the current channel to the specified file.\n"
"If the filename is an absolute path, uses that path, otherwise\n"
"creates the file in the configured monitoring directory from\n"
"asterisk.conf. Use of StopMixMonitor is required to guarantee\n"
"the audio file is available for processing during dialplan execution.\n\n"
"asterisk.conf.\n\n"
"Valid options:\n"
" a - Append to the file instead of overwriting it.\n"
" b - Only save audio to the file while the channel is bridged.\n"
" Note: Does not include conferences or sounds played to each bridged\n"
" party.\n"
" Note: If you utilize this option inside a Local channel, you must\n"
" make sure the Local channel is not optimized away. To do this,\n"
" be sure to call your Local channel with the '/n' option.\n"
" For example: Dial(Local/start@mycontext/n)\n"
" v(<x>) - Adjust the heard volume by a factor of <x> (range -4 to 4)\n"
" V(<x>) - Adjust the spoken volume by a factor of <x> (range -4 to 4)\n"
" W(<x>) - Adjust the both heard and spoken volumes by a factor of <x>\n"
@@ -76,24 +73,18 @@ static const char *desc = ""
"The variable MIXMONITOR_FILENAME will contain the filename used to record.\n"
"";
static const char *stop_app = "StopMixMonitor";
static const char *stop_synopsis = "Stop recording a call through MixMonitor";
static const char *stop_desc = ""
" StopMixMonitor():\n"
"Stop recording a call through MixMonitor, and free the recording's file handle.\n"
"";
STANDARD_LOCAL_USER;
struct module_symbols *me;
LOCAL_USER_DECL;
static const char *mixmonitor_spy_type = "MixMonitor";
struct mixmonitor {
struct ast_audiohook audiohook;
struct ast_channel_spy spy;
char *filename;
char *post_process;
char *name;
unsigned int flags;
struct mixmonitor_ds *mixmonitor_ds;
};
enum {
@@ -119,94 +110,17 @@ AST_APP_OPTIONS(mixmonitor_opts, {
AST_APP_OPTION_ARG('W', MUXFLAG_VOLUME, OPT_ARG_VOLUME),
});
/* This structure is used as a means of making sure that our pointer to
* the channel we are monitoring remains valid. This is very similar to
* what is used in app_chanspy.c.
*/
struct mixmonitor_ds {
struct ast_channel *chan;
/* These condition variables are used to be sure that the channel
* hangup code completes before the mixmonitor thread attempts to
* free this structure. The combination of a bookean flag and a
* ast_cond_t ensure that no matter what order the threads run in,
* we are guaranteed to never have the waiting thread block forever
* in the case that the signaling thread runs first.
*/
unsigned int destruction_ok;
ast_cond_t destruction_condition;
ast_mutex_t lock;
/* The filestream is held in the datastore so it can be stopped
* immediately during stop_mixmonitor or channel destruction. */
int fs_quit;
struct ast_filestream *fs;
struct ast_audiohook *audiohook;
};
/*!
* \internal
* \pre mixmonitor_ds must be locked before calling this function
*/
static void mixmonitor_ds_close_fs(struct mixmonitor_ds *mixmonitor_ds)
static int startmon(struct ast_channel *chan, struct ast_channel_spy *spy)
{
if (mixmonitor_ds->fs) {
ast_closestream(mixmonitor_ds->fs);
mixmonitor_ds->fs = NULL;
mixmonitor_ds->fs_quit = 1;
ast_verb(2, "MixMonitor close filestream\n");
}
}
static void mixmonitor_ds_destroy(void *data)
{
struct mixmonitor_ds *mixmonitor_ds = data;
ast_mutex_lock(&mixmonitor_ds->lock);
mixmonitor_ds->chan = NULL;
mixmonitor_ds->audiohook = NULL;
mixmonitor_ds->destruction_ok = 1;
ast_cond_signal(&mixmonitor_ds->destruction_condition);
ast_mutex_unlock(&mixmonitor_ds->lock);
}
static void mixmonitor_ds_chan_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
{
struct mixmonitor_ds *mixmonitor_ds = data;
ast_mutex_lock(&mixmonitor_ds->lock);
mixmonitor_ds->chan = new_chan;
ast_mutex_unlock(&mixmonitor_ds->lock);
}
static struct ast_datastore_info mixmonitor_ds_info = {
.type = "mixmonitor",
.destroy = mixmonitor_ds_destroy,
.chan_fixup = mixmonitor_ds_chan_fixup,
};
static void destroy_monitor_audiohook(struct mixmonitor *mixmonitor)
{
if (mixmonitor->mixmonitor_ds) {
ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
mixmonitor->mixmonitor_ds->audiohook = NULL;
ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
}
/* kill the audiohook.*/
ast_audiohook_lock(&mixmonitor->audiohook);
ast_audiohook_detach(&mixmonitor->audiohook);
ast_audiohook_unlock(&mixmonitor->audiohook);
ast_audiohook_destroy(&mixmonitor->audiohook);
}
static int startmon(struct ast_channel *chan, struct ast_audiohook *audiohook)
{
struct ast_channel *peer = NULL;
int res = 0;
struct ast_channel *peer;
int res;
if (!chan)
return -1;
ast_audiohook_attach(chan, audiohook);
ast_mutex_lock(&chan->lock);
res = ast_channel_spy_add(chan, spy);
ast_mutex_unlock(&chan->lock);
if (!res && ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan)))
ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);
@@ -216,139 +130,97 @@ static int startmon(struct ast_channel *chan, struct ast_audiohook *audiohook)
#define SAMPLES_PER_FRAME 160
static void mixmonitor_free(struct mixmonitor *mixmonitor)
{
if (mixmonitor) {
if (mixmonitor->mixmonitor_ds) {
ast_mutex_destroy(&mixmonitor->mixmonitor_ds->lock);
ast_cond_destroy(&mixmonitor->mixmonitor_ds->destruction_condition);
ast_free(mixmonitor->mixmonitor_ds);
}
ast_free(mixmonitor);
}
}
static void *mixmonitor_thread(void *obj)
{
struct mixmonitor *mixmonitor = obj;
struct ast_filestream **fs = NULL;
struct ast_frame *f = NULL;
struct ast_filestream *fs = NULL;
unsigned int oflags;
char *ext;
int errflag = 0;
STANDARD_INCREMENT_USECOUNT;
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Begin MixMonitor Recording %s\n", mixmonitor->name);
ast_mutex_lock(&mixmonitor->spy.lock);
ast_verb(2, "Begin MixMonitor Recording %s\n", mixmonitor->name);
while (mixmonitor->spy.chan) {
struct ast_frame *next;
int write;
fs = &mixmonitor->mixmonitor_ds->fs;
/* The audiohook must enter and exit the loop locked */
ast_audiohook_lock(&mixmonitor->audiohook);
while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING && !mixmonitor->mixmonitor_ds->fs_quit) {
struct ast_frame *fr = NULL;
if (!(fr = ast_audiohook_read_frame(&mixmonitor->audiohook, SAMPLES_PER_FRAME, AST_AUDIOHOOK_DIRECTION_BOTH, AST_FORMAT_SLINEAR))) {
ast_audiohook_trigger_wait(&mixmonitor->audiohook);
if (mixmonitor->audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) {
ast_channel_spy_trigger_wait(&mixmonitor->spy);
if (!mixmonitor->spy.chan || mixmonitor->spy.status != CHANSPY_RUNNING)
break;
while (1) {
if (!(f = ast_channel_spy_read_frame(&mixmonitor->spy, SAMPLES_PER_FRAME)))
break;
}
continue;
}
/* audiohook lock is not required for the next block.
* Unlock it, but remember to lock it before looping or exiting */
ast_audiohook_unlock(&mixmonitor->audiohook);
write = (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) ||
ast_bridged_channel(mixmonitor->spy.chan));
ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
if (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) || (mixmonitor->mixmonitor_ds->chan && ast_bridged_channel(mixmonitor->mixmonitor_ds->chan))) {
/* Initialize the file if not already done so */
if (!*fs && !errflag && !mixmonitor->mixmonitor_ds->fs_quit) {
oflags = O_CREAT | O_WRONLY;
oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC;
/* it is possible for ast_channel_spy_read_frame() to return a chain
of frames if a queue flush was necessary, so process them
*/
for (; f; f = next) {
next = f->next;
if (write && errflag == 0) {
if (!fs) {
/* Determine creation flags and filename plus extension for filestream */
oflags = O_CREAT | O_WRONLY;
oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC;
if ((ext = strrchr(mixmonitor->filename, '.')))
*(ext++) = '\0';
else
ext = "raw";
if ((ext = strrchr(mixmonitor->filename, '.')))
*(ext++) = '\0';
else
ext = "raw";
if (!(*fs = ast_writefile(mixmonitor->filename, ext, NULL, oflags, 0, 0644))) {
ast_log(LOG_ERROR, "Cannot open %s.%s\n", mixmonitor->filename, ext);
errflag = 1;
}
}
/* Write out the frame(s) */
if (*fs) {
struct ast_frame *cur;
for (cur = fr; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
ast_writestream(*fs, cur);
/* Move onto actually creating the filestream */
if (!(fs = ast_writefile(mixmonitor->filename, ext, NULL, oflags, 0, 0644))) {
ast_log(LOG_ERROR, "Cannot open %s.%s\n", mixmonitor->filename, ext);
errflag = 1;
}
}
if (fs)
ast_writestream(fs, f);
}
ast_frfree(f);
}
}
ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
/* All done! free it. */
ast_frame_free(fr, 0);
ast_audiohook_lock(&mixmonitor->audiohook);
}
ast_audiohook_unlock(&mixmonitor->audiohook);
/* Datastore cleanup. close the filestream and wait for ds destruction */
ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
mixmonitor_ds_close_fs(mixmonitor->mixmonitor_ds);
if (!mixmonitor->mixmonitor_ds->destruction_ok) {
ast_cond_wait(&mixmonitor->mixmonitor_ds->destruction_condition, &mixmonitor->mixmonitor_ds->lock);
}
ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
ast_mutex_unlock(&mixmonitor->spy.lock);
ast_channel_spy_free(&mixmonitor->spy);
/* kill the audiohook */
destroy_monitor_audiohook(mixmonitor);
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "End MixMonitor Recording %s\n", mixmonitor->name);
if (mixmonitor->post_process) {
ast_verb(2, "Executing [%s]\n", mixmonitor->post_process);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_2 "Executing [%s]\n", mixmonitor->post_process);
ast_safe_system(mixmonitor->post_process);
}
if (fs)
ast_closestream(fs);
free(mixmonitor);
STANDARD_DECREMENT_USECOUNT;
ast_verb(2, "End MixMonitor Recording %s\n", mixmonitor->name);
mixmonitor_free(mixmonitor);
return NULL;
}
static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel *chan)
{
struct ast_datastore *datastore = NULL;
struct mixmonitor_ds *mixmonitor_ds;
if (!(mixmonitor_ds = ast_calloc(1, sizeof(*mixmonitor_ds)))) {
return -1;
}
ast_mutex_init(&mixmonitor_ds->lock);
ast_cond_init(&mixmonitor_ds->destruction_condition, NULL);
if (!(datastore = ast_channel_datastore_alloc(&mixmonitor_ds_info, NULL))) {
ast_mutex_destroy(&mixmonitor_ds->lock);
ast_cond_destroy(&mixmonitor_ds->destruction_condition);
ast_free(mixmonitor_ds);
return -1;
}
/* No need to lock mixmonitor_ds since this is still operating in the channel's thread */
mixmonitor_ds->chan = chan;
mixmonitor_ds->audiohook = &mixmonitor->audiohook;
datastore->data = mixmonitor_ds;
ast_channel_lock(chan);
ast_channel_datastore_add(chan, datastore);
ast_channel_unlock(chan);
mixmonitor->mixmonitor_ds = mixmonitor_ds;
return 0;
}
static void launch_monitor_thread(struct ast_channel *chan, const char *filename, unsigned int flags,
int readvol, int writevol, const char *post_process)
{
pthread_attr_t attr;
pthread_t thread;
struct mixmonitor *mixmonitor;
char postprocess2[1024] = "";
@@ -356,7 +228,6 @@ static void launch_monitor_thread(struct ast_channel *chan, const char *filename
len = sizeof(*mixmonitor) + strlen(chan->name) + strlen(filename) + 2;
postprocess2[0] = 0;
/* If a post process system command is given attach it to the structure */
if (!ast_strlen_zero(post_process)) {
char *p1, *p2;
@@ -367,28 +238,20 @@ static void launch_monitor_thread(struct ast_channel *chan, const char *filename
*p2 = '$';
}
}
pbx_substitute_variables_helper(chan, p1, postprocess2, sizeof(postprocess2) - 1);
if (!ast_strlen_zero(postprocess2))
len += strlen(postprocess2) + 1;
}
/* Pre-allocate mixmonitor structure and spy */
if (!(mixmonitor = ast_calloc(1, len))) {
return;
}
/* Setup the actual spy before creating our thread */
if (ast_audiohook_init(&mixmonitor->audiohook, AST_AUDIOHOOK_TYPE_SPY, mixmonitor_spy_type)) {
mixmonitor_free(mixmonitor);
if (!(mixmonitor = calloc(1, len))) {
ast_log(LOG_ERROR, "Memory Error!\n");
return;
}
/* Copy over flags and channel name */
mixmonitor->flags = flags;
if (setup_mixmonitor_ds(mixmonitor, chan)) {
mixmonitor_free(mixmonitor);
return;
}
mixmonitor->name = (char *) mixmonitor + sizeof(*mixmonitor);
strcpy(mixmonitor->name, chan->name);
if (!ast_strlen_zero(postprocess2)) {
@@ -399,29 +262,45 @@ static void launch_monitor_thread(struct ast_channel *chan, const char *filename
mixmonitor->filename = (char *) mixmonitor + sizeof(*mixmonitor) + strlen(chan->name) + 1;
strcpy(mixmonitor->filename, filename);
ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_SYNC);
/* Setup the actual spy before creating our thread */
ast_set_flag(&mixmonitor->spy, CHANSPY_FORMAT_AUDIO);
ast_set_flag(&mixmonitor->spy, CHANSPY_MIXAUDIO);
mixmonitor->spy.type = mixmonitor_spy_type;
mixmonitor->spy.status = CHANSPY_RUNNING;
mixmonitor->spy.read_queue.format = AST_FORMAT_SLINEAR;
mixmonitor->spy.write_queue.format = AST_FORMAT_SLINEAR;
if (readvol) {
ast_set_flag(&mixmonitor->spy, CHANSPY_READ_VOLADJUST);
mixmonitor->spy.read_vol_adjustment = readvol;
}
if (writevol) {
ast_set_flag(&mixmonitor->spy, CHANSPY_WRITE_VOLADJUST);
mixmonitor->spy.write_vol_adjustment = writevol;
}
ast_mutex_init(&mixmonitor->spy.lock);
if (readvol)
mixmonitor->audiohook.options.read_volume = readvol;
if (writevol)
mixmonitor->audiohook.options.write_volume = writevol;
if (startmon(chan, &mixmonitor->audiohook)) {
if (startmon(chan, &mixmonitor->spy)) {
ast_log(LOG_WARNING, "Unable to add '%s' spy to channel '%s'\n",
mixmonitor_spy_type, chan->name);
ast_audiohook_destroy(&mixmonitor->audiohook);
mixmonitor_free(mixmonitor);
mixmonitor->spy.type, chan->name);
/* Since we couldn't add ourselves - bail out! */
ast_mutex_destroy(&mixmonitor->spy.lock);
free(mixmonitor);
return;
}
ast_pthread_create_detached_background(&thread, NULL, mixmonitor_thread, mixmonitor);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ast_pthread_create(&thread, &attr, mixmonitor_thread, mixmonitor);
pthread_attr_destroy(&attr);
}
static int mixmonitor_exec(struct ast_channel *chan, void *data)
{
int x, readvol = 0, writevol = 0;
struct localuser *u;
struct ast_flags flags = {0};
char *parse, *tmp, *slash;
char *parse;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(filename);
AST_APP_ARG(options);
@@ -433,12 +312,19 @@ static int mixmonitor_exec(struct ast_channel *chan, void *data)
return -1;
}
parse = ast_strdupa(data);
LOCAL_USER_ADD(u);
if (!(parse = ast_strdupa(data))) {
ast_log(LOG_WARNING, "Memory Error!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
AST_STANDARD_APP_ARGS(args, parse);
if (ast_strlen_zero(args.filename)) {
ast_log(LOG_WARNING, "MixMonitor requires an argument (filename)\n");
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -450,7 +336,7 @@ static int mixmonitor_exec(struct ast_channel *chan, void *data)
if (ast_test_flag(&flags, MUXFLAG_READVOLUME)) {
if (ast_strlen_zero(opts[OPT_ARG_READVOLUME])) {
ast_log(LOG_WARNING, "No volume level was provided for the heard volume ('v') option.\n");
} else if ((sscanf(opts[OPT_ARG_READVOLUME], "%2d", &x) != 1) || (x < -4) || (x > 4)) {
} else if ((sscanf(opts[OPT_ARG_READVOLUME], "%d", &x) != 1) || (x < -4) || (x > 4)) {
ast_log(LOG_NOTICE, "Heard volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_READVOLUME]);
} else {
readvol = get_volfactor(x);
@@ -460,7 +346,7 @@ static int mixmonitor_exec(struct ast_channel *chan, void *data)
if (ast_test_flag(&flags, MUXFLAG_WRITEVOLUME)) {
if (ast_strlen_zero(opts[OPT_ARG_WRITEVOLUME])) {
ast_log(LOG_WARNING, "No volume level was provided for the spoken volume ('V') option.\n");
} else if ((sscanf(opts[OPT_ARG_WRITEVOLUME], "%2d", &x) != 1) || (x < -4) || (x > 4)) {
} else if ((sscanf(opts[OPT_ARG_WRITEVOLUME], "%d", &x) != 1) || (x < -4) || (x > 4)) {
ast_log(LOG_NOTICE, "Spoken volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_WRITEVOLUME]);
} else {
writevol = get_volfactor(x);
@@ -470,7 +356,7 @@ static int mixmonitor_exec(struct ast_channel *chan, void *data)
if (ast_test_flag(&flags, MUXFLAG_VOLUME)) {
if (ast_strlen_zero(opts[OPT_ARG_VOLUME])) {
ast_log(LOG_WARNING, "No volume level was provided for the combined volume ('W') option.\n");
} else if ((sscanf(opts[OPT_ARG_VOLUME], "%2d", &x) != 1) || (x < -4) || (x > 4)) {
} else if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &x) != 1) || (x < -4) || (x > 4)) {
ast_log(LOG_NOTICE, "Combined volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_VOLUME]);
} else {
readvol = writevol = get_volfactor(x);
@@ -487,114 +373,82 @@ static int mixmonitor_exec(struct ast_channel *chan, void *data)
args.filename = build;
}
tmp = ast_strdupa(args.filename);
if ((slash = strrchr(tmp, '/')))
*slash = '\0';
ast_mkdir(tmp, 0777);
pbx_builtin_setvar_helper(chan, "MIXMONITOR_FILENAME", args.filename);
launch_monitor_thread(chan, args.filename, flags.flags, readvol, writevol, args.post_process);
return 0;
}
static int stop_mixmonitor_exec(struct ast_channel *chan, void *data)
{
struct ast_datastore *datastore = NULL;
ast_channel_lock(chan);
ast_audiohook_detach_source(chan, mixmonitor_spy_type);
if ((datastore = ast_channel_datastore_find(chan, &mixmonitor_ds_info, NULL))) {
struct mixmonitor_ds *mixmonitor_ds = datastore->data;
ast_mutex_lock(&mixmonitor_ds->lock);
/* closing the filestream here guarantees the file is avaliable to the dialplan
* after calling StopMixMonitor */
mixmonitor_ds_close_fs(mixmonitor_ds);
/* The mixmonitor thread may be waiting on the audiohook trigger.
* In order to exit from the mixmonitor loop before waiting on channel
* destruction, poke the audiohook trigger. */
if (mixmonitor_ds->audiohook) {
ast_audiohook_lock(mixmonitor_ds->audiohook);
ast_cond_signal(&mixmonitor_ds->audiohook->trigger);
ast_audiohook_unlock(mixmonitor_ds->audiohook);
mixmonitor_ds->audiohook = NULL;
}
ast_mutex_unlock(&mixmonitor_ds->lock);
/* Remove the datastore so the monitor thread can exit */
if (!ast_channel_datastore_remove(chan, datastore)) {
ast_channel_datastore_free(datastore);
}
}
ast_channel_unlock(chan);
LOCAL_USER_REMOVE(u);
return 0;
}
static char *handle_cli_mixmonitor(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int mixmonitor_cli(int fd, int argc, char **argv)
{
struct ast_channel *chan;
switch (cmd) {
case CLI_INIT:
e->command = "mixmonitor [start|stop]";
e->usage =
"Usage: mixmonitor <start|stop> <chan_name> [args]\n"
" The optional arguments are passed to the MixMonitor\n"
" application when the 'start' command is used.\n";
return NULL;
case CLI_GENERATE:
return ast_complete_channels(a->line, a->word, a->pos, a->n, 2);
if (argc < 3)
return RESULT_SHOWUSAGE;
if (!(chan = ast_get_channel_by_name_prefix_locked(argv[2], strlen(argv[2])))) {
ast_cli(fd, "No channel matching '%s' found.\n", argv[2]);
return RESULT_SUCCESS;
}
if (a->argc < 3)
return CLI_SHOWUSAGE;
if (!strcasecmp(argv[1], "start"))
mixmonitor_exec(chan, argv[3]);
else if (!strcasecmp(argv[1], "stop"))
ast_channel_spy_stop_by_type(chan, mixmonitor_spy_type);
if (!(chan = ast_get_channel_by_name_prefix_locked(a->argv[2], strlen(a->argv[2])))) {
ast_cli(a->fd, "No channel matching '%s' found.\n", a->argv[2]);
/* Technically this is a failure, but we don't want 2 errors printing out */
return CLI_SUCCESS;
}
ast_mutex_unlock(&chan->lock);
if (!strcasecmp(a->argv[1], "start")) {
mixmonitor_exec(chan, a->argv[3]);
ast_channel_unlock(chan);
} else {
ast_channel_unlock(chan);
ast_audiohook_detach_source(chan, mixmonitor_spy_type);
}
return CLI_SUCCESS;
return RESULT_SUCCESS;
}
static struct ast_cli_entry cli_mixmonitor[] = {
AST_CLI_DEFINE(handle_cli_mixmonitor, "Execute a MixMonitor command")
static struct ast_cli_entry cli_mixmonitor = {
{ "mixmonitor", NULL, NULL },
mixmonitor_cli,
"Execute a MixMonitor command",
"mixmonitor <start|stop> <chan_name> [<args>]\n"
};
static int unload_module(void)
int unload_module(void)
{
int res;
ast_cli_unregister_multiple(cli_mixmonitor, sizeof(cli_mixmonitor) / sizeof(struct ast_cli_entry));
res = ast_unregister_application(stop_app);
res = ast_cli_unregister(&cli_mixmonitor);
res |= ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
int res;
ast_cli_register_multiple(cli_mixmonitor, sizeof(cli_mixmonitor) / sizeof(struct ast_cli_entry));
res = ast_register_application(app, mixmonitor_exec, synopsis, desc);
res |= ast_register_application(stop_app, stop_mixmonitor_exec, stop_synopsis, stop_desc);
res = ast_cli_register(&cli_mixmonitor);
res |= ast_register_application(app, mixmonitor_exec, synopsis, desc);
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Mixed Audio Monitoring Application");
char *description(void)
{
return (char *) tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,161 +0,0 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (c) 2006, Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <app_morsecode__v001@the-tilghman.com>
*
* This code is released by the author with no restrictions on usage.
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
*/
/*! \file
*
* \brief Morsecode application
*
* \author Tilghman Lesher <app_morsecode__v001@the-tilghman.com>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
static char *app_morsecode = "Morsecode";
static char *morsecode_synopsis = "Plays morse code";
static char *morsecode_descrip =
" Morsecode(<string>):\n"
"Plays the Morse code equivalent of the passed string. If the variable\n"
"MORSEDITLEN is set, it will use that value for the length (in ms) of the dit\n"
"(defaults to 80). Additionally, if MORSETONE is set, it will use that tone\n"
"(in Hz). The tone default is 800.\n";
static char *morsecode[] = {
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 0-15 */
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", /* 16-31 */
" ", /* 32 - <space> */
".-.-.-", /* 33 - ! */
".-..-.", /* 34 - " */
"", /* 35 - # */
"", /* 36 - $ */
"", /* 37 - % */
"", /* 38 - & */
".----.", /* 39 - ' */
"-.--.-", /* 40 - ( */
"-.--.-", /* 41 - ) */
"", /* 42 - * */
"", /* 43 - + */
"--..--", /* 44 - , */
"-....-", /* 45 - - */
".-.-.-", /* 46 - . */
"-..-.", /* 47 - / */
"-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", /* 48-57 - 0-9 */
"---...", /* 58 - : */
"-.-.-.", /* 59 - ; */
"", /* 60 - < */
"-...-", /* 61 - = */
"", /* 62 - > */
"..--..", /* 63 - ? */
".--.-.", /* 64 - @ */
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
"-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..",
"-.--.-", /* 91 - [ (really '(') */
"-..-.", /* 92 - \ (really '/') */
"-.--.-", /* 93 - ] (really ')') */
"", /* 94 - ^ */
"..--.-", /* 95 - _ */
".----.", /* 96 - ` */
".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--",
"-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..",
"-.--.-", /* 123 - { (really '(') */
"", /* 124 - | */
"-.--.-", /* 125 - } (really ')') */
"-..-.", /* 126 - ~ (really bar) */
". . .", /* 127 - <del> (error) */
};
static void playtone(struct ast_channel *chan, int tone, int len)
{
char dtmf[20];
snprintf(dtmf, sizeof(dtmf), "%d/%d", tone, len);
ast_playtones_start(chan, 0, dtmf, 0);
ast_safe_sleep(chan, len);
ast_playtones_stop(chan);
}
static int morsecode_exec(struct ast_channel *chan, void *data)
{
int res=0, ditlen, tone;
char *digit;
const char *ditlenc, *tonec;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Syntax: Morsecode(<string>) - no argument found\n");
return 0;
}
/* Use variable MORESEDITLEN, if set (else 80) */
ditlenc = pbx_builtin_getvar_helper(chan, "MORSEDITLEN");
if (ast_strlen_zero(ditlenc) || (sscanf(ditlenc, "%30d", &ditlen) != 1)) {
ditlen = 80;
}
/* Use variable MORSETONE, if set (else 800) */
tonec = pbx_builtin_getvar_helper(chan, "MORSETONE");
if (ast_strlen_zero(tonec) || (sscanf(tonec, "%30d", &tone) != 1)) {
tone = 800;
}
for (digit = data; *digit; digit++) {
int digit2 = *digit;
char *dahdit;
if (digit2 < 0) {
continue;
}
for (dahdit = morsecode[digit2]; *dahdit; dahdit++) {
if (*dahdit == '-') {
playtone(chan, tone, 3 * ditlen);
} else if (*dahdit == '.') {
playtone(chan, tone, 1 * ditlen);
} else {
/* Account for ditlen of silence immediately following */
playtone(chan, 0, 2 * ditlen);
}
/* Pause slightly between each dit and dah */
playtone(chan, 0, 1 * ditlen);
}
/* Pause between characters */
playtone(chan, 0, 2 * ditlen);
}
return res;
}
static int unload_module(void)
{
return ast_unregister_application(app_morsecode);
}
static int load_module(void)
{
return ast_register_application(app_morsecode, morsecode_exec, morsecode_synopsis, morsecode_descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Morse code");

View File

@@ -19,55 +19,55 @@
/*! \file
*
* \brief Silly application to play an MP3 file -- uses mpg123
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>working_fork</depend>
***/
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <sys/time.h>
#include <signal.h>
#ifdef HAVE_CAP
#include <sys/capability.h>
#endif /* HAVE_CAP */
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/frame.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/options.h"
#define LOCAL_MPG_123 "/usr/local/bin/mpg123"
#define MPG_123 "/usr/bin/mpg123"
static char *tdesc = "Silly MP3 Application";
static char *app = "MP3Player";
static char *synopsis = "Play an MP3 file or stream";
static char *descrip =
" MP3Player(location): Executes mpg123 to play the given location,\n"
" MP3Player(location) Executes mpg123 to play the given location,\n"
"which typically would be a filename or a URL. User can exit by pressing\n"
"any key on the dialpad, or by hanging up.";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int mp3play(char *filename, int fd)
{
int res;
int x;
sigset_t fullset, oldset;
#ifdef HAVE_CAP
cap_t cap;
#endif
sigfillset(&fullset);
pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
@@ -79,23 +79,15 @@ static int mp3play(char *filename, int fd)
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
return res;
}
#ifdef HAVE_CAP
cap = cap_from_text("cap_net_admin-eip");
if (cap_set_proc(cap)) {
/* Careful with order! Logging cannot happen after we close FDs */
ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
}
cap_free(cap);
#endif
if (ast_opt_high_priority)
if (option_highpriority)
ast_set_priority(0);
signal(SIGPIPE, SIG_DFL);
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
dup2(fd, STDOUT_FILENO);
for (x=STDERR_FILENO + 1;x<256;x++) {
close(x);
if (x != STDOUT_FILENO)
close(x);
}
/* Execute mpg123, but buffer if it's a net connection */
if (!strncasecmp(filename, "http://", 7)) {
@@ -124,7 +116,7 @@ static int timed_read(int fd, void *data, int datalen, int timeout)
struct pollfd fds[1];
fds[0].fd = fd;
fds[0].events = POLLIN;
res = ast_poll(fds, 1, timeout);
res = poll(fds, 1, timeout);
if (res < 1) {
ast_log(LOG_NOTICE, "Poll timed out/errored out with %d\n", res);
return -1;
@@ -136,6 +128,7 @@ static int timed_read(int fd, void *data, int datalen, int timeout)
static int mp3_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
int fds[2];
int ms = -1;
int pid = -1;
@@ -147,17 +140,18 @@ static int mp3_exec(struct ast_channel *chan, void *data)
struct ast_frame f;
char offset[AST_FRIENDLY_OFFSET];
short frdata[160];
} myf = {
.f = { 0, },
};
} myf;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n");
return -1;
}
LOCAL_USER_ADD(u);
if (pipe(fds)) {
ast_log(LOG_WARNING, "Unable to create pipe\n");
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -167,6 +161,7 @@ static int mp3_exec(struct ast_channel *chan, void *data)
res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -201,7 +196,7 @@ static int mp3_exec(struct ast_channel *chan, void *data)
break;
}
} else {
ast_debug(1, "No more mp3\n");
ast_log(LOG_DEBUG, "No more mp3\n");
res = 0;
break;
}
@@ -209,19 +204,19 @@ static int mp3_exec(struct ast_channel *chan, void *data)
} else {
ms = ast_waitfor(chan, ms);
if (ms < 0) {
ast_debug(1, "Hangup detected\n");
ast_log(LOG_DEBUG, "Hangup detected\n");
res = -1;
break;
}
if (ms) {
f = ast_read(chan);
if (!f) {
ast_debug(1, "Null frame == hangup() detected\n");
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
res = -1;
break;
}
if (f->frametype == AST_FRAME_DTMF) {
ast_debug(1, "User pressed a key\n");
ast_log(LOG_DEBUG, "User pressed a key\n");
ast_frfree(f);
res = 0;
break;
@@ -238,18 +233,41 @@ static int mp3_exec(struct ast_channel *chan, void *data)
kill(pid, SIGKILL);
if (!res && owriteformat)
ast_set_write_format(chan, owriteformat);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app);
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, mp3_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Silly MP3 Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,35 +19,32 @@
/*! \file
*
* \brief Silly application to play an NBScat file -- uses nbscat8k
*
* \author Mark Spencer <markster@digium.com>
*
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>working_fork</depend>
***/
#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/socket.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <fcntl.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <signal.h>
#ifdef HAVE_CAP
#include <sys/capability.h>
#endif /* HAVE_CAP */
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/frame.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/options.h"
#define LOCAL_NBSCAT "/usr/local/bin/nbscat8k"
#define NBSCAT "/usr/bin/nbscat8k"
@@ -56,23 +53,25 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define AF_LOCAL AF_UNIX
#endif
static char *tdesc = "Silly NBS Stream Application";
static char *app = "NBScat";
static char *synopsis = "Play an NBS local stream";
static char *descrip =
" NBScat(): Executes nbscat to listen to the local NBS stream.\n"
"User can exit by pressing any key.\n";
" NBScat: Executes nbscat to listen to the local NBS stream.\n"
"User can exit by pressing any key\n.";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int NBScatplay(int fd)
{
int res;
int x;
sigset_t fullset, oldset;
#ifdef HAVE_CAP
cap_t cap;
#endif
sigfillset(&fullset);
pthread_sigmask(SIG_BLOCK, &fullset, &oldset);
@@ -87,16 +86,7 @@ static int NBScatplay(int fd)
signal(SIGPIPE, SIG_DFL);
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
#ifdef HAVE_CAP
cap = cap_from_text("cap_net_admin-eip");
if (cap_set_proc(cap)) {
/* Careful with order! Logging cannot happen after we close FDs */
ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
}
cap_free(cap);
#endif
if (ast_opt_high_priority)
if (option_highpriority)
ast_set_priority(0);
dup2(fd, STDOUT_FILENO);
@@ -117,7 +107,7 @@ static int timed_read(int fd, void *data, int datalen)
struct pollfd fds[1];
fds[0].fd = fd;
fds[0].events = POLLIN;
res = ast_poll(fds, 1, 2000);
res = poll(fds, 1, 2000);
if (res < 1) {
ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res);
return -1;
@@ -129,6 +119,7 @@ static int timed_read(int fd, void *data, int datalen)
static int NBScat_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
int fds[2];
int ms = -1;
int pid = -1;
@@ -141,8 +132,11 @@ static int NBScat_exec(struct ast_channel *chan, void *data)
short frdata[160];
} myf;
LOCAL_USER_ADD(u);
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
ast_log(LOG_WARNING, "Unable to create socketpair\n");
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -152,6 +146,7 @@ static int NBScat_exec(struct ast_channel *chan, void *data)
res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -183,7 +178,7 @@ static int NBScat_exec(struct ast_channel *chan, void *data)
break;
}
} else {
ast_debug(1, "No more mp3\n");
ast_log(LOG_DEBUG, "No more mp3\n");
res = 0;
break;
}
@@ -191,19 +186,19 @@ static int NBScat_exec(struct ast_channel *chan, void *data)
} else {
ms = ast_waitfor(chan, ms);
if (ms < 0) {
ast_debug(1, "Hangup detected\n");
ast_log(LOG_DEBUG, "Hangup detected\n");
res = -1;
break;
}
if (ms) {
f = ast_read(chan);
if (!f) {
ast_debug(1, "Null frame == hangup() detected\n");
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
res = -1;
break;
}
if (f->frametype == AST_FRAME_DTMF) {
ast_debug(1, "User pressed a key\n");
ast_log(LOG_DEBUG, "User pressed a key\n");
ast_frfree(f);
res = 0;
break;
@@ -221,17 +216,40 @@ static int NBScat_exec(struct ast_channel *chan, void *data)
if (!res && owriteformat)
ast_set_write_format(chan, owriteformat);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app);
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, NBScat_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Silly NBS Stream Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

File diff suppressed because it is too large Load Diff

View File

@@ -20,154 +20,179 @@
*
* \brief page() - Paging application
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
/*** MODULEINFO
<depend>dahdi</depend>
<depend>app_meetme</depend>
***/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/options.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/chanvars.h"
#include "asterisk/utils.h"
#include "asterisk/devicestate.h"
#include "asterisk/dial.h"
static const char *tdesc = "Page Multiple Phones";
static const char *app_page= "Page";
static const char *page_synopsis = "Pages phones";
static const char *page_descrip =
"Page(Technology/Resource&Technology2/Resource2[,options])\n"
"Page(Technology/Resource&Technology2/Resource2[|options])\n"
" Places outbound calls to the given technology / resource and dumps\n"
"them into a conference bridge as muted participants. The original\n"
"caller is dumped into the conference as a speaker and the room is\n"
"destroyed when the original caller leaves. Valid options are:\n"
" d - full duplex audio\n"
" q - quiet, do not play beep to caller\n"
" r - record the page into a file (see 'r' for app_meetme)\n"
" s - only dial channel if devicestate says it is not in use\n";
" q - quiet, do not play beep to caller\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
enum {
PAGE_DUPLEX = (1 << 0),
PAGE_QUIET = (1 << 1),
PAGE_RECORD = (1 << 2),
PAGE_SKIP = (1 << 3),
} page_opt_flags;
AST_APP_OPTIONS(page_opts, {
AST_APP_OPTION('d', PAGE_DUPLEX),
AST_APP_OPTION('q', PAGE_QUIET),
AST_APP_OPTION('r', PAGE_RECORD),
AST_APP_OPTION('s', PAGE_SKIP),
});
struct calloutdata {
char cidnum[64];
char cidname[64];
char tech[64];
char resource[256];
char meetmeopts[64];
struct ast_variable *variables;
};
static void *page_thread(void *data)
{
struct calloutdata *cd = data;
ast_pbx_outgoing_app(cd->tech, AST_FORMAT_SLINEAR, cd->resource, 30000,
"MeetMe", cd->meetmeopts, NULL, 0, cd->cidnum, cd->cidname, cd->variables, NULL, NULL);
free(cd);
return NULL;
}
static void launch_page(struct ast_channel *chan, const char *meetmeopts, const char *tech, const char *resource)
{
struct calloutdata *cd;
const char *varname;
struct ast_variable *lastvar = NULL;
struct ast_var_t *varptr;
pthread_t t;
pthread_attr_t attr;
cd = malloc(sizeof(struct calloutdata));
if (cd) {
memset(cd, 0, sizeof(struct calloutdata));
ast_copy_string(cd->cidnum, chan->cid.cid_num ? chan->cid.cid_num : "", sizeof(cd->cidnum));
ast_copy_string(cd->cidname, chan->cid.cid_name ? chan->cid.cid_name : "", sizeof(cd->cidname));
ast_copy_string(cd->tech, tech, sizeof(cd->tech));
ast_copy_string(cd->resource, resource, sizeof(cd->resource));
ast_copy_string(cd->meetmeopts, meetmeopts, sizeof(cd->meetmeopts));
AST_LIST_TRAVERSE(&chan->varshead, varptr, entries) {
if (!(varname = ast_var_full_name(varptr)))
continue;
if (varname[0] == '_') {
struct ast_variable *newvar = NULL;
if (varname[1] == '_') {
newvar = ast_variable_new(varname, ast_var_value(varptr));
} else {
newvar = ast_variable_new(&varname[1], ast_var_value(varptr));
}
if (newvar) {
if (lastvar)
lastvar->next = newvar;
else
cd->variables = newvar;
lastvar = newvar;
}
}
}
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (ast_pthread_create(&t, &attr, page_thread, cd)) {
ast_log(LOG_WARNING, "Unable to create paging thread: %s\n", strerror(errno));
free(cd);
}
pthread_attr_destroy(&attr);
}
}
static int page_exec(struct ast_channel *chan, void *data)
{
char *options, *tech, *resource, *tmp, *tmp2;
char meetmeopts[88], originator[AST_CHANNEL_NAME], *opts[0];
struct localuser *u;
char *options;
char *tech, *resource;
char meetmeopts[80];
struct ast_flags flags = { 0 };
unsigned int confid = ast_random();
unsigned int confid = rand();
struct ast_app *app;
int res = 0, pos = 0, i = 0;
struct ast_dial **dial_list;
unsigned int num_dials;
char *tmp;
int res=0;
char originator[AST_CHANNEL_NAME];
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "This application requires at least one argument (destination(s) to page)\n");
return -1;
}
LOCAL_USER_ADD(u);
if (!(app = pbx_findapp("MeetMe"))) {
ast_log(LOG_WARNING, "There is no MeetMe application available!\n");
LOCAL_USER_REMOVE(u);
return -1;
};
options = ast_strdupa(data);
if (!options) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
ast_copy_string(originator, chan->name, sizeof(originator));
if ((tmp = strchr(originator, '-')))
*tmp = '\0';
tmp = strsep(&options, ",");
tmp = strsep(&options, "|");
if (options)
ast_app_parse_options(page_opts, &flags, opts, options);
ast_app_parse_options(page_opts, &flags, NULL, options);
snprintf(meetmeopts, sizeof(meetmeopts), "MeetMe,%ud,%s%sqxdw(5)", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m"),
(ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
snprintf(meetmeopts, sizeof(meetmeopts), "%ud|%sqxdw(5)", confid, ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "m");
/* Count number of extensions in list by number of ampersands + 1 */
num_dials = 1;
tmp2 = tmp;
while (*tmp2) {
if (*tmp2 == '&') {
num_dials++;
}
tmp2++;
}
if (!(dial_list = ast_calloc(num_dials, sizeof(struct ast_dial *)))) {
ast_log(LOG_ERROR, "Can't allocate %ld bytes for dial list\n", (long)(sizeof(struct ast_dial *) * num_dials));
return -1;
}
/* Go through parsing/calling each device */
while ((tech = strsep(&tmp, "&"))) {
int state = 0;
struct ast_dial *dial = NULL;
/* don't call the originating device */
if (!strcasecmp(tech, originator))
continue;
/* If no resource is available, continue on */
if (!(resource = strchr(tech, '/'))) {
if ((resource = strchr(tech, '/'))) {
*resource++ = '\0';
launch_page(chan, meetmeopts, tech, resource);
} else {
ast_log(LOG_WARNING, "Incomplete destination '%s' supplied.\n", tech);
continue;
}
/* Ensure device is not in use if skip option is enabled */
if (ast_test_flag(&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, devstate2str(state));
} else if (state != AST_DEVICE_NOT_INUSE) {
ast_log(LOG_WARNING, "Destination '%s' has device state '%s'.\n", tech, devstate2str(state));
continue;
}
}
*resource++ = '\0';
/* Create a dialing structure */
if (!(dial = ast_dial_create())) {
ast_log(LOG_WARNING, "Failed to create dialing structure.\n");
continue;
}
/* Append technology and resource */
ast_dial_append(dial, tech, resource);
/* Set ANSWER_EXEC as global option */
ast_dial_option_global_enable(dial, AST_DIAL_OPTION_ANSWER_EXEC, meetmeopts);
/* Run this dial in async mode */
ast_dial_run(dial, chan, 1);
/* Put in our dialing array */
dial_list[pos++] = dial;
}
if (!ast_test_flag(&flags, PAGE_QUIET)) {
@@ -175,39 +200,47 @@ static int page_exec(struct ast_channel *chan, void *data)
if (!res)
res = ast_waitstream(chan, "");
}
if (!res) {
snprintf(meetmeopts, sizeof(meetmeopts), "%ud,A%s%sqxd", confid, (ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t"),
(ast_test_flag(&flags, PAGE_RECORD) ? "r" : "") );
pbx_exec(chan, app, meetmeopts);
snprintf(meetmeopts, sizeof(meetmeopts), "%ud|A%sqxd", confid, ast_test_flag(&flags, PAGE_DUPLEX) ? "" : "t");
pbx_exec(chan, app, meetmeopts, 1);
}
/* Go through each dial attempt cancelling, joining, and destroying */
for (i = 0; i < pos; i++) {
struct ast_dial *dial = dial_list[i];
/* We have to wait for the async thread to exit as it's possible Meetme won't throw them out immediately */
ast_dial_join(dial);
/* Hangup all channels */
ast_dial_hangup(dial);
/* Destroy dialing structure */
ast_dial_destroy(dial);
}
LOCAL_USER_REMOVE(u);
return -1;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app_page);
int res;
res = ast_unregister_application(app_page);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app_page, page_exec, page_synopsis, page_descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Page Multiple Phones");
char *description(void)
{
return (char *) tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,7 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2006, Digium, Inc.
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
@@ -22,123 +22,186 @@
/*! \file
*
* \brief ParkAndAnnounce application for Asterisk
*
* \author Ben Miller <bgmiller@dccinc.com>
* \arg With TONS of help from Mark!
*
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/features.h"
#include "asterisk/options.h"
#include "asterisk/logger.h"
#include "asterisk/say.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
static char *tdesc = "Call Parking and Announce Application";
static char *app = "ParkAndAnnounce";
static char *synopsis = "Park and Announce";
static char *descrip =
" ParkAndAnnounce(announce:template,timeout,dial[,return_context]):\n"
"Park a call into the parkinglot and announce the call to another channel.\n"
"\n"
"announce template: Colon-separated list of files to announce. The word PARKED\n"
" will be replaced by a say_digits of the extension in which\n"
" the call is parked.\n"
"timeout: Time in seconds before the call returns into the return\n"
" context.\n"
"dial: The app_dial style resource to call to make the\n"
" announcement. Console/dsp calls the console.\n"
"return_context: The goto-style label to jump the call back into after\n"
" timeout. Default <priority+1>.\n"
"\n"
"The variable ${PARKEDAT} will contain the parking extension into which the\n"
"call was placed. Use with the Local channel to allow the dialplan to make\n"
"use of this information.\n";
" ParkAndAnnounce(announce:template|timeout|dial|[return_context]):\n"
"Park a call into the parkinglot and announce the call over the console.\n"
"announce template: colon separated list of files to announce, the word PARKED\n"
" will be replaced by a say_digits of the ext the call is parked in\n"
"timeout: time in seconds before the call returns into the return context.\n"
"dial: The app_dial style resource to call to make the announcement. Console/dsp calls the console.\n"
"return_context: the goto style label to jump the call back into after timeout. default=prio+1\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int parkandannounce_exec(struct ast_channel *chan, void *data)
{
int res = -1;
int lot, timeout = 0, dres;
char *dialtech, *tmp[100], buf[13];
int looptemp, i;
char *s;
int res=0;
char *return_context;
int l, lot, timeout = 0, dres;
char *working, *context, *exten, *priority, *dial, *dialtech, *dialstr;
char *template, *tpl_working, *tpl_current;
char *tmp[100];
int looptemp=0,i=0;
char *s,*orig_s;
struct ast_channel *dchan;
struct outgoing_helper oh = { 0, };
struct outgoing_helper oh;
int outstate;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(template);
AST_APP_ARG(timeout);
AST_APP_ARG(dial);
AST_APP_ARG(return_context);
);
struct localuser *u;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "ParkAndAnnounce requires arguments: (announce:template|timeout|dial|[return_context])\n");
return -1;
}
s = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, s);
LOCAL_USER_ADD(u);
if (args.timeout)
timeout = atoi(args.timeout) * 1000;
if (ast_strlen_zero(args.dial)) {
ast_log(LOG_WARNING, "PARK: A dial resource must be specified i.e: Console/dsp or DAHDI/g1/5551212\n");
l=strlen(data)+2;
orig_s=malloc(l);
if(!orig_s) {
ast_log(LOG_WARNING, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
s=orig_s;
strncpy(s,data,l);
dialtech = strsep(&args.dial, "/");
ast_verb(3, "Dial Tech,String: (%s,%s)\n", dialtech, args.dial);
if (!ast_strlen_zero(args.return_context)) {
ast_clear_flag(chan, AST_FLAG_IN_AUTOLOOP);
ast_parseable_goto(chan, args.return_context);
template=strsep(&s,"|");
if(! template) {
ast_log(LOG_WARNING, "PARK: An announce template must be defined\n");
free(orig_s);
LOCAL_USER_REMOVE(u);
return -1;
}
if(s) {
timeout = atoi(strsep(&s, "|"));
timeout *= 1000;
}
dial=strsep(&s, "|");
if(!dial) {
ast_log(LOG_WARNING, "PARK: A dial resource must be specified i.e: Console/dsp or Zap/g1/5551212\n");
free(orig_s);
LOCAL_USER_REMOVE(u);
return -1;
} else {
dialtech=strsep(&dial, "/");
dialstr=dial;
ast_verbose( VERBOSE_PREFIX_3 "Dial Tech,String: (%s,%s)\n", dialtech,dialstr);
}
ast_verb(3, "Return Context: (%s,%s,%d) ID: %s\n", chan->context, chan->exten, chan->priority, chan->cid.cid_num);
if (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
ast_verb(3, "Warning: Return Context Invalid, call will return to default|s\n");
return_context = s;
if(return_context != NULL) {
/* set the return context. Code borrowed from the Goto builtin */
working = return_context;
context = strsep(&working, "|");
exten = strsep(&working, "|");
if(!exten) {
/* Only a priority in this one */
priority = context;
exten = NULL;
context = NULL;
} else {
priority = strsep(&working, "|");
if(!priority) {
/* Only an extension and priority in this one */
priority = exten;
exten = context;
context = NULL;
}
}
if(atoi(priority) < 0) {
ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
free(orig_s);
LOCAL_USER_REMOVE(u);
return -1;
}
/* At this point we have a priority and maybe an extension and a context */
chan->priority = atoi(priority);
if(exten && strcasecmp(exten, "BYEXTENSION"))
strncpy(chan->exten, exten, sizeof(chan->exten)-1);
if(context)
strncpy(chan->context, context, sizeof(chan->context)-1);
} else { /* increment the priority by default*/
chan->priority++;
}
if(option_verbose > 2) {
ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->cid.cid_num);
if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) {
ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
}
}
/* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
res = ast_masq_park_call(chan, NULL, timeout, &lot);
if (res == -1)
return res;
ast_masq_park_call(chan, NULL, timeout, &lot);
ast_verb(3, "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, args.return_context);
res=-1;
/* Now place the call to the extension */
ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
snprintf(buf, sizeof(buf), "%d", lot);
/* Now place the call to the extention */
memset(&oh, 0, sizeof(oh));
oh.parent_channel = chan;
oh.vars = ast_variable_new("_PARKEDAT", buf, "");
dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, args.dial, 30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
dchan = __ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
if (dchan) {
if (dchan->_state == AST_STATE_UP) {
ast_verb(4, "Channel %s was answered.\n", dchan->name);
if(dchan) {
if(dchan->_state == AST_STATE_UP) {
if(option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", dchan->name);
} else {
ast_verb(4, "Channel %s was never answered.\n", dchan->name);
if(option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", dchan->name);
ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name);
ast_hangup(dchan);
free(orig_s);
LOCAL_USER_REMOVE(u);
return -1;
}
} else {
ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
free(orig_s);
LOCAL_USER_REMOVE(u);
return -1;
}
@@ -146,22 +209,24 @@ static int parkandannounce_exec(struct ast_channel *chan, void *data)
/* now we have the call placed and are ready to play stuff to it */
ast_verb(4, "Announce Template:%s\n", args.template);
ast_verbose(VERBOSE_PREFIX_4 "Announce Template:%s\n", template);
for (looptemp = 0; looptemp < ARRAY_LEN(tmp); looptemp++) {
if ((tmp[looptemp] = strsep(&args.template, ":")) != NULL)
continue;
else
break;
tpl_working = template;
tpl_current=strsep(&tpl_working, ":");
while(tpl_current && looptemp < sizeof(tmp)) {
tmp[looptemp]=tpl_current;
looptemp++;
tpl_current=strsep(&tpl_working,":");
}
for (i = 0; i < looptemp; i++) {
ast_verb(4, "Announce:%s\n", tmp[i]);
if (!strcmp(tmp[i], "PARKED")) {
for(i=0; i<looptemp; i++) {
ast_verbose(VERBOSE_PREFIX_4 "Announce:%s\n", tmp[i]);
if(!strcmp(tmp[i], "PARKED")) {
ast_say_digits(dchan, lot, "", dchan->language);
} else {
dres = ast_streamfile(dchan, tmp[i], dchan->language);
if (!dres) {
if(!dres) {
dres = ast_waitstream(dchan, "");
} else {
ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], dchan->name);
@@ -172,19 +237,45 @@ static int parkandannounce_exec(struct ast_channel *chan, void *data)
ast_stopstream(dchan);
ast_hangup(dchan);
free(orig_s);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app);
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
/* return ast_register_application(app, park_exec); */
return ast_register_application(app, parkandannounce_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Call Parking and Announce Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,174 +0,0 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2008, Gary Cook
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Pickup a ringing channel
*
* \author Gary Cook
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
#include "asterisk/options.h"
static const char *app = "PickupChan";
static const char *synopsis = "Pickup a ringing channel";
static const char *descrip =
" PickupChan(channel[&channel...]): This application can pickup any ringing channel\n";
/*! \todo This application should return a result code, like PICKUPRESULT */
/*! \brief Helper function that determines whether a channel is capable of being picked up */
static int can_pickup(struct ast_channel *chan)
{
ast_debug(3, "Checking Pickup '%s' state '%s ( %d )'\n", chan->name, ast_state2str(chan->_state), chan->_state);
if (!chan->pbx && (chan->_state == AST_STATE_RINGING || chan->_state == AST_STATE_RING)) {
return 1;
} else {
return 0;
}
}
/*! \brief Helper Function to walk through ALL channels checking NAME and STATE */
static struct ast_channel *my_ast_get_channel_by_name_locked(char *channame)
{
struct ast_channel *chan;
char *chkchan = alloca(strlen(channame) + 2);
/* need to append a '-' for the comparison so we check full channel name,
* i.e SIP/hgc- , use a temporary variable so original stays the same for
* debugging.
*/
strcpy(chkchan, channame);
strcat(chkchan, "-");
for (chan = ast_walk_channel_by_name_prefix_locked(NULL, channame, strlen(channame));
chan;
chan = ast_walk_channel_by_name_prefix_locked(chan, channame, strlen(channame))) {
if (!strncasecmp(chan->name, chkchan, strlen(chkchan)) && can_pickup(chan))
return chan;
ast_channel_unlock(chan);
}
return NULL;
}
/*! \brief Perform actual pickup between two channels */
static int pickup_do(struct ast_channel *chan, struct ast_channel *target)
{
int res = 0;
ast_debug(3, "Call pickup on '%s' by '%s'\n", target->name, chan->name);
if ((res = ast_answer(chan))) {
ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
return -1;
}
if ((res = ast_queue_control(chan, AST_CONTROL_ANSWER))) {
ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
return -1;
}
if ((res = ast_channel_masquerade(target, chan))) {
ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
return -1;
}
return res;
}
/*! \brief Attempt to pick up specified channel named , does not use context */
static int pickup_by_channel(struct ast_channel *chan, char *pickup)
{
int res = 0;
struct ast_channel *target;
if (!(target = my_ast_get_channel_by_name_locked(pickup)))
return -1;
/* Just check that we are not picking up the SAME as target */
if (chan->name != target->name && chan != target) {
res = pickup_do(chan, target);
ast_channel_unlock(target);
}
return res;
}
/*! \brief Main application entry point */
static int pickupchan_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct ast_module_user *u = NULL;
char *tmp = ast_strdupa(data);
char *pickup = NULL, *context = NULL;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Pickup requires an argument (channel)!\n");
return -1;
}
u = ast_module_user_add(chan);
/* Parse channel (and ignore context if there) */
while (!ast_strlen_zero(tmp) && (pickup = strsep(&tmp, "&"))) {
if ((context = strchr(pickup , '@'))) {
*context++ = '\0';
}
if (!strncasecmp(chan->name, pickup , strlen(pickup))) {
ast_log(LOG_NOTICE, "Cannot pickup your own channel %s.\n", pickup);
} else {
if (!pickup_by_channel(chan, pickup)) {
break;
}
ast_log(LOG_NOTICE, "No target channel found for %s.\n", pickup);
}
}
ast_module_user_remove(u);
return res;
}
static int unload_module(void)
{
return ast_unregister_application(app);
}
static int load_module(void)
{
return ast_register_application(app, pickupchan_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel Pickup Application");

View File

@@ -19,388 +19,64 @@
/*! \file
*
* \brief Trivial application to playback a sound file
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
#include "asterisk/app.h"
/* This file provides config-file based 'say' functions, and implenents
* some CLI commands.
*/
#include "asterisk/say.h" /* provides config-file based 'say' functions */
#include "asterisk/cli.h"
static char *tdesc = "Sound File Playback Application";
static char *app = "Playback";
static char *synopsis = "Play a file";
static char *descrip =
" Playback(filename[&filename2...][,option]): Plays back given filenames (do not put\n"
"extension). Options may also be included following a comma.\n"
"The 'skip' option causes the playback of the message to be skipped if the channel\n"
" Playback(filename[&filename2...][|option]): Plays back given filenames (do not put\n"
"extension). Options may also be included following a pipe symbol. The 'skip'\n"
"option causes the playback of the message to be skipped if the channel\n"
"is not in the 'up' state (i.e. it hasn't been answered yet). If 'skip' is \n"
"specified, the application will return immediately should the channel not be\n"
"off hook. Otherwise, unless 'noanswer' is specified, the channel will\n"
"be answered before the sound is played. Not all channels support playing\n"
"messages while still on hook.\n"
"messages while still on hook. If 'j' is specified, the application\n"
"will jump to priority n+101 if present when a file specified to be played\n"
"does not exist.\n"
"This application sets the following channel variable upon completion:\n"
" PLAYBACKSTATUS The status of the playback attempt as a text string, one of\n"
" SUCCESS | FAILED\n"
"See Also: Background (application) -- for playing soundfiles that are interruptible\n"
" WaitExten (application) -- wait for digits from caller, optionally play music on hold\n"
;
STANDARD_LOCAL_USER;
static struct ast_config *say_cfg = NULL;
/* save the say' api calls.
* The first entry is NULL if we have the standard source,
* otherwise we are sourcing from here.
* 'say load [new|old]' will enable the new or old method, or report status
*/
static const void *say_api_buf[40];
static const char *say_old = "old";
static const char *say_new = "new";
static void save_say_mode(const void *arg)
{
int i = 0;
say_api_buf[i++] = arg;
say_api_buf[i++] = ast_say_number_full;
say_api_buf[i++] = ast_say_enumeration_full;
say_api_buf[i++] = ast_say_digit_str_full;
say_api_buf[i++] = ast_say_character_str_full;
say_api_buf[i++] = ast_say_phonetic_str_full;
say_api_buf[i++] = ast_say_datetime;
say_api_buf[i++] = ast_say_time;
say_api_buf[i++] = ast_say_date;
say_api_buf[i++] = ast_say_datetime_from_now;
say_api_buf[i++] = ast_say_date_with_format;
}
static void restore_say_mode(void *arg)
{
int i = 0;
say_api_buf[i++] = arg;
ast_say_number_full = say_api_buf[i++];
ast_say_enumeration_full = say_api_buf[i++];
ast_say_digit_str_full = say_api_buf[i++];
ast_say_character_str_full = say_api_buf[i++];
ast_say_phonetic_str_full = say_api_buf[i++];
ast_say_datetime = say_api_buf[i++];
ast_say_time = say_api_buf[i++];
ast_say_date = say_api_buf[i++];
ast_say_datetime_from_now = say_api_buf[i++];
ast_say_date_with_format = say_api_buf[i++];
}
/*
* Typical 'say' arguments in addition to the date or number or string
* to say. We do not include 'options' because they may be different
* in recursive calls, and so they are better left as an external
* parameter.
*/
typedef struct {
struct ast_channel *chan;
const char *ints;
const char *language;
int audiofd;
int ctrlfd;
} say_args_t;
static int s_streamwait3(const say_args_t *a, const char *fn)
{
int res = ast_streamfile(a->chan, fn, a->language);
if (res) {
ast_log(LOG_WARNING, "Unable to play message %s\n", fn);
return res;
}
res = (a->audiofd > -1 && a->ctrlfd > -1) ?
ast_waitstream_full(a->chan, a->ints, a->audiofd, a->ctrlfd) :
ast_waitstream(a->chan, a->ints);
ast_stopstream(a->chan);
return res;
}
/*
* the string is 'prefix:data' or prefix:fmt:data'
* with ':' being invalid in strings.
*/
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;
int ret = 0;
struct varshead head = { .first = NULL, .last = NULL };
struct ast_var_t *n;
ast_debug(2, "string <%s> depth <%d>\n", s, depth);
if (depth++ > 10) {
ast_log(LOG_WARNING, "recursion too deep, exiting\n");
return -1;
} else if (!say_cfg) {
ast_log(LOG_WARNING, "no say.conf, cannot spell '%s'\n", s);
return -1;
}
/* scan languages same as in file.c */
if (a->language == NULL)
a->language = "en"; /* default */
ast_debug(2, "try <%s> in <%s>\n", s, a->language);
lang = ast_strdupa(a->language);
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);
break;
}
}
if (rule)
break;
if ( (x = strchr(lang, '_')) )
*x = '\0'; /* try without suffix */
else if (strcmp(lang, "en"))
lang = "en"; /* last resort, try 'en' if not done yet */
else
break;
}
if (!rule)
return 0;
/* skip up to two prefixes to get the value */
if ( (x = strchr(s, ':')) )
s = x + 1;
if ( (x = strchr(s, ':')) )
s = x + 1;
ast_debug(2, "value is <%s>\n", s);
n = ast_var_assign("SAY", s);
AST_LIST_INSERT_HEAD(&head, n, entries);
/* scan the body, one piece at a time */
while ( !ret && (x = strsep(&rule, ",")) ) { /* exit on key */
char fn[128];
const char *p, *fmt, *data; /* format and data pointers */
/* prepare a decent file name */
x = ast_skip_blanks(x);
ast_trim_blanks(x);
/* replace variables */
pbx_substitute_variables_varshead(&head, x, fn, sizeof(fn));
ast_debug(2, "doing [%s]\n", fn);
/* locate prefix and data, if any */
fmt = strchr(fn, ':');
if (!fmt || fmt == fn) { /* regular filename */
ret = s_streamwait3(a, fn);
continue;
}
fmt++;
data = strchr(fmt, ':'); /* colon before data */
if (!data || data == fmt) { /* simple prefix-fmt */
ret = do_say(a, fn, options, depth);
continue;
}
/* prefix:fmt:data */
for (p = fmt; p < data && ret <= 0; p++) {
char fn2[sizeof(fn)];
if (*p == ' ' || *p == '\t') /* skip blanks */
continue;
if (*p == '\'') {/* file name - we trim them */
char *y;
strcpy(fn2, ast_skip_blanks(p+1)); /* make a full copy */
y = strchr(fn2, '\'');
if (!y) {
p = data; /* invalid. prepare to end */
break;
}
*y = '\0';
ast_trim_blanks(fn2);
p = strchr(p+1, '\'');
ret = s_streamwait3(a, fn2);
} else {
int l = fmt-fn;
strcpy(fn2, fn); /* copy everything */
/* after prefix, append the format */
fn2[l++] = *p;
strcpy(fn2 + l, data);
ret = do_say(a, fn2, options, depth);
}
if (ret) {
break;
}
}
}
ast_var_delete(n);
return ret;
}
static int say_full(struct ast_channel *chan, const char *string,
const char *ints, const char *lang, const char *options,
int audiofd, int ctrlfd)
{
say_args_t a = { chan, ints, lang, audiofd, ctrlfd };
return do_say(&a, string, options, 0);
}
static int say_number_full(struct ast_channel *chan, int num,
const char *ints, const char *lang, const char *options,
int audiofd, int ctrlfd)
{
char buf[64];
say_args_t a = { chan, ints, lang, audiofd, ctrlfd };
snprintf(buf, sizeof(buf), "num:%d", num);
return do_say(&a, buf, options, 0);
}
static int say_enumeration_full(struct ast_channel *chan, int num,
const char *ints, const char *lang, const char *options,
int audiofd, int ctrlfd)
{
char buf[64];
say_args_t a = { chan, ints, lang, audiofd, ctrlfd };
snprintf(buf, sizeof(buf), "enum:%d", num);
return do_say(&a, buf, options, 0);
}
static int say_date_generic(struct ast_channel *chan, time_t t,
const char *ints, const char *lang, const char *format, const char *timezone, const char *prefix)
{
char buf[128];
struct ast_tm tm;
struct timeval tv = { t, 0 };
say_args_t a = { chan, ints, lang, -1, -1 };
if (format == NULL)
format = "";
ast_localtime(&tv, &tm, NULL);
snprintf(buf, sizeof(buf), "%s:%s:%04d%02d%02d%02d%02d.%02d-%d-%3d",
prefix,
format,
tm.tm_year+1900,
tm.tm_mon+1,
tm.tm_mday,
tm.tm_hour,
tm.tm_min,
tm.tm_sec,
tm.tm_wday,
tm.tm_yday);
return do_say(&a, buf, NULL, 0);
}
static int say_date_with_format(struct ast_channel *chan, time_t t,
const char *ints, const char *lang, const char *format, const char *timezone)
{
return say_date_generic(chan, t, ints, lang, format, timezone, "datetime");
}
static int say_date(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
{
return say_date_generic(chan, t, ints, lang, "", NULL, "date");
}
static int say_time(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
{
return say_date_generic(chan, t, ints, lang, "", NULL, "time");
}
static int say_datetime(struct ast_channel *chan, time_t t, const char *ints, const char *lang)
{
return say_date_generic(chan, t, ints, lang, "", NULL, "datetime");
}
/*
* remap the 'say' functions to use those in this file
*/
static int say_init_mode(const char *mode) {
if (!strcmp(mode, say_new)) {
if (say_cfg == NULL) {
ast_log(LOG_ERROR, "There is no say.conf file to use new mode\n");
return -1;
}
save_say_mode(say_new);
ast_say_number_full = say_number_full;
ast_say_enumeration_full = say_enumeration_full;
#if 0
ast_say_digits_full = say_digits_full;
ast_say_digit_str_full = say_digit_str_full;
ast_say_character_str_full = say_character_str_full;
ast_say_phonetic_str_full = say_phonetic_str_full;
ast_say_datetime_from_now = say_datetime_from_now;
#endif
ast_say_datetime = say_datetime;
ast_say_time = say_time;
ast_say_date = say_date;
ast_say_date_with_format = say_date_with_format;
} else if (!strcmp(mode, say_old) && say_api_buf[0] == say_new) {
restore_say_mode(NULL);
} else if (strcmp(mode, say_old)) {
ast_log(LOG_WARNING, "unrecognized mode %s\n", mode);
return -1;
}
return 0;
}
static char *__say_cli_init(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
const char *old_mode = say_api_buf[0] ? say_new : say_old;
char *mode;
switch (cmd) {
case CLI_INIT:
e->command = "say load [new|old]";
e->usage =
"Usage: say load [new|old]\n"
" say load\n"
" Report status of current say mode\n"
" say load new\n"
" Set say method, configured in say.conf\n"
" say load old\n"
" Set old say method, coded in asterisk core\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc == 2) {
ast_cli(a->fd, "say mode is [%s]\n", old_mode);
return CLI_SUCCESS;
} else if (a->argc != e->args)
return CLI_SHOWUSAGE;
mode = a->argv[2];
if (!strcmp(mode, old_mode))
ast_cli(a->fd, "say mode is %s already\n", mode);
else
if (say_init_mode(mode) == 0)
ast_cli(a->fd, "setting say mode from %s to %s\n", old_mode, mode);
return CLI_SUCCESS;
}
static struct ast_cli_entry cli_playback[] = {
AST_CLI_DEFINE(__say_cli_init, "Set or show the say mode"),
};
LOCAL_USER_DECL;
static int playback_exec(struct ast_channel *chan, void *data)
{
int res = 0;
int mres = 0;
char *tmp;
int res = 0, mres = 0;
struct localuser *u;
char *tmp = NULL;
int option_skip=0;
int option_say=0;
int option_noanswer = 0;
char *front = NULL, *back = NULL;
int priority_jump = 0;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(filenames);
AST_APP_ARG(options);
@@ -411,117 +87,95 @@ static int playback_exec(struct ast_channel *chan, void *data)
return -1;
}
LOCAL_USER_ADD(u);
tmp = ast_strdupa(data);
if (!tmp) {
ast_log(LOG_ERROR, "Out of memory!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
AST_STANDARD_APP_ARGS(args, tmp);
if (args.options) {
if (strcasestr(args.options, "skip"))
option_skip = 1;
if (strcasestr(args.options, "say"))
option_say = 1;
if (strcasestr(args.options, "noanswer"))
option_noanswer = 1;
}
if (strchr(args.options, 'j'))
priority_jump = 1;
}
if (chan->_state != AST_STATE_UP) {
if (option_skip) {
/* At the user's option, skip if the line is not up */
goto done;
} else if (!option_noanswer) {
pbx_builtin_setvar_helper(chan, "PLAYBACKSTATUS", "SUCCESS");
LOCAL_USER_REMOVE(u);
return 0;
} else if (!option_noanswer)
/* Otherwise answer unless we're supposed to send this while on-hook */
res = ast_answer(chan);
}
}
if (!res) {
char *back = args.filenames;
char *front;
ast_stopstream(chan);
while (!res && (front = strsep(&back, "&"))) {
if (option_say)
res = say_full(chan, front, "", chan->language, NULL, -1, -1);
else
res = ast_streamfile(chan, front, chan->language);
front = tmp;
while (!res && front) {
if ((back = strchr(front, '&'))) {
*back = '\0';
back++;
}
res = ast_streamfile(chan, front, chan->language);
if (!res) {
res = ast_waitstream(chan, "");
ast_stopstream(chan);
} else {
ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
if (priority_jump || option_priority_jumping)
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
res = 0;
mres = 1;
}
front = back;
}
}
done:
pbx_builtin_setvar_helper(chan, "PLAYBACKSTATUS", mres ? "FAILED" : "SUCCESS");
if (mres)
pbx_builtin_setvar_helper(chan, "PLAYBACKSTATUS", "FAILED");
else
pbx_builtin_setvar_helper(chan, "PLAYBACKSTATUS", "SUCCESS");
LOCAL_USER_REMOVE(u);
return res;
}
static int reload(void)
{
struct ast_variable *v;
struct ast_flags config_flags = { CONFIG_FLAG_FILEUNCHANGED };
struct ast_config *newcfg;
if ((newcfg = ast_config_load("say.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
return 0;
if (say_cfg) {
ast_config_destroy(say_cfg);
ast_log(LOG_NOTICE, "Reloading say.conf\n");
say_cfg = newcfg;
}
if (say_cfg) {
for (v = ast_variable_browse(say_cfg, "general"); v ; v = v->next) {
if (ast_extension_match(v->name, "mode")) {
say_init_mode(v->value);
break;
}
}
}
/*
* XXX here we should sort rules according to the same order
* we have in pbx.c so we have the same matching behaviour.
*/
return 0;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
ast_cli_unregister_multiple(cli_playback, sizeof(cli_playback) / sizeof(struct ast_cli_entry));
if (say_cfg)
ast_config_destroy(say_cfg);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
struct ast_variable *v;
struct ast_flags config_flags = { 0 };
say_cfg = ast_config_load("say.conf", config_flags);
if (say_cfg) {
for (v = ast_variable_browse(say_cfg, "general"); v ; v = v->next) {
if (ast_extension_match(v->name, "mode")) {
say_init_mode(v->value);
break;
}
}
}
ast_cli_register_multiple(cli_playback, sizeof(cli_playback) / sizeof(struct ast_cli_entry));
return ast_register_application(app, playback_exec, synopsis, descrip);
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Sound File Playback Application",
.load = load_module,
.unload = unload_module,
.reload = reload,
);
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,12 +19,14 @@
/*! \file
*
* \brief Block all calls without Caller*ID, require phone # to be entered
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
@@ -32,6 +34,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/utils.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
@@ -41,24 +45,40 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/app.h"
#include "asterisk/config.h"
#define PRIV_CONFIG "privacy.conf"
static char *tdesc = "Require phone number to be entered, if no CallerID sent";
static char *app = "PrivacyManager";
static char *synopsis = "Require phone number to be entered, if no CallerID sent";
static char *descrip =
" PrivacyManager([maxretries][,minlength]): If no Caller*ID \n"
" PrivacyManager([maxretries[|minlength[|options]]]): If no Caller*ID \n"
"is sent, PrivacyManager answers the channel and asks the caller to\n"
"enter their phone number. The caller is given 'maxretries' attempts to do so.\n"
"enter their phone number. The caller is given 3 attempts to do so.\n"
"The application does nothing if Caller*ID was received on the channel.\n"
" Configuration file privacy.conf contains two variables:\n"
" maxretries default 3 -maximum number of attempts the caller is allowed \n"
" to input a callerid.\n"
" minlength default 10 -minimum allowable digits in the input callerid number.\n"
"If you don't want to use the config file and have an i/o operation with\n"
"every call, you can also specify maxretries and minlength as application\n"
"parameters. Doing so supercedes any values set in privacy.conf.\n"
"The option string may contain the following character: \n"
" 'j' -- jump to n+101 priority after <maxretries> failed attempts to collect\n"
" the minlength number of digits.\n"
"The application sets the following channel variable upon completion: \n"
"PRIVACYMGRSTATUS The status of the privacy manager's attempt to collect \n"
" a phone number from the user. A text string that is either:\n"
" SUCCESS | FAILED \n"
;
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int privacy_exec (struct ast_channel *chan, void *data)
{
@@ -67,51 +87,89 @@ static int privacy_exec (struct ast_channel *chan, void *data)
int maxretries = 3;
int minlength = 10;
int x = 0;
char *s;
char phone[30];
struct localuser *u;
struct ast_config *cfg = NULL;
char *parse = NULL;
int priority_jump = 0;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(maxretries);
AST_APP_ARG(minlength);
AST_APP_ARG(options);
);
LOCAL_USER_ADD (u);
if (!ast_strlen_zero(chan->cid.cid_num)) {
ast_verb(3, "CallerID Present: Skipping\n");
if (option_verbose > 2)
ast_verbose (VERBOSE_PREFIX_3 "CallerID Present: Skipping\n");
} else {
/*Answer the channel if it is not already*/
if (chan->_state != AST_STATE_UP) {
if ((res = ast_answer(chan)))
res = ast_answer(chan);
if (res) {
LOCAL_USER_REMOVE(u);
return -1;
}
}
if (!ast_strlen_zero(data)) {
if (!ast_strlen_zero((char *)data))
{
parse = ast_strdupa(data);
if (!parse) {
ast_log(LOG_ERROR, "Out of memory!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
AST_STANDARD_APP_ARGS(args, parse);
if (args.maxretries) {
if (sscanf(args.maxretries, "%30d", &x) == 1)
if (sscanf(args.maxretries, "%d", &x) == 1)
maxretries = x;
else
ast_log(LOG_WARNING, "Invalid max retries argument\n");
}
if (args.minlength) {
if (sscanf(args.minlength, "%30d", &x) == 1)
if (sscanf(args.minlength, "%d", &x) == 1)
minlength = x;
else
ast_log(LOG_WARNING, "Invalid min length argument\n");
}
if (args.options)
if (strchr(args.options, 'j'))
priority_jump = 1;
}
/* Play unidentified call */
if (!x)
{
/*Read in the config file*/
cfg = ast_config_load(PRIV_CONFIG);
if (cfg && (s = ast_variable_retrieve(cfg, "general", "maxretries"))) {
if (sscanf(s, "%d", &x) == 1)
maxretries = x;
else
ast_log(LOG_WARNING, "Invalid max retries argument\n");
}
if (cfg && (s = ast_variable_retrieve(cfg, "general", "minlength"))) {
if (sscanf(s, "%d", &x) == 1)
minlength = x;
else
ast_log(LOG_WARNING, "Invalid min length argument\n");
}
}
/*Play unidentified call*/
res = ast_safe_sleep(chan, 1000);
if (!res)
res = ast_streamfile(chan, "privacy-unident", chan->language);
if (!res)
res = ast_waitstream(chan, "");
/* Ask for 10 digit number, give 3 attempts */
/*Ask for 10 digit number, give 3 attempts*/
for (retries = 0; retries < maxretries; retries++) {
if (!res)
res = ast_streamfile(chan, "privacy-prompt", chan->language);
@@ -124,7 +182,7 @@ static int privacy_exec (struct ast_channel *chan, void *data)
if (res < 0)
break;
/* Make sure we get at least digits */
/*Make sure we get at least digits*/
if (strlen(phone) >= minlength )
break;
else {
@@ -134,7 +192,7 @@ static int privacy_exec (struct ast_channel *chan, void *data)
}
}
/* Got a number, play sounds and send them on their way */
/*Got a number, play sounds and send them on their way*/
if ((retries < maxretries) && res >= 0 ) {
res = ast_streamfile(chan, "privacy-thankyou", chan->language);
if (!res)
@@ -147,25 +205,58 @@ static int privacy_exec (struct ast_channel *chan, void *data)
*/
chan->cid.cid_pres &= (AST_PRES_UNAVAILABLE ^ 0xFF);
ast_verb(3, "Changed Caller*ID to %s, callerpres to %d\n",phone,chan->cid.cid_pres);
if (option_verbose > 2) {
ast_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s, callerpres to %d\n",phone,chan->cid.cid_pres);
}
pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS");
} else {
if (priority_jump || option_priority_jumping)
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "FAILED");
}
if (cfg)
ast_config_destroy(cfg);
}
return 0;
LOCAL_USER_REMOVE (u);
return 0;
}
static int unload_module(void)
int
unload_module (void)
{
return ast_unregister_application (app);
int res;
res = ast_unregister_application (app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int
load_module (void)
{
return ast_register_application(app, privacy_exec, synopsis, descrip);
return ast_register_application (app, privacy_exec, synopsis,
descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Require phone number to be entered, if no CallerID sent");
char *
description (void)
{
return tdesc;
}
int
usecount (void)
{
int res;
STANDARD_USECOUNT (res);
return res;
}
char *
key ()
{
return ASTERISK_GPL_KEY;
}

File diff suppressed because it is too large Load Diff

126
apps/app_random.c Normal file
View File

@@ -0,0 +1,126 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (c) 2003 - 2005 Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <asterisk__app_random__200508@the-tilghman.com>
*
* This code is released by the author with no restrictions on usage or distribution.
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
*/
/*! \file
*
* \brief Random application
*
* \author Tilghman Lesher <asterisk__app_random__200508@the-tilghman.com>
* \ingroup applications
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
static char *tdesc = "Random goto";
static char *app_random = "Random";
static char *random_synopsis = "Conditionally branches, based upon a probability";
static char *random_descrip =
"Random([probability]:[[context|]extension|]priority)\n"
" probability := INTEGER in the range 1 to 100\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static char random_state[256];
static int random_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *s;
char *prob;
int probint;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Random requires an argument ([probability]:[[context|]extension|]priority)\n");
return -1;
}
LOCAL_USER_ADD(u);
s = ast_strdupa(data);
if (!s) {
ast_log(LOG_ERROR, "Out of memory!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
prob = strsep(&s,":");
if ((!prob) || (sscanf(prob, "%d", &probint) != 1))
probint = 0;
if ((random() % 100) + probint >= 100) {
res = ast_parseable_goto(chan, s);
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "Random branches to (%s,%s,%d)\n",
chan->context,chan->exten, chan->priority+1);
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
int res;
res = ast_unregister_application(app_random);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
initstate((getppid() * 65535 + getpid()) % RAND_MAX, random_state, 256);
return ast_register_application(app_random, random_exec, random_synopsis, random_descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
/* Don't allow unload, since rand(3) depends upon this module being here. */
return 1;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,213 +19,217 @@
/*! \file
*
* \brief Trivial application to read a variable
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/pbx.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/translate.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
enum {
OPT_SKIP = (1 << 0),
OPT_INDICATION = (1 << 1),
OPT_NOANSWER = (1 << 2),
} read_option_flags;
AST_APP_OPTIONS(read_app_options, {
AST_APP_OPTION('s', OPT_SKIP),
AST_APP_OPTION('i', OPT_INDICATION),
AST_APP_OPTION('n', OPT_NOANSWER),
});
static char *tdesc = "Read Variable Application";
static char *app = "Read";
static char *synopsis = "Read a variable";
static char *descrip =
" Read(variable[,filename[&filename2...]][,maxdigits][,option][,attempts][,timeout])\n\n"
" Read(variable[|filename][|maxdigits][|option][|attempts][|timeout])\n\n"
"Reads a #-terminated string of digits a certain number of times from the\n"
"user in to the given variable.\n"
" filename -- file(s) to play before reading digits or tone with option i\n"
" filename -- file to play before reading digits.\n"
" maxdigits -- maximum acceptable number of digits. Stops reading after\n"
" maxdigits have been entered (without requiring the user to\n"
" press the '#' key).\n"
" Defaults to 0 - no limit - wait for the user press the '#' key.\n"
" Any value below 0 means the same. Max accepted value is 255.\n"
" option -- options are 's' , 'i', 'n'\n"
" 's' to return immediately if the line is not up,\n"
" 'i' to play filename as an indication tone from your indications.conf\n"
" 'n' to read digits even if the line is not up.\n"
" option -- may be 'skip' to return immediately if the line is not up,\n"
" or 'noanswer' to read digits even if the line is not up.\n"
" attempts -- if greater than 1, that many attempts will be made in the \n"
" event no data is entered.\n"
" timeout -- The number of seconds to wait for a digit response. If greater\n"
" than 0, that value will override the default timeout. Can be floating point.\n"
"This application sets the following channel variable upon completion:\n"
" READSTATUS - This is the status of the read operation.\n"
" Possible values are:\n"
" OK | ERROR | HANGUP | INTERRUPTED | SKIPPED | TIMEOUT\n";
" timeout -- if greater than 0, that value will override the default timeout.\n\n"
"Read should disconnect if the function fails or errors out.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
#define ast_next_data(instr,ptr,delim) if((ptr=strchr(instr,delim))) { *(ptr) = '\0' ; ptr++;}
static int read_exec(struct ast_channel *chan, void *data)
{
int res = 0;
char tmp[256] = "";
int maxdigits = 255;
int tries = 1, to = 0, x = 0;
double tosec;
struct localuser *u;
char tmp[256];
char *timeout = NULL;
char *varname = NULL;
char *filename = NULL;
char *loops;
char *maxdigitstr=NULL;
char *options=NULL;
int option_skip = 0;
int option_noanswer = 0;
int maxdigits=255;
int tries = 1;
int to = 0;
int x = 0;
char *argcopy = NULL;
struct tone_zone_sound *ts = NULL;
struct ast_flags flags = {0};
const char *status = "ERROR";
char *args[8];
AST_DECLARE_APP_ARGS(arglist,
AST_APP_ARG(variable);
AST_APP_ARG(filename);
AST_APP_ARG(maxdigits);
AST_APP_ARG(options);
AST_APP_ARG(attempts);
AST_APP_ARG(timeout);
);
pbx_builtin_setvar_helper(chan, "READSTATUS", status);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "Read requires an argument (variable)\n");
return 0;
return -1;
}
LOCAL_USER_ADD(u);
argcopy = ast_strdupa(data);
AST_STANDARD_APP_ARGS(arglist, argcopy);
if (!ast_strlen_zero(arglist.options)) {
ast_app_parse_options(read_app_options, &flags, NULL, arglist.options);
if (!argcopy) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
if (ast_app_separate_args(argcopy, '|', args, sizeof(args) / sizeof(args[0])) < 1) {
ast_log(LOG_WARNING, "Cannot Parse Arguments.\n");
LOCAL_USER_REMOVE(u);
return -1;
}
varname = args[x++];
filename = args[x++];
maxdigitstr = args[x++];
options = args[x++];
loops = args[x++];
timeout = args[x++];
if (!ast_strlen_zero(arglist.attempts)) {
tries = atoi(arglist.attempts);
if (tries <= 0)
if (options) {
if (!strcasecmp(options, "skip"))
option_skip = 1;
else if (!strcasecmp(options, "noanswer"))
option_noanswer = 1;
else {
if (strchr(options, 's'))
option_skip = 1;
if (strchr(options, 'n'))
option_noanswer = 1;
}
}
if(loops) {
tries = atoi(loops);
if(tries <= 0)
tries = 1;
}
if (!ast_strlen_zero(arglist.timeout)) {
tosec = atof(arglist.timeout);
if (tosec <= 0)
if(timeout) {
to = atoi(timeout);
if (to <= 0)
to = 0;
else
to = tosec * 1000.0;
to *= 1000;
}
if (ast_strlen_zero(arglist.filename)) {
arglist.filename = NULL;
if (ast_strlen_zero(filename))
filename = NULL;
if (maxdigitstr) {
maxdigits = atoi(maxdigitstr);
if ((maxdigits<1) || (maxdigits>255)) {
maxdigits = 255;
} else if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Accepting a maximum of %d digits.\n", maxdigits);
}
if (!ast_strlen_zero(arglist.maxdigits)) {
maxdigits = atoi(arglist.maxdigits);
if ((maxdigits < 1) || (maxdigits > 255)) {
maxdigits = 255;
} else
ast_verb(3, "Accepting a maximum of %d digits.\n", maxdigits);
}
if (ast_strlen_zero(arglist.variable)) {
ast_log(LOG_WARNING, "Invalid! Usage: Read(variable[,filename][,maxdigits][,option][,attempts][,timeout])\n\n");
return 0;
}
if (ast_test_flag(&flags, OPT_INDICATION)) {
if (! ast_strlen_zero(arglist.filename)) {
ts = ast_get_indication_tone(chan->zone, arglist.filename);
}
if (ast_strlen_zero(varname)) {
ast_log(LOG_WARNING, "Invalid! Usage: Read(variable[|filename][|maxdigits][|option][|attempts][|timeout])\n\n");
LOCAL_USER_REMOVE(u);
return -1;
}
if (chan->_state != AST_STATE_UP) {
if (ast_test_flag(&flags, OPT_SKIP)) {
if (option_skip) {
/* At the user's option, skip if the line is not up */
pbx_builtin_setvar_helper(chan, arglist.variable, "");
pbx_builtin_setvar_helper(chan, "READSTATUS", "SKIPPED");
pbx_builtin_setvar_helper(chan, varname, "\0");
LOCAL_USER_REMOVE(u);
return 0;
} else if (!ast_test_flag(&flags, OPT_NOANSWER)) {
} else if (!option_noanswer) {
/* Otherwise answer unless we're supposed to read while on-hook */
res = ast_answer(chan);
}
}
if (!res) {
while (tries && !res) {
while(tries && !res) {
ast_stopstream(chan);
if (ts && ts->data[0]) {
if (!to)
to = chan->pbx ? chan->pbx->rtimeout * 1000 : 6000;
res = ast_playtones_start(chan, 0, ts->data, 0);
for (x = 0; x < maxdigits; ) {
res = ast_waitfordigit(chan, to);
ast_playtones_stop(chan);
if (res < 1) {
if (res == 0)
status = "TIMEOUT";
tmp[x]='\0';
break;
}
tmp[x++] = res;
if (tmp[x-1] == '#') {
tmp[x-1] = '\0';
status = "OK";
break;
}
if (x >= maxdigits) {
status = "OK";
}
}
} else {
res = ast_app_getdata(chan, arglist.filename, tmp, maxdigits, to);
if (res == AST_GETDATA_COMPLETE || res == AST_GETDATA_EMPTY_END_TERMINATED)
status = "OK";
else if (res == AST_GETDATA_TIMEOUT)
status = "TIMEOUT";
else if (res == AST_GETDATA_INTERRUPTED)
status = "INTERRUPTED";
}
res = ast_app_getdata(chan, filename, tmp, maxdigits, to);
if (res > -1) {
pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
pbx_builtin_setvar_helper(chan, varname, tmp);
if (!ast_strlen_zero(tmp)) {
ast_verb(3, "User entered '%s'\n", tmp);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "User entered '%s'\n", tmp);
tries = 0;
} else {
tries--;
if (tries)
ast_verb(3, "User entered nothing, %d chance%s left\n", tries, (tries != 1) ? "s" : "");
else
ast_verb(3, "User entered nothing.\n");
if (option_verbose > 2) {
if (tries)
ast_verbose(VERBOSE_PREFIX_3 "User entered nothing, %d chance%s left\n", tries, (tries != 1) ? "s" : "");
else
ast_verbose(VERBOSE_PREFIX_3 "User entered nothing.\n");
}
}
res = 0;
} else {
pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
ast_verb(3, "User disconnected\n");
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "User disconnected\n");
}
}
}
if (ast_check_hangup(chan))
status = "HANGUP";
pbx_builtin_setvar_helper(chan, "READSTATUS", status);
return 0;
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app);
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, read_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Read Variable Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -1,258 +0,0 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2007 Dave Chappell
*
* David Chappell <David.Chappell@trincoll.edu>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Trivial application to read an extension into a variable
*
* \author David Chappell <David.Chappell@trincoll.edu>
*
* \ingroup applications
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"
#include "asterisk/module.h"
#include "asterisk/indications.h"
#include "asterisk/channel.h"
enum {
OPT_SKIP = (1 << 0),
OPT_INDICATION = (1 << 1),
OPT_NOANSWER = (1 << 2),
} readexten_option_flags;
AST_APP_OPTIONS(readexten_app_options, {
AST_APP_OPTION('s', OPT_SKIP),
AST_APP_OPTION('i', OPT_INDICATION),
AST_APP_OPTION('n', OPT_NOANSWER),
});
static char *app = "ReadExten";
static char *synopsis = "Read an extension into a variable";
static char *descrip =
" ReadExten(<variable>[,[<filename>][,[<context>][,[<option>][,<timeout>]]]])\n\n"
"Reads a #-terminated string of digits from the user into the given variable.\n"
" filename file to play before reading digits or tone with option i\n"
" context context in which to match extensions\n"
" option options are:\n"
" s - Return immediately if the channel is not answered,\n"
" i - Play filename as an indication tone from your\n"
" indications.conf\n"
" n - Read digits even if the channel is not answered.\n"
" timeout An integer number of seconds to wait for a digit response. If\n"
" greater than 0, that value will override the default timeout.\n\n"
"ReadExten will set READEXTENSTATUS on exit with one of the following statuses:\n"
" OK A valid extension exists in ${variable}\n"
" TIMEOUT No extension was entered in the specified time\n"
" INVALID An invalid extension, ${INVALID_EXTEN}, was entered\n"
" SKIP Line was not up and the option 's' was specified\n"
" ERROR Invalid arguments were passed\n";
static int readexten_exec(struct ast_channel *chan, void *data)
{
int res = 0;
char exten[256] = "";
int maxdigits = sizeof(exten) - 1;
int timeout = 0, digit_timeout = 0, x = 0;
char *argcopy = NULL, *status = "";
struct tone_zone_sound *ts = NULL;
struct ast_flags flags = {0};
AST_DECLARE_APP_ARGS(arglist,
AST_APP_ARG(variable);
AST_APP_ARG(filename);
AST_APP_ARG(context);
AST_APP_ARG(options);
AST_APP_ARG(timeout);
);
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "ReadExten requires at least one argument\n");
pbx_builtin_setvar_helper(chan, "READEXTENSTATUS", "ERROR");
return 0;
}
argcopy = ast_strdupa(data);
AST_STANDARD_APP_ARGS(arglist, argcopy);
if (ast_strlen_zero(arglist.variable)) {
ast_log(LOG_WARNING, "Invalid! Usage: ReadExten(variable[|filename][|context][|options][|timeout])\n\n");
pbx_builtin_setvar_helper(chan, "READEXTENSTATUS", "ERROR");
return 0;
}
if (ast_strlen_zero(arglist.filename))
arglist.filename = NULL;
if (ast_strlen_zero(arglist.context))
arglist.context = chan->context;
if (!ast_strlen_zero(arglist.options))
ast_app_parse_options(readexten_app_options, &flags, NULL, arglist.options);
if (!ast_strlen_zero(arglist.timeout)) {
timeout = atoi(arglist.timeout);
if (timeout > 0)
timeout *= 1000;
}
if (timeout <= 0)
timeout = chan->pbx ? chan->pbx->rtimeout * 1000 : 10000;
if (digit_timeout <= 0)
digit_timeout = chan->pbx ? chan->pbx->dtimeout * 1000 : 5000;
if (ast_test_flag(&flags, OPT_INDICATION) && !ast_strlen_zero(arglist.filename))
ts = ast_get_indication_tone(chan->zone, arglist.filename);
do {
if (chan->_state != AST_STATE_UP) {
if (ast_test_flag(&flags, OPT_SKIP)) {
/* At the user's option, skip if the line is not up */
pbx_builtin_setvar_helper(chan, arglist.variable, "");
status = "SKIP";
break;
} else if (!ast_test_flag(&flags, OPT_NOANSWER)) {
/* Otherwise answer unless we're supposed to read while on-hook */
res = ast_answer(chan);
}
}
if (res < 0) {
status = "HANGUP";
break;
}
ast_playtones_stop(chan);
ast_stopstream(chan);
if (ts && ts->data[0])
res = ast_playtones_start(chan, 0, ts->data, 0);
else if (arglist.filename)
res = ast_streamfile(chan, arglist.filename, chan->language);
for (x = 0; x < maxdigits; x++) {
ast_debug(3, "extension so far: '%s', timeout: %d\n", exten, timeout);
res = ast_waitfordigit(chan, timeout);
ast_playtones_stop(chan);
ast_stopstream(chan);
timeout = digit_timeout;
if (res < 1) { /* timeout expired or hangup */
if (ast_check_hangup(chan))
status = "HANGUP";
else
status = "TIMEOUT";
break;
} else if (res == '#') {
break;
}
exten[x] = res;
if (!ast_matchmore_extension(chan, arglist.context, exten, 1 /* priority */, chan->cid.cid_num)) {
break;
}
}
if (!ast_strlen_zero(status))
break;
if (ast_exists_extension(chan, arglist.context, exten, 1, chan->cid.cid_num)) {
ast_debug(3, "User entered valid extension '%s'\n", exten);
pbx_builtin_setvar_helper(chan, arglist.variable, exten);
status = "OK";
} else {
ast_debug(3, "User dialed invalid extension '%s' in context '%s' on %s\n", exten, arglist.context, chan->name);
pbx_builtin_setvar_helper(chan, "INVALID_EXTEN", exten);
status = "INVALID";
}
} while (0);
pbx_builtin_setvar_helper(chan, "READEXTENSTATUS", status);
return status[0] == 'H' ? -1 : 0;
}
static int acf_isexten_exec(struct ast_channel *chan, const char *cmd, char *parse, char *buffer, size_t buflen)
{
int priority_int;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(context);
AST_APP_ARG(extension);
AST_APP_ARG(priority);
);
AST_STANDARD_APP_ARGS(args, parse);
if (ast_strlen_zero(args.context))
args.context = chan->context;
if (ast_strlen_zero(args.extension)) {
ast_log(LOG_WARNING, "Syntax: VALID_EXTEN([<context>],<extension>[,<priority>]) - missing argument <extension>!\n");
return -1;
}
if (ast_strlen_zero(args.priority))
priority_int = 1;
else
priority_int = atoi(args.priority);
if (ast_exists_extension(chan, args.context, args.extension, priority_int, chan->cid.cid_num))
ast_copy_string(buffer, "1", buflen);
else
ast_copy_string(buffer, "0", buflen);
return 0;
}
static struct ast_custom_function acf_isexten = {
.name = "VALID_EXTEN",
.synopsis = "Determine whether an extension exists or not",
.syntax = "VALID_EXTEN([<context>],<extension>[,<priority>])",
.desc =
"Returns a true value if the indicated context, extension, and priority exist.\n"
"Context defaults to the current context, priority defaults to 1.\n",
.read = acf_isexten_exec,
};
static int unload_module(void)
{
int res = ast_unregister_application(app);
res |= ast_custom_function_unregister(&acf_isexten);
return res;
}
static int load_module(void)
{
int res = ast_register_application(app, readexten_exec, synopsis, descrip);
res |= ast_custom_function_register(&acf_isexten);
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Read and evaluate extension validity");

View File

@@ -20,60 +20,76 @@
*
* \brief ReadFile application -- Reads in a File for you.
*
* \author Matt O'Gorman <mogorman@digium.com>
*
* \ingroup applications
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"
#include "asterisk/module.h"
static char *tdesc = "Stores output of file into a variable";
static char *app_readfile = "ReadFile";
static char *readfile_synopsis = "Read the contents of a text file into a channel variable";
static char *readfile_synopsis = "ReadFile(varname=file,length)";
static char *readfile_descrip =
"ReadFile(varname=file,length)\n"
" varname - Result stored here.\n"
" file - The name of the file to read.\n"
" length - Maximum number of characters to capture.\n";
" Varname - Result stored here.\n"
" File - The name of the file to read.\n"
" Length - Maximum number of characters to capture.\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int readfile_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
char *s, *varname=NULL, *file=NULL, *length=NULL, *returnvar=NULL;
int len=0;
static int deprecation_warning = 0;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "ReadFile require an argument!\n");
return -1;
}
LOCAL_USER_ADD(u);
s = ast_strdupa(data);
if (!s) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
varname = strsep(&s, "=");
file = strsep(&s, ",");
file = strsep(&s, "|");
length = s;
if (deprecation_warning++ % 10 == 0)
ast_log(LOG_WARNING, "ReadFile has been deprecated in favor of Set(%s=${FILE(%s,0,%s)})\n", varname, file, length);
if (!varname || !file) {
ast_log(LOG_ERROR, "No file or variable specified!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
if (length) {
if ((sscanf(length, "%30d", &len) != 1) || (len < 0)) {
if ((sscanf(length, "%d", &len) != 1) || (len < 0)) {
ast_log(LOG_WARNING, "%s is not a positive number, defaulting length to max\n", length);
len = 0;
}
@@ -87,21 +103,42 @@ static int readfile_exec(struct ast_channel *chan, void *data)
ast_log(LOG_WARNING, "%s is longer than %d, and %d \n", file, len, (int)strlen(returnvar));
}
pbx_builtin_setvar_helper(chan, varname, returnvar);
ast_free(returnvar);
free(returnvar);
}
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app_readfile);
int res;
res = ast_unregister_application(app_readfile);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app_readfile, readfile_exec, readfile_synopsis, readfile_descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Stores output of file into a variable");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

262
apps/app_realtime.c Normal file
View File

@@ -0,0 +1,262 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 1999 - 2005, Digium, Inc.
*
* Anthony Minessale <anthmct@yahoo.com>
* Mark Spencer <markster@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief RealTime App
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/options.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/cli.h"
#define next_one(var) var = var->next
#define crop_data(str) { *(str) = '\0' ; (str)++; }
static char *tdesc = "Realtime Data Lookup/Rewrite";
static char *app = "RealTime";
static char *uapp = "RealTimeUpdate";
static char *synopsis = "Realtime Data Lookup";
static char *usynopsis = "Realtime Data Rewrite";
static char *USAGE = "RealTime(<family>|<colmatch>|<value>[|<prefix>])";
static char *UUSAGE = "RealTimeUpdate(<family>|<colmatch>|<value>|<newcol>|<newval>)";
static char *desc = "Use the RealTime config handler system to read data into channel variables.\n"
"RealTime(<family>|<colmatch>|<value>[|<prefix>])\n\n"
"All unique column names will be set as channel variables with optional prefix to the name.\n"
"e.g. prefix of 'var_' would make the column 'name' become the variable ${var_name}\n\n";
static char *udesc = "Use the RealTime config handler system to update a value\n"
"RealTimeUpdate(<family>|<colmatch>|<value>|<newcol>|<newval>)\n\n"
"The column <newcol> in 'family' matching column <colmatch>=<value> will be updated to <newval>\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int cli_load_realtime(int fd, int argc, char **argv)
{
char *header_format = "%30s %-30s\n";
struct ast_variable *var=NULL;
if(argc<5) {
ast_cli(fd, "You must supply a family name, a column to match on, and a value to match to.\n");
return RESULT_FAILURE;
}
var = ast_load_realtime(argv[2], argv[3], argv[4], NULL);
if(var) {
ast_cli(fd, header_format, "Column Name", "Column Value");
ast_cli(fd, header_format, "--------------------", "--------------------");
while(var) {
ast_cli(fd, header_format, var->name, var->value);
var = var->next;
}
} else {
ast_cli(fd, "No rows found matching search criteria.\n");
}
return RESULT_SUCCESS;
}
static int cli_update_realtime(int fd, int argc, char **argv) {
int res = 0;
if(argc<7) {
ast_cli(fd, "You must supply a family name, a column to update on, a new value, column to match, and value to to match.\n");
ast_cli(fd, "Ex: realtime update sipfriends name bobsphone port 4343\n will execute SQL as UPDATE sipfriends SET port = 4343 WHERE name = bobsphone\n");
return RESULT_FAILURE;
}
res = ast_update_realtime(argv[2], argv[3], argv[4], argv[5], argv[6], NULL);
if(res < 0) {
ast_cli(fd, "Failed to update. Check the debug log for possible SQL related entries.\n");
return RESULT_SUCCESS;
}
ast_cli(fd, "Updated %d RealTime record%s.\n", res, (res != 1) ? "s" : "");
return RESULT_SUCCESS;
}
static char cli_load_realtime_usage[] =
"Usage: realtime load <family> <colmatch> <value>\n"
" Prints out a list of variables using the RealTime driver.\n";
static struct ast_cli_entry cli_load_realtime_cmd = {
{ "realtime", "load", NULL, NULL }, cli_load_realtime,
"Used to print out RealTime variables.", cli_load_realtime_usage, NULL };
static char cli_update_realtime_usage[] =
"Usage: realtime update <family> <colmatch> <value>\n"
" Update a single variable using the RealTime driver.\n";
static struct ast_cli_entry cli_update_realtime_cmd = {
{ "realtime", "update", NULL, NULL }, cli_update_realtime,
"Used to update RealTime variables.", cli_update_realtime_usage, NULL };
static int realtime_update_exec(struct ast_channel *chan, void *data)
{
char *family=NULL, *colmatch=NULL, *value=NULL, *newcol=NULL, *newval=NULL;
struct localuser *u;
int res = 0;
if (ast_strlen_zero(data)) {
ast_log(LOG_ERROR,"Invalid input: usage %s\n",UUSAGE);
return -1;
}
LOCAL_USER_ADD(u);
if ((family = ast_strdupa(data))) {
if ((colmatch = strchr(family,'|'))) {
crop_data(colmatch);
if ((value = strchr(colmatch,'|'))) {
crop_data(value);
if ((newcol = strchr(value,'|'))) {
crop_data(newcol);
if ((newval = strchr(newcol,'|')))
crop_data(newval);
}
}
}
}
if (! (family && value && colmatch && newcol && newval) ) {
ast_log(LOG_ERROR,"Invalid input: usage %s\n",UUSAGE);
res = -1;
} else {
ast_update_realtime(family,colmatch,value,newcol,newval,NULL);
}
LOCAL_USER_REMOVE(u);
return res;
}
static int realtime_exec(struct ast_channel *chan, void *data)
{
int res=0;
struct localuser *u;
struct ast_variable *var, *itt;
char *family=NULL, *colmatch=NULL, *value=NULL, *prefix=NULL, *vname=NULL;
size_t len;
if (ast_strlen_zero(data)) {
ast_log(LOG_ERROR,"Invalid input: usage %s\n",USAGE);
return -1;
}
LOCAL_USER_ADD(u);
if ((family = ast_strdupa(data))) {
if ((colmatch = strchr(family,'|'))) {
crop_data(colmatch);
if ((value = strchr(colmatch,'|'))) {
crop_data(value);
if ((prefix = strchr(value,'|')))
crop_data(prefix);
}
}
}
if (! (family && value && colmatch) ) {
ast_log(LOG_ERROR,"Invalid input: usage %s\n",USAGE);
res = -1;
} else {
if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4"Realtime Lookup: family:'%s' colmatch:'%s' value:'%s'\n",family,colmatch,value);
if ((var = ast_load_realtime(family, colmatch, value, NULL))) {
for (itt = var; itt; itt = itt->next) {
if(prefix) {
len = strlen(prefix) + strlen(itt->name) + 2;
vname = alloca(len);
snprintf(vname,len,"%s%s",prefix,itt->name);
} else
vname = itt->name;
pbx_builtin_setvar_helper(chan, vname, itt->value);
}
ast_variables_destroy(var);
} else if (option_verbose > 3)
ast_verbose(VERBOSE_PREFIX_4"No Realtime Matches Found.\n");
}
LOCAL_USER_REMOVE(u);
return res;
}
int unload_module(void)
{
int res;
res = ast_cli_unregister(&cli_load_realtime_cmd);
res |= ast_cli_unregister(&cli_update_realtime_cmd);
res |= ast_unregister_application(uapp);
res |= ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
int load_module(void)
{
int res;
res = ast_cli_register(&cli_load_realtime_cmd);
res |= ast_cli_register(&cli_update_realtime_cmd);
res |= ast_register_application(uapp, realtime_update_exec, usynopsis, udesc);
res |= ast_register_application(app, realtime_exec, synopsis, desc);
return res;
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -20,28 +20,37 @@
*
* \brief Trivial application to record a sound file
*
* \author Matthew Fredrickson <creslin@digium.com>
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/dsp.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"
#include "asterisk/app.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h" /* use dsp routines for silence detection */
static char *tdesc = "Trivial Record Application";
static char *app = "Record";
static char *synopsis = "Record to a file";
static char *descrip =
" Record(filename.format,silence[,maxduration][,options])\n\n"
" Record(filename.format|silence[|maxduration][|options])\n\n"
"Records from the channel into a given filename. If the file exists it will\n"
"be overwritten.\n"
"- 'format' is the format of the file type to be recorded (wav, gsm, etc).\n"
@@ -50,52 +59,35 @@ static char *descrip =
"or 0 there is no maximum.\n"
"- 'options' may contain any of the following letters:\n"
" 'a' : append to existing recording rather than replacing\n"
" 'k' : keep recorded file upon hangup\n"
" 'n' : do not answer, but record anyway if line not yet answered\n"
" 'q' : quiet (do not play a beep tone)\n"
" 's' : skip recording if the line is not yet answered\n"
" 't' : use alternate '*' terminator key (DTMF) instead of default '#'\n"
" 'x' : ignore all terminator keys (DTMF) and keep recording until hangup\n"
" 't' : use alternate '*' terminator key instead of default '#'\n"
"\n"
"If filename contains '%d', these characters will be replaced with a number\n"
"incremented by one each time the file is recorded. A channel variable\n"
"named RECORDED_FILE will also be set, which contains the final filemname.\n\n"
"Use 'core show file formats' to see the available formats on your system\n\n"
"Use 'show file formats' to see the available formats on your system\n\n"
"User can press '#' to terminate the recording and continue to the next priority.\n\n"
"If the user should hangup during a recording, all data will be lost and the\n"
"application will teminate. \n";
enum {
OPTION_APPEND = (1 << 0),
OPTION_NOANSWER = (1 << 1),
OPTION_QUIET = (1 << 2),
OPTION_SKIP = (1 << 3),
OPTION_STAR_TERMINATE = (1 << 4),
OPTION_IGNORE_TERMINATE = (1 << 5),
OPTION_KEEP = (1 << 6),
FLAG_HAS_PERCENT = (1 << 7),
};
STANDARD_LOCAL_USER;
AST_APP_OPTIONS(app_opts,{
AST_APP_OPTION('a', OPTION_APPEND),
AST_APP_OPTION('k', OPTION_KEEP),
AST_APP_OPTION('n', OPTION_NOANSWER),
AST_APP_OPTION('q', OPTION_QUIET),
AST_APP_OPTION('s', OPTION_SKIP),
AST_APP_OPTION('t', OPTION_STAR_TERMINATE),
AST_APP_OPTION('x', OPTION_IGNORE_TERMINATE),
});
LOCAL_USER_DECL;
static int record_exec(struct ast_channel *chan, void *data)
{
int res = 0;
int count = 0;
char *ext = NULL, *opts[0];
char *parse, *dir, *file;
int percentflag = 0;
char *filename, *ext = NULL, *silstr, *maxstr, *options;
char *vdata, *p;
int i = 0;
char tmp[256];
struct ast_filestream *s = NULL;
struct ast_filestream *s = '\0';
struct localuser *u;
struct ast_frame *f = NULL;
struct ast_dsp *sildet = NULL; /* silence detector dsp */
@@ -105,18 +97,15 @@ static int record_exec(struct ast_channel *chan, void *data)
int gotsilence = 0; /* did we timeout for silence? */
int maxduration = 0; /* max duration of recording in milliseconds */
int gottimeout = 0; /* did we timeout for maxduration exceeded? */
int option_skip = 0;
int option_noanswer = 0;
int option_append = 0;
int terminator = '#';
int option_quiet = 0;
int rfmt = 0;
int ioflags;
int flags;
int waitres;
struct ast_silence_generator *silgen = NULL;
struct ast_flags flags = { 0, };
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(filename);
AST_APP_ARG(silence);
AST_APP_ARG(maxduration);
AST_APP_ARG(options);
);
/* The next few lines of code parse out the filename and header from the input string */
if (ast_strlen_zero(data)) { /* no data implies no filename or anything is present */
@@ -124,17 +113,28 @@ static int record_exec(struct ast_channel *chan, void *data)
return -1;
}
parse = ast_strdupa(data);
AST_STANDARD_APP_ARGS(args, parse);
if (args.argc == 4)
ast_app_parse_options(app_opts, &flags, opts, args.options);
LOCAL_USER_ADD(u);
if (!ast_strlen_zero(args.filename)) {
if (strstr(args.filename, "%d"))
ast_set_flag(&flags, FLAG_HAS_PERCENT);
ext = strrchr(args.filename, '.'); /* to support filename with a . in the filename, not format */
/* Yay for strsep being easy */
vdata = ast_strdupa(data);
if (!vdata) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
p = vdata;
filename = strsep(&p, "|");
silstr = strsep(&p, "|");
maxstr = strsep(&p, "|");
options = strsep(&p, "|");
if (filename) {
if (strstr(filename, "%d"))
percentflag = 1;
ext = strrchr(filename, '.'); /* to support filename with a . in the filename, not format */
if (!ext)
ext = strchr(args.filename, ':');
ext = strchr(filename, ':');
if (ext) {
*ext = '\0';
ext++;
@@ -142,43 +142,59 @@ static int record_exec(struct ast_channel *chan, void *data)
}
if (!ext) {
ast_log(LOG_WARNING, "No extension specified to filename!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
if (args.silence) {
if ((sscanf(args.silence, "%30d", &i) == 1) && (i > -1)) {
if (silstr) {
if ((sscanf(silstr, "%d", &i) == 1) && (i > -1)) {
silence = i * 1000;
} else if (!ast_strlen_zero(args.silence)) {
ast_log(LOG_WARNING, "'%s' is not a valid silence duration\n", args.silence);
} else if (!ast_strlen_zero(silstr)) {
ast_log(LOG_WARNING, "'%s' is not a valid silence duration\n", silstr);
}
}
if (args.maxduration) {
if ((sscanf(args.maxduration, "%30d", &i) == 1) && (i > -1))
if (maxstr) {
if ((sscanf(maxstr, "%d", &i) == 1) && (i > -1))
/* Convert duration to milliseconds */
maxduration = i * 1000;
else if (!ast_strlen_zero(args.maxduration))
ast_log(LOG_WARNING, "'%s' is not a valid maximum duration\n", args.maxduration);
else if (!ast_strlen_zero(maxstr))
ast_log(LOG_WARNING, "'%s' is not a valid maximum duration\n", maxstr);
}
if (ast_test_flag(&flags, OPTION_STAR_TERMINATE))
terminator = '*';
if (ast_test_flag(&flags, OPTION_IGNORE_TERMINATE))
terminator = '\0';
if (options) {
/* Retain backwards compatibility with old style options */
if (!strcasecmp(options, "skip"))
option_skip = 1;
else if (!strcasecmp(options, "noanswer"))
option_noanswer = 1;
else {
if (strchr(options, 's'))
option_skip = 1;
if (strchr(options, 'n'))
option_noanswer = 1;
if (strchr(options, 'a'))
option_append = 1;
if (strchr(options, 't'))
terminator = '*';
if (strchr(options, 'q'))
option_quiet = 1;
}
}
/* done parsing */
/* these are to allow the use of the %d in the config file for a wild card of sort to
create a new file with the inputed name scheme */
if (ast_test_flag(&flags, FLAG_HAS_PERCENT)) {
if (percentflag) {
AST_DECLARE_APP_ARGS(fname,
AST_APP_ARG(piece)[100];
);
char *tmp2 = ast_strdupa(args.filename);
char *tmp2 = ast_strdupa(filename);
char countstring[15];
int i;
/* Separate each piece out by the format specifier */
AST_NONSTANDARD_APP_ARGS(fname, tmp2, '%');
/* AST_NONSTANDARD_APP_ARGS(fname, tmp2, '%'); */
fname.argc = ast_app_separate_args(tmp2, '%', fname.argv, (sizeof(fname) - sizeof(fname.argc)) / sizeof(fname.argv[0]));
do {
int tmplen;
/* First piece has no leading percent, so it's copied verbatim */
@@ -199,28 +215,31 @@ static int record_exec(struct ast_channel *chan, void *data)
ast_copy_string(tmp + tmplen, &(fname.piece[i][1]), sizeof(tmp) - tmplen);
}
count++;
} while (ast_fileexists(tmp, ext, chan->language) > 0);
} while ( ast_fileexists(tmp, ext, chan->language) != -1 );
pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp);
} else
ast_copy_string(tmp, args.filename, sizeof(tmp));
strncpy(tmp, filename, sizeof(tmp)-1);
/* end of routine mentioned */
if (chan->_state != AST_STATE_UP) {
if (ast_test_flag(&flags, OPTION_SKIP)) {
if (option_skip) {
/* At the user's option, skip if the line is not up */
LOCAL_USER_REMOVE(u);
return 0;
} else if (!ast_test_flag(&flags, OPTION_NOANSWER)) {
} else if (!option_noanswer) {
/* Otherwise answer unless we're supposed to record while on-hook */
res = ast_answer(chan);
}
}
if (res) {
ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
goto out;
}
if (!ast_test_flag(&flags, OPTION_QUIET)) {
if (!option_quiet) {
/* Some code to play a nice little beep to signify the start of the record operation */
res = ast_streamfile(chan, "beep", chan->language);
if (!res) {
@@ -230,47 +249,44 @@ static int record_exec(struct ast_channel *chan, void *data)
}
ast_stopstream(chan);
}
/* The end of beep code. Now the recording starts */
if (silence > 0) {
rfmt = chan->readformat;
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
if (res < 0) {
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
LOCAL_USER_REMOVE(u);
return -1;
}
sildet = ast_dsp_new();
if (!sildet) {
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
LOCAL_USER_REMOVE(u);
return -1;
}
ast_dsp_set_threshold(sildet, 256);
}
/* Create the directory if it does not exist. */
dir = ast_strdupa(tmp);
if ((file = strrchr(dir, '/')))
*file++ = '\0';
ast_mkdir (dir, 0777);
ioflags = ast_test_flag(&flags, OPTION_APPEND) ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY;
s = ast_writefile(tmp, ext, NULL, ioflags, 0, AST_FILE_MODE);
flags = option_append ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY;
s = ast_writefile( tmp, ext, NULL, flags , 0, 0644);
if (!s) {
ast_log(LOG_WARNING, "Could not create file %s\n", args.filename);
ast_log(LOG_WARNING, "Could not create file %s\n", filename);
goto out;
}
if (ast_opt_transmit_silence)
if (option_transmit_silence_during_record)
silgen = ast_channel_start_silence_generator(chan);
/* Request a video update */
ast_indicate(chan, AST_CONTROL_VIDUPDATE);
if (maxduration <= 0)
maxduration = -1;
while ((waitres = ast_waitfor(chan, maxduration)) > -1) {
if (maxduration > 0) {
if (waitres == 0) {
@@ -279,7 +295,7 @@ static int record_exec(struct ast_channel *chan, void *data)
}
maxduration = waitres;
}
f = ast_read(chan);
if (!f) {
res = -1;
@@ -287,13 +303,13 @@ static int record_exec(struct ast_channel *chan, void *data)
}
if (f->frametype == AST_FRAME_VOICE) {
res = ast_writestream(s, f);
if (res) {
ast_log(LOG_WARNING, "Problem writing frame\n");
ast_frfree(f);
break;
}
if (silence > 0) {
dspsilence = 0;
ast_dsp_silence(sildet, f, &dspsilence);
@@ -311,7 +327,7 @@ static int record_exec(struct ast_channel *chan, void *data)
}
} else if (f->frametype == AST_FRAME_VIDEO) {
res = ast_writestream(s, f);
if (res) {
ast_log(LOG_WARNING, "Problem writing frame\n");
ast_frfree(f);
@@ -325,15 +341,12 @@ static int record_exec(struct ast_channel *chan, void *data)
ast_frfree(f);
}
if (!f) {
ast_debug(1, "Got hangup\n");
ast_log(LOG_DEBUG, "Got hangup\n");
res = -1;
if (!ast_test_flag(&flags, OPTION_KEEP)) {
ast_filedelete(args.filename, NULL);
}
}
if (gotsilence) {
ast_stream_rewind(s, silence - 1000);
ast_stream_rewind(s, silence-1000);
ast_truncstream(s);
} else if (!gottimeout) {
/* Strip off the last 1/4 second of it */
@@ -344,8 +357,8 @@ static int record_exec(struct ast_channel *chan, void *data)
if (silgen)
ast_channel_stop_silence_generator(chan, silgen);
out:
out:
if ((silence > 0) && rfmt) {
res = ast_set_read_format(chan, rfmt);
if (res)
@@ -354,17 +367,40 @@ out:
ast_dsp_free(sildet);
}
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app);
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, record_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Trivial Record Application");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,7 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (c) 2003, 2006 Tilghman Lesher. All rights reserved.
* Copyright (c) 2006 Digium, Inc.
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
*
* Tilghman Lesher <app_sayunixtime__200309@the-tilghman.com>
*
@@ -19,22 +18,29 @@
/*! \file
*
* \brief SayUnixTime application
*
* \author Tilghman Lesher <app_sayunixtime__200309@the-tilghman.com>
*
* \ingroup applications
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/say.h"
#include "asterisk/app.h"
static char *tdesc = "Say time";
static char *app_sayunixtime = "SayUnixTime";
static char *app_datetime = "DateTime";
@@ -42,64 +48,94 @@ static char *app_datetime = "DateTime";
static char *sayunixtime_synopsis = "Says a specified time in a custom format";
static char *sayunixtime_descrip =
"SayUnixTime([unixtime][,[timezone][,format]])\n"
" unixtime - time, in seconds since Jan 1, 1970. May be negative.\n"
"SayUnixTime([unixtime][|[timezone][|format]])\n"
" unixtime: time, in seconds since Jan 1, 1970. May be negative.\n"
" defaults to now.\n"
" timezone - timezone, see /usr/share/zoneinfo for a list.\n"
" timezone: timezone, see /usr/share/zoneinfo for a list.\n"
" defaults to machine default.\n"
" format - a format the time is to be said in. See voicemail.conf.\n"
" format: a format the time is to be said in. See voicemail.conf.\n"
" defaults to \"ABdY 'digits/at' IMp\"\n";
static char *datetime_descrip =
"DateTime([unixtime][,[timezone][,format]])\n"
" unixtime - time, in seconds since Jan 1, 1970. May be negative.\n"
"DateTime([unixtime][|[timezone][|format]])\n"
" unixtime: time, in seconds since Jan 1, 1970. May be negative.\n"
" defaults to now.\n"
" timezone - timezone, see /usr/share/zoneinfo for a list.\n"
" timezone: timezone, see /usr/share/zoneinfo for a list.\n"
" defaults to machine default.\n"
" format: - a format the time is to be said in. See voicemail.conf.\n"
" format: a format the time is to be said in. See voicemail.conf.\n"
" defaults to \"ABdY 'digits/at' IMp\"\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int sayunixtime_exec(struct ast_channel *chan, void *data)
{
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(timeval);
AST_APP_ARG(timezone);
AST_APP_ARG(format);
);
char *parse;
int res = 0;
int res=0;
struct localuser *u;
char *s,*zone=NULL,*timec,*format;
time_t unixtime;
struct timeval tv;
if (!data)
return 0;
LOCAL_USER_ADD(u);
parse = ast_strdupa(data);
tv = ast_tvnow();
unixtime = (time_t)tv.tv_sec;
AST_STANDARD_APP_ARGS(args, parse);
if( !strcasecmp(chan->language, "da" ) ) {
format = "A dBY HMS";
} else if ( !strcasecmp(chan->language, "de" ) ) {
format = "A dBY HMS";
} else {
format = "ABdY 'digits/at' IMp";
}
ast_get_time_t(args.timeval, &unixtime, time(NULL), NULL);
if (data) {
s = data;
s = ast_strdupa(s);
if (s) {
timec = strsep(&s,"|");
if ((timec) && (*timec != '\0')) {
long timein;
if (sscanf(timec,"%ld",&timein) == 1) {
unixtime = (time_t)timein;
}
}
if (s) {
zone = strsep(&s,"|");
if (zone && (*zone == '\0'))
zone = NULL;
if (s) {
format = s;
}
}
} else {
ast_log(LOG_ERROR, "Out of memory error\n");
}
}
if (chan->_state != AST_STATE_UP)
if (chan->_state != AST_STATE_UP) {
res = ast_answer(chan);
}
if (!res)
res = ast_say_date_with_format(chan, unixtime, AST_DIGIT_ANY,
chan->language, args.format, args.timezone);
res = ast_say_date_with_format(chan, unixtime, AST_DIGIT_ANY, chan->language, format, zone);
LOCAL_USER_REMOVE(u);
return res;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app_sayunixtime);
res |= ast_unregister_application(app_datetime);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
int res;
@@ -109,4 +145,19 @@ static int load_module(void)
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Say time");
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,111 +19,111 @@
/*! \file
*
* \brief App to send DTMF digits
*
* \author Mark Spencer <markster@digium.com>
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/manager.h"
#include "asterisk/channel.h"
static char *tdesc = "Send DTMF digits Application";
static char *app = "SendDTMF";
static char *synopsis = "Sends arbitrary DTMF digits";
static char *descrip =
" SendDTMF(digits[,[timeout_ms][,duration_ms]]): Sends DTMF digits on a channel. \n"
" Accepted digits: 0-9, *#abcd, (default .25s pause between digits)\n"
" SendDTMF(digits[|timeout_ms]): Sends DTMF digits on a channel. \n"
" Accepted digits: 0-9, *#abcd, w (.5s pause)\n"
" The application will either pass the assigned digits or terminate if it\n"
" encounters an error.\n"
" Optional Params: \n"
" timeout_ms: pause between digits.\n"
" duration_ms: duration of each digit.\n";
" encounters an error.\n";
static int senddtmf_exec(struct ast_channel *chan, void *vdata)
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int senddtmf_exec(struct ast_channel *chan, void *data)
{
int res = 0;
char *data;
int timeout = 0, duration = 0;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(digits);
AST_APP_ARG(timeout);
AST_APP_ARG(duration);
);
struct localuser *u;
char *digits = NULL, *to = NULL;
int timeout = 250;
if (ast_strlen_zero(vdata)) {
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "SendDTMF requires an argument (digits or *#aAbBcCdD)\n");
return 0;
}
data = ast_strdupa(vdata);
AST_STANDARD_APP_ARGS(args, data);
LOCAL_USER_ADD(u);
if (!ast_strlen_zero(args.timeout))
timeout = atoi(args.timeout);
if (!ast_strlen_zero(args.duration))
duration = atoi(args.duration);
res = ast_dtmf_stream(chan, NULL, args.digits, timeout <= 0 ? 250 : timeout, duration);
digits = ast_strdupa(data);
if (!digits) {
ast_log(LOG_ERROR, "Out of Memory!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
if ((to = strchr(digits,'|'))) {
*to = '\0';
to++;
timeout = atoi(to);
}
if(timeout <= 0)
timeout = 250;
res = ast_dtmf_stream(chan,NULL,digits,timeout);
LOCAL_USER_REMOVE(u);
return res;
}
static char mandescr_playdtmf[] =
"Description: Plays a dtmf digit on the specified channel.\n"
"Variables: (all are required)\n"
" Channel: Channel name to send digit to\n"
" Digit: The dtmf digit to play\n";
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");
struct ast_channel *chan = ast_get_channel_by_name_locked(channel);
if (!chan) {
astman_send_error(s, m, "Channel not specified");
return 0;
}
if (ast_strlen_zero(digit)) {
astman_send_error(s, m, "No digit specified");
ast_channel_unlock(chan);
return 0;
}
ast_senddigit(chan, *digit, 0);
ast_channel_unlock(chan);
astman_send_ack(s, m, "DTMF successfully queued");
return 0;
}
static int unload_module(void)
int unload_module(void)
{
int res;
res = ast_unregister_application(app);
res |= ast_manager_unregister("PlayDTMF");
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, senddtmf_exec, synopsis, descrip);
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
res = ast_manager_register2( "PlayDTMF", EVENT_FLAG_CALL, manager_play_dtmf, "Play DTMF signal on a specific channel.", mandescr_playdtmf );
res |= ast_register_application(app, senddtmf_exec, synopsis, descrip);
STANDARD_USECOUNT(res);
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Send DTMF digits Application");
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -19,81 +19,138 @@
/*! \file
*
* \brief App to transmit a text message
*
* \author Mark Spencer <markster@digium.com>
*
* \note Requires support of sending text messages from channel driver
* Requires support of sending text messages from channel driver
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/image.h"
#include "asterisk/options.h"
#include "asterisk/app.h"
static const char *tdesc = "Send Text Applications";
static const char *app = "SendText";
static const char *synopsis = "Send a Text Message";
static const char *descrip =
" SendText(text): Sends text to current channel (callee).\n"
" SendText(text[|options]): Sends text to current channel (callee).\n"
"Result of transmission will be stored in the SENDTEXTSTATUS\n"
"channel variable:\n"
" SUCCESS Transmission succeeded\n"
" FAILURE Transmission failed\n"
" UNSUPPORTED Text transmission not supported by channel\n"
"\n"
"At this moment, text is supposed to be 7 bit ASCII in most channels.\n";
"At this moment, text is supposed to be 7 bit ASCII in most channels.\n"
"The option string many contain the following character:\n"
"'j' -- jump to n+101 priority if the channel doesn't support\n"
" text transport\n";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static int sendtext_exec(struct ast_channel *chan, void *data)
{
int res = 0;
struct localuser *u;
char *status = "UNSUPPORTED";
char *parse = NULL;
int priority_jump = 0;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(text);
AST_APP_ARG(options);
);
LOCAL_USER_ADD(u);
/* NOT ast_strlen_zero, because some protocols (e.g. SIP) MUST be able to
* send a zero-length message. */
if (!data) {
ast_log(LOG_WARNING, "SendText requires an argument (text)\n");
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "SendText requires an argument (text[|options])\n");
LOCAL_USER_REMOVE(u);
return -1;
} else
} else {
parse = ast_strdupa(data);
if (!parse) {
ast_log(LOG_ERROR, "Out of memory!\n");
LOCAL_USER_REMOVE(u);
return -1;
}
}
AST_STANDARD_APP_ARGS(args, parse);
ast_channel_lock(chan);
if (args.options) {
if (strchr(args.options, 'j'))
priority_jump = 1;
}
ast_mutex_lock(&chan->lock);
if (!chan->tech->send_text) {
ast_channel_unlock(chan);
ast_mutex_unlock(&chan->lock);
/* Does not support transport */
pbx_builtin_setvar_helper(chan, "SENDTEXTSTATUS", status);
if (priority_jump || option_priority_jumping)
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
LOCAL_USER_REMOVE(u);
return 0;
}
status = "FAILURE";
ast_channel_unlock(chan);
ast_mutex_unlock(&chan->lock);
res = ast_sendtext(chan, args.text);
if (!res)
status = "SUCCESS";
pbx_builtin_setvar_helper(chan, "SENDTEXTSTATUS", status);
LOCAL_USER_REMOVE(u);
return 0;
}
static int unload_module(void)
int unload_module(void)
{
return ast_unregister_application(app);
int res;
res = ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
static int load_module(void)
int load_module(void)
{
return ast_register_application(app, sendtext_exec, synopsis, descrip);
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Send Text Applications");
char *description(void)
{
return (char *) tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

View File

@@ -18,19 +18,22 @@
/*! \file
*
* \brief App to set callerid presentation
*
* \author Mark Spencer <markster@digium.com>
* \brief App to set callerid
*
* \ingroup applications
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
@@ -42,6 +45,9 @@ static char *app2 = "SetCallerPres";
static char *synopsis2 = "Set CallerID Presentation";
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
static char *descrip2 =
" SetCallerPres(presentation): Set Caller*ID presentation on a call.\n"
@@ -61,37 +67,112 @@ static char *descrip2 =
static int setcallerid_pres_exec(struct ast_channel *chan, void *data)
{
struct localuser *u;
int pres = -1;
static int deprecated = 0;
if (!deprecated) {
deprecated = 1;
ast_log(LOG_WARNING, "SetCallerPres is deprecated. Please use Set(CALLERPRES()=%s) instead.\n", (char *)data);
}
/* For interface consistency, permit the argument to be specified as a number */
if (sscanf(data, "%30d", &pres) != 1 || pres < 0 || pres > 255 || (pres & 0x9c)) {
pres = ast_parse_caller_presentation(data);
}
LOCAL_USER_ADD(u);
pres = ast_parse_caller_presentation(data);
if (pres < 0) {
ast_log(LOG_WARNING, "'%s' is not a valid presentation (see 'show application SetCallerPres')\n",
(char *) data);
LOCAL_USER_REMOVE(u);
return 0;
}
chan->cid.cid_pres = pres;
LOCAL_USER_REMOVE(u);
return 0;
}
static int unload_module(void)
static char *tdesc = "Set CallerID Application";
static char *app = "SetCallerID";
static char *synopsis = "Set CallerID";
static char *descrip =
" SetCallerID(clid[|a]): Set Caller*ID on a call to a new\n"
"value. Sets ANI as well if a flag is used. \n";
static int setcallerid_exec(struct ast_channel *chan, void *data)
{
return ast_unregister_application(app2);
int res = 0;
char *tmp = NULL;
char name[256];
char num[256];
struct localuser *u;
char *opt;
int anitoo = 0;
if (ast_strlen_zero(data)) {
ast_log(LOG_WARNING, "SetCallerID requires an argument!\n");
return 0;
}
LOCAL_USER_ADD(u);
tmp = ast_strdupa(data);
if (!tmp) {
ast_log(LOG_ERROR, "Out of memory\n");
LOCAL_USER_REMOVE(u);
return -1;
}
opt = strchr(tmp, '|');
if (opt) {
*opt = '\0';
opt++;
if (*opt == 'a')
anitoo = 1;
}
ast_callerid_split(tmp, name, sizeof(name), num, sizeof(num));
ast_set_callerid(chan, num, name, anitoo ? num : NULL);
LOCAL_USER_REMOVE(u);
return res;
}
static int load_module(void)
int unload_module(void)
{
return ast_register_application(app2, setcallerid_pres_exec, synopsis2, descrip2);
int res;
res = ast_unregister_application(app2);
res |= ast_unregister_application(app);
STANDARD_HANGUP_LOCALUSERS;
return res;
}
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Set CallerID Presentation Application");
int load_module(void)
{
int res;
res = ast_register_application(app2, setcallerid_pres_exec, synopsis2, descrip2);
res |= ast_register_application(app, setcallerid_exec, synopsis, descrip);
return res;
}
char *description(void)
{
return tdesc;
}
int usecount(void)
{
int res;
STANDARD_USECOUNT(res);
return res;
}
char *key()
{
return ASTERISK_GPL_KEY;
}

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