mirror of
https://github.com/asterisk/asterisk.git
synced 2026-03-21 13:26:53 +00:00
Compare commits
1264 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c2151c9fd | ||
|
|
1ed83f02b4 | ||
|
|
7b5998d403 | ||
|
|
7a8cc66e30 | ||
|
|
3e6b299656 | ||
|
|
5fc112b07e | ||
|
|
3489410e0d | ||
|
|
d45abc9ef4 | ||
|
|
e1a27ddc08 | ||
|
|
fe80ce7e5d | ||
|
|
78130b6b77 | ||
|
|
6cab7dba9d | ||
|
|
42555c22d3 | ||
|
|
a84fc48984 | ||
|
|
0a5c91de26 | ||
|
|
3fa8ad9c7d | ||
|
|
6732590f86 | ||
|
|
cc0350b8ce | ||
|
|
542ca7ab3a | ||
|
|
4f69043680 | ||
|
|
2581eeb8e8 | ||
|
|
5f4befcba9 | ||
|
|
c59f154763 | ||
|
|
a989a2432a | ||
|
|
be05c4a246 | ||
|
|
6e820514a9 | ||
|
|
a37491c125 | ||
|
|
27af3cf46a | ||
|
|
4ed56df62c | ||
|
|
f42ada7a25 | ||
|
|
84c5074ec3 | ||
|
|
932f5ca647 | ||
|
|
71fdd7d526 | ||
|
|
643879cabc | ||
|
|
703220f1f4 | ||
|
|
27290e8976 | ||
|
|
ec11516f11 | ||
|
|
43ea28d8f6 | ||
|
|
ef549fe985 | ||
|
|
40520cc2a4 | ||
|
|
c5c3cb32f1 | ||
|
|
3ce33b090c | ||
|
|
f8d551bd2b | ||
|
|
a698166af0 | ||
|
|
38419fb811 | ||
|
|
8f7422b931 | ||
|
|
1501383484 | ||
|
|
3c780866b3 | ||
|
|
62766834c8 | ||
|
|
53ca368854 | ||
|
|
866bf7984a | ||
|
|
dd7fd5e641 | ||
|
|
47b472894b | ||
|
|
4208af2204 | ||
|
|
04e4f3d345 | ||
|
|
0f7afb14e4 | ||
|
|
1e6902b29d | ||
|
|
1897d857f0 | ||
|
|
c58235bed4 | ||
|
|
0edee75c07 | ||
|
|
726fa701da | ||
|
|
330090142f | ||
|
|
2cdedcbe94 | ||
|
|
ea98dd3dfc | ||
|
|
32ade7d7fc | ||
|
|
325bfeeda5 | ||
|
|
f95db061fd | ||
|
|
a62bba55d8 | ||
|
|
2405536de9 | ||
|
|
44b5abf39f | ||
|
|
831ebbebb7 | ||
|
|
a7047b7ed5 | ||
|
|
9df29ba46f | ||
|
|
6b5a7a6f64 | ||
|
|
dc4a74f57f | ||
|
|
dd77af3fe3 | ||
|
|
d359de6edb | ||
|
|
d0b4144eb4 | ||
|
|
d2cb9b0d3b | ||
|
|
6fc518335e | ||
|
|
ffae2ad2fa | ||
|
|
e38a7d523c | ||
|
|
8e7cb1aa7a | ||
|
|
a8d3745147 | ||
|
|
ab2a84f410 | ||
|
|
460df0480b | ||
|
|
577c0ebedd | ||
|
|
2c757b4ab7 | ||
|
|
140c936792 | ||
|
|
4307bca95c | ||
|
|
7055d9fe45 | ||
|
|
01412290a2 | ||
|
|
5dd56e420c | ||
|
|
71fa9ce0c4 | ||
|
|
c908fb91d1 | ||
|
|
abf682606c | ||
|
|
abcb24bd12 | ||
|
|
319b105e17 | ||
|
|
29da454042 | ||
|
|
0a22a51525 | ||
|
|
5e8172892e | ||
|
|
ed261253d5 | ||
|
|
3735871ed4 | ||
|
|
585de1223e | ||
|
|
0b2c98ac3e | ||
|
|
e32e830419 | ||
|
|
1dc2b9c0f7 | ||
|
|
bf7b174b08 | ||
|
|
ce99e9d955 | ||
|
|
479d7e4738 | ||
|
|
ff1c0bfa20 | ||
|
|
2676d6c595 | ||
|
|
d60de2804e | ||
|
|
4dfa0b47a7 | ||
|
|
defd4eb3e2 | ||
|
|
fc4111b44f | ||
|
|
aac9dd609c | ||
|
|
dcdfb4aa89 | ||
|
|
7b9318fedd | ||
|
|
5c8b322f8d | ||
|
|
eeafa5951e | ||
|
|
89cc2e4b70 | ||
|
|
2303602f15 | ||
|
|
4ce4fe74ae | ||
|
|
3637816f4c | ||
|
|
5f272436b9 | ||
|
|
085065ac35 | ||
|
|
16ecedee04 | ||
|
|
c2cfb7ba64 | ||
|
|
8f2a415995 | ||
|
|
5be40827e5 | ||
|
|
76b4eb5daa | ||
|
|
fb50a2da95 | ||
|
|
f7a787c757 | ||
|
|
7e22d574a7 | ||
|
|
01f5e6d56b | ||
|
|
b9000f54b2 | ||
|
|
c25932a107 | ||
|
|
e179ccaff2 | ||
|
|
7a7b6536c7 | ||
|
|
d8d4454ae5 | ||
|
|
6357ad5659 | ||
|
|
a1cc9b4966 | ||
|
|
cfaead2b9c | ||
|
|
f5f018a209 | ||
|
|
7fc236e53b | ||
|
|
ede913f976 | ||
|
|
8da289e13c | ||
|
|
3d1a5f71c5 | ||
|
|
6e0248318b | ||
|
|
07b9fc569f | ||
|
|
e21d079484 | ||
|
|
3322095dea | ||
|
|
234b7d22fe | ||
|
|
dc41ce9857 | ||
|
|
ff8bb42cbc | ||
|
|
9aa74f204a | ||
|
|
dc41cf2347 | ||
|
|
fab1ba87cd | ||
|
|
0156942fe0 | ||
|
|
ba372aa9a4 | ||
|
|
28464199ee | ||
|
|
37ded96cfa | ||
|
|
7bb272f942 | ||
|
|
9809905c76 | ||
|
|
41421be994 | ||
|
|
5cc2b1078e | ||
|
|
086aba207e | ||
|
|
d8fb68b9cb | ||
|
|
49ffa786ff | ||
|
|
c00062ff31 | ||
|
|
a3961d646a | ||
|
|
9c0627eab0 | ||
|
|
084ede4507 | ||
|
|
3a2e0e1ed9 | ||
|
|
76fdb9418b | ||
|
|
a05ab92728 | ||
|
|
f002ad09a3 | ||
|
|
e7590d0aec | ||
|
|
e0f4f4969c | ||
|
|
3cd1c84e8d | ||
|
|
dd412388a1 | ||
|
|
c78acd2896 | ||
|
|
22fe1b73cc | ||
|
|
c0ce087e43 | ||
|
|
fc6d28a932 | ||
|
|
c4e7d9fef5 | ||
|
|
2cb2558eb1 | ||
|
|
ad2f350d39 | ||
|
|
17175c7d54 | ||
|
|
cba8e2f704 | ||
|
|
9edd1e094c | ||
|
|
2f0f1f5e00 | ||
|
|
03ad135134 | ||
|
|
0b6da8d56e | ||
|
|
fd1fc0a9c1 | ||
|
|
86882515a8 | ||
|
|
21ea4dc3f1 | ||
|
|
58bcd919d5 | ||
|
|
06b2955d26 | ||
|
|
b2f84c347f | ||
|
|
dfd24c33d2 | ||
|
|
9ebfde54a1 | ||
|
|
80e4abca3d | ||
|
|
aa9ff74af5 | ||
|
|
b60fd4bc20 | ||
|
|
3b1ad79633 | ||
|
|
29aa7c809b | ||
|
|
074cc21291 | ||
|
|
07ba0e379b | ||
|
|
818c25352e | ||
|
|
7dc491d090 | ||
|
|
47047d5004 | ||
|
|
fcad34fd9f | ||
|
|
25930c842f | ||
|
|
048000f9d6 | ||
|
|
616e3502e7 | ||
|
|
71befa9884 | ||
|
|
999633ab4f | ||
|
|
3a218f3a09 | ||
|
|
2102128500 | ||
|
|
70e95c4846 | ||
|
|
de32406990 | ||
|
|
0b78d1542c | ||
|
|
26cab38b64 | ||
|
|
9b71a5799b | ||
|
|
c8a90488d6 | ||
|
|
8da91a20e3 | ||
|
|
274afdc345 | ||
|
|
80d88816df | ||
|
|
d97b6e3d34 | ||
|
|
3bafdca29f | ||
|
|
babe9cbbef | ||
|
|
897b4c0ca3 | ||
|
|
cd3ef82ba4 | ||
|
|
bc604c9e9a | ||
|
|
85cff883ee | ||
|
|
6ab97a0292 | ||
|
|
eab557da86 | ||
|
|
c5a87ff71d | ||
|
|
1cde24d633 | ||
|
|
654c04bfc9 | ||
|
|
a31a2ef862 | ||
|
|
f1edea1129 | ||
|
|
3682e51ba7 | ||
|
|
c28413ff94 | ||
|
|
57185823d1 | ||
|
|
e4467b3837 | ||
|
|
062368a175 | ||
|
|
4b17148846 | ||
|
|
2128909ad4 | ||
|
|
a36f57e7fc | ||
|
|
1159b7761a | ||
|
|
104b12df79 | ||
|
|
1330496973 | ||
|
|
1a92fec845 | ||
|
|
62de701abb | ||
|
|
2eaae45f81 | ||
|
|
b9ec441aa9 | ||
|
|
f2680a35d4 | ||
|
|
2e1fe209de | ||
|
|
abe55bf16f | ||
|
|
d971b4ba93 | ||
|
|
5cbe22e0f7 | ||
|
|
6374772250 | ||
|
|
dd108f60f3 | ||
|
|
2bed78a613 | ||
|
|
3f71ad082e | ||
|
|
d0991f6e1f | ||
|
|
7a18c89ba8 | ||
|
|
683a345699 | ||
|
|
e237711157 | ||
|
|
a19d352438 | ||
|
|
f96aef8d79 | ||
|
|
5ded94acbe | ||
|
|
b18a9b92c8 | ||
|
|
5e01069962 | ||
|
|
30fd84d952 | ||
|
|
e299df7a75 | ||
|
|
51366b90d0 | ||
|
|
8a416b420d | ||
|
|
ec7458a460 | ||
|
|
9956c33fec | ||
|
|
b87695d824 | ||
|
|
b254610b88 | ||
|
|
08c29fea9f | ||
|
|
7ca5863965 | ||
|
|
43ac3f119b | ||
|
|
653b6f22c5 | ||
|
|
ec9fb9a970 | ||
|
|
4a5d66f867 | ||
|
|
681c63cd92 | ||
|
|
9593ae4269 | ||
|
|
714e570302 | ||
|
|
fe9bbc5dfc | ||
|
|
0b4eeda153 | ||
|
|
74b331c4d0 | ||
|
|
79c08e3a46 | ||
|
|
ae319d34d5 | ||
|
|
0939887739 | ||
|
|
3b2e8feab4 | ||
|
|
7158b80498 | ||
|
|
6af97b5d59 | ||
|
|
5941cc916c | ||
|
|
c0cf86d6c8 | ||
|
|
130b54f4b7 | ||
|
|
c072213569 | ||
|
|
6f098541d0 | ||
|
|
7c9bc7fd0d | ||
|
|
c7c8b06817 | ||
|
|
7d74199c6f | ||
|
|
75ce9f86b8 | ||
|
|
58818031b1 | ||
|
|
c17a4c7f53 | ||
|
|
7bcc4569bb | ||
|
|
dfcff16e09 | ||
|
|
12a38f8e56 | ||
|
|
a9252f4549 | ||
|
|
6bf891f353 | ||
|
|
6752748d87 | ||
|
|
4d5bf84ce1 | ||
|
|
84ab66498f | ||
|
|
c8a883fd2f | ||
|
|
93c0385bc0 | ||
|
|
7312a2eb3d | ||
|
|
2e64cf06e5 | ||
|
|
87c0a12a03 | ||
|
|
1c26e1c717 | ||
|
|
4fb7eb1b7b | ||
|
|
ca7fbd749e | ||
|
|
c966ea6e2d | ||
|
|
c9d26b5a89 | ||
|
|
aa54a5f91b | ||
|
|
50feace3ca | ||
|
|
602c5bb8c3 | ||
|
|
960d22deb4 | ||
|
|
82bc576ea4 | ||
|
|
fababa3b74 | ||
|
|
179c829291 | ||
|
|
9736c57aab | ||
|
|
975f117300 | ||
|
|
ff04058bff | ||
|
|
c9c943e8e2 | ||
|
|
28c428929e | ||
|
|
2802ea3eeb | ||
|
|
d44c7d9c54 | ||
|
|
041061ca36 | ||
|
|
a17395f9f3 | ||
|
|
3b38b3f632 | ||
|
|
5f3b33f0f5 | ||
|
|
27a1f39f78 | ||
|
|
f49ce518ba | ||
|
|
d2261a98af | ||
|
|
7d1af2b829 | ||
|
|
4fa9370412 | ||
|
|
99ba264f63 | ||
|
|
fed5b6a9b4 | ||
|
|
8c161f55e4 | ||
|
|
15538c732c | ||
|
|
8ab0b28aba | ||
|
|
ade14f36ea | ||
|
|
d7dd6ed0a7 | ||
|
|
8754f03658 | ||
|
|
8ea5a33c9e | ||
|
|
f8bed34be9 | ||
|
|
bc926d7f33 | ||
|
|
f9db7779f0 | ||
|
|
6564129ee7 | ||
|
|
ccce21be4f | ||
|
|
fe394f23d4 | ||
|
|
ccd780463d | ||
|
|
65a8360531 | ||
|
|
29d168987c | ||
|
|
ec4c828386 | ||
|
|
3d12e45f06 | ||
|
|
8ba938b508 | ||
|
|
4659a0ac41 | ||
|
|
e06d0f644b | ||
|
|
5e9fdf2aa7 | ||
|
|
1cb1bbbe8d | ||
|
|
245cdf50ba | ||
|
|
5823b29f58 | ||
|
|
75d7a0309a | ||
|
|
34b5cd1de5 | ||
|
|
9eaff06d26 | ||
|
|
bd06c9494b | ||
|
|
e1dc278941 | ||
|
|
14eece85c9 | ||
|
|
edca3010a4 | ||
|
|
d46636d6fa | ||
|
|
0a73ba87b1 | ||
|
|
91d1c70906 | ||
|
|
6926dd0fbe | ||
|
|
3f07bd5034 | ||
|
|
6f1d7511d1 | ||
|
|
cbfeb816e1 | ||
|
|
0fad242a19 | ||
|
|
7015408cf8 | ||
|
|
c69d99c830 | ||
|
|
84a751aecd | ||
|
|
ed7bdda7b0 | ||
|
|
e9b6a2c807 | ||
|
|
741131aaa2 | ||
|
|
321c032c5e | ||
|
|
808bcff9d0 | ||
|
|
2e738d5a7c | ||
|
|
5704d29ffa | ||
|
|
ec695243af | ||
|
|
f5507d2431 | ||
|
|
ef53c893c3 | ||
|
|
4e779b5b43 | ||
|
|
a0afc6c927 | ||
|
|
9713819c85 | ||
|
|
8ca9fedc42 | ||
|
|
be0be1b4f1 | ||
|
|
2194a0b079 | ||
|
|
99815228f2 | ||
|
|
82016c83d2 | ||
|
|
58f6fb69fb | ||
|
|
9c8bcc3c1c | ||
|
|
6e6fa1c71f | ||
|
|
6e7786ab99 | ||
|
|
59ae6dac08 | ||
|
|
c355d9667b | ||
|
|
847ddc1e2c | ||
|
|
798116918e | ||
|
|
c54cc039e8 | ||
|
|
f28947f7ef | ||
|
|
526b32f5e6 | ||
|
|
7716c778e4 | ||
|
|
c3b8d9f510 | ||
|
|
b9bddd3063 | ||
|
|
9cc5b12741 | ||
|
|
72c5d5a16b | ||
|
|
ffdbc25cb9 | ||
|
|
2cbdcb35b1 | ||
|
|
983d09bc21 | ||
|
|
611a9778bb | ||
|
|
f2df4138cb | ||
|
|
d79533bd94 | ||
|
|
26676beff5 | ||
|
|
6d3c784a84 | ||
|
|
d37fee2b0f | ||
|
|
95a18631a4 | ||
|
|
8eb9c059e5 | ||
|
|
c70018c590 | ||
|
|
31759faca8 | ||
|
|
9ce01ec196 | ||
|
|
8c413a42eb | ||
|
|
6502bf97af | ||
|
|
37d6a18db1 | ||
|
|
49135c3ee5 | ||
|
|
e76ee063e6 | ||
|
|
37db91a3b8 | ||
|
|
1b287f7406 | ||
|
|
efe92601c5 | ||
|
|
274f9027f3 | ||
|
|
6180390206 | ||
|
|
3781699230 | ||
|
|
faee7ae5f1 | ||
|
|
d707910edb | ||
|
|
b6c058c6c4 | ||
|
|
0c18e0a5e1 | ||
|
|
9bb51868ca | ||
|
|
54fc8c75d1 | ||
|
|
96a36252b6 | ||
|
|
f4137d1609 | ||
|
|
279ebd00c5 | ||
|
|
e189ffe5b5 | ||
|
|
0e783db690 | ||
|
|
426bdb3b17 | ||
|
|
fea6c62d61 | ||
|
|
0b9a8ee148 | ||
|
|
ad0f8df528 | ||
|
|
b5d03cfa96 | ||
|
|
91464b50ab | ||
|
|
0127860f60 | ||
|
|
e51a0e25f2 | ||
|
|
08570a5080 | ||
|
|
e3de4d3653 | ||
|
|
f41333b1c4 | ||
|
|
c446ef9782 | ||
|
|
3b2f1f1773 | ||
|
|
2d94af17a7 | ||
|
|
9c3789a5fd | ||
|
|
f72827b78c | ||
|
|
bedd43d2f9 | ||
|
|
f1d6ccc16f | ||
|
|
618dd887f1 | ||
|
|
e49736b059 | ||
|
|
5cea7867b3 | ||
|
|
62cb689e89 | ||
|
|
b640d51d40 | ||
|
|
442781850b | ||
|
|
ff0ce011a0 | ||
|
|
0d9602565f | ||
|
|
a99b6a1c97 | ||
|
|
ec623148c0 | ||
|
|
18f4324baf | ||
|
|
474abf4656 | ||
|
|
55867f295a | ||
|
|
a7e9e0893b | ||
|
|
06f51cc52f | ||
|
|
a173aeca9d | ||
|
|
e37d7b6682 | ||
|
|
735b4cf688 | ||
|
|
e301bc352f | ||
|
|
b4392d33ed | ||
|
|
7c651a64a7 | ||
|
|
f18766c30a | ||
|
|
769113c53f | ||
|
|
1961bac13d | ||
|
|
7908be0c2f | ||
|
|
e6465e0e69 | ||
|
|
3ac718e5f4 | ||
|
|
d4b36ffde5 | ||
|
|
78ccdbc123 | ||
|
|
38ba4c204e | ||
|
|
6a662fe33e | ||
|
|
e807fbcec5 | ||
|
|
2405e775b1 | ||
|
|
093d6d9554 | ||
|
|
f8da54e092 | ||
|
|
234408e7c1 | ||
|
|
0449e24db1 | ||
|
|
154c4e9504 | ||
|
|
2bec3b7627 | ||
|
|
bf20deeba1 | ||
|
|
dc0cb27752 | ||
|
|
7a5dd9d78b | ||
|
|
3ecf516f8f | ||
|
|
34934b48fe | ||
|
|
67f0e37177 | ||
|
|
4dc847a0f4 | ||
|
|
78d7b2641a | ||
|
|
8b75024fdf | ||
|
|
f7ccb0e458 | ||
|
|
0d26753de2 | ||
|
|
e0cbd7f2d9 | ||
|
|
c1666e921d | ||
|
|
16ce7edf1f | ||
|
|
2b0634ab95 | ||
|
|
01a7955445 | ||
|
|
e64fa8614d | ||
|
|
5e3d5c55b4 | ||
|
|
ce069b0c77 | ||
|
|
1775cae084 | ||
|
|
d0649af76d | ||
|
|
170abc16b0 | ||
|
|
58477e2410 | ||
|
|
0bd76b00b2 | ||
|
|
4981d1c5dd | ||
|
|
ffb75188e1 | ||
|
|
722d56e081 | ||
|
|
cd79e99638 | ||
|
|
bfbbc4de78 | ||
|
|
4e717c8ea6 | ||
|
|
8684599f6c | ||
|
|
a8c86fb9b2 | ||
|
|
87706f538e | ||
|
|
4f0d22fde1 | ||
|
|
eae488f164 | ||
|
|
0b4f47c3c3 | ||
|
|
9c405de30d | ||
|
|
e0408416d3 | ||
|
|
7e7a5bfc73 | ||
|
|
d1f421a9f6 | ||
|
|
77a645d0c6 | ||
|
|
73138db44a | ||
|
|
02ae73bd6a | ||
|
|
87803a8ac6 | ||
|
|
7620e04612 | ||
|
|
fb599cc53e | ||
|
|
dc268f1e6e | ||
|
|
34adb7efe6 | ||
|
|
f6ddf4e7d4 | ||
|
|
a2d98d6c7c | ||
|
|
e247b8ab33 | ||
|
|
0d9ea31f3a | ||
|
|
630930dd7f | ||
|
|
8c2fee974a | ||
|
|
ff41b0ae36 | ||
|
|
12afd66083 | ||
|
|
a0da756f2a | ||
|
|
83b377451c | ||
|
|
00ca92aeee | ||
|
|
c6e25717b4 | ||
|
|
e095711654 | ||
|
|
a6751ecf3a | ||
|
|
377dac8495 | ||
|
|
942768c022 | ||
|
|
6728ebb72c | ||
|
|
eb4bd38c92 | ||
|
|
b1708137da | ||
|
|
c8821eb38a | ||
|
|
e42bf94e06 | ||
|
|
88ccb83574 | ||
|
|
a729fb97e4 | ||
|
|
b2122691de | ||
|
|
1df9da9fef | ||
|
|
ca79503d56 | ||
|
|
9c8d9ce377 | ||
|
|
438f99e100 | ||
|
|
fd0496f3f6 | ||
|
|
cc0f191aab | ||
|
|
ed09034360 | ||
|
|
25c493ffdc | ||
|
|
ec7535bba2 | ||
|
|
a4e28347fe | ||
|
|
0cfb462845 | ||
|
|
0367363edb | ||
|
|
d3d62f3678 | ||
|
|
283039a071 | ||
|
|
754cb0114f | ||
|
|
ff9fce4bb8 | ||
|
|
8be5b66038 | ||
|
|
e627ecb8a7 | ||
|
|
68de3c0b29 | ||
|
|
cc82df15ff | ||
|
|
9eb92ed083 | ||
|
|
a05a361fc3 | ||
|
|
aaf0ad7b77 | ||
|
|
919cb0b1a8 | ||
|
|
c3b61adc5b | ||
|
|
1e21d7a537 | ||
|
|
abb4e3a3a4 | ||
|
|
c42a8d9b99 | ||
|
|
a5641b46de | ||
|
|
abfcb8d31e | ||
|
|
e174a3c762 | ||
|
|
6b466228c4 | ||
|
|
955aa04edc | ||
|
|
41fad4887e | ||
|
|
c6d94b0d89 | ||
|
|
c4f13b4c28 | ||
|
|
6daea8e8fb | ||
|
|
640f0361b9 | ||
|
|
3bfeacea91 | ||
|
|
e83bbab1ec | ||
|
|
034a919e1f | ||
|
|
761d98663f | ||
|
|
fac91f48ef | ||
|
|
39e622f7cf | ||
|
|
dad6bc4d32 | ||
|
|
4514a22df3 | ||
|
|
c7a845c978 | ||
|
|
379785c401 | ||
|
|
d98055d875 | ||
|
|
86b0330dc5 | ||
|
|
2650ee2f9a | ||
|
|
71b348be1c | ||
|
|
2f5c21ded7 | ||
|
|
3d759745f9 | ||
|
|
afedbd97af | ||
|
|
4098ad798d | ||
|
|
c3a46b712e | ||
|
|
465207a28d | ||
|
|
f4e47e9b51 | ||
|
|
7b46b7133d | ||
|
|
b740b45902 | ||
|
|
fdfc694ca3 | ||
|
|
1204f825d7 | ||
|
|
f4c24d5d62 | ||
|
|
e81646d2dd | ||
|
|
54b8d83e4f | ||
|
|
183541b44d | ||
|
|
66b15a3461 | ||
|
|
5e3b7eec7d | ||
|
|
a56f08e345 | ||
|
|
84ad1fe0f3 | ||
|
|
8ddb00adaa | ||
|
|
4f3b40fe79 | ||
|
|
83f9228c1d | ||
|
|
532ff6487b | ||
|
|
f41b9baed4 | ||
|
|
af0052ee94 | ||
|
|
70d6a82a9f | ||
|
|
1020b9d11a | ||
|
|
2e7e645c77 | ||
|
|
7b9abdf138 | ||
|
|
6afc9c6c8f | ||
|
|
228c35198c | ||
|
|
0b6aa9cd29 | ||
|
|
425c51cfd5 | ||
|
|
46012df0b6 | ||
|
|
96048caf41 | ||
|
|
f46ab63b6c | ||
|
|
1cd1b27779 | ||
|
|
b97c12b80b | ||
|
|
09a334573e | ||
|
|
dfe118c2fd | ||
|
|
f23368365a | ||
|
|
c5623e2acd | ||
|
|
ce37a590e5 | ||
|
|
6ea65400a0 | ||
|
|
1d8f732f3f | ||
|
|
88ccb628f9 | ||
|
|
fcf0d79afa | ||
|
|
39882ad2f7 | ||
|
|
ff3890a952 | ||
|
|
0c754a13a8 | ||
|
|
ff29ba6296 | ||
|
|
648bc1828d | ||
|
|
fe1708f190 | ||
|
|
f009c13db7 | ||
|
|
3d8ef8de96 | ||
|
|
152df40d57 | ||
|
|
f1b2416353 | ||
|
|
84881a0662 | ||
|
|
b617860594 | ||
|
|
5a86fcf1f8 | ||
|
|
1a1ae6b104 | ||
|
|
f452a64598 | ||
|
|
2211a552d3 | ||
|
|
b8e4f60589 | ||
|
|
1cf6171b0c | ||
|
|
99b3637d6a | ||
|
|
d89517f348 | ||
|
|
4bee2f3210 | ||
|
|
2f0b62b8d3 | ||
|
|
55247bea10 | ||
|
|
ab4bdf1e3f | ||
|
|
27aa56e14e | ||
|
|
3d09ddb98e | ||
|
|
bbcb713b68 | ||
|
|
f6b683b302 | ||
|
|
64def5d791 | ||
|
|
4564907b41 | ||
|
|
6d2cff5290 | ||
|
|
e5505d1baf | ||
|
|
43ad959914 | ||
|
|
4c688bb3b3 | ||
|
|
1eb2822b3b | ||
|
|
4893f1917f | ||
|
|
7807373222 | ||
|
|
3cf57b8066 | ||
|
|
d00c50cd14 | ||
|
|
2159afd1ae | ||
|
|
55ba8ef5c4 | ||
|
|
b9e587a361 | ||
|
|
724b3d0004 | ||
|
|
2d7e3395a6 | ||
|
|
5ae03d8ff8 | ||
|
|
4fb3d5bf31 | ||
|
|
ec39ee2c34 | ||
|
|
ecbc33eb78 | ||
|
|
2a72316550 | ||
|
|
d1afe5c64f | ||
|
|
9807f83d64 | ||
|
|
cb1dc40802 | ||
|
|
070d4d3976 | ||
|
|
0cce2fe2e9 | ||
|
|
dcebecb76e | ||
|
|
332880b8bc | ||
|
|
59224d0f9f | ||
|
|
33661e9258 | ||
|
|
4003aff342 | ||
|
|
de0d5de853 | ||
|
|
9c99053126 | ||
|
|
9d9a6da961 | ||
|
|
c38c7a1f46 | ||
|
|
5ccc5a9e53 | ||
|
|
43f10147fe | ||
|
|
4de28aa7cc | ||
|
|
a19de52a1e | ||
|
|
8daadb91c1 | ||
|
|
95cd30dc01 | ||
|
|
43fa2d54ef | ||
|
|
f0d3be1740 | ||
|
|
c515ef705c | ||
|
|
5684ba5966 | ||
|
|
9c5890a138 | ||
|
|
efee6cdadf | ||
|
|
3feead3415 | ||
|
|
84c0989323 | ||
|
|
f963ebd1ab | ||
|
|
71d9095626 | ||
|
|
dbfbe2c679 | ||
|
|
eeb613ea3d | ||
|
|
f43b8a655d | ||
|
|
c882c82377 | ||
|
|
a6a17f1789 | ||
|
|
a94248e7dc | ||
|
|
f1744d3e31 | ||
|
|
9ef31203c9 | ||
|
|
5e266283e9 | ||
|
|
ce4e323638 | ||
|
|
547a070805 | ||
|
|
b2e084ae6d | ||
|
|
6b101367b8 | ||
|
|
5ecca96df5 | ||
|
|
3e830d9a85 | ||
|
|
42e50f7eae | ||
|
|
63ffcdfda2 | ||
|
|
e9d164d468 | ||
|
|
f5765a22fc | ||
|
|
84790a577b | ||
|
|
76066c2b74 | ||
|
|
9739139287 | ||
|
|
6d3d5e1649 | ||
|
|
d6873875cc | ||
|
|
f84891dfbb | ||
|
|
75ca02dbaa | ||
|
|
f1c97e7df8 | ||
|
|
919e8741b4 | ||
|
|
7018a80e91 | ||
|
|
f0e022bbad | ||
|
|
6691ebf59f | ||
|
|
d5a7d2e170 | ||
|
|
1795ff12cd | ||
|
|
ee808b6187 | ||
|
|
e0989958cc | ||
|
|
9123735599 | ||
|
|
4eef3ef785 | ||
|
|
0c4cc3b0ce | ||
|
|
a0c5fed6e8 | ||
|
|
8506e078c5 | ||
|
|
dda49ce86b | ||
|
|
63c91a899e | ||
|
|
892d98aca0 | ||
|
|
14285e5b2b | ||
|
|
89da276678 | ||
|
|
53a0b36973 | ||
|
|
bfbf66aec6 | ||
|
|
2ef43a770b | ||
|
|
25d2c99737 | ||
|
|
3c8d8caca1 | ||
|
|
a6d8b31956 | ||
|
|
9911943d3d | ||
|
|
3361be7b6e | ||
|
|
8b96daf53e | ||
|
|
968d069242 | ||
|
|
bc3570ac0f | ||
|
|
d5d56f98c3 | ||
|
|
728e1d9a31 | ||
|
|
961bcfe98c | ||
|
|
e6254eeb34 | ||
|
|
ee46d2d92e | ||
|
|
dd260ec707 | ||
|
|
bb0812be95 | ||
|
|
78986fe938 | ||
|
|
adbfc9d3c7 | ||
|
|
b2e48e3c22 | ||
|
|
6b93396fb9 | ||
|
|
6af35712ef | ||
|
|
249760b951 | ||
|
|
d46fa7e825 | ||
|
|
41210a37d6 | ||
|
|
72fe69919c | ||
|
|
b3d0a54a6b | ||
|
|
053f005508 | ||
|
|
a7987a4d36 | ||
|
|
960ad9e350 | ||
|
|
eb19888db5 | ||
|
|
0f643c18be | ||
|
|
3bc1111ea8 | ||
|
|
d27c901fa2 | ||
|
|
9d0eead218 | ||
|
|
c7ee76b69f | ||
|
|
092055c3a5 | ||
|
|
1b107baf37 | ||
|
|
83dc76b389 | ||
|
|
87d78ee383 | ||
|
|
316e536e5c | ||
|
|
49aa847408 | ||
|
|
00c0af845d | ||
|
|
822ea9615a | ||
|
|
b7f8ee4a6d | ||
|
|
d3d73f3499 | ||
|
|
9426da88b7 | ||
|
|
3e1ca33f4e | ||
|
|
37e9f9a15c | ||
|
|
a7961494bd | ||
|
|
5d04193649 | ||
|
|
4397e6dd42 | ||
|
|
e5c7e5df97 | ||
|
|
8ecd579aec | ||
|
|
d762abaf3b | ||
|
|
d0aef28b0e | ||
|
|
cecda9a947 | ||
|
|
d9b9996a59 | ||
|
|
891c6d599e | ||
|
|
f2dc4f491d | ||
|
|
089900af32 | ||
|
|
95bdc91eaf | ||
|
|
9d5f3974d3 | ||
|
|
e6b64adab2 | ||
|
|
6abf8e5e92 | ||
|
|
0c108cb1ec | ||
|
|
2939ab99bd | ||
|
|
4bea5adcbf | ||
|
|
bd9026f975 | ||
|
|
9a13dc9d99 | ||
|
|
829bf52765 | ||
|
|
b224ed93ca | ||
|
|
c3d195a2b3 | ||
|
|
aea2d73afa | ||
|
|
5bc6b3b6fd | ||
|
|
58c3bdc8f1 | ||
|
|
6f7efa99d5 | ||
|
|
fb912bc629 | ||
|
|
95dc3bba01 | ||
|
|
83b525e2cb | ||
|
|
4a40420978 | ||
|
|
08cc142495 | ||
|
|
48d13f84a5 | ||
|
|
7b12d67e50 | ||
|
|
d98317c7ad | ||
|
|
ce8275960e | ||
|
|
a6e5c98723 | ||
|
|
60df6b45d2 | ||
|
|
235212182e | ||
|
|
831a96aac1 | ||
|
|
bdea273046 | ||
|
|
f08096e951 | ||
|
|
d5a3b59ccf | ||
|
|
457bdd22bb | ||
|
|
43fde6acce | ||
|
|
adf51ade80 | ||
|
|
65f95fee51 | ||
|
|
bca4868578 | ||
|
|
9a729f7aff | ||
|
|
d125a1a278 | ||
|
|
6c0ac0721e | ||
|
|
65acfca5af | ||
|
|
3585625b40 | ||
|
|
c43f01c211 | ||
|
|
52aa07e2b2 | ||
|
|
b97c1529fc | ||
|
|
0a48c19845 | ||
|
|
8aa27f2c5c | ||
|
|
0bb7b71572 | ||
|
|
ac1e4d72dd | ||
|
|
ecf158b51e | ||
|
|
8d417967ce | ||
|
|
8d1c316519 | ||
|
|
70bd3bebc5 | ||
|
|
8c63eaec22 | ||
|
|
35ea822831 | ||
|
|
420f3d12aa | ||
|
|
469e6d539a | ||
|
|
09bf0c3032 | ||
|
|
3db3883d3d | ||
|
|
b85f9ea8fb | ||
|
|
84b4d40f79 | ||
|
|
ea4baa91d0 | ||
|
|
eb76fca6a3 | ||
|
|
677ed9a31a | ||
|
|
dea7edda6b | ||
|
|
da3df5ec26 | ||
|
|
0a0470ad00 | ||
|
|
b89b296584 | ||
|
|
41feb1c7ff | ||
|
|
9884c9637a | ||
|
|
b0f4874196 | ||
|
|
3667b25224 | ||
|
|
dcccda229d | ||
|
|
d31a0d9e7b | ||
|
|
674425a343 | ||
|
|
efd60d1d1f | ||
|
|
0cfcb22bbc | ||
|
|
9925080ca6 | ||
|
|
e34983cde0 | ||
|
|
17187101f6 | ||
|
|
747495fc0e | ||
|
|
d564b81083 | ||
|
|
50249c732b | ||
|
|
108275cf6c | ||
|
|
13b57f8255 | ||
|
|
6b8f2a96f1 | ||
|
|
b21dc2c0c2 | ||
|
|
f096152b20 | ||
|
|
3b776cdfdc | ||
|
|
9593aa0aa1 | ||
|
|
4edd97a713 | ||
|
|
eb1b6f313e | ||
|
|
38ca23948d | ||
|
|
e6ae8990bc | ||
|
|
14e8c4c5a3 | ||
|
|
b2bd6c27db | ||
|
|
d3080cc1ae | ||
|
|
023a312f65 | ||
|
|
89995395d9 | ||
|
|
fbe6931218 | ||
|
|
8545a6d4c0 | ||
|
|
3388661f38 | ||
|
|
1d58eff4a7 | ||
|
|
cc4595f85e | ||
|
|
ac9f562712 | ||
|
|
b3af62dc4f | ||
|
|
a70900ccd0 | ||
|
|
782eb432ab | ||
|
|
4e3b9d6389 | ||
|
|
dbc0f5d2e2 | ||
|
|
ea27f3c186 | ||
|
|
2dc23188a2 | ||
|
|
a4725e9c73 | ||
|
|
575c2bccd5 | ||
|
|
2d5cc8be5c | ||
|
|
10191fe126 | ||
|
|
4a391da1bd | ||
|
|
86406e8ba0 | ||
|
|
536dcc2058 | ||
|
|
c4c44af8e3 | ||
|
|
b26f150b75 | ||
|
|
271ccecaf2 | ||
|
|
0742e08800 | ||
|
|
34a135da3b | ||
|
|
39139b2802 | ||
|
|
799247b4d5 | ||
|
|
677a22c209 | ||
|
|
973a1dec88 | ||
|
|
dfc0e65f4b | ||
|
|
1e94621214 | ||
|
|
5fbe407b98 | ||
|
|
a3ce65e5cd | ||
|
|
fcf8040825 | ||
|
|
842e9246a6 | ||
|
|
6b682d34ff | ||
|
|
1ef0003131 | ||
|
|
4e884dbd28 | ||
|
|
0a1d8918d8 | ||
|
|
3da520e492 | ||
|
|
0a0cf51877 | ||
|
|
cab988b595 | ||
|
|
507c47ffa4 | ||
|
|
7c92ffe150 | ||
|
|
f522e07cbd | ||
|
|
df18b234b1 | ||
|
|
7652fdda20 | ||
|
|
bab77bbab1 | ||
|
|
ce008d40a1 | ||
|
|
710445b5b1 | ||
|
|
ba001a7d15 | ||
|
|
4f144aa5e3 | ||
|
|
8d66f50877 | ||
|
|
e0db36550e | ||
|
|
13f4e66b14 | ||
|
|
ae8fe3738b | ||
|
|
b5111fb985 | ||
|
|
671cde62de | ||
|
|
0ea76a52a9 | ||
|
|
db467378b4 | ||
|
|
e27d844918 | ||
|
|
3b0edd5cfe | ||
|
|
74eef60486 | ||
|
|
b3a8fbf495 | ||
|
|
bae6e7b617 | ||
|
|
cf015dbefc | ||
|
|
32cc1bedc1 | ||
|
|
a96ecb64a6 | ||
|
|
d1757b3b49 | ||
|
|
917259bcd3 | ||
|
|
eb177856db | ||
|
|
9849ad993d | ||
|
|
bb886dd488 | ||
|
|
48fb967c05 | ||
|
|
e74a7116e5 | ||
|
|
fd25b81993 | ||
|
|
dcd9d8d58f | ||
|
|
1d9b2a9df1 | ||
|
|
659da47b95 | ||
|
|
e83bfee678 | ||
|
|
ab209c7d92 | ||
|
|
dc08bd8501 | ||
|
|
aca3c1f79d | ||
|
|
e07c977f18 | ||
|
|
2ae21cc5c3 | ||
|
|
05fed23d06 | ||
|
|
2f43722570 | ||
|
|
7ea315539c | ||
|
|
10d527906a | ||
|
|
2f1d118537 | ||
|
|
696922defe | ||
|
|
cea50c9247 | ||
|
|
636f956bf0 | ||
|
|
64b1d91701 | ||
|
|
ff83f7c6ed | ||
|
|
87c0cd2667 | ||
|
|
366c8a99ef | ||
|
|
30f2aff526 | ||
|
|
962cffffc7 | ||
|
|
f196484187 | ||
|
|
c40fe2f71a | ||
|
|
74c149e891 | ||
|
|
57c82eb66f | ||
|
|
5460606cff | ||
|
|
1a509417a4 | ||
|
|
898cd20ceb | ||
|
|
792b78b317 | ||
|
|
4efe647169 | ||
|
|
4fbba55f14 | ||
|
|
2efc5a9e83 | ||
|
|
57144d5102 | ||
|
|
555bbffec3 | ||
|
|
e22510658b | ||
|
|
cb08e49303 | ||
|
|
dee03d2b80 | ||
|
|
b5ec3e47fa | ||
|
|
ffb11fb950 | ||
|
|
fbee1f0ed7 | ||
|
|
131ada1116 | ||
|
|
b0609b29aa | ||
|
|
bbb59b8c5e | ||
|
|
72deed0c37 | ||
|
|
b9f8c60fa7 | ||
|
|
87b36e1ff1 | ||
|
|
d8c5d338cb | ||
|
|
417438fea0 | ||
|
|
5488ffb6d4 | ||
|
|
e8725ce940 | ||
|
|
0e734920e8 | ||
|
|
ad598a2060 | ||
|
|
bb47f95262 | ||
|
|
a7a2115b9c | ||
|
|
18429f2a69 | ||
|
|
7e6430787c | ||
|
|
dc3ba8c223 | ||
|
|
2fd6520a7e | ||
|
|
7a61b36104 | ||
|
|
2f4783a770 | ||
|
|
6056391a78 | ||
|
|
213b3575ce | ||
|
|
3821e18d08 | ||
|
|
224c6e3f7c | ||
|
|
18ab6f429c | ||
|
|
07f8542ce7 | ||
|
|
cf293c224d | ||
|
|
e234ad0011 | ||
|
|
229b778b0b | ||
|
|
66f484defe | ||
|
|
ed523e248a | ||
|
|
3c49f27bf4 | ||
|
|
226d146b25 | ||
|
|
1892289329 | ||
|
|
5529fc0355 | ||
|
|
73ef559240 | ||
|
|
b59a63c8cd | ||
|
|
c36927137f | ||
|
|
649aaad100 | ||
|
|
ea4c262482 | ||
|
|
89de6c9df6 | ||
|
|
4578bc3b0c | ||
|
|
8df1e4866a | ||
|
|
9f92220a9c | ||
|
|
09a9e7bcb7 | ||
|
|
a434f8877a | ||
|
|
ef891dc0a7 | ||
|
|
3ebe29c983 | ||
|
|
1028e43464 | ||
|
|
4979f66f28 | ||
|
|
a5e9fe97c8 | ||
|
|
2293cfaf84 | ||
|
|
d252dde933 | ||
|
|
37a49a5992 | ||
|
|
2783801610 | ||
|
|
82f19c9a91 | ||
|
|
71d9531e45 | ||
|
|
3bbeaefa57 | ||
|
|
4611be805a | ||
|
|
587493fdfc | ||
|
|
50079144e3 | ||
|
|
2ca80e76a0 | ||
|
|
68e6502484 | ||
|
|
1e91dfa5df | ||
|
|
e4e5f7c65b | ||
|
|
8ef66261f1 | ||
|
|
90812b536c | ||
|
|
2b880d3ef8 | ||
|
|
6ab729aeb3 | ||
|
|
c9f97f49c5 | ||
|
|
8b352fcb94 | ||
|
|
5a06af4d57 | ||
|
|
2ede900bfd | ||
|
|
fb0ffc7784 | ||
|
|
e69171dc06 | ||
|
|
8452f6b494 | ||
|
|
f9bc6f8afc | ||
|
|
f9f44d7d9b | ||
|
|
86bb1472cc | ||
|
|
ef09c506c8 | ||
|
|
af7b3b420e | ||
|
|
3b80a35a66 | ||
|
|
f59b27258c | ||
|
|
d38fff38f9 | ||
|
|
91c5b12f25 | ||
|
|
894bdd5cda | ||
|
|
d8c58ca6c8 | ||
|
|
43f7956422 | ||
|
|
96fcc02900 | ||
|
|
2e8b6e7f20 | ||
|
|
3ed93398e9 | ||
|
|
d84e0caea8 | ||
|
|
5c1da58b90 | ||
|
|
018c617199 | ||
|
|
a49f954f6a | ||
|
|
03a8791440 | ||
|
|
78ad17381e | ||
|
|
5b03803e2f | ||
|
|
ee1e461a57 | ||
|
|
a543725311 | ||
|
|
8c701a0861 | ||
|
|
5fbe566524 | ||
|
|
e14cf31bc9 | ||
|
|
0042c03c7e | ||
|
|
41023ecb9c | ||
|
|
fb8d0a544d | ||
|
|
acaf8c9cc9 | ||
|
|
0d3fc8d103 | ||
|
|
9bbfbacacc | ||
|
|
8e301c629f | ||
|
|
9576d8a081 | ||
|
|
7db96672bf | ||
|
|
0d8f099ca2 | ||
|
|
0a4d7e5068 | ||
|
|
a32f75b800 | ||
|
|
78f37c51ef | ||
|
|
d6e5eb75ee | ||
|
|
6f433a7e7b | ||
|
|
ce2ecb5582 | ||
|
|
45c15e8561 | ||
|
|
5e3f4186da | ||
|
|
d03694df19 | ||
|
|
d52e8fa7d2 | ||
|
|
77c6cd0bff | ||
|
|
463ebe8b4b | ||
|
|
a563eab49a | ||
|
|
bf9d4b103d | ||
|
|
7dc2449f3a | ||
|
|
27cc20db11 | ||
|
|
4e04f5f731 | ||
|
|
5ec3844077 | ||
|
|
f641c7cd0d | ||
|
|
49aa54cafc | ||
|
|
e3b81e66a1 | ||
|
|
7bb6b928b5 | ||
|
|
ad4dc7c4a9 | ||
|
|
feb9764721 | ||
|
|
8c74501001 | ||
|
|
5861d3fd64 | ||
|
|
08acdc6a86 | ||
|
|
3b50570c9b | ||
|
|
00d7e962a7 | ||
|
|
192f7413c2 | ||
|
|
5bdb8074aa | ||
|
|
6abe5e1b23 | ||
|
|
4612b4ccca | ||
|
|
3245bf61a1 | ||
|
|
9ee13167bb | ||
|
|
ca9633ca9b | ||
|
|
e04884545c | ||
|
|
aa2239a050 | ||
|
|
40a1b60cbd | ||
|
|
cccb11916f | ||
|
|
49641825eb | ||
|
|
c14c078405 | ||
|
|
f2af073588 | ||
|
|
b9a5eddb6d | ||
|
|
bffc815375 | ||
|
|
5c3f322364 | ||
|
|
3a6fae817c | ||
|
|
d8f74ecb94 | ||
|
|
f7f2b1b033 | ||
|
|
601ab7ff82 |
@@ -1 +1 @@
|
||||
28
|
||||
9
|
||||
|
||||
@@ -1 +1 @@
|
||||
28
|
||||
9
|
||||
|
||||
2
BUGS
2
BUGS
@@ -7,7 +7,7 @@ the official Asterisk Bug Tracker at:
|
||||
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
|
||||
|
||||
466
CHANGES
466
CHANGES
@@ -1,341 +1,127 @@
|
||||
Changes since Asterisk 1.2:
|
||||
Changes since Asterisk 1.2.0-beta2:
|
||||
|
||||
* over 4,000 commits since 1.2
|
||||
* queue member naming
|
||||
* CLI commands rework
|
||||
o Change the way CLI commands are structured.
|
||||
o Most commands are now <module> <verb> <args>
|
||||
* chan_h323 update
|
||||
* RTP packetization
|
||||
* SLA (Shared Line Appearance) support
|
||||
* T.38 Passthrough Support for faxing in SIP
|
||||
* Generic channel jitterbuffer (spawned from RTP)
|
||||
* Variable Length DTMF for better DTMF compatibility
|
||||
* Improved chan_iax2 scalability by using multithreading
|
||||
* AEL2 has replaced the original implementation of AEL. The "2" is removed. For more details,
|
||||
read: http://www.voip-info.org/wiki/view/Asterisk+AEL2
|
||||
AEL is no longer considered experimental.
|
||||
* New sounds; English, Spanish, and French prompts, as well as music on hold files, in
|
||||
multiple Asterisk native formats.
|
||||
* IMAP storage of voicemail
|
||||
* Jabber/GoogleTalk integration
|
||||
* New speech recognition API for interfacing to different Voice Recognition software packages
|
||||
* much more customizable and portable build system
|
||||
o also for asterisk-addons
|
||||
* Radius CDR logging
|
||||
* SNMP support
|
||||
* SMDI (Simplified Message Desk Interface) support
|
||||
* Redesign of MusicOnHold configuration settings
|
||||
* Manager over HTTP
|
||||
* Significant chan_skinny updates
|
||||
* Significant chan_misdn updates
|
||||
* Improved SIP transfers
|
||||
* SIP MWI subscription support
|
||||
* Much improved support for SIP video
|
||||
* Control over SIP transfers and subscriptions (enable/disable per device)
|
||||
* ChanSpy whisper mode (Whisper Paging)
|
||||
* Configurable language support for saying dates and times
|
||||
* Significant architecture improvements for memory usage and performance
|
||||
* Media-only IAX2 transfers
|
||||
* Updates to the Radio Repeater app code
|
||||
* Deprecation of AgentCallbackLogin in favor of a dialplan-based solution
|
||||
* uClibc builds supported
|
||||
* Work done for freeBSD portability
|
||||
* Work done for Solaris portability
|
||||
* FreeTDS-based database can be used with Realtime
|
||||
* New internal data structure, stringfields, is implemented in IAX and SIP, reducing memory consumption by about 50%.
|
||||
* Use of thread local storage for reduced memory allocation/freeing and lower stack consumption
|
||||
* Reorganized files into docs/ main/ configs/, including name changes in some cases
|
||||
* Much effort was expended in arranging documentation in source files in doxygen format
|
||||
* Improved IP TOS support for IAX and SIP
|
||||
* Builtin mini HTTP server
|
||||
* Added support for Sigma Designs cards.
|
||||
* Frame header caching to reduce memory allocation/freeing
|
||||
* Passthrough and record/playback support for G.722 wideband audio
|
||||
* using mpg123 to play MP3 files for music-on-hold will be deprecated in 1.4 (start using the "native support")
|
||||
* New Apps:
|
||||
1. AMD() ;; Answering Machine Detection
|
||||
2. ChannelRedirect() ;; asynch goto, redirect chan to context/exten/priority
|
||||
3. ContinueWhile() ;; Addition to the While() suite. Acts like "continue".
|
||||
4. ExitWhile() ;; Addition to the While() suite. Acts like "break".
|
||||
5. ExtenSpy() ;; A close cousin to ChanSpy().
|
||||
6. FollowMe() ;; findme/followme call redirect app
|
||||
7. Log() ;; Send a message to the log, based on severity level.
|
||||
8. MacroExclusive() ;; No more than one invocation of this macro allowed at any one time.
|
||||
9. MorseCode() ;; turns strings into dits and dahs. A playground for ham radio licensees!
|
||||
10. OSPAuth() ;; OSP authentication
|
||||
11. QueueLog() ;; allows you to write your own events into the queue log
|
||||
12. SLAStation() ;; Shared Line Appearance
|
||||
13. SLATrunk() ;; Shared Line Appearance
|
||||
14. SpeechCreate() ;; Voice Recognition Engine interface...
|
||||
15. SpeechActivateGrammar()
|
||||
16. SpeechStart()
|
||||
17. SpeechBackground
|
||||
18. SpeechDeactivateGrammar()
|
||||
19. SpeechProcessingSound()
|
||||
20. SpeechDestroy()
|
||||
21. SpeechLoadGrammar()
|
||||
22. SpeechUnloadGrammar()
|
||||
23. StopMixMonitor() ;; to stop the MixMonitor App.
|
||||
24. TryExec() ;; execute dialplan app without fatal consequences
|
||||
* Apps removed:
|
||||
1. CheckGroup -- do a comparison to ${GROUP()}
|
||||
2. Curl -- use the function CURL() instead
|
||||
3. Cut -- use the function CUT() instead
|
||||
4. DateTime -- use sayunixtime() app instead.
|
||||
5. DBget -- deprecated in 1.2, now removed.
|
||||
6. DBput -- deprecated in 1.2, now removed.
|
||||
7. Enumlookup -- use the function ENUMLOOKUP() instead
|
||||
8. Eval -- use the function EVAL() instead
|
||||
9. GetGroupCount -- use the function GROUP_COUNT() instead
|
||||
10. GetGroupMatchCount -- use the function GROUP_MATCH_COUNT() instead
|
||||
11. Intercom -- use the chan_oss module instead
|
||||
12. Math -- use the function MATH() instead
|
||||
13. MD5 -- use the function MD5() instead
|
||||
14. SetCIDname -- use the function CALLERID(name) instead
|
||||
15. SetCIDnum -- use the function CALLERID(number) instead
|
||||
16. SetGroup -- use Set(GROUP=group) instead
|
||||
17. SetRDNIS -- use the function CALLERID(rdnis) instead
|
||||
18. Sql_postgres -- was deprecated in 1.2, now removed
|
||||
19. Txtcidname -- use the function TXTCIDNAME instead
|
||||
* New Dialplan Functions:
|
||||
1. ARRAY()
|
||||
2. BASE_64_DECODE()
|
||||
3. BASE_64_ENCODE()
|
||||
4. CHANNEL()
|
||||
5. CURL()
|
||||
6. CUT()
|
||||
7. DB_DELETE()
|
||||
8. FILTER()
|
||||
9. GLOBAL()
|
||||
10. IFTIME()
|
||||
11. KEYPADHASH()
|
||||
12. ODBC()
|
||||
13. QUOTE()
|
||||
14. RAND()
|
||||
15. REALTIME()
|
||||
16. SHA1()
|
||||
17. SORT()
|
||||
18. SPRINTF()
|
||||
19. SQL_ESC()
|
||||
20. STAT()
|
||||
21. STRPTIME()
|
||||
* Apps that have changes to their interface:
|
||||
1. Authenticate() -- optional maxdigits argument added.
|
||||
2. ChanSpy() -- new options:
|
||||
o w -- Enable 'whisper' mode, so the spying channel can talk to...
|
||||
o W -- Enable 'private whisper' mode, so the spying channel can...
|
||||
3. DBdel() -- now marked as DEPRECATED in favor of the DB_DELETE func
|
||||
4. Dial()
|
||||
o New Option: O([x]) for Zaptel operator mode
|
||||
o New Option: K/k parking via dtmf tones
|
||||
5. Dictate() -- optional filename argument added.
|
||||
6. Directory() -- new option: e - In addition to the name, also read the extension number...
|
||||
7. Meetme() -- new options:
|
||||
o 'I' -- announce user join/leave without review
|
||||
o 'l' -- set listen only mode (Listen only, no talking)
|
||||
o 'o' -- set talker optimization - treats talkers who aren't speaking as...
|
||||
o '1' -- do not play message when first person enters
|
||||
8. MeetmeAdmin() -- new options:
|
||||
o 'r' -- Reset one user's volume settings
|
||||
o 'R' -- Reset all users volume settings
|
||||
o 's' -- Lower entire conference speaking volume
|
||||
o 'S' -- Raise entire conference speaking volume
|
||||
o 't' -- Lower one user's talk volume
|
||||
o 'T' -- Lower all users talk volume
|
||||
o 'u' -- Lower one user's listen volume
|
||||
o 'U' -- Lower all users listen volume
|
||||
o 'v' -- Lower entire conference listening volume
|
||||
o 'V' -- Raise entire conference listening volume
|
||||
9. OSPFinish() : now also can return ERROR result.
|
||||
10. OSPLookup() : Sets more variables, also now returns ERROR result.
|
||||
11. Page() -- New option: r - record the page into a file (see 'r' for app_meetme)
|
||||
12. Pickup() -- multiple extensions, PICKUPMARK; read the description!
|
||||
13. Queue()
|
||||
o New Argument: AGI
|
||||
o New option: i
|
||||
14. Random() -- is now deprecated in 1.4
|
||||
15. Read() -- replace 'skip' and 'noanswer' options with 's', 'n', add 'i' option.
|
||||
16. Record() -- New option: 'x' : ignore all terminator keys (DTMF) and keep recording until hangup
|
||||
17. UserEvent() -- slight change in behavior. Read the description.
|
||||
18. VoiceMailMain() -- new a(#) option, goes to folder # directly.
|
||||
19. WaitForSilence() -- new optional 3rd arg, time delay before returning.
|
||||
* Functions that have changes to their interfaces:
|
||||
1. CDR -- new option: u
|
||||
2. LANGUAGE -- Deprecated. Use CHANNEL(language) instead.
|
||||
3. MUSICCLASS -- Deprecated. Use CHANNEL(musicclass) instead.
|
||||
* Configuration File Changes:
|
||||
1. NEW config files:
|
||||
1. amd.conf -- Answering Machine Detection parameters
|
||||
2. followme.conf -- parameters for the findme/followme call forwarding
|
||||
3. func_odbc.conf -- define sql access functions here
|
||||
4. gtalk.conf -- how to handle gtalk protocol calls
|
||||
5. h323.conf -- h323 configuration
|
||||
6. http.conf -- config for the builtin mini-http server in asterisk
|
||||
7. jabber.conf -- jabber interface
|
||||
8. jingle.conf -- jingle protocol interface config
|
||||
10. res_snmp.conf -- to enable snmp in asterisk, and define full/sub agent status
|
||||
11. say.conf -- define per-language rules for numbers, dates, etc.
|
||||
12. skinny.conf -- for those special skinny phones you want to use...
|
||||
13. sla.conf -- Shared Line Appearance config
|
||||
14. smdi.conf -- SMDI messaging config
|
||||
15. udptl.conf -- T38's udptl transport config
|
||||
16. users.conf -- user config
|
||||
2. Changes to Existing Config files:
|
||||
1. In General:
|
||||
o Jitterbuffer support added to several channels. Usually adds these variables to a config file:
|
||||
1. jbenable
|
||||
2. jbmaxsize
|
||||
3. jbresyncthreshold
|
||||
4. jbimpl
|
||||
5. jblog
|
||||
o MusicOnHold upgrade introduces two new variables:
|
||||
1. mohinterpret
|
||||
2. mohsuggest
|
||||
2. agents.conf
|
||||
o maxlogintries variable added
|
||||
o autologoffunavail variable added
|
||||
o endcall variable added
|
||||
o agentgoodbye variable added
|
||||
o createlink variable REMOVED
|
||||
3. alsa.conf
|
||||
o mohinterpret variable added
|
||||
o Jitterbuffer variables added
|
||||
4. cdr.conf
|
||||
o endbeforehexten variable added
|
||||
o sections for csv and radius added, with variables usegmtime, loguniqueid,
|
||||
loguserfield, and radiuscfg variables.
|
||||
5. cdr_tds.conf
|
||||
o table variable added
|
||||
6. extensions.ael
|
||||
o Many upgrades. See the info at http://www.voip-info.org/wiki/view/Asterisk+AEL2
|
||||
7. extensions.conf
|
||||
o autofallthru now set to "yes" by default
|
||||
o userscontext variable added
|
||||
o added info/examples on paging and hints.
|
||||
8. features.conf
|
||||
o parkedplay variable added (who to beep at)
|
||||
o parkedmusicclass
|
||||
o atxfernoanswertimeout variable added
|
||||
o parkcall variable added (one step parking)
|
||||
o improved documentation for dynamic feature declarations!
|
||||
9. iax.conf
|
||||
o adsi variable added
|
||||
o mohinterpret variable added
|
||||
o mohsuggest variable added
|
||||
o jitterbuffer updates
|
||||
o iaxthreadcount variable added
|
||||
o iaxmaxthreadcount variable added
|
||||
o the way to specify TOS has changed.
|
||||
o mailboxdetail variable has been REMOVED.
|
||||
10. indications.conf
|
||||
o [bg] entry added (Bulgaria).
|
||||
o [il] entry added (Israel)
|
||||
o [in] entry added (India)
|
||||
o [jp] entry added (Japan)
|
||||
o [my] entry added (Malaysia)
|
||||
o [th] entry added (Thailand)
|
||||
11. manager.conf
|
||||
o webenabled variable added
|
||||
o httptimeout variable added
|
||||
o timestampevents variable added
|
||||
12. mgcp.conf
|
||||
o Jitterbuffer support added
|
||||
13. misdn.conf
|
||||
o l1watcher_timeout variable added
|
||||
o pp_l2_check variable added
|
||||
o echocancelwhenbridged variable added
|
||||
o echotraining variable added
|
||||
o max_incoming variable added
|
||||
o max_outgoing variable added
|
||||
14. modules.conf
|
||||
o a comment for preloading res_speech.so is added
|
||||
o mention of global symbols is removed
|
||||
o obsolesced entries for chan_modem_* and app_intercom have been removed
|
||||
15. musiconhold.conf
|
||||
o the default is now to do native moh from /var/lib/asterisk/moh
|
||||
16. osp.conf
|
||||
o authpolicy variable added
|
||||
17. oss.conf
|
||||
o debug variable added
|
||||
o device variable added
|
||||
o mixer variable added
|
||||
o boost variable added
|
||||
o callerid variable added
|
||||
o autohangup variable added
|
||||
o queuesize variable added
|
||||
o frags variable added
|
||||
o JitterBuffer support
|
||||
o sections to define alternate sound cards
|
||||
18. queues.conf
|
||||
o autofill variable added
|
||||
o monitor-type variable added
|
||||
o musiconhold is now musicclass, with a difference in interpretation
|
||||
o autofill variable added
|
||||
o autopause variable added
|
||||
o setinterfacevar variable added
|
||||
o ringinuse variable added
|
||||
19. res_odbc.conf
|
||||
o pooling variable added
|
||||
20. rpt.conf
|
||||
o duplex variable added
|
||||
o tailmessagetime variable added
|
||||
o tailsquashedtime variable added
|
||||
o tailmessages variable added
|
||||
21. rtp.conf
|
||||
o rtcpinterval varaible added
|
||||
22. sip.conf
|
||||
o allowoverlap variable added
|
||||
o allowtransfer variable added
|
||||
o tos variable REMOVED
|
||||
o tos_sip variable added
|
||||
o tos_audio variable added
|
||||
o tos_video variable added
|
||||
o minexpiry variable added
|
||||
o t1min variable added
|
||||
o musicclass variable REMOVED
|
||||
o mohinterpret variable added
|
||||
o maxcallbitratesuggest variable added
|
||||
o allowsubscribe variable added
|
||||
o videosupport variable added
|
||||
o maxcallbitrate variable added
|
||||
o g726nonstandard variable added
|
||||
o dumphistory variable added
|
||||
o allowsubscribe variable added
|
||||
o t38pt_udptl variable added
|
||||
o canreinvite variable can also now be set to 'nonat'
|
||||
o rtsavesysname variable added
|
||||
o JitterBuffer support added
|
||||
23. skinny.conf
|
||||
o port variable renamed to bindport
|
||||
o JitterBuffer support added
|
||||
o model variable REMOVED
|
||||
o mohinterpret variable added
|
||||
o mohsuggest variable added
|
||||
o speeddial variable added
|
||||
o addon variable added
|
||||
24. voicemail.conf
|
||||
o userscontext variable added
|
||||
o smdiport variable added
|
||||
o attachfmt variable added
|
||||
o volgain variable added
|
||||
o tempgreetwarn variable added
|
||||
25. zapata.conf
|
||||
o pritimer variable has improved documentation
|
||||
o New signalling method: fgccama
|
||||
o New signalling method: fgccamamf
|
||||
o outsignalling variable added
|
||||
o distinctiveringaftercid variable added
|
||||
o cidsignalling now also accepts v23_jp, and smdi
|
||||
o usesmdi variable added
|
||||
o smdiport variable added
|
||||
o mohinterpret variable added
|
||||
o mohsuggest variable added
|
||||
o JitterBuffer support added
|
||||
* Removed Codecs/Channels:
|
||||
1. codec_g723 was removed because the actual codec implementation it was designed to use is not distributable
|
||||
2. chan_modem_* and related modules are gone because the kernel support for those interfaces is old, buggy and unsupported
|
||||
* New Utils:
|
||||
1. aelparse -- compile .ael files outside of asterisk
|
||||
* New manager events:
|
||||
1. OriginateResponse event comes to replace OriginateSuccess and OriginateFailure
|
||||
* Cygwin build system portability
|
||||
* Optional generation of outbound silence during channel recording
|
||||
|
||||
Changes since Asterisk 1.2.0-beta1:
|
||||
|
||||
* 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()
|
||||
|
||||
Changes since Asterisk 1.0:
|
||||
|
||||
This list currently only containts changes made from the end of November until
|
||||
March 26, 2005.
|
||||
|
||||
* 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
|
||||
|
||||
92
CREDITS
92
CREDITS
@@ -27,149 +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 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; 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.
|
||||
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@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@esoft.pf http://www.esoft.pf
|
||||
|
||||
William Jordan / Vonage - MySQL enhancements to Voicemail
|
||||
wjordan@vonage.com
|
||||
|
||||
Jac Kersing - Various fixes
|
||||
|
||||
Steven Critchfield - Seek and Trunc functions for playback and recording
|
||||
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@oa.com.au
|
||||
|
||||
James Dennis - Cisco SIP compatibility patches to work with SIP service
|
||||
providers. Can be contacted at asterisk@jdennis.net
|
||||
|
||||
Tilghman Lesher - ast_localtime(); ast_say_date_with_format();
|
||||
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@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@sigmasoft.com
|
||||
|
||||
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@whiteoaklabs.com http://whiteoaklabs.com
|
||||
|
||||
Simon Lockhart - Porting to Solaris (based on work of Logan ???)
|
||||
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@stevek.com
|
||||
|
||||
Constantine Filin - major contributions to the Asterisk Realtime Architecture
|
||||
|
||||
Steve Murphy - privacy support, $[ ] parser upgrade, AEL2 parser upgrade
|
||||
|
||||
Steve Murphy - privacy support
|
||||
Claude Patry - bug fixes, feature enhancements, and bug marshalling
|
||||
cpatry@gmail.com
|
||||
|
||||
Miroslav Nachev, miro@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@securax.be
|
||||
|
||||
Roy Sigurd Karlsbakk - providing funding for generic jitterbuffer development
|
||||
roy@karlsbakk.net, Briiz Telecom AS
|
||||
|
||||
Voop A/S, Nuvio Inc, Inotel S.A and Foniris Telecom A/S - funding for rewrite of SIP transfers
|
||||
|
||||
Philippe Sultan - RADIUS CDR module
|
||||
INRIA, http://www.inria.fr/
|
||||
|
||||
John Martin, Aupix - Improved video support in the SIP channel
|
||||
|
||||
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@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@gdspartners.com
|
||||
|
||||
Bartosz Supczinski - Support for Polish added by DIR (www.dir.pl) Bartosz.Supczinski@dir.pl
|
||||
|
||||
James Rothenberger - Support for IMAP storage integration added by OneBizTone LLC Work funded by University of Pennsylvania jar@onebiztone.com
|
||||
|
||||
Paul Cadach - Bringing chan_h323 up to date, bug fixes, and more!
|
||||
|
||||
=== 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@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:
|
||||
|
||||
@@ -11,7 +11,10 @@ Zaptel compatible hardware
|
||||
==========================
|
||||
|
||||
-- Digium (Primary author of Asterisk)
|
||||
http://www.digium.com, http://store.digium.com
|
||||
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.
|
||||
@@ -25,6 +28,9 @@ Zaptel compatible hardware
|
||||
* 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.
|
||||
|
||||
@@ -43,26 +49,16 @@ Non-zaptel compatible hardware
|
||||
* Internet LineJack - Single FXS or FXO interface. Supports Linux
|
||||
telephony interface.
|
||||
|
||||
mISDN compatible hardware
|
||||
=========================
|
||||
mISDN homepage: http://www.isdn4linux.de/mISDN/
|
||||
|
||||
Any adapter with an mISDN driver should be compatible with
|
||||
chan_misdn. See misdn.txt for information.
|
||||
|
||||
-- beroNet
|
||||
http://www.beronet.com
|
||||
|
||||
* BN4S0 - 4 Port BRI card (TE/NT)
|
||||
|
||||
* BN8S0 - 8 Port BRI card (TE/NT)
|
||||
|
||||
* Billion Card - Single Port BRI card (TE (/NT with crossed cable) )
|
||||
|
||||
|
||||
Miscellaneous other interfaces
|
||||
==============================
|
||||
|
||||
-- ISDN4Linux
|
||||
http://www.isdn4linux.de/
|
||||
|
||||
* Any ISDN terminal adapter supported by isdn4linux should provide
|
||||
connectivity.
|
||||
|
||||
-- ALSA
|
||||
http://www.alsa-project.org
|
||||
|
||||
7
LICENSE
7
LICENSE
@@ -32,7 +32,7 @@ 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 and
|
||||
OpenH323.
|
||||
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
|
||||
@@ -50,8 +50,7 @@ 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:
|
||||
@@ -59,7 +58,7 @@ contact us:
|
||||
+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/misery.digium.com/6000 (via IAX2)
|
||||
IAX2/pbx.digium.com (via IAX2)
|
||||
licensing@digium.com (via email)
|
||||
|
||||
Digium, Inc.
|
||||
|
||||
@@ -1,84 +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
|
||||
#
|
||||
|
||||
ifneq ($(findstring MALLOC_DEBUG,$(MENUSELECT_CFLAGS)),)
|
||||
ifeq ($(findstring astmm.h,$(ASTCFLAGS)),)
|
||||
ASTCFLAGS+=-include $(ASTTOPDIR)/include/asterisk/astmm.h
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),)
|
||||
ASTCFLAGS+=${GC_CFLAGS}
|
||||
endif
|
||||
|
||||
ifneq ($(findstring STATIC_BUILD,$(MENUSELECT_CFLAGS)),)
|
||||
STATIC_BUILD=-static
|
||||
endif
|
||||
|
||||
include $(ASTTOPDIR)/Makefile.rules
|
||||
|
||||
comma:=,
|
||||
|
||||
$(addsuffix .o,$(C_MODS)): ASTCFLAGS+=-DAST_MODULE=\"$*\" $(MENUSELECT_OPTS_$*:%=-D%) $(foreach dep,$(MENUSELECT_DEPENDS_$*),$(value $(dep)_INCLUDE))
|
||||
$(addsuffix .oo,$(CC_MODS)): ASTCFLAGS+=-DAST_MODULE=\"$*\" $(MENUSELECT_OPTS_$*:%=-D%) $(foreach dep,$(MENUSELECT_DEPENDS_$*),$(value $(dep)_INCLUDE))
|
||||
|
||||
$(LOADABLE_MODS:%=%.so): ASTCFLAGS+=-fPIC
|
||||
$(LOADABLE_MODS:%=%.so): LIBS+=$(foreach dep,$(MENUSELECT_DEPENDS_$*),$(value $(dep)_LIB))
|
||||
$(LOADABLE_MODS:%=%.so): ASTLDFLAGS+=$(foreach dep,$(MENUSELECT_DEPENDS_$*),$(value $(dep)_LDFLAGS))
|
||||
|
||||
$(addsuffix .so,$(filter $(LOADABLE_MODS),$(C_MODS))): %.so: %.o
|
||||
$(addsuffix .so,$(filter $(LOADABLE_MODS),$(CC_MODS))): %.so: %.oo
|
||||
|
||||
modules.link: $(addsuffix .o,$(filter $(EMBEDDED_MODS),$(C_MODS)))
|
||||
modules.link: $(addsuffix .oo,$(filter $(EMBEDDED_MODS),$(CC_MODS)))
|
||||
|
||||
.PHONY: clean uninstall _all
|
||||
|
||||
ifneq ($(LOADABLE_MODS),)
|
||||
_all: $(LOADABLE_MODS:%=%.so)
|
||||
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 %.o,$^)); do echo "INPUT (../$${file})" >> $@; done
|
||||
@for file in $(patsubst %,$(SUBDIR)/%,$(filter-out %.o,$^)); do echo "INPUT (../$${file})" >> $@; done
|
||||
|
||||
clean::
|
||||
rm -f *.so *.o *.oo
|
||||
rm -f .*.o.d .*.oo.d
|
||||
rm -f modules.link
|
||||
|
||||
install:: all
|
||||
for x in $(LOADABLE_MODS:%=%.so); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
|
||||
|
||||
uninstall::
|
||||
|
||||
ifneq ($(wildcard .*.d),)
|
||||
include .*.d
|
||||
endif
|
||||
@@ -1,81 +0,0 @@
|
||||
#
|
||||
# Asterisk -- A telephony toolkit for Linux.
|
||||
#
|
||||
# Makefile rules
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
# 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
|
||||
|
||||
ifeq ($(NOISY_BUILD),)
|
||||
ECHO_PREFIX=@
|
||||
CMD_PREFIX=@
|
||||
else
|
||||
ECHO_PREFIX=@\#
|
||||
CMD_PREFIX=
|
||||
endif
|
||||
|
||||
ifeq ($(findstring DONT_OPTIMIZE,$(MENUSELECT_CFLAGS)),)
|
||||
# More GSM codec optimization
|
||||
# Uncomment to enable MMXTM optimizations for x86 architecture CPU's
|
||||
# which support MMX instructions. This should be newer pentiums,
|
||||
# ppro's, etc, as well as the AMD K6 and K7.
|
||||
#K6OPT=-DK6OPT
|
||||
|
||||
OPTIMIZE?=-O6
|
||||
ASTCFLAGS+=$(OPTIMIZE)
|
||||
endif
|
||||
|
||||
%.o: %.c
|
||||
$(ECHO_PREFIX) echo " [CC] $< -> $@"
|
||||
ifeq ($(AST_DEVMODE),yes)
|
||||
$(CMD_PREFIX) $(CC) -o $@ -c $< $(PTHREAD_CFLAGS) $(ASTCFLAGS) -MMD -MT $@ -MF .$(subst /,_,$@).d -MP
|
||||
else
|
||||
$(CMD_PREFIX) $(CC) -o $@ -c $< $(PTHREAD_CFLAGS) $(ASTCFLAGS)
|
||||
endif
|
||||
|
||||
%.o: %.s
|
||||
$(ECHO_PREFIX) echo " [AS] $< -> $@"
|
||||
ifeq ($(AST_DEVMODE),yes)
|
||||
$(CMD_PREFIX) $(CC) -o $@ -c $< $(PTHREAD_CFLAGS) $(ASTCFLAGS) -MMD -MT $@ -MF .$(subst /,_,$@).d -MP
|
||||
else
|
||||
$(CMD_PREFIX) $(CC) -o $@ -c $< $(PTHREAD_CFLAGS) $(ASTCFLAGS)
|
||||
endif
|
||||
|
||||
%.oo: %.cc
|
||||
$(ECHO_PREFIX) echo " [CXX] $< -> $@"
|
||||
ifeq ($(AST_DEVMODE),yes)
|
||||
$(CMD_PREFIX) $(CXX) -o $@ -c $< $(PTHREAD_CFLAGS) $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations,$(ASTCFLAGS)) -MMD -MT $@ -MF .$(subst /,_,$@).d -MP
|
||||
else
|
||||
$(CMD_PREFIX) $(CXX) -o $@ -c $< $(PTHREAD_CFLAGS) $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations,$(ASTCFLAGS))
|
||||
endif
|
||||
|
||||
%.c: %.y
|
||||
$(ECHO_PREFIX) echo " [BISON] $< -> $@"
|
||||
$(CMD_PREFIX) bison -o $@ -d --name-prefix=ast_yy $<
|
||||
|
||||
%.c: %.fl
|
||||
$(ECHO_PREFIX) echo " [FLEX] $< -> $@"
|
||||
$(CMD_PREFIX) flex -o $@ --full $<
|
||||
|
||||
%.so: %.o
|
||||
$(ECHO_PREFIX) echo " [LD] $^ -> $@"
|
||||
$(CMD_PREFIX) $(CC) $(STATIC_BUILD) -o $@ $(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK) $^ $(PTHREAD_LIBS) $(LIBS)
|
||||
|
||||
%.so: %.oo
|
||||
$(ECHO_PREFIX) echo " [LDXX] $^ -> $@"
|
||||
$(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(PTHREAD_CFLAGS) $(ASTLDFLAGS) $(SOLINK) $^ $(PTHREAD_LIBS) $(LIBS)
|
||||
|
||||
%: %.o
|
||||
$(ECHO_PREFIX) echo " [LD] $^ -> $@"
|
||||
$(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(PTHREAD_CFLAGS) $(ASTLDFLAGS) $^ $(PTHREAD_LIBS) $(LIBS)
|
||||
44
README
44
README
@@ -1,15 +1,15 @@
|
||||
The Asterisk(R) Open Source PBX
|
||||
The Asterisk Open Source PBX
|
||||
by Mark Spencer <markster@digium.com>
|
||||
and the Asterisk.org developer community
|
||||
|
||||
Copyright (C) 2001-2006 Digium, Inc.
|
||||
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 file (doc/security.txt) before you attempt
|
||||
to configure and run an Asterisk server.
|
||||
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
|
||||
@@ -51,15 +51,13 @@ ANY special hardware, not even a soundcard) to install and run Asterisk.
|
||||
* 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 or OSS
|
||||
* any ISDN card supported by mISDN on Linux (BRI)
|
||||
* The Xorcom AstriBank channel bank
|
||||
* 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 and
|
||||
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
|
||||
@@ -84,31 +82,14 @@ On many distributions, these files are installed by packages with names like
|
||||
|
||||
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 modules dependencies.
|
||||
|
||||
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 the repository, you are strongly
|
||||
encouraged to ensure all previous object files are removed to avoid internal
|
||||
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.
|
||||
@@ -116,7 +97,7 @@ 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 config files you have.
|
||||
|
||||
@@ -257,6 +238,3 @@ you're interested in getting more information.
|
||||
Welcome to the growing worldwide community of Asterisk users!
|
||||
|
||||
Mark Spencer
|
||||
|
||||
----
|
||||
Asterisk is a trademark belonging to Digium, inc
|
||||
|
||||
295
README-SERIOUSLY.bestpractices.txt
Normal file
295
README-SERIOUSLY.bestpractices.txt
Normal file
@@ -0,0 +1,295 @@
|
||||
==================
|
||||
| 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
22
README.opsound
Normal 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
|
||||
638
UPGRADE.txt
638
UPGRADE.txt
@@ -1,461 +1,225 @@
|
||||
Information for Upgrading From Previous Asterisk Releases
|
||||
=========================================================
|
||||
|
||||
Build Process (configure script):
|
||||
IAX2:
|
||||
|
||||
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:
|
||||
* 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.
|
||||
|
||||
$ ./configure --help
|
||||
Compiling:
|
||||
|
||||
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.
|
||||
* 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.
|
||||
|
||||
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.
|
||||
Dialplan Expressions:
|
||||
|
||||
Build Process (module selection):
|
||||
* 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.
|
||||
|
||||
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.
|
||||
Agents:
|
||||
|
||||
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.
|
||||
* 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.
|
||||
|
||||
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'.
|
||||
* 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.
|
||||
|
||||
Build Process (Makefile targets):
|
||||
Parking:
|
||||
|
||||
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.
|
||||
* 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.
|
||||
|
||||
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'.
|
||||
Dialing:
|
||||
|
||||
Sound (prompt) and Music On Hold files:
|
||||
* 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.
|
||||
|
||||
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.
|
||||
IAX:
|
||||
|
||||
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.
|
||||
* 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.
|
||||
|
||||
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.
|
||||
SIP:
|
||||
|
||||
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.
|
||||
* 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.
|
||||
|
||||
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 '!'.
|
||||
* The "Registry" event now uses "Username" rather than "User" for
|
||||
consistency with IAX.
|
||||
|
||||
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.
|
||||
|
||||
* 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'.
|
||||
|
||||
* 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:
|
||||
|
||||
* 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
|
||||
* 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
|
||||
|
||||
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.
|
||||
|
||||
943
acinclude.m4
943
acinclude.m4
@@ -1,943 +0,0 @@
|
||||
# AST_GCC_ATTRIBUTE([attribute name])
|
||||
|
||||
AC_DEFUN([AST_GCC_ATTRIBUTE],
|
||||
[
|
||||
AC_MSG_CHECKING(for compiler 'attribute $1' support)
|
||||
AC_COMPILE_IFELSE(
|
||||
AC_LANG_PROGRAM([static int __attribute__(($1)) test(void) {}],
|
||||
[]),
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE_UNQUOTED([HAVE_ATTRIBUTE_$1], 1, [Define to 1 if your GCC C compiler supports the '$1' attribute.]),
|
||||
AC_MSG_RESULT(no))
|
||||
])
|
||||
|
||||
# AST_EXT_LIB_SETUP([package symbol name], [package friendly name], [package option name], [additional help text])
|
||||
|
||||
AC_DEFUN([AST_EXT_LIB_SETUP],
|
||||
[
|
||||
$1_DESCRIP="$2"
|
||||
$1_OPTION="$3"
|
||||
AC_ARG_WITH([$3], AC_HELP_STRING([--with-$3=PATH],[use $2 files in PATH $4]),[
|
||||
case ${withval} in
|
||||
n|no)
|
||||
USE_$1=no
|
||||
;;
|
||||
y|ye|yes)
|
||||
$1_MANDATORY="yes"
|
||||
;;
|
||||
*)
|
||||
$1_DIR="${withval}"
|
||||
$1_MANDATORY="yes"
|
||||
;;
|
||||
esac
|
||||
])
|
||||
PBX_$1=0
|
||||
AC_SUBST([$1_LIB])
|
||||
AC_SUBST([$1_INCLUDE])
|
||||
AC_SUBST([$1_DIR])
|
||||
AC_SUBST([PBX_$1])
|
||||
])
|
||||
|
||||
# AST_EXT_LIB_CHECK([package symbol name], [package library name], [function to check], [package header], [additional LIB data])
|
||||
|
||||
AC_DEFUN([AST_EXT_LIB_CHECK],
|
||||
[
|
||||
if test "${USE_$1}" != "no"; then
|
||||
pbxlibdir=""
|
||||
if test "x${$1_DIR}" != "x"; then
|
||||
if test -d ${$1_DIR}/lib; then
|
||||
pbxlibdir="-L${$1_DIR}/lib"
|
||||
else
|
||||
pbxlibdir="-L${$1_DIR}"
|
||||
fi
|
||||
fi
|
||||
AC_CHECK_LIB([$2], [$3], [AST_$1_FOUND=yes], [AST_$1_FOUND=no], ${pbxlibdir} $5)
|
||||
|
||||
if test "${AST_$1_FOUND}" = "yes"; then
|
||||
$1_LIB="-l$2 $5"
|
||||
$1_HEADER_FOUND="1"
|
||||
if test "x${$1_DIR}" != "x"; then
|
||||
$1_LIB="${pbxlibdir} ${$1_LIB}"
|
||||
$1_INCLUDE="-I${$1_DIR}/include"
|
||||
saved_cppflags="${CPPFLAGS}"
|
||||
CPPFLAGS="${CPPFLAGS} -I${$1_DIR}/include"
|
||||
if test "x$4" != "x" ; then
|
||||
AC_CHECK_HEADER([${$1_DIR}/include/$4], [$1_HEADER_FOUND=1], [$1_HEADER_FOUND=0])
|
||||
fi
|
||||
CPPFLAGS="${saved_cppflags}"
|
||||
else
|
||||
if test "x$4" != "x" ; then
|
||||
AC_CHECK_HEADER([$4], [$1_HEADER_FOUND=1], [$1_HEADER_FOUND=0])
|
||||
fi
|
||||
fi
|
||||
if test "x${$1_HEADER_FOUND}" = "x0" ; then
|
||||
if test -n "${$1_MANDATORY}" ;
|
||||
then
|
||||
AC_MSG_NOTICE([***])
|
||||
AC_MSG_NOTICE([*** It appears that you do not have the $2 development package installed.])
|
||||
AC_MSG_NOTICE([*** Please install it to include ${$1_DESCRIP} support, or re-run configure])
|
||||
AC_MSG_NOTICE([*** without explicitly specifying --with-${$1_OPTION}])
|
||||
exit 1
|
||||
fi
|
||||
$1_LIB=""
|
||||
$1_INCLUDE=""
|
||||
PBX_$1=0
|
||||
else
|
||||
PBX_$1=1
|
||||
AC_DEFINE_UNQUOTED([HAVE_$1], 1, [Define to indicate the ${$1_DESCRIP} library])
|
||||
fi
|
||||
elif test -n "${$1_MANDATORY}";
|
||||
then
|
||||
AC_MSG_NOTICE([***])
|
||||
AC_MSG_NOTICE([*** The ${$1_DESCRIP} installation on this system appears to be broken.])
|
||||
AC_MSG_NOTICE([*** Either correct the installation, or run configure])
|
||||
AC_MSG_NOTICE([*** without explicitly specifying --with-${$1_OPTION}])
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN(
|
||||
[AST_CHECK_GNU_MAKE], [AC_CACHE_CHECK(for GNU make, GNU_MAKE,
|
||||
GNU_MAKE='Not Found' ;
|
||||
GNU_MAKE_VERSION_MAJOR=0 ;
|
||||
GNU_MAKE_VERSION_MINOR=0 ;
|
||||
for a in make gmake gnumake ; do
|
||||
if test -z "$a" ; then continue ; fi ;
|
||||
if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) ; then
|
||||
GNU_MAKE=$a ;
|
||||
GNU_MAKE_VERSION_MAJOR=`$GNU_MAKE --version | grep "GNU Make" | cut -f3 -d' ' | cut -f1 -d'.'`
|
||||
GNU_MAKE_VERSION_MINOR=`$GNU_MAKE --version | grep "GNU Make" | cut -f2 -d'.' | cut -c1-2`
|
||||
break;
|
||||
fi
|
||||
done ;
|
||||
) ;
|
||||
if test "x$GNU_MAKE" = "xNot Found" ; then
|
||||
AC_MSG_ERROR( *** Please install GNU make. It is required to build Asterisk!)
|
||||
exit 1
|
||||
fi
|
||||
AC_SUBST([GNU_MAKE])
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN(
|
||||
[AST_CHECK_PWLIB], [
|
||||
PWLIB_INCDIR=
|
||||
PWLIB_LIBDIR=
|
||||
AC_LANG_PUSH([C++])
|
||||
if test "${PWLIBDIR:-unset}" != "unset" ; then
|
||||
AC_CHECK_HEADER(${PWLIBDIR}/version.h, HAS_PWLIB=1, )
|
||||
fi
|
||||
if test "${HAS_PWLIB:-unset}" = "unset" ; then
|
||||
if test "${OPENH323DIR:-unset}" != "unset"; then
|
||||
AC_CHECK_HEADER(${OPENH323DIR}/../pwlib/version.h, HAS_PWLIB=1, )
|
||||
fi
|
||||
if test "${HAS_PWLIB:-unset}" != "unset" ; then
|
||||
PWLIBDIR="${OPENH323DIR}/../pwlib"
|
||||
else
|
||||
AC_CHECK_HEADER(${HOME}/pwlib/include/ptlib.h, HAS_PWLIB=1, )
|
||||
if test "${HAS_PWLIB:-unset}" != "unset" ; then
|
||||
PWLIBDIR="${HOME}/pwlib"
|
||||
else
|
||||
AC_CHECK_HEADER(/usr/local/include/ptlib.h, HAS_PWLIB=1, )
|
||||
if test "${HAS_PWLIB:-unset}" != "unset" ; then
|
||||
AC_PATH_PROG(PTLIB_CONFIG, ptlib-config, , /usr/local/bin)
|
||||
if test "${PTLIB_CONFIG:-unset}" = "unset" ; then
|
||||
AC_PATH_PROG(PTLIB_CONFIG, ptlib-config, , /usr/local/share/pwlib/make)
|
||||
fi
|
||||
PWLIB_INCDIR="/usr/local/include"
|
||||
PWLIB_LIBDIR=`${PTLIB_CONFIG} --pwlibdir`
|
||||
if test "${PWLIB_LIBDIR:-unset}" = "unset"; then
|
||||
if test "x$LIB64" != "x"; then
|
||||
PWLIB_LIBDIR="/usr/local/lib64"
|
||||
else
|
||||
PWLIB_LIBDIR="/usr/local/lib"
|
||||
fi
|
||||
fi
|
||||
PWLIB_LIB=`${PTLIB_CONFIG} --ldflags --libs`
|
||||
PWLIB_LIB="-L${PWLIB_LIBDIR} `echo ${PWLIB_LIB}`"
|
||||
else
|
||||
AC_CHECK_HEADER(/usr/include/ptlib.h, HAS_PWLIB=1, )
|
||||
if test "${HAS_PWLIB:-unset}" != "unset" ; then
|
||||
AC_PATH_PROG(PTLIB_CONFIG, ptlib-config, , /usr/share/pwlib/make)
|
||||
PWLIB_INCDIR="/usr/include"
|
||||
PWLIB_LIBDIR=`${PTLIB_CONFIG} --pwlibdir`
|
||||
if test "${PWLIB_LIBDIR:-unset}" = "unset"; then
|
||||
if test "x$LIB64" != "x"; then
|
||||
PWLIB_LIBDIR="/usr/lib64"
|
||||
else
|
||||
PWLIB_LIBDIR="/usr/lib"
|
||||
fi
|
||||
fi
|
||||
PWLIB_LIB=`${PTLIB_CONFIG} --ldflags --libs`
|
||||
PWLIB_LIB="-L${PWLIB_LIBDIR} `echo ${PWLIB_LIB}`"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
#if test "${HAS_PWLIB:-unset}" = "unset" ; then
|
||||
# echo "Cannot find pwlib - please install or set PWLIBDIR and try again"
|
||||
# exit
|
||||
#fi
|
||||
|
||||
if test "${HAS_PWLIB:-unset}" != "unset" ; then
|
||||
if test "${PWLIBDIR:-unset}" = "unset" ; then
|
||||
if test "${PTLIB_CONFIG:-unset}" != "unset" ; then
|
||||
PWLIBDIR=`$PTLIB_CONFIG --prefix`
|
||||
else
|
||||
echo "Cannot find ptlib-config - please install and try again"
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$PWLIBDIR" = "x/usr" -o "x$PWLIBDIR" = "x/usr/"; then
|
||||
PWLIBDIR="/usr/share/pwlib"
|
||||
PWLIB_INCDIR="/usr/include"
|
||||
if test "x$LIB64" != "x"; then
|
||||
PWLIB_LIBDIR="/usr/lib64"
|
||||
else
|
||||
PWLIB_LIBDIR="/usr/lib"
|
||||
fi
|
||||
fi
|
||||
if test "x$PWLIBDIR" = "x/usr/local" -o "x$PWLIBDIR" = "x/usr/"; then
|
||||
PWLIBDIR="/usr/local/share/pwlib"
|
||||
PWLIB_INCDIR="/usr/local/include"
|
||||
if test "x$LIB64" != "x"; then
|
||||
PWLIB_LIBDIR="/usr/local/lib64"
|
||||
else
|
||||
PWLIB_LIBDIR="/usr/local/lib"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "${PWLIB_INCDIR:-unset}" = "unset"; then
|
||||
PWLIB_INCDIR="${PWLIBDIR}/include"
|
||||
fi
|
||||
if test "${PWLIB_LIBDIR:-unset}" = "unset"; then
|
||||
PWLIB_LIBDIR="${PWLIBDIR}/lib"
|
||||
fi
|
||||
|
||||
AC_SUBST([PWLIBDIR])
|
||||
AC_SUBST([PWLIB_INCDIR])
|
||||
AC_SUBST([PWLIB_LIBDIR])
|
||||
fi
|
||||
AC_LANG_POP([C++])
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN(
|
||||
[AST_CHECK_OPENH323_PLATFORM], [
|
||||
PWLIB_OSTYPE=
|
||||
case "$host_os" in
|
||||
linux*) PWLIB_OSTYPE=linux ;
|
||||
;;
|
||||
freebsd* ) PWLIB_OSTYPE=FreeBSD ;
|
||||
;;
|
||||
openbsd* ) PWLIB_OSTYPE=OpenBSD ;
|
||||
ENDLDLIBS="-lossaudio" ;
|
||||
;;
|
||||
netbsd* ) PWLIB_OSTYPE=NetBSD ;
|
||||
ENDLDLIBS="-lossaudio" ;
|
||||
;;
|
||||
solaris* | sunos* ) PWLIB_OSTYPE=solaris ;
|
||||
;;
|
||||
darwin* ) PWLIB_OSTYPE=Darwin ;
|
||||
;;
|
||||
beos*) PWLIB_OSTYPE=beos ;
|
||||
STDCCFLAGS="$STDCCFLAGS -D__BEOS__"
|
||||
;;
|
||||
cygwin*) PWLIB_OSTYPE=cygwin ;
|
||||
;;
|
||||
mingw*) PWLIB_OSTYPE=mingw ;
|
||||
STDCCFLAGS="$STDCCFLAGS -mms-bitfields" ;
|
||||
ENDLDLIBS="-lwinmm -lwsock32 -lsnmpapi -lmpr -lcomdlg32 -lgdi32 -lavicap32" ;
|
||||
;;
|
||||
* ) PWLIB_OSTYPE="$host_os" ;
|
||||
AC_MSG_WARN("OS $PWLIB_OSTYPE not recognized - proceed with caution!") ;
|
||||
;;
|
||||
esac
|
||||
|
||||
PWLIB_MACHTYPE=
|
||||
case "$host_cpu" in
|
||||
x86 | i686 | i586 | i486 | i386 ) PWLIB_MACHTYPE=x86
|
||||
;;
|
||||
|
||||
x86_64) PWLIB_MACHTYPE=x86_64 ;
|
||||
P_64BIT=1 ;
|
||||
LIB64=1 ;
|
||||
;;
|
||||
|
||||
alpha | alphaev56 | alphaev6 | alphaev67 | alphaev7) PWLIB_MACHTYPE=alpha ;
|
||||
P_64BIT=1 ;
|
||||
;;
|
||||
|
||||
sparc ) PWLIB_MACHTYPE=sparc ;
|
||||
;;
|
||||
|
||||
powerpc ) PWLIB_MACHTYPE=ppc ;
|
||||
;;
|
||||
|
||||
ppc ) PWLIB_MACHTYPE=ppc ;
|
||||
;;
|
||||
|
||||
powerpc64 ) PWLIB_MACHTYPE=ppc64 ;
|
||||
P_64BIT=1 ;
|
||||
LIB64=1 ;
|
||||
;;
|
||||
|
||||
ppc64 ) PWLIB_MACHTYPE=ppc64 ;
|
||||
P_64BIT=1 ;
|
||||
LIB64=1 ;
|
||||
;;
|
||||
|
||||
ia64) PWLIB_MACHTYPE=ia64 ;
|
||||
P_64BIT=1 ;
|
||||
;;
|
||||
|
||||
s390x) PWLIB_MACHTYPE=s390x ;
|
||||
P_64BIT=1 ;
|
||||
LIB64=1 ;
|
||||
;;
|
||||
|
||||
s390) PWLIB_MACHTYPE=s390 ;
|
||||
;;
|
||||
|
||||
* ) PWLIB_MACHTYPE="$host_cpu";
|
||||
AC_MSG_WARN("CPU $PWLIB_MACHTYPE not recognized - proceed with caution!") ;;
|
||||
esac
|
||||
|
||||
PWLIB_PLATFORM="${PWLIB_OSTYPE}_${PWLIB_MACHTYPE}"
|
||||
|
||||
AC_SUBST([PWLIB_PLATFORM])
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN(
|
||||
[AST_CHECK_OPENH323], [
|
||||
OPENH323_INCDIR=
|
||||
OPENH323_LIBDIR=
|
||||
AC_LANG_PUSH([C++])
|
||||
if test "${OPENH323DIR:-unset}" != "unset" ; then
|
||||
AC_CHECK_HEADER(${OPENH323DIR}/version.h, HAS_OPENH323=1, )
|
||||
fi
|
||||
if test "${HAS_OPENH323:-unset}" = "unset" ; then
|
||||
AC_CHECK_HEADER(${PWLIBDIR}/../openh323/version.h, OPENH323DIR="${PWLIBDIR}/../openh323"; HAS_OPENH323=1, )
|
||||
if test "${HAS_OPENH323:-unset}" != "unset" ; then
|
||||
OPENH323DIR="${PWLIBDIR}/../openh323"
|
||||
AC_CHECK_HEADER(${OPENH323DIR}/include/h323.h, , OPENH323_INCDIR="${PWLIB_INCDIR}/openh323"; OPENH323_LIBDIR="${PWLIB_LIBDIR}")
|
||||
else
|
||||
AC_CHECK_HEADER(${HOME}/openh323/include/h323.h, HAS_OPENH323=1, )
|
||||
if test "${HAS_OPENH323:-unset}" != "unset" ; then
|
||||
OPENH323DIR="${HOME}/openh323"
|
||||
else
|
||||
AC_CHECK_HEADER(/usr/local/include/openh323/h323.h, HAS_OPENH323=1, )
|
||||
if test "${HAS_OPENH323:-unset}" != "unset" ; then
|
||||
OPENH323DIR="/usr/local/share/openh323"
|
||||
OPENH323_INCDIR="/usr/local/include/openh323"
|
||||
if test "x$LIB64" != "x"; then
|
||||
OPENH323_LIBDIR="/usr/local/lib64"
|
||||
else
|
||||
OPENH323_LIBDIR="/usr/local/lib"
|
||||
fi
|
||||
else
|
||||
AC_CHECK_HEADER(/usr/include/openh323/h323.h, HAS_OPENH323=1, )
|
||||
if test "${HAS_OPENH323:-unset}" != "unset" ; then
|
||||
OPENH323DIR="/usr/share/openh323"
|
||||
OPENH323_INCDIR="/usr/include/openh323"
|
||||
if test "x$LIB64" != "x"; then
|
||||
OPENH323_LIBDIR="/usr/lib64"
|
||||
else
|
||||
OPENH323_LIBDIR="/usr/lib"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "${HAS_OPENH323:-unset}" != "unset" ; then
|
||||
if test "${OPENH323_INCDIR:-unset}" = "unset"; then
|
||||
OPENH323_INCDIR="${OPENH323DIR}/include"
|
||||
fi
|
||||
if test "${OPENH323_LIBDIR:-unset}" = "unset"; then
|
||||
OPENH323_LIBDIR="${OPENH323DIR}/lib"
|
||||
fi
|
||||
|
||||
OPENH323_LIBDIR="`cd ${OPENH323_LIBDIR}; pwd`"
|
||||
OPENH323_INCDIR="`cd ${OPENH323_INCDIR}; pwd`"
|
||||
OPENH323DIR="`cd ${OPENH323DIR}; pwd`"
|
||||
|
||||
AC_SUBST([OPENH323DIR])
|
||||
AC_SUBST([OPENH323_INCDIR])
|
||||
AC_SUBST([OPENH323_LIBDIR])
|
||||
fi
|
||||
AC_LANG_POP([C++])
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN(
|
||||
[AST_CHECK_PWLIB_VERSION], [
|
||||
if test "${HAS_$2:-unset}" != "unset"; then
|
||||
$2_VERSION=`grep "$2_VERSION" ${$2_INCDIR}/$3 | cut -f2 -d ' ' | sed -e 's/"//g'`
|
||||
$2_MAJOR_VERSION=`echo ${$2_VERSION} | cut -f1 -d.`
|
||||
$2_MINOR_VERSION=`echo ${$2_VERSION} | cut -f2 -d.`
|
||||
$2_BUILD_NUMBER=`echo ${$2_VERSION} | cut -f3 -d.`
|
||||
let $2_VER=${$2_MAJOR_VERSION}*10000+${$2_MINOR_VERSION}*100+${$2_BUILD_NUMBER}
|
||||
let $2_REQ=$4*10000+$5*100+$6
|
||||
|
||||
AC_MSG_CHECKING(if $1 version ${$2_VERSION} is compatible with chan_h323)
|
||||
if test ${$2_VER} -lt ${$2_REQ}; then
|
||||
AC_MSG_RESULT(no)
|
||||
unset HAS_$2
|
||||
else
|
||||
AC_MSG_RESULT(yes)
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN(
|
||||
[AST_CHECK_PWLIB_BUILD], [
|
||||
if test "${HAS_$2:-unset}" != "unset"; then
|
||||
AC_MSG_CHECKING($1 installation validity)
|
||||
|
||||
saved_cppflags="${CPPFLAGS}"
|
||||
saved_libs="${LIBS}"
|
||||
if test "${$2_LIB:-unset}" != "unset"; then
|
||||
LIBS="${LIBS} ${$2_LIB} $7"
|
||||
else
|
||||
LIBS="${LIBS} -L${$2_LIBDIR} -l${PLATFORM_$2} $7"
|
||||
fi
|
||||
CPPFLAGS="${CPPFLAGS} -I${$2_INCDIR} $6"
|
||||
|
||||
AC_LANG_PUSH([C++])
|
||||
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([$4],[$5])],
|
||||
[ AC_MSG_RESULT(yes)
|
||||
ac_cv_lib_$2="yes"
|
||||
],
|
||||
[ AC_MSG_RESULT(no)
|
||||
ac_cv_lib_$2="no"
|
||||
]
|
||||
)
|
||||
|
||||
AC_LANG_POP([C++])
|
||||
|
||||
LIBS="${saved_libs}"
|
||||
CPPFLAGS="${saved_cppflags}"
|
||||
|
||||
if test "${ac_cv_lib_$2}" = "yes"; then
|
||||
if test "${$2_LIB:-undef}" = "undef"; then
|
||||
if test "${$2_LIBDIR}" != "" -a "${$2_LIBDIR}" != "/usr/lib"; then
|
||||
$2_LIB="-L${$2_LIBDIR} -l${PLATFORM_$2}"
|
||||
else
|
||||
$2_LIB="-l${PLATFORM_$2}"
|
||||
fi
|
||||
fi
|
||||
if test "${$2_INCDIR}" != "" -a "${$2_INCDIR}" != "/usr/include"; then
|
||||
$2_INCLUDE="-I${$2_INCDIR}"
|
||||
fi
|
||||
PBX_$2=1
|
||||
AC_DEFINE([HAVE_$2], 1, [$3])
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN(
|
||||
[AST_CHECK_OPENH323_BUILD], [
|
||||
if test "${HAS_OPENH323:-unset}" != "unset"; then
|
||||
AC_MSG_CHECKING(OpenH323 build option)
|
||||
OPENH323_SUFFIX=
|
||||
prefixes="h323_${PWLIB_PLATFORM}_ h323_ openh323"
|
||||
for pfx in $prefixes; do
|
||||
files=`ls -l ${OPENH323_LIBDIR}/lib${pfx}*.so* 2>/dev/null`
|
||||
libfile=
|
||||
if test -n "$files"; then
|
||||
for f in $files; do
|
||||
if test -f $f -a ! -L $f; then
|
||||
libfile=`basename $f`
|
||||
break;
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if test -n "$libfile"; then
|
||||
OPENH323_PREFIX=$pfx
|
||||
break;
|
||||
fi
|
||||
done
|
||||
if test "${libfile:-unset}" != "unset"; then
|
||||
OPENH323_SUFFIX=`eval "echo ${libfile} | sed -e 's/lib${OPENH323_PREFIX}\(@<:@^.@:>@*\)\..*/\1/'"`
|
||||
fi
|
||||
case "${OPENH323_SUFFIX}" in
|
||||
n)
|
||||
OPENH323_BUILD="notrace";;
|
||||
r)
|
||||
OPENH323_BUILD="opt";;
|
||||
d)
|
||||
OPENH323_BUILD="debug";;
|
||||
*)
|
||||
if test "${OPENH323_PREFIX:-undef}" = "openh323"; then
|
||||
notrace=`eval "grep NOTRACE ${OPENH323DIR}/openh323u.mak | grep = | sed -e 's/@<:@A-Z0-9_@:>@*@<:@ @:>@*=@<:@ @:>@*//'"`
|
||||
if test "x$notrace" = "x"; then
|
||||
notrace="0"
|
||||
fi
|
||||
if test "$notrace" -ne 0; then
|
||||
OPENH323_BUILD="notrace"
|
||||
else
|
||||
OPENH323_BUILD="opt"
|
||||
fi
|
||||
OPENH323_LIB="-l${OPENH323_PREFIX}"
|
||||
else
|
||||
OPENH323_BUILD="notrace"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AC_MSG_RESULT(${OPENH323_BUILD})
|
||||
|
||||
AC_SUBST([OPENH323_SUFFIX])
|
||||
AC_SUBST([OPENH323_BUILD])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
# AST_FUNC_FORK
|
||||
# -------------
|
||||
AN_FUNCTION([fork], [AST_FUNC_FORK])
|
||||
AN_FUNCTION([vfork], [AST_FUNC_FORK])
|
||||
AC_DEFUN([AST_FUNC_FORK],
|
||||
[AC_REQUIRE([AC_TYPE_PID_T])dnl
|
||||
AC_CHECK_HEADERS(vfork.h)
|
||||
AC_CHECK_FUNCS(fork vfork)
|
||||
if test "x$ac_cv_func_fork" = xyes; then
|
||||
_AST_FUNC_FORK
|
||||
else
|
||||
ac_cv_func_fork_works=$ac_cv_func_fork
|
||||
fi
|
||||
if test "x$ac_cv_func_fork_works" = xcross; then
|
||||
case $host in
|
||||
*-*-amigaos* | *-*-msdosdjgpp* | *-*-uclinux* | *-*-linux-uclibc* )
|
||||
# Override, as these systems have only a dummy fork() stub
|
||||
ac_cv_func_fork_works=no
|
||||
;;
|
||||
*)
|
||||
ac_cv_func_fork_works=yes
|
||||
;;
|
||||
esac
|
||||
AC_MSG_WARN([result $ac_cv_func_fork_works guessed because of cross compilation])
|
||||
fi
|
||||
ac_cv_func_vfork_works=$ac_cv_func_vfork
|
||||
if test "x$ac_cv_func_vfork" = xyes; then
|
||||
_AC_FUNC_VFORK
|
||||
fi;
|
||||
if test "x$ac_cv_func_fork_works" = xcross; then
|
||||
ac_cv_func_vfork_works=$ac_cv_func_vfork
|
||||
AC_MSG_WARN([result $ac_cv_func_vfork_works guessed because of cross compilation])
|
||||
fi
|
||||
|
||||
if test "x$ac_cv_func_vfork_works" = xyes; then
|
||||
AC_DEFINE(HAVE_WORKING_VFORK, 1, [Define to 1 if `vfork' works.])
|
||||
else
|
||||
AC_DEFINE(vfork, fork, [Define as `fork' if `vfork' does not work.])
|
||||
fi
|
||||
if test "x$ac_cv_func_fork_works" = xyes; then
|
||||
AC_DEFINE(HAVE_WORKING_FORK, 1, [Define to 1 if `fork' works.])
|
||||
fi
|
||||
])# AST_FUNC_FORK
|
||||
|
||||
|
||||
# _AST_FUNC_FORK
|
||||
# -------------
|
||||
AC_DEFUN([_AST_FUNC_FORK],
|
||||
[AC_CACHE_CHECK(for working fork, ac_cv_func_fork_works,
|
||||
[AC_RUN_IFELSE(
|
||||
[AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
|
||||
[
|
||||
/* By Ruediger Kuhlmann. */
|
||||
return fork () < 0;
|
||||
])],
|
||||
[ac_cv_func_fork_works=yes],
|
||||
[ac_cv_func_fork_works=no],
|
||||
[ac_cv_func_fork_works=cross])])]
|
||||
)# _AST_FUNC_FORK
|
||||
|
||||
# AST_PROG_LD
|
||||
# ----------
|
||||
# find the pathname to the GNU or non-GNU linker
|
||||
AC_DEFUN([AST_PROG_LD],
|
||||
[AC_ARG_WITH([gnu-ld],
|
||||
[AC_HELP_STRING([--with-gnu-ld],
|
||||
[assume the C compiler uses GNU ld @<:@default=no@:>@])],
|
||||
[test "$withval" = no || with_gnu_ld=yes],
|
||||
[with_gnu_ld=no])
|
||||
AC_REQUIRE([AST_PROG_SED])dnl
|
||||
AC_REQUIRE([AC_PROG_CC])dnl
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])dnl
|
||||
AC_REQUIRE([AC_CANONICAL_BUILD])dnl
|
||||
ac_prog=ld
|
||||
if test "$GCC" = yes; then
|
||||
# Check if gcc -print-prog-name=ld gives a path.
|
||||
AC_MSG_CHECKING([for ld used by $CC])
|
||||
case $host in
|
||||
*-*-mingw*)
|
||||
# gcc leaves a trailing carriage return which upsets mingw
|
||||
ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
|
||||
*)
|
||||
ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
|
||||
esac
|
||||
case $ac_prog in
|
||||
# Accept absolute paths.
|
||||
[[\\/]]* | ?:[[\\/]]*)
|
||||
re_direlt='/[[^/]][[^/]]*/\.\./'
|
||||
# Canonicalize the pathname of ld
|
||||
ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
|
||||
while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
|
||||
ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
|
||||
done
|
||||
test -z "$LD" && LD="$ac_prog"
|
||||
;;
|
||||
"")
|
||||
# If it fails, then pretend we aren't using GCC.
|
||||
ac_prog=ld
|
||||
;;
|
||||
*)
|
||||
# If it is relative, then search for the first ld in PATH.
|
||||
with_gnu_ld=unknown
|
||||
;;
|
||||
esac
|
||||
elif test "$with_gnu_ld" = yes; then
|
||||
AC_MSG_CHECKING([for GNU ld])
|
||||
else
|
||||
AC_MSG_CHECKING([for non-GNU ld])
|
||||
fi
|
||||
AC_CACHE_VAL(lt_cv_path_LD,
|
||||
[if test -z "$LD"; then
|
||||
lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
|
||||
for ac_dir in $PATH; do
|
||||
IFS="$lt_save_ifs"
|
||||
test -z "$ac_dir" && ac_dir=.
|
||||
if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
|
||||
lt_cv_path_LD="$ac_dir/$ac_prog"
|
||||
# Check to see if the program is GNU ld. I'd rather use --version,
|
||||
# but apparently some variants of GNU ld only accept -v.
|
||||
# Break only if it was the GNU/non-GNU ld that we prefer.
|
||||
case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
|
||||
*GNU* | *'with BFD'*)
|
||||
test "$with_gnu_ld" != no && break
|
||||
;;
|
||||
*)
|
||||
test "$with_gnu_ld" != yes && break
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
done
|
||||
IFS="$lt_save_ifs"
|
||||
else
|
||||
lt_cv_path_LD="$LD" # Let the user override the test with a path.
|
||||
fi])
|
||||
LD="$lt_cv_path_LD"
|
||||
if test -n "$LD"; then
|
||||
AC_MSG_RESULT($LD)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
|
||||
AST_PROG_LD_GNU
|
||||
])# AST_PROG_LD
|
||||
|
||||
|
||||
# AST_PROG_LD_GNU
|
||||
# --------------
|
||||
AC_DEFUN([AST_PROG_LD_GNU],
|
||||
[AC_REQUIRE([AST_PROG_EGREP])dnl
|
||||
AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
|
||||
[# I'd rather use --version here, but apparently some GNU lds only accept -v.
|
||||
case `$LD -v 2>&1 </dev/null` in
|
||||
*GNU* | *'with BFD'*)
|
||||
lt_cv_prog_gnu_ld=yes
|
||||
;;
|
||||
*)
|
||||
lt_cv_prog_gnu_ld=no
|
||||
;;
|
||||
esac])
|
||||
with_gnu_ld=$lt_cv_prog_gnu_ld
|
||||
])# AST_PROG_LD_GNU
|
||||
|
||||
# AST_PROG_EGREP
|
||||
# -------------
|
||||
m4_ifndef([AST_PROG_EGREP], [AC_DEFUN([AST_PROG_EGREP],
|
||||
[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep],
|
||||
[if echo a | (grep -E '(a|b)') >/dev/null 2>&1
|
||||
then ac_cv_prog_egrep='grep -E'
|
||||
else ac_cv_prog_egrep='egrep'
|
||||
fi])
|
||||
EGREP=$ac_cv_prog_egrep
|
||||
AC_SUBST([EGREP])
|
||||
])]) # AST_PROG_EGREP
|
||||
|
||||
# AST_PROG_SED
|
||||
# -----------
|
||||
# Check for a fully functional sed program that truncates
|
||||
# as few characters as possible. Prefer GNU sed if found.
|
||||
AC_DEFUN([AST_PROG_SED],
|
||||
[AC_CACHE_CHECK([for a sed that does not truncate output], ac_cv_path_SED,
|
||||
[dnl ac_script should not contain more than 99 commands (for HP-UX sed),
|
||||
dnl but more than about 7000 bytes, to catch a limit in Solaris 8 /usr/ucb/sed.
|
||||
ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
|
||||
for ac_i in 1 2 3 4 5 6 7; do
|
||||
ac_script="$ac_script$as_nl$ac_script"
|
||||
done
|
||||
echo "$ac_script" | sed 99q >conftest.sed
|
||||
$as_unset ac_script || ac_script=
|
||||
_AC_PATH_PROG_FEATURE_CHECK(SED, [sed gsed],
|
||||
[_AC_FEATURE_CHECK_LENGTH([ac_path_SED], [ac_cv_path_SED],
|
||||
["$ac_path_SED" -f conftest.sed])])])
|
||||
SED="$ac_cv_path_SED"
|
||||
AC_SUBST([SED])dnl
|
||||
rm -f conftest.sed
|
||||
])# AST_PROG_SED
|
||||
|
||||
dnl @synopsis ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
|
||||
dnl
|
||||
dnl @summary figure out how to build C programs using POSIX threads
|
||||
dnl
|
||||
dnl This macro figures out how to build C programs using POSIX threads.
|
||||
dnl It sets the PTHREAD_LIBS output variable to the threads library and
|
||||
dnl linker flags, and the PTHREAD_CFLAGS output variable to any special
|
||||
dnl C compiler flags that are needed. (The user can also force certain
|
||||
dnl compiler flags/libs to be tested by setting these environment
|
||||
dnl variables.)
|
||||
dnl
|
||||
dnl Also sets PTHREAD_CC to any special C compiler that is needed for
|
||||
dnl multi-threaded programs (defaults to the value of CC otherwise).
|
||||
dnl (This is necessary on AIX to use the special cc_r compiler alias.)
|
||||
dnl
|
||||
dnl NOTE: You are assumed to not only compile your program with these
|
||||
dnl flags, but also link it with them as well. e.g. you should link
|
||||
dnl with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS
|
||||
dnl $LIBS
|
||||
dnl
|
||||
dnl If you are only building threads programs, you may wish to use
|
||||
dnl these variables in your default LIBS, CFLAGS, and CC:
|
||||
dnl
|
||||
dnl LIBS="$PTHREAD_LIBS $LIBS"
|
||||
dnl CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
dnl CC="$PTHREAD_CC"
|
||||
dnl
|
||||
dnl In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute
|
||||
dnl constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to
|
||||
dnl that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
||||
dnl
|
||||
dnl ACTION-IF-FOUND is a list of shell commands to run if a threads
|
||||
dnl library is found, and ACTION-IF-NOT-FOUND is a list of commands to
|
||||
dnl run it if it is not found. If ACTION-IF-FOUND is not specified, the
|
||||
dnl default action will define HAVE_PTHREAD.
|
||||
dnl
|
||||
dnl Please let the authors know if this macro fails on any platform, or
|
||||
dnl if you have any other suggestions or comments. This macro was based
|
||||
dnl on work by SGJ on autoconf scripts for FFTW (www.fftw.org) (with
|
||||
dnl help from M. Frigo), as well as ac_pthread and hb_pthread macros
|
||||
dnl posted by Alejandro Forero Cuervo to the autoconf macro repository.
|
||||
dnl We are also grateful for the helpful feedback of numerous users.
|
||||
dnl
|
||||
dnl @category InstalledPackages
|
||||
dnl @author Steven G. Johnson <stevenj@alum.mit.edu>
|
||||
dnl @version 2006-05-29
|
||||
dnl @license GPLWithACException
|
||||
|
||||
AC_DEFUN([ACX_PTHREAD], [
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
AC_LANG_SAVE
|
||||
AC_LANG_C
|
||||
acx_pthread_ok=no
|
||||
|
||||
# We used to check for pthread.h first, but this fails if pthread.h
|
||||
# requires special compiler flags (e.g. on True64 or Sequent).
|
||||
# It gets checked for in the link test anyway.
|
||||
|
||||
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
||||
# etcetera environment variables, and if threads linking works using
|
||||
# them:
|
||||
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
|
||||
save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
|
||||
AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
|
||||
AC_MSG_RESULT($acx_pthread_ok)
|
||||
if test x"$acx_pthread_ok" = xno; then
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
fi
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
fi
|
||||
|
||||
# We must check for the threads library under a number of different
|
||||
# names; the ordering is very important because some systems
|
||||
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
|
||||
# libraries is broken (non-POSIX).
|
||||
|
||||
# Create a list of thread flags to try. Items starting with a "-" are
|
||||
# C compiler flags, and other items are library names, except for "none"
|
||||
# which indicates that we try without any flags at all, and "pthread-config"
|
||||
# which is a program returning the flags for the Pth emulation library.
|
||||
|
||||
acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
||||
|
||||
# The ordering *is* (sometimes) important. Some notes on the
|
||||
# individual items follow:
|
||||
|
||||
# pthreads: AIX (must check this before -lpthread)
|
||||
# none: in case threads are in libc; should be tried before -Kthread and
|
||||
# other compiler flags to prevent continual compiler warnings
|
||||
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
|
||||
# -pthreads: Solaris/gcc
|
||||
# -mthreads: Mingw32/gcc, Lynx/gcc
|
||||
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
||||
# doesn't hurt to check since this sometimes defines pthreads too;
|
||||
# also defines -D_REENTRANT)
|
||||
# ... -mt is also the pthreads flag for HP/aCC
|
||||
# pthread: Linux, etcetera
|
||||
# --thread-safe: KAI C++
|
||||
# pthread-config: use pthread-config program (for GNU Pth library)
|
||||
|
||||
case "${host_cpu}-${host_os}" in
|
||||
*solaris*)
|
||||
|
||||
# On Solaris (at least, for some versions), libc contains stubbed
|
||||
# (non-functional) versions of the pthreads routines, so link-based
|
||||
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
|
||||
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
|
||||
# a function called by this macro, so we could check for that, but
|
||||
# who knows whether they'll stub that too in a future libc.) So,
|
||||
# we'll just look for -pthreads and -lpthread first:
|
||||
|
||||
acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags"
|
||||
;;
|
||||
esac
|
||||
|
||||
if test x"$acx_pthread_ok" = xno; then
|
||||
for flag in $acx_pthread_flags; do
|
||||
|
||||
case $flag in
|
||||
none)
|
||||
AC_MSG_CHECKING([whether pthreads work without any flags])
|
||||
;;
|
||||
|
||||
-*)
|
||||
AC_MSG_CHECKING([whether pthreads work with $flag])
|
||||
PTHREAD_CFLAGS="$flag"
|
||||
;;
|
||||
|
||||
pthread-config)
|
||||
AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no)
|
||||
if test x"$acx_pthread_config" = xno; then continue; fi
|
||||
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
||||
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
||||
;;
|
||||
|
||||
*)
|
||||
AC_MSG_CHECKING([for the pthreads library -l$flag])
|
||||
PTHREAD_LIBS="-l$flag"
|
||||
;;
|
||||
esac
|
||||
|
||||
save_LIBS="$LIBS"
|
||||
save_CFLAGS="$CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
|
||||
# Check for various functions. We must include pthread.h,
|
||||
# since some functions may be macros. (On the Sequent, we
|
||||
# need a special flag -Kthread to make this header compile.)
|
||||
# We check for pthread_join because it is in -lpthread on IRIX
|
||||
# while pthread_create is in libc. We check for pthread_attr_init
|
||||
# due to DEC craziness with -lpthreads. We check for
|
||||
# pthread_cleanup_push because it is one of the few pthread
|
||||
# functions on Solaris that doesn't have a non-functional libc stub.
|
||||
# We try pthread_create on general principles.
|
||||
AC_TRY_LINK([#include <pthread.h>],
|
||||
[pthread_t th; pthread_join(th, 0);
|
||||
pthread_attr_init(0); pthread_cleanup_push(0, 0);
|
||||
pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
|
||||
[acx_pthread_ok=yes])
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
|
||||
AC_MSG_RESULT($acx_pthread_ok)
|
||||
if test "x$acx_pthread_ok" = xyes; then
|
||||
break;
|
||||
fi
|
||||
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
done
|
||||
fi
|
||||
|
||||
# Various other checks:
|
||||
if test "x$acx_pthread_ok" = xyes; then
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
|
||||
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
||||
AC_MSG_CHECKING([for joinable pthread attribute])
|
||||
attr_name=unknown
|
||||
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
||||
AC_TRY_LINK([#include <pthread.h>], [int attr=$attr; return attr;],
|
||||
[attr_name=$attr; break])
|
||||
done
|
||||
AC_MSG_RESULT($attr_name)
|
||||
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
|
||||
AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
|
||||
[Define to necessary symbol if this constant
|
||||
uses a non-standard name on your system.])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([if more special flags are required for pthreads])
|
||||
flag=no
|
||||
case "${host_cpu}-${host_os}" in
|
||||
*-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
|
||||
*solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
|
||||
esac
|
||||
AC_MSG_RESULT(${flag})
|
||||
if test "x$flag" != xno; then
|
||||
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
|
||||
fi
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
|
||||
# More AIX lossage: must compile with xlc_r or cc_r
|
||||
if test x"$GCC" != xyes; then
|
||||
AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
|
||||
else
|
||||
PTHREAD_CC=$CC
|
||||
fi
|
||||
else
|
||||
PTHREAD_CC="$CC"
|
||||
fi
|
||||
|
||||
AC_SUBST(PTHREAD_LIBS)
|
||||
AC_SUBST(PTHREAD_CFLAGS)
|
||||
AC_SUBST(PTHREAD_CC)
|
||||
|
||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||
if test x"$acx_pthread_ok" = xyes; then
|
||||
ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
|
||||
:
|
||||
else
|
||||
acx_pthread_ok=no
|
||||
$2
|
||||
fi
|
||||
AC_LANG_RESTORE
|
||||
])dnl ACX_PTHREAD
|
||||
@@ -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>
|
||||
*
|
||||
@@ -19,14 +19,9 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief Various sorts of access control
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -62,6 +57,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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"
|
||||
@@ -69,14 +68,11 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/srv.h"
|
||||
#include "asterisk/compat.h"
|
||||
|
||||
struct ast_ha {
|
||||
/* Host access rule */
|
||||
struct in_addr netaddr;
|
||||
struct in_addr netmask;
|
||||
int sense;
|
||||
struct ast_ha *next;
|
||||
};
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
|
||||
AST_MUTEX_DEFINE_STATIC(routeseq_lock);
|
||||
#endif
|
||||
|
||||
/* Default IP - if not otherwise set, don't breathe garbage */
|
||||
static struct in_addr __ourip = { 0x00000000 };
|
||||
@@ -90,7 +86,7 @@ struct my_ifreq {
|
||||
void ast_free_ha(struct ast_ha *ha)
|
||||
{
|
||||
struct ast_ha *hal;
|
||||
while (ha) {
|
||||
while(ha) {
|
||||
hal = ha;
|
||||
ha = ha->next;
|
||||
free(hal);
|
||||
@@ -98,7 +94,7 @@ void ast_free_ha(struct ast_ha *ha)
|
||||
}
|
||||
|
||||
/* Copy HA structure */
|
||||
static void ast_copy_ha(struct ast_ha *from, struct ast_ha *to)
|
||||
void ast_copy_ha(const struct ast_ha *from, struct ast_ha *to)
|
||||
{
|
||||
memcpy(&to->netaddr, &from->netaddr, sizeof(from->netaddr));
|
||||
memcpy(&to->netmask, &from->netmask, sizeof(from->netmask));
|
||||
@@ -108,12 +104,9 @@ static void ast_copy_ha(struct ast_ha *from, struct ast_ha *to)
|
||||
/* Create duplicate of ha structure */
|
||||
static struct ast_ha *ast_duplicate_ha(struct ast_ha *original)
|
||||
{
|
||||
struct ast_ha *new_ha;
|
||||
|
||||
if ((new_ha = ast_malloc(sizeof(*new_ha)))) {
|
||||
/* Copy from original to new object */
|
||||
ast_copy_ha(original, new_ha);
|
||||
}
|
||||
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;
|
||||
}
|
||||
@@ -122,16 +115,16 @@ static struct ast_ha *ast_duplicate_ha(struct ast_ha *original)
|
||||
/* Used in chan_sip2 templates */
|
||||
struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original)
|
||||
{
|
||||
struct ast_ha *start = original;
|
||||
struct ast_ha *start=original;
|
||||
struct ast_ha *ret = NULL;
|
||||
struct ast_ha *link, *prev = 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)
|
||||
if (!ret)
|
||||
ret = link; /* Save starting point */
|
||||
|
||||
start = start->next; /* Go to next object */
|
||||
@@ -140,22 +133,21 @@ struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original)
|
||||
return ret; /* Return start of list */
|
||||
}
|
||||
|
||||
struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
|
||||
struct ast_ha *ast_append_ha(char *sense, const char *stuff, struct ast_ha *path)
|
||||
{
|
||||
struct ast_ha *ha;
|
||||
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_malloc(sizeof(*ha)))) {
|
||||
if (ha) {
|
||||
ast_copy_string(tmp, stuff, sizeof(tmp));
|
||||
nm = strchr(tmp, '/');
|
||||
if (!nm) {
|
||||
@@ -165,9 +157,9 @@ struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
|
||||
nm++;
|
||||
}
|
||||
if (!strchr(nm, '.')) {
|
||||
if ((sscanf(nm, "%d", &x) == 1) && (x >= 0) && (x <= 32)) {
|
||||
if ((sscanf(nm, "%30d", &x) == 1) && (x >= 0) && (x <= 32)) {
|
||||
y = 0;
|
||||
for (z = 0; z < x; z++) {
|
||||
for (z=0;z<x;z++) {
|
||||
y >>= 1;
|
||||
y |= 0x80000000;
|
||||
}
|
||||
@@ -196,8 +188,7 @@ struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
|
||||
ret = ha;
|
||||
}
|
||||
}
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "%s/%s appended to acl for peer\n", stuff, nm);
|
||||
ast_log(LOG_DEBUG, "%s/%s appended to acl for peer\n", stuff, nm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -209,10 +200,10 @@ int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
|
||||
char iabuf[INET_ADDRSTRLEN];
|
||||
char iabuf2[INET_ADDRSTRLEN];
|
||||
/* DEBUG */
|
||||
ast_copy_string(iabuf, ast_inet_ntoa(sin->sin_addr), sizeof(iabuf));
|
||||
ast_copy_string(iabuf2, ast_inet_ntoa(ha->netaddr), sizeof(iabuf2));
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "##### Testing %s with %s\n", iabuf, iabuf2);
|
||||
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)
|
||||
@@ -248,55 +239,12 @@ int ast_get_ip_or_srv(struct sockaddr_in *sin, const char *value, const char *se
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dscp_codepoint {
|
||||
char *name;
|
||||
unsigned int space;
|
||||
};
|
||||
|
||||
/* IANA registered DSCP codepoints */
|
||||
|
||||
static const struct dscp_codepoint dscp_pool1[] = {
|
||||
{ "CS0", 0x00 },
|
||||
{ "CS1", 0x08 },
|
||||
{ "CS2", 0x10 },
|
||||
{ "CS3", 0x18 },
|
||||
{ "CS4", 0x20 },
|
||||
{ "CS5", 0x28 },
|
||||
{ "CS6", 0x30 },
|
||||
{ "CS7", 0x38 },
|
||||
{ "AF11", 0x0A },
|
||||
{ "AF12", 0x0C },
|
||||
{ "AF13", 0x0E },
|
||||
{ "AF21", 0x12 },
|
||||
{ "AF22", 0x14 },
|
||||
{ "AF23", 0x16 },
|
||||
{ "AF31", 0x1A },
|
||||
{ "AF32", 0x1C },
|
||||
{ "AF33", 0x1E },
|
||||
{ "AF41", 0x22 },
|
||||
{ "AF42", 0x24 },
|
||||
{ "AF43", 0x26 },
|
||||
{ "EF", 0x2E },
|
||||
};
|
||||
|
||||
int ast_str2tos(const char *value, unsigned int *tos)
|
||||
int ast_str2tos(const char *value, int *tos)
|
||||
{
|
||||
int fval;
|
||||
unsigned int x;
|
||||
|
||||
if (sscanf(value, "%i", &fval) == 1) {
|
||||
*tos = fval & 0xFF;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (x = 0; x < sizeof(dscp_pool1) / sizeof(dscp_pool1[0]); x++) {
|
||||
if (!strcasecmp(value, dscp_pool1[x].name)) {
|
||||
*tos = dscp_pool1[x].space << 2;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcasecmp(value, "lowdelay"))
|
||||
if (sscanf(value, "%30i", &fval) == 1)
|
||||
*tos = fval & 0xff;
|
||||
else if (!strcasecmp(value, "lowdelay"))
|
||||
*tos = IPTOS_LOWDELAY;
|
||||
else if (!strcasecmp(value, "throughput"))
|
||||
*tos = IPTOS_THROUGHPUT;
|
||||
@@ -308,44 +256,16 @@ int ast_str2tos(const char *value, unsigned int *tos)
|
||||
*tos = 0;
|
||||
else
|
||||
return -1;
|
||||
|
||||
ast_log(LOG_WARNING, "TOS value %s is deprecated. Please see doc/ip-tos.txt for more information.\n", value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *ast_tos2str(unsigned int tos)
|
||||
{
|
||||
unsigned int x;
|
||||
|
||||
switch (tos) {
|
||||
case 0:
|
||||
return "none";
|
||||
case IPTOS_LOWDELAY:
|
||||
return "lowdelay";
|
||||
case IPTOS_THROUGHPUT:
|
||||
return "throughput";
|
||||
case IPTOS_RELIABILITY:
|
||||
return "reliability";
|
||||
case IPTOS_MINCOST:
|
||||
return "mincost";
|
||||
default:
|
||||
for (x = 0; x < sizeof(dscp_pool1) / sizeof(dscp_pool1[0]); x++) {
|
||||
if (dscp_pool1[x].space == (tos >> 2))
|
||||
return dscp_pool1[x].name;
|
||||
}
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
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 ast_lookup_iface(char *iface, struct in_addr *address)
|
||||
{
|
||||
int mysock, res = 0;
|
||||
struct my_ifreq ifreq;
|
||||
@@ -31,16 +31,12 @@
|
||||
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"
|
||||
|
||||
@@ -31,15 +31,11 @@
|
||||
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"
|
||||
|
||||
45
agi/Makefile
45
agi/Makefile
@@ -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,37 +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
|
||||
|
||||
include $(ASTTOPDIR)/Makefile.rules
|
||||
ifeq ($(findstring BSD,${OSARCH}),BSD)
|
||||
CFLAGS+=-I$(CROSS_COMPILE_TARGET)/usr/local/include -L$(CROSS_COMPILE_TARGET)/usr/local/lib
|
||||
endif
|
||||
|
||||
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 .*.o.d .*.oo.d
|
||||
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`
|
||||
|
||||
@@ -17,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)
|
||||
|
||||
|
||||
@@ -11,10 +11,7 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
#include "asterisk/compat.h"
|
||||
#include <asterisk/compat.h>
|
||||
|
||||
#define AUDIO_FILENO (STDERR_FILENO + 1)
|
||||
|
||||
|
||||
488
agi/jukebox.agi
488
agi/jukebox.agi
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -19,8 +19,7 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief u-Law to Signed linear conversion
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
File diff suppressed because it is too large
Load Diff
127
apps/Makefile
127
apps/Makefile
@@ -3,39 +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 ../menuselect.makeopts ../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
|
||||
|
||||
C_MODS:=$(filter-out $(MENUSELECT_APPS),$(patsubst %.c,%,$(wildcard app_*.c)))
|
||||
CC_MODS:=$(filter-out $(MENUSELECT_APPS),$(patsubst %.cc,%,$(wildcard app_*.cc)))
|
||||
#
|
||||
# Obsolete things...
|
||||
#
|
||||
#APPS+=app_sql_postgres.so
|
||||
#APPS+=app_sql_odbc.so
|
||||
|
||||
LOADABLE_MODS:=$(C_MODS) $(CC_MODS)
|
||||
#
|
||||
# Experimental things
|
||||
#
|
||||
#APPS+=app_ivrdemo.so
|
||||
#APPS+=app_skel.so
|
||||
#APPS+=app_rpt.so
|
||||
|
||||
ifneq ($(findstring apps,$(MENUSELECT_EMBED)),)
|
||||
EMBEDDED_MODS:=$(LOADABLE_MODS)
|
||||
LOADABLE_MODS:=
|
||||
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
|
||||
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
|
||||
|
||||
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)
|
||||
ifeq ($(findstring BSD,${OSARCH}),BSD)
|
||||
CFLAGS+=-I$(CROSS_COMPILE_TARGET)/usr/local/include -L$(CROSS_COMPILE_TARGET)/usr/local/lib
|
||||
endif
|
||||
ifneq ($(findstring IMAP_STORAGE,$(MENUSELECT_OPTS_app_voicemail)),)
|
||||
MENUSELECT_DEPENDS_app_voicemail+=$(MENUSELECT_DEPENDS_IMAP_STORAGE)
|
||||
MENUSELECT_DEPENDS_app_directory+=$(MENUSELECT_DEPENDS_IMAP_STORAGE)
|
||||
|
||||
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))
|
||||
MENUSELECT_DEPENDS_app_chanspy+=RT
|
||||
RT_LIB=-lrt
|
||||
app_chanspy.so: app_chanspy.o
|
||||
$(CC) $(SOLINK) -o $@ $< -lrt
|
||||
endif
|
||||
|
||||
all: _all
|
||||
|
||||
include $(ASTTOPDIR)/Makefile.moddir_rules
|
||||
ifneq ($(wildcard .depend),)
|
||||
include .depend
|
||||
endif
|
||||
|
||||
depend: .depend
|
||||
|
||||
.depend:
|
||||
../build_tools/mkdep $(CFLAGS) `ls *.c`
|
||||
|
||||
env:
|
||||
env
|
||||
|
||||
@@ -17,22 +17,11 @@
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Program Asterisk ADSI Scripts into phone
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<depend>res_adsi</depend>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdlib.h>
|
||||
@@ -43,6 +32,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
@@ -53,6 +46,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/lock.h"
|
||||
|
||||
static char *tdesc = "Asterisk ADSI Programming Application";
|
||||
|
||||
static char *app = "ADSIProg";
|
||||
|
||||
static char *synopsis = "Load Asterisk ADSI Scripts into phone";
|
||||
@@ -63,6 +58,10 @@ static char *descrip =
|
||||
" ADSIProg(script): This application programs an ADSI Phone with the given\n"
|
||||
"script. If nothing is specified, the default script (asterisk.adsi) is used.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
struct adsi_event {
|
||||
int id;
|
||||
char *name;
|
||||
@@ -195,7 +194,7 @@ static int process_token(void *out, char *src, int maxlen, int argtype)
|
||||
if (!(argtype & ARG_NUMBER))
|
||||
return -1;
|
||||
/* Octal value */
|
||||
if (sscanf(src, "%o", (int *)out) != 1)
|
||||
if (sscanf(src, "%30o", (int *)out) != 1)
|
||||
return -1;
|
||||
if (argtype & ARG_STRING) {
|
||||
/* Convert */
|
||||
@@ -205,7 +204,7 @@ static int process_token(void *out, char *src, int maxlen, int argtype)
|
||||
if (!(argtype & ARG_NUMBER))
|
||||
return -1;
|
||||
/* Hex value */
|
||||
if (sscanf(src + 2, "%x", (unsigned int *)out) != 1)
|
||||
if (sscanf(src + 2, "%30x", (unsigned int *)out) != 1)
|
||||
return -1;
|
||||
if (argtype & ARG_STRING) {
|
||||
/* Convert */
|
||||
@@ -215,7 +214,7 @@ static int process_token(void *out, char *src, int maxlen, int argtype)
|
||||
if (!(argtype & ARG_NUMBER))
|
||||
return -1;
|
||||
/* Hex value */
|
||||
if (sscanf(src, "%d", (int *)out) != 1)
|
||||
if (sscanf(src, "%30d", (int *)out) != 1)
|
||||
return -1;
|
||||
if (argtype & ARG_STRING) {
|
||||
/* Convert */
|
||||
@@ -1357,10 +1356,13 @@ static struct adsi_script *compile_script(char *script)
|
||||
ast_log(LOG_WARNING, "Can't open file '%s'\n", fn);
|
||||
return NULL;
|
||||
}
|
||||
if (!(scr = ast_calloc(1, sizeof(*scr)))) {
|
||||
scr = malloc(sizeof(struct adsi_script));
|
||||
if (!scr) {
|
||||
fclose(f);
|
||||
ast_log(LOG_WARNING, "Out of memory loading script '%s'\n", fn);
|
||||
return NULL;
|
||||
}
|
||||
memset(scr, 0, sizeof(struct adsi_script));
|
||||
/* Create "main" as first subroutine */
|
||||
getsubbyname(scr, "main", NULL, 0);
|
||||
while(!feof(f)) {
|
||||
@@ -1442,11 +1444,11 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
return -1;
|
||||
|
||||
/* Start an empty ADSI Session */
|
||||
if (ast_adsi_load_session(chan, NULL, 0, 1) < 1)
|
||||
if (adsi_load_session(chan, NULL, 0, 1) < 1)
|
||||
return -1;
|
||||
|
||||
/* Now begin the download attempt */
|
||||
if (ast_adsi_begin_download(chan, scr->desc, scr->fdn, scr->sec, scr->ver)) {
|
||||
if (adsi_begin_download(chan, scr->desc, scr->fdn, scr->sec, scr->ver)) {
|
||||
/* User rejected us for some reason */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User rejected download attempt\n");
|
||||
@@ -1460,7 +1462,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
for (x=0;x<scr->numkeys;x++) {
|
||||
if (bytes + scr->keys[x].retstrlen > 253) {
|
||||
/* Send what we've collected so far */
|
||||
if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
|
||||
return -1;
|
||||
}
|
||||
@@ -1473,7 +1475,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
#endif
|
||||
}
|
||||
if (bytes) {
|
||||
if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
|
||||
return -1;
|
||||
}
|
||||
@@ -1484,7 +1486,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
for (x=0;x<scr->numdisplays;x++) {
|
||||
if (bytes + scr->displays[x].datalen > 253) {
|
||||
/* Send what we've collected so far */
|
||||
if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
|
||||
return -1;
|
||||
}
|
||||
@@ -1497,7 +1499,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
#endif
|
||||
}
|
||||
if (bytes) {
|
||||
if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
|
||||
return -1;
|
||||
}
|
||||
@@ -1508,7 +1510,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
for (x=0;x<scr->numsubs;x++) {
|
||||
if (bytes + scr->subs[x].datalen > 253) {
|
||||
/* Send what we've collected so far */
|
||||
if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
|
||||
return -1;
|
||||
}
|
||||
@@ -1521,7 +1523,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
#endif
|
||||
}
|
||||
if (bytes) {
|
||||
if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
|
||||
return -1;
|
||||
}
|
||||
@@ -1529,11 +1531,11 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
|
||||
|
||||
bytes = 0;
|
||||
bytes += ast_adsi_display(buf, ADSI_INFO_PAGE, 1, ADSI_JUST_LEFT, 0, "Download complete.", "");
|
||||
bytes += ast_adsi_set_line(buf, ADSI_INFO_PAGE, 1);
|
||||
if (ast_adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY) < 0)
|
||||
bytes += adsi_display(buf, ADSI_INFO_PAGE, 1, ADSI_JUST_LEFT, 0, "Download complete.", "");
|
||||
bytes += adsi_set_line(buf, ADSI_INFO_PAGE, 1);
|
||||
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY) < 0)
|
||||
return -1;
|
||||
if (ast_adsi_end_download(chan)) {
|
||||
if (adsi_end_download(chan)) {
|
||||
/* Download failed for some reason */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Download attempt failed\n");
|
||||
@@ -1542,21 +1544,21 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
return -1;
|
||||
}
|
||||
free(scr);
|
||||
ast_adsi_unload_session(chan);
|
||||
adsi_unload_session(chan);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adsi_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (ast_strlen_zero(data))
|
||||
data = "asterisk.adsi";
|
||||
|
||||
if (!ast_adsi_available(chan)) {
|
||||
if (!adsi_available(chan)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "ADSI Unavailable on CPE. Not bothering to try.\n");
|
||||
} else {
|
||||
@@ -1565,26 +1567,40 @@ static int adsi_exec(struct ast_channel *chan, void *data)
|
||||
res = adsi_prog(chan, data);
|
||||
}
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, adsi_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Asterisk ADSI Programming Application");
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -22,17 +22,13 @@
|
||||
*
|
||||
* *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***
|
||||
*
|
||||
* Use at your own risk. Please consult the GNU GPL license document included with Asterisk. *
|
||||
* Use at your own risk. Please consult the GNU GPL license document included with Asterisk details. *
|
||||
*
|
||||
* *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@@ -41,6 +37,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
@@ -56,7 +56,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/localtime.h"
|
||||
#include "asterisk/callerid.h"
|
||||
#include "asterisk/astdb.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
#define ALMRCV_CONFIG "alarmreceiver.conf"
|
||||
#define ADEMCO_CONTACT_ID "ADEMCO_CONTACT_ID"
|
||||
@@ -68,9 +67,11 @@ struct event_node{
|
||||
|
||||
typedef struct event_node event_node_t;
|
||||
|
||||
static char *tdesc = "Alarm Receiver for Asterisk";
|
||||
|
||||
static char *app = "AlarmReceiver";
|
||||
|
||||
static char *synopsis = "Provide support for receiving alarm reports from a burglar or fire alarm panel";
|
||||
static char *synopsis = "Provide support for receving alarm reports from a burglar or fire alarm panel";
|
||||
static char *descrip =
|
||||
" AlarmReceiver(): Only 1 signalling format is supported at this time: Ademco\n"
|
||||
"Contact ID. This application should be called whenever there is an alarm\n"
|
||||
@@ -93,10 +94,18 @@ static char event_app[128] = {'\0'};
|
||||
static char db_family[128] = {'\0'};
|
||||
static char time_stamp_format[128] = {"%a %b %d, %Y @ %H:%M:%S %Z"};
|
||||
|
||||
|
||||
/* Misc variables */
|
||||
|
||||
|
||||
static char event_file[14] = "/event-XXXXXX";
|
||||
|
||||
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
/*
|
||||
* Attempt to access a database variable and increment it,
|
||||
* provided that the user defined db-family in alarmreceiver.conf
|
||||
@@ -125,7 +134,7 @@ static void database_increment( char *key )
|
||||
return;
|
||||
}
|
||||
|
||||
sscanf(value, "%u", &v);
|
||||
sscanf(value, "%30u", &v);
|
||||
v++;
|
||||
|
||||
if(option_verbose >= 4)
|
||||
@@ -549,9 +558,9 @@ static int receive_ademco_contact_id( struct ast_channel *chan, void *data, int
|
||||
|
||||
checksum = checksum % 15;
|
||||
|
||||
if (checksum) {
|
||||
if(checksum){
|
||||
database_increment("checksum-errors");
|
||||
if (option_verbose >= 2)
|
||||
if(option_verbose >= 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Nonzero checksum\n");
|
||||
ast_log(LOG_DEBUG, "AlarmReceiver: Nonzero checksum\n");
|
||||
continue;
|
||||
@@ -571,11 +580,17 @@ static int receive_ademco_contact_id( struct ast_channel *chan, void *data, int
|
||||
|
||||
events_received++;
|
||||
|
||||
/* Queue the Event */
|
||||
if (!(enew = ast_calloc(1, sizeof(*enew)))) {
|
||||
/* Queue the Event */
|
||||
|
||||
if((enew = malloc(sizeof(event_node_t))) == NULL){
|
||||
if(option_verbose >= 1)
|
||||
ast_verbose(VERBOSE_PREFIX_1 "AlarmReceiver: Failed to allocate memory\n");
|
||||
ast_log(LOG_WARNING, "AlarmReceiver Failed to allocate memory\n");
|
||||
res = -1;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
memset(enew, 0, sizeof(event_node_t));
|
||||
|
||||
enew->next = NULL;
|
||||
ast_copy_string(enew->data, event, sizeof(enew->data));
|
||||
@@ -626,13 +641,13 @@ static int receive_ademco_contact_id( struct ast_channel *chan, void *data, int
|
||||
static int alarmreceiver_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
event_node_t *elp, *efree;
|
||||
char signalling_type[64] = "";
|
||||
|
||||
event_node_t *event_head = NULL;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Set write and read formats to ULAW */
|
||||
|
||||
@@ -641,13 +656,13 @@ static int alarmreceiver_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
if (ast_set_write_format(chan,AST_FORMAT_ULAW)){
|
||||
ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",chan->name);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ast_set_read_format(chan,AST_FORMAT_ULAW)){
|
||||
ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",chan->name);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -666,7 +681,7 @@ static int alarmreceiver_exec(struct ast_channel *chan, void *data)
|
||||
res = ast_answer(chan);
|
||||
|
||||
if (res) {
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -721,7 +736,7 @@ static int alarmreceiver_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -733,7 +748,7 @@ static int alarmreceiver_exec(struct ast_channel *chan, void *data)
|
||||
static int load_config(void)
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
const char *p;
|
||||
char *p;
|
||||
|
||||
/* Read in the config file */
|
||||
|
||||
@@ -743,7 +758,6 @@ static int load_config(void)
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: No config file\n");
|
||||
return 0;
|
||||
}
|
||||
else{
|
||||
|
||||
@@ -810,7 +824,7 @@ static int load_config(void)
|
||||
}
|
||||
ast_config_destroy(cfg);
|
||||
}
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -819,23 +833,36 @@ static int load_config(void)
|
||||
*/
|
||||
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
int load_module(void)
|
||||
{
|
||||
if(load_config())
|
||||
return ast_register_application(app, alarmreceiver_exec, synopsis, descrip);
|
||||
else
|
||||
return AST_MODULE_LOAD_DECLINE;
|
||||
load_config();
|
||||
return ast_register_application(app, alarmreceiver_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Alarm Receiver for Asterisk");
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
398
apps/app_amd.c
398
apps/app_amd.c
@@ -1,398 +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.
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/options.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])\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"
|
||||
"This application sets the following channel variable 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";
|
||||
|
||||
#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 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;
|
||||
int inInitialSilence = 1;
|
||||
int inGreeting = 0;
|
||||
int voiceDuration = 0;
|
||||
int silenceDuration = 0;
|
||||
int iTotalTime = 0;
|
||||
int iWordsCount = 0;
|
||||
int currentState = STATE_IN_SILENCE;
|
||||
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;
|
||||
|
||||
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);
|
||||
);
|
||||
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_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);
|
||||
} else if (option_debug)
|
||||
ast_log(LOG_DEBUG, "AMD using the default parameters.\n");
|
||||
|
||||
/* Now we're ready to roll! */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "AMD: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] "
|
||||
"totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] \n",
|
||||
initialSilence, greeting, afterGreetingSilence, totalAnalysisTime,
|
||||
minimumWordLength, betweenWordsSilence, maximumNumberOfWords, silenceThreshold );
|
||||
|
||||
/* 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, totalAnalysisTime)) > -1) {
|
||||
/* If we fail to read in a frame, that means they hung up */
|
||||
if (!(f = ast_read(chan))) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "AMD: HANGUP\n");
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "Got hangup\n");
|
||||
strcpy(amdStatus, "HANGUP");
|
||||
break;
|
||||
}
|
||||
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
/* If the total time exceeds the analysis time then give up as we are not too sure */
|
||||
framelength = (ast_codec_get_samples(f) / DEFAULT_SAMPLES_PER_MS);
|
||||
iTotalTime += framelength;
|
||||
if (iTotalTime >= totalAnalysisTime) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_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 */
|
||||
dspsilence = 0;
|
||||
ast_dsp_silence(silenceDetector, f, &dspsilence);
|
||||
if (dspsilence) {
|
||||
silenceDuration = dspsilence;
|
||||
|
||||
if (silenceDuration >= betweenWordsSilence) {
|
||||
if (currentState != STATE_IN_SILENCE ) {
|
||||
previousState = currentState;
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "AMD: Changed state to STATE_IN_SILENCE\n");
|
||||
}
|
||||
currentState = STATE_IN_SILENCE;
|
||||
consecutiveVoiceDuration = 0;
|
||||
}
|
||||
|
||||
if (inInitialSilence == 1 && silenceDuration >= initialSilence) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: silenceDuration:%d initialSilence:%d\n",
|
||||
silenceDuration, initialSilence);
|
||||
ast_frfree(f);
|
||||
strcpy(amdStatus , "MACHINE");
|
||||
sprintf(amdCause , "INITIALSILENCE-%d-%d", silenceDuration, initialSilence);
|
||||
break;
|
||||
}
|
||||
|
||||
if (silenceDuration >= afterGreetingSilence && inGreeting == 1) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "AMD: HUMAN: silenceDuration:%d afterGreetingSilence:%d\n",
|
||||
silenceDuration, afterGreetingSilence);
|
||||
ast_frfree(f);
|
||||
strcpy(amdStatus , "HUMAN");
|
||||
sprintf(amdCause , "HUMAN-%d-%d", silenceDuration, afterGreetingSilence);
|
||||
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++;
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "AMD: Word detected. iWordsCount:%d\n", iWordsCount);
|
||||
previousState = currentState;
|
||||
currentState = STATE_IN_WORD;
|
||||
}
|
||||
|
||||
if (iWordsCount >= maximumNumberOfWords) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: iWordsCount:%d\n", iWordsCount);
|
||||
ast_frfree(f);
|
||||
strcpy(amdStatus , "MACHINE");
|
||||
sprintf(amdCause , "MAXWORDS-%d-%d", iWordsCount, maximumNumberOfWords);
|
||||
break;
|
||||
}
|
||||
|
||||
if (inGreeting == 1 && voiceDuration >= greeting) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "AMD: ANSWERING MACHINE: voiceDuration:%d greeting:%d\n", voiceDuration, greeting);
|
||||
ast_frfree(f);
|
||||
strcpy(amdStatus , "MACHINE");
|
||||
sprintf(amdCause , "LONGGREETING-%d-%d", voiceDuration, greeting);
|
||||
break;
|
||||
}
|
||||
|
||||
if (voiceDuration >= minimumWordLength ) {
|
||||
silenceDuration = 0;
|
||||
inInitialSilence = 0;
|
||||
inGreeting = 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
/* It took too long to get a frame back. Giving up. */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_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)
|
||||
{
|
||||
struct ast_module_user *u = NULL;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
isAnsweringMachine(chan, data);
|
||||
ast_module_user_remove(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void load_config(void)
|
||||
{
|
||||
struct ast_config *cfg = NULL;
|
||||
char *cat = NULL;
|
||||
struct ast_variable *var = NULL;
|
||||
|
||||
if (!(cfg = ast_config_load("amd.conf"))) {
|
||||
ast_log(LOG_ERROR, "Configuration file amd.conf missing.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
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 {
|
||||
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);
|
||||
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "AMD defaults: initialSilence [%d] greeting [%d] afterGreetingSilence [%d] "
|
||||
"totalAnalysisTime [%d] minimumWordLength [%d] betweenWordsSilence [%d] maximumNumberOfWords [%d] silenceThreshold [%d] \n",
|
||||
dfltInitialSilence, dfltGreeting, dfltAfterGreetingSilence, dfltTotalAnalysisTime,
|
||||
dfltMinimumWordLength, dfltBetweenWordsSilence, dfltMaximumNumberOfWords, dfltSilenceThreshold );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
ast_module_user_hangup_all();
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
{
|
||||
load_config();
|
||||
return ast_register_application(app, amd_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
static int reload(void)
|
||||
{
|
||||
load_config();
|
||||
return 0;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Answering Machine Detection Application",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.reload = reload,
|
||||
);
|
||||
@@ -17,24 +17,21 @@
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Execute arbitrary authenticate commands
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -44,33 +41,17 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/astdb.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/options.h"
|
||||
|
||||
enum {
|
||||
OPT_ACCOUNT = (1 << 0),
|
||||
OPT_DATABASE = (1 << 1),
|
||||
OPT_JUMP = (1 << 2),
|
||||
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('j', OPT_JUMP),
|
||||
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. If the\n"
|
||||
@@ -85,82 +66,69 @@ static char *descrip =
|
||||
" 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;
|
||||
int jump = 0;
|
||||
int retries;
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
char password[256]="";
|
||||
char passwd[256];
|
||||
char *opts;
|
||||
char *prompt;
|
||||
int maxdigits;
|
||||
char *argcopy =NULL;
|
||||
struct ast_flags flags = {0};
|
||||
|
||||
AST_DECLARE_APP_ARGS(arglist,
|
||||
AST_APP_ARG(password);
|
||||
AST_APP_ARG(options);
|
||||
AST_APP_ARG(maxdigits);
|
||||
);
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "Authenticate requires an argument(password)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
res = ast_answer(chan);
|
||||
if (res) {
|
||||
ast_module_user_remove(u);
|
||||
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++) {
|
||||
res = ast_app_getdata(chan, prompt, passwd, maxdigits, 0);
|
||||
res = ast_app_getdata(chan, prompt, passwd, sizeof(passwd) - 2, 0);
|
||||
if (res < 0)
|
||||
break;
|
||||
res = 0;
|
||||
if (arglist.password[0] == '/') {
|
||||
if (ast_test_flag(&flags,OPT_DATABASE)) {
|
||||
if (password[0] == '/') {
|
||||
if (strchr(opts, 'd')) {
|
||||
char tmp[256];
|
||||
/* Compare against a database key */
|
||||
if (!ast_db_get(arglist.password + 1, passwd, tmp, sizeof(tmp))) {
|
||||
if (!ast_db_get(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);
|
||||
if (strchr(opts, 'r')) {
|
||||
ast_db_del(password + 1, passwd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Compare against a file */
|
||||
FILE *f;
|
||||
f = fopen(arglist.password, "r");
|
||||
f = fopen(password, "r");
|
||||
if (f) {
|
||||
char buf[256] = "";
|
||||
char md5passwd[33] = "";
|
||||
@@ -170,7 +138,7 @@ static int auth_exec(struct ast_channel *chan, void *data)
|
||||
fgets(buf, sizeof(buf), f);
|
||||
if (!feof(f) && !ast_strlen_zero(buf)) {
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
if (ast_test_flag(&flags,OPT_MULTIPLE)) {
|
||||
if (strchr(opts, 'm')) {
|
||||
md5secret = strchr(buf, ':');
|
||||
if (md5secret == NULL)
|
||||
continue;
|
||||
@@ -178,13 +146,13 @@ static int auth_exec(struct ast_channel *chan, void *data)
|
||||
md5secret++;
|
||||
ast_md5_hash(md5passwd, passwd);
|
||||
if (!strcmp(md5passwd, md5secret)) {
|
||||
if (ast_test_flag(&flags,OPT_ACCOUNT))
|
||||
if (strchr(opts, 'a'))
|
||||
ast_cdr_setaccount(chan, buf);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (!strcmp(passwd, buf)) {
|
||||
if (ast_test_flag(&flags,OPT_ACCOUNT))
|
||||
if (strchr(opts, 'a'))
|
||||
ast_cdr_setaccount(chan, buf);
|
||||
break;
|
||||
}
|
||||
@@ -193,7 +161,7 @@ static int auth_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
fclose(f);
|
||||
if (!ast_strlen_zero(buf)) {
|
||||
if (ast_test_flag(&flags,OPT_MULTIPLE)) {
|
||||
if (strchr(opts, 'm')) {
|
||||
if (md5secret && !strcmp(md5passwd, md5secret))
|
||||
break;
|
||||
} else {
|
||||
@@ -202,23 +170,23 @@ static int auth_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
}
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", arglist.password, strerror(errno));
|
||||
ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", password, strerror(errno));
|
||||
}
|
||||
} else {
|
||||
/* Compare against a fixed password */
|
||||
if (!strcmp(passwd, arglist.password))
|
||||
if (!strcmp(passwd, password))
|
||||
break;
|
||||
}
|
||||
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);
|
||||
res = ast_streamfile(chan, "auth-thankyou", chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, "");
|
||||
} else {
|
||||
if (ast_test_flag(&flags,OPT_JUMP) && ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0) {
|
||||
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))
|
||||
@@ -226,25 +194,39 @@ static int auth_exec(struct ast_channel *chan, void *data)
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
int load_module(void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -17,25 +17,25 @@
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Applications connected with CDR engine
|
||||
*
|
||||
* Martin Pycko <martinp@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/pbx.h"
|
||||
|
||||
|
||||
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";
|
||||
@@ -43,36 +43,55 @@ static char *nocdr_descrip =
|
||||
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)
|
||||
{
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (chan->cdr) {
|
||||
ast_set_flag(chan->cdr, AST_CDR_FLAG_POST_DISABLED);
|
||||
ast_cdr_free(chan->cdr);
|
||||
chan->cdr = NULL;
|
||||
}
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(nocdr_app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
int load_module(void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -18,19 +18,11 @@
|
||||
*/
|
||||
|
||||
/*! \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 "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -38,6 +30,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
@@ -48,6 +44,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/devicestate.h"
|
||||
#include "asterisk/options.h"
|
||||
|
||||
static char *tdesc = "Check channel availability";
|
||||
|
||||
static char *app = "ChanIsAvail";
|
||||
|
||||
static char *synopsis = "Check channel availability";
|
||||
@@ -63,37 +61,36 @@ static char *descrip =
|
||||
" 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, priority_jump=0;
|
||||
int status;
|
||||
struct ast_module_user *u;
|
||||
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 (Zap/1&Zap/2)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
info = ast_strdupa(data);
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, info);
|
||||
|
||||
if (args.options) {
|
||||
if (strchr(args.options, 's'))
|
||||
stringp = info;
|
||||
strsep(&stringp, "|");
|
||||
options = strsep(&stringp, "|");
|
||||
if (options) {
|
||||
if (strchr(options, 's'))
|
||||
option_state = 1;
|
||||
if (strchr(args.options, 'j'))
|
||||
if (strchr(options, 'j'))
|
||||
priority_jump = 1;
|
||||
}
|
||||
peers = args.reqchans;
|
||||
peers = info;
|
||||
if (peers) {
|
||||
cur = peers;
|
||||
do {
|
||||
@@ -107,7 +104,7 @@ 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");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
*number = '\0';
|
||||
@@ -142,32 +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 || ast_opt_priority_jumping) {
|
||||
if (priority_jump || option_priority_jumping) {
|
||||
if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) {
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,140 +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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.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/features.h"
|
||||
#include "asterisk/options.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";
|
||||
|
||||
|
||||
static int asyncgoto_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = -1;
|
||||
struct ast_module_user *u;
|
||||
char *info, *context, *exten, *priority;
|
||||
int prio = 1;
|
||||
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;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
|
||||
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);
|
||||
goto quit;
|
||||
}
|
||||
|
||||
chan2 = ast_get_channel_by_name_locked(args.channel);
|
||||
if (!chan2) {
|
||||
ast_log(LOG_WARNING, "No such channel: %s\n", args.channel);
|
||||
goto quit;
|
||||
}
|
||||
|
||||
/* Parsed right to left, so standard parsing won't work */
|
||||
context = strsep(&args.label, "|");
|
||||
exten = strsep(&args.label, "|");
|
||||
if (exten) {
|
||||
priority = strsep(&args.label, "|");
|
||||
if (!priority) {
|
||||
priority = exten;
|
||||
exten = context;
|
||||
context = NULL;
|
||||
}
|
||||
} else {
|
||||
priority = context;
|
||||
context = NULL;
|
||||
}
|
||||
|
||||
/* ast_findlabel_extension does not convert numeric priorities; it only does a lookup */
|
||||
if (!(prio = atoi(priority)) && !(prio = ast_findlabel_extension(chan2, S_OR(context, chan2->context),
|
||||
S_OR(exten, chan2->exten), priority, chan2->cid.cid_num))) {
|
||||
ast_log(LOG_WARNING, "'%s' is not a known priority or label\n", priority);
|
||||
goto chanquit;
|
||||
}
|
||||
|
||||
if (option_debug > 1)
|
||||
ast_log(LOG_DEBUG, "Attempting async goto (%s) to %s|%s|%d\n", args.channel, S_OR(context, chan2->context), S_OR(exten, chan2->exten), prio);
|
||||
|
||||
if (ast_async_goto_if_exists(chan2, S_OR(context, chan2->context), S_OR(exten, chan2->exten), prio))
|
||||
ast_log(LOG_WARNING, "%s failed for %s\n", app, args.channel);
|
||||
else
|
||||
res = 0;
|
||||
|
||||
chanquit:
|
||||
ast_mutex_unlock(&chan2->lock);
|
||||
quit:
|
||||
ast_module_user_remove(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, asyncgoto_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Channel Redirect");
|
||||
@@ -2,7 +2,6 @@
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2005 Anthony Minessale II (anthmct@yahoo.com)
|
||||
* Copyright (C) 2005 - 2006, Digium, Inc.
|
||||
*
|
||||
* A license has been granted to Digium (via disclaimer) for the use of
|
||||
* this code.
|
||||
@@ -19,24 +18,21 @@
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief ChanSpy: Listen in on any channel.
|
||||
*
|
||||
* \author Anthony Minessale II <anthmct@yahoo.com>
|
||||
*
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
@@ -51,76 +47,46 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/lock.h"
|
||||
|
||||
#define AST_NAME_STRLEN 256
|
||||
AST_MUTEX_DEFINE_STATIC(modlock);
|
||||
|
||||
static const char *tdesc = "Listen to a channel, and optionally whisper into it";
|
||||
static const char *app_chan = "ChanSpy";
|
||||
static const char *desc_chan =
|
||||
#define AST_NAME_STRLEN 256
|
||||
#define ALL_DONE(u, ret) LOCAL_USER_REMOVE(u); return ret;
|
||||
#define get_volfactor(x) x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0
|
||||
|
||||
static const char *synopsis = "Listen to the audio of an active channel";
|
||||
static const char *app = "ChanSpy";
|
||||
static const char *desc =
|
||||
" ChanSpy([chanprefix][|options]): This application is used to listen to the\n"
|
||||
"audio from an Asterisk channel. This includes the audio coming in and\n"
|
||||
"audio from an active Asterisk channel. This includes the audio coming in and\n"
|
||||
"out of the channel being spied on. If the 'chanprefix' parameter is specified,\n"
|
||||
"only channels beginning with this string will be spied upon.\n"
|
||||
" While spying, the following actions may be performed:\n"
|
||||
" While Spying, the following actions may be performed:\n"
|
||||
" - Dialing # cycles the volume level.\n"
|
||||
" - Dialing * will stop spying and look for another channel to spy on.\n"
|
||||
" - Dialing a series of digits followed by # builds a channel name to append\n"
|
||||
" to 'chanprefix'. For example, executing ChanSpy(Agent) and then dialing\n"
|
||||
" the digits '1234#' while spying will begin spying on the channel\n"
|
||||
" the digits '1234#' while spying will begin spying on the channel,\n"
|
||||
" 'Agent/1234'.\n"
|
||||
" Options:\n"
|
||||
" b - Only spy on channels involved in a bridged call.\n"
|
||||
" g(grp) - Match only channels where their ${SPYGROUP} variable is set to\n"
|
||||
" contain 'grp' in an optional : delimited list.\n"
|
||||
" q - Don't play a beep when beginning to spy on a channel, or speak the\n"
|
||||
" selected channel name.\n"
|
||||
" b - Only spy on channels involved in a bridged call.\n"
|
||||
" g(grp) - Match only channels where their ${SPYGROUP} variable is set to\n"
|
||||
" 'grp'.\n"
|
||||
" q - Don't play a beep when beginning to spy on a channel.\n"
|
||||
" r[(basename)] - Record the session to the monitor spool directory. An\n"
|
||||
" optional base for the filename may be specified. The\n"
|
||||
" default is 'chanspy'.\n"
|
||||
" v([value]) - Adjust the initial volume in the range from -4 to 4. A\n"
|
||||
" negative value refers to a quieter setting.\n"
|
||||
" w - Enable 'whisper' mode, so the spying channel can talk to\n"
|
||||
" the spied-on channel.\n"
|
||||
" W - Enable 'private whisper' mode, so the spying channel can\n"
|
||||
" talk to the spied-on channel but cannot listen to that\n"
|
||||
" channel.\n"
|
||||
" v([value]) - Adjust the initial volume in the range from -4 to 4. A\n"
|
||||
" negative value refers to a quieter setting.\n"
|
||||
;
|
||||
|
||||
static const char *app_ext = "ExtenSpy";
|
||||
static const char *desc_ext =
|
||||
" ExtenSpy(exten[@context][|options]): This application is used to listen to the\n"
|
||||
"audio from an Asterisk channel. This includes the audio coming in and\n"
|
||||
"out of the channel being spied on. Only channels created by outgoing calls for the\n"
|
||||
"specified extension will be selected for spying. If the optional context is not\n"
|
||||
"supplied, the current channel's context will be used.\n"
|
||||
" While spying, the following actions may be performed:\n"
|
||||
" - Dialing # cycles the volume level.\n"
|
||||
" - Dialing * will stop spying and look for another channel to spy on.\n"
|
||||
" Options:\n"
|
||||
" b - Only spy on channels involved in a bridged call.\n"
|
||||
" g(grp) - Match only channels where their ${SPYGROUP} variable is set to\n"
|
||||
" contain 'grp' in an optional : delimited list.\n"
|
||||
" q - Don't play a beep when beginning to spy on a channel, or speak the\n"
|
||||
" selected channel name.\n"
|
||||
" r[(basename)] - Record the session to the monitor spool directory. An\n"
|
||||
" optional base for the filename may be specified. The\n"
|
||||
" default is 'chanspy'.\n"
|
||||
" v([value]) - Adjust the initial volume in the range from -4 to 4. A\n"
|
||||
" negative value refers to a quieter setting.\n"
|
||||
" w - Enable 'whisper' mode, so the spying channel can talk to\n"
|
||||
" the spied-on channel.\n"
|
||||
" W - Enable 'private whisper' mode, so the spying channel can\n"
|
||||
" talk to the spied-on channel but cannot listen to that\n"
|
||||
" channel.\n"
|
||||
;
|
||||
static const char *chanspy_spy_type = "ChanSpy";
|
||||
|
||||
enum {
|
||||
OPTION_QUIET = (1 << 0), /* Quiet, no announcement */
|
||||
OPTION_BRIDGED = (1 << 1), /* Only look at bridged calls */
|
||||
OPTION_VOLUME = (1 << 2), /* Specify initial volume */
|
||||
OPTION_GROUP = (1 << 3), /* Only look at channels in group */
|
||||
OPTION_RECORD = (1 << 4),
|
||||
OPTION_WHISPER = (1 << 5),
|
||||
OPTION_PRIVATE = (1 << 6), /* Private Whisper mode */
|
||||
OPTION_RECORD = (1 << 4), /* Record */
|
||||
} chanspy_opt_flags;
|
||||
|
||||
enum {
|
||||
@@ -130,16 +96,16 @@ enum {
|
||||
OPT_ARG_ARRAY_SIZE,
|
||||
} chanspy_opt_args;
|
||||
|
||||
AST_APP_OPTIONS(spy_opts, {
|
||||
AST_APP_OPTIONS(chanspy_opts, {
|
||||
AST_APP_OPTION('q', OPTION_QUIET),
|
||||
AST_APP_OPTION('b', OPTION_BRIDGED),
|
||||
AST_APP_OPTION('w', OPTION_WHISPER),
|
||||
AST_APP_OPTION('W', OPTION_PRIVATE),
|
||||
AST_APP_OPTION_ARG('v', OPTION_VOLUME, OPT_ARG_VOLUME),
|
||||
AST_APP_OPTION_ARG('g', OPTION_GROUP, OPT_ARG_GROUP),
|
||||
AST_APP_OPTION_ARG('r', OPTION_RECORD, OPT_ARG_RECORD),
|
||||
});
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
struct chanspy_translation_helper {
|
||||
/* spy data */
|
||||
@@ -148,6 +114,34 @@ struct chanspy_translation_helper {
|
||||
int volfactor;
|
||||
};
|
||||
|
||||
static struct ast_channel *local_channel_walk(struct ast_channel *chan)
|
||||
{
|
||||
struct ast_channel *ret;
|
||||
ast_mutex_lock(&modlock);
|
||||
if ((ret = ast_channel_walk_locked(chan))) {
|
||||
ast_mutex_unlock(&ret->lock);
|
||||
}
|
||||
ast_mutex_unlock(&modlock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct ast_channel *local_get_channel_begin_name(char *name)
|
||||
{
|
||||
struct ast_channel *chan, *ret = NULL;
|
||||
ast_mutex_lock(&modlock);
|
||||
chan = local_channel_walk(NULL);
|
||||
while (chan) {
|
||||
if (!strncmp(chan->name, name, strlen(name)) && strncmp(chan->name, "Zap/pseudo", 10)) {
|
||||
ret = chan;
|
||||
break;
|
||||
}
|
||||
chan = local_channel_walk(chan);
|
||||
}
|
||||
ast_mutex_unlock(&modlock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *spy_alloc(struct ast_channel *chan, void *data)
|
||||
{
|
||||
/* just store the data pointer in the channel structure */
|
||||
@@ -188,6 +182,7 @@ static int spy_generate(struct ast_channel *chan, void *data, int len, int sampl
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct ast_generator spygen = {
|
||||
.alloc = spy_alloc,
|
||||
.release = spy_release,
|
||||
@@ -201,12 +196,13 @@ static int start_spying(struct ast_channel *chan, struct ast_channel *spychan, s
|
||||
|
||||
ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan->name, chan->name);
|
||||
|
||||
ast_channel_lock(chan);
|
||||
ast_mutex_lock(&chan->lock);
|
||||
res = ast_channel_spy_add(chan, spy);
|
||||
ast_channel_unlock(chan);
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
|
||||
if (!res && ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan)))
|
||||
if (!res && ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan))) {
|
||||
ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -236,32 +232,27 @@ static void set_volume(struct ast_channel *chan, struct chanspy_translation_help
|
||||
|
||||
if (!ast_channel_setoption(chan, AST_OPTION_TXGAIN, &volume_adjust, sizeof(volume_adjust), 0))
|
||||
csth->volfactor = 0;
|
||||
csth->spy.read_vol_adjustment = csth->volfactor;
|
||||
csth->spy.write_vol_adjustment = csth->volfactor;
|
||||
}
|
||||
|
||||
static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int *volfactor, int fd,
|
||||
const struct ast_flags *flags)
|
||||
static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int *volfactor, int fd)
|
||||
{
|
||||
struct chanspy_translation_helper csth;
|
||||
int running = 0, res, x = 0;
|
||||
char inp[24] = {0};
|
||||
char *name;
|
||||
struct ast_frame *f;
|
||||
struct ast_silence_generator *silgen = NULL;
|
||||
int running = 0, res = 0, x = 0;
|
||||
char inp[24] = "", *name = NULL;
|
||||
struct ast_frame *f = NULL;
|
||||
|
||||
if (ast_check_hangup(chan) || ast_check_hangup(spyee))
|
||||
if ((chan && ast_check_hangup(chan)) || (spyee && ast_check_hangup(spyee)))
|
||||
return 0;
|
||||
|
||||
name = ast_strdupa(spyee->name);
|
||||
if (option_verbose >= 2)
|
||||
if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Spying on channel %s\n", name);
|
||||
|
||||
memset(&csth, 0, sizeof(csth));
|
||||
ast_set_flag(&csth.spy, CHANSPY_FORMAT_AUDIO);
|
||||
ast_set_flag(&csth.spy, CHANSPY_TRIGGER_NONE);
|
||||
ast_set_flag(&csth.spy, CHANSPY_MIXAUDIO);
|
||||
csth.spy.type = "ChanSpy";
|
||||
csth.spy.type = chanspy_spy_type;
|
||||
csth.spy.status = CHANSPY_RUNNING;
|
||||
csth.spy.read_queue.format = AST_FORMAT_SLINEAR;
|
||||
csth.spy.write_queue.format = AST_FORMAT_SLINEAR;
|
||||
@@ -275,474 +266,320 @@ static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int
|
||||
csth.spy.write_vol_adjustment = csth.volfactor;
|
||||
}
|
||||
csth.fd = fd;
|
||||
|
||||
|
||||
if (start_spying(spyee, chan, &csth.spy)) {
|
||||
ast_mutex_destroy(&csth.spy.lock);
|
||||
ast_channel_spy_free(&csth.spy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ast_test_flag(flags, OPTION_WHISPER)) {
|
||||
struct ast_filestream *beepstream;
|
||||
int old_write_format = 0;
|
||||
ast_activate_generator(chan, &spygen, &csth);
|
||||
|
||||
ast_channel_whisper_start(csth.spy.chan);
|
||||
old_write_format = chan->writeformat;
|
||||
if ((beepstream = ast_openstream_full(chan, "beep", chan->language, 1))) {
|
||||
struct ast_frame *f;
|
||||
|
||||
while ((f = ast_readframe(beepstream))) {
|
||||
ast_channel_whisper_feed(csth.spy.chan, f);
|
||||
ast_frfree(f);
|
||||
}
|
||||
|
||||
ast_closestream(beepstream);
|
||||
chan->stream = NULL;
|
||||
}
|
||||
if (old_write_format)
|
||||
ast_set_write_format(chan, old_write_format);
|
||||
}
|
||||
|
||||
if (ast_test_flag(flags, OPTION_PRIVATE))
|
||||
silgen = ast_channel_start_silence_generator(chan);
|
||||
else
|
||||
ast_activate_generator(chan, &spygen, &csth);
|
||||
|
||||
/* We can no longer rely on 'spyee' being an actual channel;
|
||||
it can be hung up and freed out from under us. However, the
|
||||
channel destructor will put NULL into our csth.spy.chan
|
||||
field when that happens, so that is our signal that the spyee
|
||||
channel has gone away.
|
||||
*/
|
||||
|
||||
/* Note: it is very important that the ast_waitfor() be the first
|
||||
condition in this expression, so that if we wait for some period
|
||||
of time before receiving a frame from our spying channel, we check
|
||||
for hangup on the spied-on channel _after_ knowing that a frame
|
||||
has arrived, since the spied-on channel could have gone away while
|
||||
we were waiting
|
||||
*/
|
||||
while ((res = ast_waitfor(chan, -1) > -1) &&
|
||||
csth.spy.status == CHANSPY_RUNNING &&
|
||||
csth.spy.chan) {
|
||||
if (!(f = ast_read(chan)) || ast_check_hangup(chan)) {
|
||||
running = -1;
|
||||
while (csth.spy.status == CHANSPY_RUNNING &&
|
||||
(res = ast_waitfor(chan, -1) > -1)) {
|
||||
|
||||
/* Read in frame from channel, break out if no frame */
|
||||
if (!(f = ast_read(chan)))
|
||||
break;
|
||||
}
|
||||
|
||||
if (ast_test_flag(flags, OPTION_WHISPER) &&
|
||||
(f->frametype == AST_FRAME_VOICE)) {
|
||||
ast_channel_whisper_feed(csth.spy.chan, f);
|
||||
ast_frfree(f);
|
||||
continue;
|
||||
}
|
||||
|
||||
res = (f->frametype == AST_FRAME_DTMF) ? f->subclass : 0;
|
||||
|
||||
/* Now if this is DTMF then we have to handle it as such, otherwise just skip it */
|
||||
res = 0;
|
||||
if (f->frametype == AST_FRAME_DTMF)
|
||||
res = f->subclass;
|
||||
ast_frfree(f);
|
||||
if (!res)
|
||||
continue;
|
||||
|
||||
|
||||
if (x == sizeof(inp))
|
||||
x = 0;
|
||||
|
||||
|
||||
if (res < 0) {
|
||||
running = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (res == '*') {
|
||||
running = 0;
|
||||
break;
|
||||
} else if (res == '#') {
|
||||
|
||||
/* Process DTMF digits */
|
||||
if (res == '#') {
|
||||
if (!ast_strlen_zero(inp)) {
|
||||
running = atoi(inp);
|
||||
running = x ? atoi(inp) : -1;
|
||||
break;
|
||||
}
|
||||
|
||||
(*volfactor)++;
|
||||
if (*volfactor > 4)
|
||||
*volfactor = -4;
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Setting spy volume on %s to %d\n", chan->name, *volfactor);
|
||||
csth.volfactor = *volfactor;
|
||||
set_volume(chan, &csth);
|
||||
if (csth.volfactor) {
|
||||
ast_set_flag(&csth.spy, CHANSPY_READ_VOLADJUST);
|
||||
csth.spy.read_vol_adjustment = csth.volfactor;
|
||||
ast_set_flag(&csth.spy, CHANSPY_WRITE_VOLADJUST);
|
||||
csth.spy.write_vol_adjustment = csth.volfactor;
|
||||
} else {
|
||||
ast_clear_flag(&csth.spy, CHANSPY_READ_VOLADJUST);
|
||||
ast_clear_flag(&csth.spy, CHANSPY_WRITE_VOLADJUST);
|
||||
(*volfactor)++;
|
||||
if (*volfactor > 4)
|
||||
*volfactor = -1;
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Setting spy volume on %s to %d\n", chan->name, *volfactor);
|
||||
csth.volfactor = *volfactor;
|
||||
set_volume(chan, &csth);
|
||||
if (csth.volfactor) {
|
||||
ast_set_flag(&csth.spy, CHANSPY_READ_VOLADJUST);
|
||||
csth.spy.read_vol_adjustment = csth.volfactor;
|
||||
ast_set_flag(&csth.spy, CHANSPY_WRITE_VOLADJUST);
|
||||
csth.spy.write_vol_adjustment = csth.volfactor;
|
||||
} else {
|
||||
ast_clear_flag(&csth.spy, CHANSPY_READ_VOLADJUST);
|
||||
ast_clear_flag(&csth.spy, CHANSPY_WRITE_VOLADJUST);
|
||||
}
|
||||
}
|
||||
} else if (res >= '0' && res <= '9') {
|
||||
} else if (res == '*') {
|
||||
break;
|
||||
} else if (res >= 48 && res <= 57) {
|
||||
inp[x++] = res;
|
||||
}
|
||||
}
|
||||
|
||||
if (ast_test_flag(flags, OPTION_WHISPER) && csth.spy.chan)
|
||||
ast_channel_whisper_stop(csth.spy.chan);
|
||||
|
||||
if (ast_test_flag(flags, OPTION_PRIVATE))
|
||||
ast_channel_stop_silence_generator(chan, silgen);
|
||||
else
|
||||
ast_deactivate_generator(chan);
|
||||
|
||||
ast_deactivate_generator(chan);
|
||||
|
||||
csth.spy.status = CHANSPY_DONE;
|
||||
|
||||
/* If a channel still exists on our spy structure then we need to remove ourselves */
|
||||
ast_mutex_lock(&csth.spy.lock);
|
||||
if (csth.spy.chan) {
|
||||
ast_channel_lock(csth.spy.chan);
|
||||
ast_mutex_lock(&csth.spy.chan->lock);
|
||||
ast_channel_spy_remove(csth.spy.chan, &csth.spy);
|
||||
ast_channel_unlock(csth.spy.chan);
|
||||
ast_mutex_unlock(&csth.spy.chan->lock);
|
||||
}
|
||||
ast_channel_spy_free(&csth.spy);
|
||||
|
||||
if (option_verbose >= 2)
|
||||
ast_mutex_unlock(&csth.spy.lock);
|
||||
|
||||
if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Done Spying on channel %s\n", name);
|
||||
|
||||
|
||||
ast_channel_spy_free(&csth.spy);
|
||||
|
||||
return running;
|
||||
}
|
||||
|
||||
static struct ast_channel *next_channel(const struct ast_channel *last, const char *spec,
|
||||
const char *exten, const char *context)
|
||||
static int chanspy_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct ast_channel *this;
|
||||
struct localuser *u;
|
||||
struct ast_channel *peer=NULL, *prev=NULL;
|
||||
char name[AST_NAME_STRLEN],
|
||||
peer_name[AST_NAME_STRLEN + 5],
|
||||
*args,
|
||||
*ptr = NULL,
|
||||
*options = NULL,
|
||||
*spec = NULL,
|
||||
*argv[5],
|
||||
*mygroup = NULL,
|
||||
*recbase = NULL;
|
||||
int res = -1,
|
||||
volfactor = 0,
|
||||
silent = 0,
|
||||
argc = 0,
|
||||
bronly = 0,
|
||||
chosen = 0,
|
||||
count=0,
|
||||
waitms = 100,
|
||||
num = 0,
|
||||
oldrf = 0,
|
||||
oldwf = 0,
|
||||
fd = 0;
|
||||
struct ast_flags flags;
|
||||
signed char zero_volume = 0;
|
||||
|
||||
redo:
|
||||
if (spec)
|
||||
this = ast_walk_channel_by_name_prefix_locked(last, spec, strlen(spec));
|
||||
else if (exten)
|
||||
this = ast_walk_channel_by_exten_locked(last, exten, context);
|
||||
else
|
||||
this = ast_channel_walk_locked(last);
|
||||
|
||||
if (this) {
|
||||
ast_channel_unlock(this);
|
||||
if (!strncmp(this->name, "Zap/pseudo", 10))
|
||||
goto redo;
|
||||
if (!(args = ast_strdupa((char *)data))) {
|
||||
ast_log(LOG_ERROR, "Out of memory!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
static int common_exec(struct ast_channel *chan, const struct ast_flags *flags,
|
||||
int volfactor, const int fd, const char *mygroup, const char *spec,
|
||||
const char *exten, const char *context)
|
||||
{
|
||||
struct ast_channel *peer, *prev, *next;
|
||||
char nameprefix[AST_NAME_STRLEN];
|
||||
char peer_name[AST_NAME_STRLEN + 5];
|
||||
signed char zero_volume = 0;
|
||||
int waitms;
|
||||
int res;
|
||||
char *ptr;
|
||||
int num;
|
||||
oldrf = chan->readformat;
|
||||
oldwf = chan->writeformat;
|
||||
if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) {
|
||||
ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
|
||||
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
ast_answer(chan);
|
||||
ast_answer(chan);
|
||||
|
||||
ast_set_flag(chan, AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */
|
||||
|
||||
waitms = 100;
|
||||
if ((argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
|
||||
spec = argv[0];
|
||||
if ( argc > 1) {
|
||||
options = argv[1];
|
||||
}
|
||||
if (ast_strlen_zero(spec) || !strcmp(spec, "all")) {
|
||||
spec = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (options) {
|
||||
char *opts[OPT_ARG_ARRAY_SIZE];
|
||||
ast_app_parse_options(chanspy_opts, &flags, opts, options);
|
||||
if (ast_test_flag(&flags, OPTION_GROUP)) {
|
||||
mygroup = opts[OPT_ARG_GROUP];
|
||||
}
|
||||
if (ast_test_flag(&flags, OPTION_RECORD)) {
|
||||
if (!(recbase = opts[OPT_ARG_RECORD])) {
|
||||
recbase = "chanspy";
|
||||
}
|
||||
}
|
||||
silent = ast_test_flag(&flags, OPTION_QUIET);
|
||||
bronly = ast_test_flag(&flags, OPTION_BRIDGED);
|
||||
if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
|
||||
int vol;
|
||||
|
||||
for (;;) {
|
||||
if (!ast_test_flag(flags, OPTION_QUIET)) {
|
||||
if ((sscanf(opts[OPT_ARG_VOLUME], "%30d", &vol) != 1) || (vol > 4) || (vol < -4))
|
||||
ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
|
||||
else
|
||||
volfactor = vol;
|
||||
}
|
||||
}
|
||||
else
|
||||
ast_clear_flag(&flags, AST_FLAGS_ALL);
|
||||
|
||||
if (recbase) {
|
||||
char filename[512];
|
||||
snprintf(filename,sizeof(filename),"%s/%s.%d.raw",ast_config_AST_MONITOR_DIR, recbase, (int)time(NULL));
|
||||
if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644)) <= 0) {
|
||||
ast_log(LOG_WARNING, "Cannot open %s for recording\n", filename);
|
||||
fd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
if (!silent) {
|
||||
res = ast_streamfile(chan, "beep", chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, "");
|
||||
else if (res < 0) {
|
||||
if (res < 0) {
|
||||
ast_clear_flag(chan, AST_FLAG_SPYING);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
count = 0;
|
||||
res = ast_waitfordigit(chan, waitms);
|
||||
if (res < 0) {
|
||||
ast_clear_flag(chan, AST_FLAG_SPYING);
|
||||
break;
|
||||
}
|
||||
|
||||
/* reset for the next loop around, unless overridden later */
|
||||
waitms = 100;
|
||||
peer = prev = next = NULL;
|
||||
peer = local_channel_walk(NULL);
|
||||
prev=NULL;
|
||||
while(peer) {
|
||||
if (peer != chan) {
|
||||
char *group = NULL;
|
||||
int igrp = 1;
|
||||
|
||||
for (peer = next_channel(peer, spec, exten, context);
|
||||
peer;
|
||||
prev = peer, peer = next ? next : next_channel(peer, spec, exten, context), next = NULL) {
|
||||
const char *group;
|
||||
int igrp = !mygroup;
|
||||
char *groups[25];
|
||||
int num_groups = 0;
|
||||
char *dup_group;
|
||||
int x;
|
||||
char *s;
|
||||
|
||||
if (peer == prev)
|
||||
break;
|
||||
|
||||
if (peer == chan)
|
||||
continue;
|
||||
|
||||
if (ast_test_flag(flags, OPTION_BRIDGED) && !ast_bridged_channel(peer))
|
||||
continue;
|
||||
|
||||
if (ast_check_hangup(peer) || ast_test_flag(peer, AST_FLAG_SPYING))
|
||||
continue;
|
||||
|
||||
if (mygroup) {
|
||||
if ((group = pbx_builtin_getvar_helper(peer, "SPYGROUP"))) {
|
||||
dup_group = ast_strdupa(group);
|
||||
num_groups = ast_app_separate_args(dup_group, ':', groups,
|
||||
sizeof(groups) / sizeof(groups[0]));
|
||||
if (peer == prev && !chosen) {
|
||||
break;
|
||||
}
|
||||
chosen = 0;
|
||||
group = pbx_builtin_getvar_helper(peer, "SPYGROUP");
|
||||
if (mygroup) {
|
||||
if (!group || strcmp(mygroup, group)) {
|
||||
igrp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (x = 0; x < num_groups; x++) {
|
||||
if (!strcmp(mygroup, groups[x])) {
|
||||
igrp = 1;
|
||||
break;
|
||||
if (igrp && (!spec || ((strlen(spec) <= strlen(peer->name) &&
|
||||
!strncasecmp(peer->name, spec, strlen(spec)))))) {
|
||||
if (peer && (!bronly || ast_bridged_channel(peer)) &&
|
||||
!ast_check_hangup(peer) && !ast_test_flag(peer, AST_FLAG_SPYING)) {
|
||||
int x = 0;
|
||||
strncpy(peer_name, "spy-", 5);
|
||||
strncpy(peer_name + strlen(peer_name), peer->name, AST_NAME_STRLEN);
|
||||
ptr = strchr(peer_name, '/');
|
||||
*ptr = '\0';
|
||||
ptr++;
|
||||
for (x = 0 ; x < strlen(peer_name) ; x++) {
|
||||
if (peer_name[x] == '/') {
|
||||
break;
|
||||
}
|
||||
peer_name[x] = tolower(peer_name[x]);
|
||||
}
|
||||
|
||||
if (!silent) {
|
||||
if (ast_fileexists(peer_name, NULL, NULL) != -1) {
|
||||
res = ast_streamfile(chan, peer_name, chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, "");
|
||||
if (res)
|
||||
break;
|
||||
} else
|
||||
res = ast_say_character_str(chan, peer_name, "", chan->language);
|
||||
if ((num=atoi(ptr)))
|
||||
ast_say_digits(chan, atoi(ptr), "", chan->language);
|
||||
}
|
||||
count++;
|
||||
prev = peer;
|
||||
res = channel_spy(chan, peer, &volfactor, fd);
|
||||
if (res == -1) {
|
||||
break;
|
||||
} else if (res > 1 && spec) {
|
||||
snprintf(name, AST_NAME_STRLEN, "%s/%d", spec, res);
|
||||
if ((peer = local_get_channel_begin_name(name))) {
|
||||
chosen = 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!igrp)
|
||||
continue;
|
||||
|
||||
strcpy(peer_name, "spy-");
|
||||
strncat(peer_name, peer->name, AST_NAME_STRLEN);
|
||||
ptr = strchr(peer_name, '/');
|
||||
*ptr++ = '\0';
|
||||
|
||||
for (s = peer_name; s < ptr; s++)
|
||||
*s = tolower(*s);
|
||||
|
||||
if (!ast_test_flag(flags, OPTION_QUIET)) {
|
||||
if (ast_fileexists(peer_name, NULL, NULL) != -1) {
|
||||
res = ast_streamfile(chan, peer_name, chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, "");
|
||||
if (res)
|
||||
break;
|
||||
} else
|
||||
res = ast_say_character_str(chan, peer_name, "", chan->language);
|
||||
if ((num = atoi(ptr)))
|
||||
ast_say_digits(chan, atoi(ptr), "", chan->language);
|
||||
}
|
||||
|
||||
waitms = 5000;
|
||||
res = channel_spy(chan, peer, &volfactor, fd, flags);
|
||||
|
||||
if (res == -1) {
|
||||
if ((peer = local_channel_walk(peer)) == NULL) {
|
||||
break;
|
||||
} else if (res > 1 && spec) {
|
||||
snprintf(nameprefix, AST_NAME_STRLEN, "%s/%d", spec, res);
|
||||
if ((next = ast_get_channel_by_name_prefix_locked(nameprefix, strlen(nameprefix)))) {
|
||||
ast_channel_unlock(next);
|
||||
} else {
|
||||
/* stay on this channel */
|
||||
next = peer;
|
||||
}
|
||||
peer = NULL;
|
||||
}
|
||||
}
|
||||
if (res == -1)
|
||||
break;
|
||||
waitms = count ? 100 : 5000;
|
||||
}
|
||||
|
||||
|
||||
if (fd > 0) {
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (oldrf && ast_set_read_format(chan, oldrf) < 0) {
|
||||
ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
|
||||
}
|
||||
|
||||
if (oldwf && ast_set_write_format(chan, oldwf) < 0) {
|
||||
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
|
||||
}
|
||||
|
||||
ast_clear_flag(chan, AST_FLAG_SPYING);
|
||||
|
||||
ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);
|
||||
|
||||
return res;
|
||||
ALL_DONE(u, res);
|
||||
}
|
||||
|
||||
static int chanspy_exec(struct ast_channel *chan, void *data)
|
||||
int unload_module(void)
|
||||
{
|
||||
struct ast_module_user *u;
|
||||
char *options = NULL;
|
||||
char *spec = NULL;
|
||||
char *argv[2];
|
||||
char *mygroup = NULL;
|
||||
char *recbase = NULL;
|
||||
int fd = 0;
|
||||
struct ast_flags flags;
|
||||
int oldwf = 0;
|
||||
int argc = 0;
|
||||
int volfactor = 0;
|
||||
int res;
|
||||
|
||||
data = ast_strdupa(data);
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
|
||||
if ((argc = ast_app_separate_args(data, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
|
||||
spec = argv[0];
|
||||
if (argc > 1)
|
||||
options = argv[1];
|
||||
|
||||
if (ast_strlen_zero(spec) || !strcmp(spec, "all"))
|
||||
spec = NULL;
|
||||
}
|
||||
|
||||
if (options) {
|
||||
char *opts[OPT_ARG_ARRAY_SIZE];
|
||||
|
||||
ast_app_parse_options(spy_opts, &flags, opts, options);
|
||||
if (ast_test_flag(&flags, OPTION_GROUP))
|
||||
mygroup = opts[OPT_ARG_GROUP];
|
||||
|
||||
if (ast_test_flag(&flags, OPTION_RECORD) &&
|
||||
!(recbase = opts[OPT_ARG_RECORD]))
|
||||
recbase = "chanspy";
|
||||
|
||||
if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
|
||||
int vol;
|
||||
|
||||
if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &vol) != 1) || (vol > 4) || (vol < -4))
|
||||
ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
|
||||
else
|
||||
volfactor = vol;
|
||||
}
|
||||
|
||||
if (ast_test_flag(&flags, OPTION_PRIVATE))
|
||||
ast_set_flag(&flags, OPTION_WHISPER);
|
||||
} else
|
||||
ast_clear_flag(&flags, AST_FLAGS_ALL);
|
||||
|
||||
oldwf = chan->writeformat;
|
||||
if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
|
||||
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
|
||||
ast_module_user_remove(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (recbase) {
|
||||
char filename[512];
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
|
||||
if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644)) <= 0) {
|
||||
ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
|
||||
fd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
res = common_exec(chan, &flags, volfactor, fd, mygroup, spec, NULL, NULL);
|
||||
|
||||
if (fd)
|
||||
close(fd);
|
||||
|
||||
if (oldwf && ast_set_write_format(chan, oldwf) < 0)
|
||||
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
|
||||
|
||||
ast_module_user_remove(u);
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int extenspy_exec(struct ast_channel *chan, void *data)
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, chanspy_exec, synopsis, desc);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return (char *) synopsis;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
struct ast_module_user *u;
|
||||
char *options = NULL;
|
||||
char *exten = NULL;
|
||||
char *context = NULL;
|
||||
char *argv[2];
|
||||
char *mygroup = NULL;
|
||||
char *recbase = NULL;
|
||||
int fd = 0;
|
||||
struct ast_flags flags;
|
||||
int oldwf = 0;
|
||||
int argc = 0;
|
||||
int volfactor = 0;
|
||||
int res;
|
||||
|
||||
data = ast_strdupa(data);
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
|
||||
if ((argc = ast_app_separate_args(data, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
|
||||
context = argv[0];
|
||||
if (!ast_strlen_zero(argv[0]))
|
||||
exten = strsep(&context, "@");
|
||||
if (ast_strlen_zero(context))
|
||||
context = ast_strdupa(chan->context);
|
||||
if (argc > 1)
|
||||
options = argv[1];
|
||||
}
|
||||
|
||||
if (options) {
|
||||
char *opts[OPT_ARG_ARRAY_SIZE];
|
||||
|
||||
ast_app_parse_options(spy_opts, &flags, opts, options);
|
||||
if (ast_test_flag(&flags, OPTION_GROUP))
|
||||
mygroup = opts[OPT_ARG_GROUP];
|
||||
|
||||
if (ast_test_flag(&flags, OPTION_RECORD) &&
|
||||
!(recbase = opts[OPT_ARG_RECORD]))
|
||||
recbase = "chanspy";
|
||||
|
||||
if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
|
||||
int vol;
|
||||
|
||||
if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &vol) != 1) || (vol > 4) || (vol < -4))
|
||||
ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
|
||||
else
|
||||
volfactor = vol;
|
||||
}
|
||||
|
||||
if (ast_test_flag(&flags, OPTION_PRIVATE))
|
||||
ast_set_flag(&flags, OPTION_WHISPER);
|
||||
} else
|
||||
ast_clear_flag(&flags, AST_FLAGS_ALL);
|
||||
|
||||
oldwf = chan->writeformat;
|
||||
if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
|
||||
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
|
||||
ast_module_user_remove(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (recbase) {
|
||||
char filename[512];
|
||||
|
||||
snprintf(filename, sizeof(filename), "%s/%s.%d.raw", ast_config_AST_MONITOR_DIR, recbase, (int) time(NULL));
|
||||
if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644)) <= 0) {
|
||||
ast_log(LOG_WARNING, "Cannot open '%s' for recording\n", filename);
|
||||
fd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
res = common_exec(chan, &flags, volfactor, fd, mygroup, NULL, exten, context);
|
||||
|
||||
if (fd)
|
||||
close(fd);
|
||||
|
||||
if (oldwf && ast_set_write_format(chan, oldwf) < 0)
|
||||
ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
|
||||
|
||||
ast_module_user_remove(u);
|
||||
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
char *key()
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
res |= ast_unregister_application(app_chan);
|
||||
res |= ast_unregister_application(app_ext);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
|
||||
return res;
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
res |= ast_register_application(app_chan, chanspy_exec, tdesc, desc_chan);
|
||||
res |= ast_register_application(app_ext, extenspy_exec, tdesc, desc_ext);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Listen to the audio of an active channel");
|
||||
|
||||
@@ -17,22 +17,19 @@
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Trivial application to control playback of a sound file
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -44,6 +41,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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";
|
||||
@@ -66,6 +65,9 @@ static const char *descrip =
|
||||
" CPLAYBACKSTATUS - This variable contains the status of the attempt as a text\n"
|
||||
" string, one of: SUCCESS | USERSTOPPED | ERROR\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int is_on_phonepad(char key)
|
||||
{
|
||||
@@ -76,7 +78,7 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0, priority_jump = 0;
|
||||
int skipms = 0;
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
char *tmp;
|
||||
int argc;
|
||||
char *argv[8];
|
||||
@@ -96,7 +98,7 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
tmp = ast_strdupa(data);
|
||||
memset(argv, 0, sizeof(argv));
|
||||
@@ -105,7 +107,7 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
if (argc < 1) {
|
||||
ast_log(LOG_WARNING, "ControlPlayback requires an argument (filename)\n");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -137,7 +139,7 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
|
||||
pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "USERSTOPPED");
|
||||
} else {
|
||||
if (res < 0) {
|
||||
if (priority_jump || ast_opt_priority_jumping) {
|
||||
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");
|
||||
}
|
||||
@@ -148,21 +150,41 @@ static int controlplayback_exec(struct ast_channel *chan, void *data)
|
||||
pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "SUCCESS");
|
||||
}
|
||||
|
||||
ast_module_user_remove(u);
|
||||
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
257
apps/app_curl.c
Normal 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
473
apps/app_cut.c
Normal 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, "%30f", &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, "%30d-%30d", &num1, &num2) == 2) {
|
||||
/* range with both start and end */
|
||||
} else if (sscanf(nextgroup, "-%30d", &num2) == 1) {
|
||||
/* range with end */
|
||||
num1 = 0;
|
||||
} else if ((sscanf(nextgroup, "%30d%1c", &num1, &trashchar) == 2) && (trashchar == '-')) {
|
||||
/* range with start */
|
||||
num2 = MAXRESULT;
|
||||
} else if (sscanf(nextgroup, "%30d", &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
101
apps/app_datetime.c
Normal 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;
|
||||
}
|
||||
212
apps/app_db.c
212
apps/app_db.c
@@ -22,22 +22,19 @@
|
||||
*
|
||||
* \brief Database access functions
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
* \author Jefferson Noxon <jeff@debian.org>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -48,38 +45,65 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/options.h"
|
||||
|
||||
/*! \todo XXX Remove this application after 1.4 is relased */
|
||||
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";
|
||||
|
||||
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 ast_module_user *u;
|
||||
struct localuser *u;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
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_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
if (ast_strlen_zero(keytree))
|
||||
@@ -101,7 +125,7 @@ static int deltree_exec(struct ast_channel *chan, void *data)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "DBdeltree: Error deleting key from database.\n");
|
||||
}
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -109,24 +133,23 @@ static int deltree_exec(struct ast_channel *chan, void *data)
|
||||
static int del_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
char *argv, *family, *key;
|
||||
struct ast_module_user *u;
|
||||
static int deprecation_warning = 0;
|
||||
struct localuser *u;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
|
||||
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_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
if (option_verbose > 2)
|
||||
@@ -139,29 +162,162 @@ static int del_exec(struct ast_channel *chan, void *data)
|
||||
ast_log(LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
}
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
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 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;
|
||||
}
|
||||
|
||||
1504
apps/app_dial.c
1504
apps/app_dial.c
File diff suppressed because it is too large
Load Diff
@@ -22,20 +22,18 @@
|
||||
*
|
||||
* \brief Virtual Dictation Machine Application For Asterisk
|
||||
*
|
||||
* \author Anthony Minessale II <anthmct@yahoo.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/stat.h> /* for mkdir */
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
@@ -46,12 +44,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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),
|
||||
@@ -78,20 +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 ast_module_user *u;
|
||||
struct localuser *u;
|
||||
int ffactor = 320 * 80,
|
||||
res = 0,
|
||||
argc = 0,
|
||||
done = 0,
|
||||
oldr = 0,
|
||||
lastop = 0,
|
||||
@@ -102,43 +100,35 @@ static int dictate_exec(struct ast_channel *chan, void *data)
|
||||
maxlen = 0,
|
||||
mode = 0;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
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 (!ast_strlen_zero(data) && (mydata = ast_strdupa(data))) {
|
||||
argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
|
||||
}
|
||||
|
||||
if (args.argc && !ast_strlen_zero(args.base)) {
|
||||
base = args.base;
|
||||
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");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
mkdir(base, 0755);
|
||||
len = strlen(base) + strlen(filein) + 2;
|
||||
if (!path || len > maxlen) {
|
||||
@@ -330,20 +320,40 @@ static int dictate_exec(struct ast_channel *chan, void *data)
|
||||
if (oldr) {
|
||||
ast_set_read_format(chan, oldr);
|
||||
}
|
||||
ast_module_user_remove(u);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,20 +20,18 @@
|
||||
*
|
||||
* \brief Directed Call Pickup Support
|
||||
*
|
||||
* \author Joshua Colp <jcolp@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -41,141 +39,131 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/options.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 pickup any ringing channel\n"
|
||||
" 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. If you use the special string \"PICKUPMARK\" for the context parameter, for example\n"
|
||||
"10@PICKUPMARK, this application tries to find a channel which has defined a channel variable with the same content\n"
|
||||
"as \"extension\".";
|
||||
"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;
|
||||
|
||||
if (option_debug)
|
||||
ast_log(LOG_DEBUG, "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))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Attempt to pick up specified extension with context */
|
||||
static int pickup_by_exten(struct ast_channel *chan, char *exten, 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) &&
|
||||
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, 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;
|
||||
struct ast_module_user *u = NULL;
|
||||
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)) {
|
||||
ast_log(LOG_WARNING, "Pickup requires an argument (extension)!\n");
|
||||
ast_log(LOG_WARNING, "Pickup requires an argument (extension) !\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Parse extension (and context if there) */
|
||||
while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) {
|
||||
if ((context = strchr(exten, '@')))
|
||||
*context++ = '\0';
|
||||
if (context && !strcasecmp(context, PICKUPMARK)) {
|
||||
if (!pickup_by_mark(chan, exten))
|
||||
break;
|
||||
} else {
|
||||
if (!pickup_by_exten(chan, exten, context ? context : chan->context))
|
||||
break;
|
||||
}
|
||||
ast_log(LOG_NOTICE, "No target channel found for %s.\n", exten);
|
||||
/* Get the extension and context if present */
|
||||
exten = data;
|
||||
context = strchr(data, '@');
|
||||
if (context) {
|
||||
*context = '\0';
|
||||
context++;
|
||||
}
|
||||
|
||||
ast_module_user_remove(u);
|
||||
/* 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");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -19,21 +19,19 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief Provide a directory of extensions
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.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"
|
||||
@@ -43,9 +41,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/config.h"
|
||||
#include "asterisk/say.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/app.h"
|
||||
|
||||
#ifdef ODBC_STORAGE
|
||||
#ifdef USE_ODBC_STORAGE
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include "asterisk/res_odbc.h"
|
||||
@@ -55,6 +52,7 @@ static char odbc_table[80] = "voicemessages";
|
||||
static char vmfmts[80] = "wav";
|
||||
#endif
|
||||
|
||||
static char *tdesc = "Extension Directory";
|
||||
static char *app = "Directory";
|
||||
|
||||
static char *synopsis = "Provide directory of voicemail extensions";
|
||||
@@ -74,10 +72,8 @@ static char *descrip =
|
||||
" extension that the user has selected, or when jumping to the\n"
|
||||
" 'o' or 'a' extension.\n\n"
|
||||
" Options:\n"
|
||||
" e - In addition to the name, also read the extension number to the\n"
|
||||
" caller before presenting dialing options.\n"
|
||||
" f - Allow the caller to enter the first name of a user in the directory\n"
|
||||
" instead of using the last name.\n";
|
||||
" instead of using the last name.\n";
|
||||
|
||||
/* For simplicity, I'm keeping the format compatible with the voicemail config,
|
||||
but i'm open to suggestions for isolating it */
|
||||
@@ -87,8 +83,11 @@ static char *descrip =
|
||||
/* How many digits to read in */
|
||||
#define NUMDIGITS 3
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
#ifdef ODBC_STORAGE
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
#ifdef USE_ODBC_STORAGE
|
||||
static void retrieve_file(char *dir)
|
||||
{
|
||||
int x = 0;
|
||||
@@ -102,9 +101,9 @@ static void retrieve_file(char *dir)
|
||||
char *c;
|
||||
SQLLEN colsize;
|
||||
char full_fn[256];
|
||||
struct odbc_obj *obj;
|
||||
|
||||
obj = ast_odbc_request_obj(odbc_database, 1);
|
||||
odbc_obj *obj;
|
||||
obj = fetch_odbc_obj(odbc_database, 0);
|
||||
if (obj) {
|
||||
do {
|
||||
ast_copy_string(fmt, vmfmts, sizeof(fmt));
|
||||
@@ -127,7 +126,7 @@ static void retrieve_file(char *dir)
|
||||
break;
|
||||
}
|
||||
SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(dir), 0, (void *)dir, 0, NULL);
|
||||
res = ast_odbc_smart_execute(obj, stmt);
|
||||
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);
|
||||
@@ -173,7 +172,6 @@ static void retrieve_file(char *dir)
|
||||
}
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
|
||||
} while (0);
|
||||
ast_odbc_release_obj(obj);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Failed to obtain database object for '%s'!\n", odbc_database);
|
||||
if (fdm != MAP_FAILED)
|
||||
@@ -184,11 +182,11 @@ static void retrieve_file(char *dir)
|
||||
}
|
||||
#endif
|
||||
|
||||
static char *convert(const char *lastname)
|
||||
static char *convert(char *lastname)
|
||||
{
|
||||
char *tmp;
|
||||
int lcount = 0;
|
||||
tmp = ast_malloc(NUMDIGITS + 1);
|
||||
tmp = malloc(NUMDIGITS + 1);
|
||||
if (tmp) {
|
||||
while((*lastname > 32) && lcount < NUMDIGITS) {
|
||||
switch(toupper(*lastname)) {
|
||||
@@ -258,79 +256,95 @@ static char *convert(const char *lastname)
|
||||
* '1' for selected entry from directory
|
||||
* '*' for skipped entry from directory
|
||||
*/
|
||||
static int play_mailbox_owner(struct ast_channel *chan, char *context,
|
||||
char *dialcontext, char *ext, char *name, int readext,
|
||||
int fromappvm)
|
||||
{
|
||||
static int play_mailbox_owner(struct ast_channel *chan, char *context, char *dialcontext, char *ext, char *name, int fromappvm) {
|
||||
int res = 0;
|
||||
int loop;
|
||||
int loop = 3;
|
||||
char fn[256];
|
||||
char fn2[256];
|
||||
|
||||
/* Check for the VoiceMail2 greeting first */
|
||||
snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet",
|
||||
ast_config_AST_SPOOL_DIR, context, ext);
|
||||
#ifdef ODBC_STORAGE
|
||||
(char *)ast_config_AST_SPOOL_DIR, context, ext);
|
||||
#ifdef USE_ODBC_STORAGE
|
||||
retrieve_file(fn);
|
||||
#endif
|
||||
|
||||
if (ast_fileexists(fn, NULL, chan->language) <= 0) {
|
||||
/* no file, check for an old-style Voicemail greeting */
|
||||
snprintf(fn, sizeof(fn), "%s/vm/%s/greet",
|
||||
ast_config_AST_SPOOL_DIR, ext);
|
||||
}
|
||||
#ifdef ODBC_STORAGE
|
||||
retrieve_file(fn);
|
||||
/* Otherwise, check for an old-style Voicemail greeting */
|
||||
snprintf(fn2, sizeof(fn2), "%s/vm/%s/greet",
|
||||
(char *)ast_config_AST_SPOOL_DIR, ext);
|
||||
#ifdef USE_ODBC_STORAGE
|
||||
retrieve_file(fn2);
|
||||
#endif
|
||||
|
||||
if (ast_fileexists(fn, NULL, chan->language) > 0) {
|
||||
res = ast_stream_and_wait(chan, fn, chan->language, AST_DIGIT_ANY);
|
||||
res = ast_streamfile(chan, fn, chan->language);
|
||||
if (!res) {
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
}
|
||||
ast_stopstream(chan);
|
||||
/* If Option 'e' was specified, also read the extension number with the name */
|
||||
if (readext) {
|
||||
ast_stream_and_wait(chan, "vm-extension", chan->language, AST_DIGIT_ANY);
|
||||
res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language);
|
||||
} else if (ast_fileexists(fn2, NULL, chan->language) > 0) {
|
||||
res = ast_streamfile(chan, fn2, chan->language);
|
||||
if (!res) {
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
}
|
||||
ast_stopstream(chan);
|
||||
} else {
|
||||
res = ast_say_character_str(chan, S_OR(name, ext), AST_DIGIT_ANY, chan->language);
|
||||
if (!ast_strlen_zero(name) && readext) {
|
||||
ast_stream_and_wait(chan, "vm-extension", chan->language, AST_DIGIT_ANY);
|
||||
res = ast_say_character_str(chan, ext, AST_DIGIT_ANY, chan->language);
|
||||
}
|
||||
res = ast_say_character_str(chan, !ast_strlen_zero(name) ? name : ext,
|
||||
AST_DIGIT_ANY, chan->language);
|
||||
}
|
||||
#ifdef ODBC_STORAGE
|
||||
#ifdef USE_ODBC_STORAGE
|
||||
ast_filedelete(fn, NULL);
|
||||
ast_filedelete(fn2, NULL);
|
||||
#endif
|
||||
|
||||
for (loop = 3 ; loop > 0; loop--) {
|
||||
if (!res)
|
||||
res = ast_stream_and_wait(chan, "dir-instr", chan->language, AST_DIGIT_ANY);
|
||||
if (!res)
|
||||
while (loop) {
|
||||
if (!res) {
|
||||
res = ast_streamfile(chan, "dir-instr", chan->language);
|
||||
}
|
||||
if (!res) {
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
}
|
||||
if (!res) {
|
||||
res = ast_waitfordigit(chan, 3000);
|
||||
}
|
||||
ast_stopstream(chan);
|
||||
|
||||
if (res < 0) /* User hungup, so jump out now */
|
||||
break;
|
||||
if (res == '1') { /* Name selected */
|
||||
if (fromappvm) {
|
||||
/* We still want to set the exten though */
|
||||
ast_copy_string(chan->exten, ext, sizeof(chan->exten));
|
||||
} else {
|
||||
if (ast_goto_if_exists(chan, dialcontext, ext, 1)) {
|
||||
ast_log(LOG_WARNING,
|
||||
"Can't find extension '%s' in context '%s'. "
|
||||
"Did you pass the wrong context to Directory?\n",
|
||||
ext, dialcontext);
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (res > -1) {
|
||||
switch (res) {
|
||||
case '1':
|
||||
/* Name selected */
|
||||
loop = 0;
|
||||
if (fromappvm) {
|
||||
/* We still want to set the exten */
|
||||
ast_copy_string(chan->exten, ext, sizeof(chan->exten));
|
||||
} else {
|
||||
if (ast_goto_if_exists(chan, dialcontext, ext, 1)) {
|
||||
ast_log(LOG_WARNING,
|
||||
"Can't find extension '%s' in context '%s'. "
|
||||
"Did you pass the wrong context to Directory?\n",
|
||||
ext, dialcontext);
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '*':
|
||||
/* Skip to next match in list */
|
||||
loop = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Not '1', or '*', so decrement number of tries */
|
||||
res = 0;
|
||||
loop--;
|
||||
break;
|
||||
} /* end switch */
|
||||
} /* end if */
|
||||
else {
|
||||
/* User hungup, so jump out now */
|
||||
loop = 0;
|
||||
}
|
||||
if (res == '*') /* Skip to next match in list */
|
||||
break;
|
||||
|
||||
/* Not '1', or '*', so decrement number of tries */
|
||||
res = 0;
|
||||
}
|
||||
} /* end while */
|
||||
|
||||
return(res);
|
||||
}
|
||||
@@ -342,8 +356,8 @@ static struct ast_config *realtime_directory(char *context)
|
||||
struct ast_category *cat;
|
||||
struct ast_variable *var;
|
||||
char *mailbox;
|
||||
const char *fullname;
|
||||
const char *hidefromdir;
|
||||
char *fullname;
|
||||
char *hidefromdir;
|
||||
char tmp[100];
|
||||
|
||||
/* Load flat file config. */
|
||||
@@ -375,8 +389,8 @@ static struct ast_config *realtime_directory(char *context)
|
||||
ast_category_append(cfg, cat);
|
||||
}
|
||||
|
||||
mailbox = NULL;
|
||||
while ( (mailbox = ast_category_browse(rtdata, mailbox)) ) {
|
||||
mailbox = ast_category_browse(rtdata, NULL);
|
||||
while (mailbox) {
|
||||
fullname = ast_variable_retrieve(rtdata, mailbox, "fullname");
|
||||
hidefromdir = ast_variable_retrieve(rtdata, mailbox, "hidefromdir");
|
||||
snprintf(tmp, sizeof(tmp), "no-password,%s,hidefromdir=%s",
|
||||
@@ -387,24 +401,23 @@ static struct ast_config *realtime_directory(char *context)
|
||||
ast_variable_append(cat, var);
|
||||
else
|
||||
ast_log(LOG_WARNING, "Out of memory adding mailbox '%s'\n", mailbox);
|
||||
mailbox = ast_category_browse(rtdata, mailbox);
|
||||
}
|
||||
ast_config_destroy(rtdata);
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
static int do_directory(struct ast_channel *chan, struct ast_config *cfg, struct ast_config *ucfg, char *context, char *dialcontext, char digit, int last, int readext, int fromappvm)
|
||||
static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *context, char *dialcontext, char digit, int last, int fromappvm)
|
||||
{
|
||||
/* Read in the first three digits.. "digit" is the first digit, already read */
|
||||
char ext[NUMDIGITS + 1], *cat;
|
||||
char ext[NUMDIGITS + 1];
|
||||
char name[80] = "";
|
||||
struct ast_variable *v;
|
||||
int res;
|
||||
int found=0;
|
||||
int lastuserchoice = 0;
|
||||
char *start, *conv, *stringp = NULL;
|
||||
const char *pos;
|
||||
int breakout = 0;
|
||||
char *start, *pos, *conv,*stringp=NULL;
|
||||
|
||||
if (ast_strlen_zero(context)) {
|
||||
ast_log(LOG_WARNING,
|
||||
@@ -474,7 +487,7 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, struct
|
||||
|
||||
if (v) {
|
||||
/* We have a match -- play a greeting if they have it */
|
||||
res = play_mailbox_owner(chan, context, dialcontext, v->name, name, readext, fromappvm);
|
||||
res = play_mailbox_owner(chan, context, dialcontext, v->name, name, fromappvm);
|
||||
switch (res) {
|
||||
case -1:
|
||||
/* user pressed '1' but extension does not exist, or
|
||||
@@ -501,66 +514,11 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, struct
|
||||
}
|
||||
}
|
||||
|
||||
if (!res && ucfg) {
|
||||
/* Search users.conf for all names which start with those digits */
|
||||
for (cat = ast_category_browse(ucfg, NULL); cat && !res ; cat = ast_category_browse(ucfg, cat)) {
|
||||
if (!strcasecmp(cat, "general"))
|
||||
continue;
|
||||
if (!ast_true(ast_config_option(ucfg, cat, "hasdirectory")))
|
||||
continue;
|
||||
|
||||
/* Find all candidate extensions */
|
||||
if ((pos = ast_variable_retrieve(ucfg, cat, "fullname"))) {
|
||||
ast_copy_string(name, pos, sizeof(name));
|
||||
/* Grab the last name */
|
||||
if (last && strrchr(pos,' '))
|
||||
pos = strrchr(pos, ' ') + 1;
|
||||
conv = convert(pos);
|
||||
if (conv) {
|
||||
if (!strcmp(conv, ext)) {
|
||||
/* Match! */
|
||||
found++;
|
||||
/* We have a match -- play a greeting if they have it */
|
||||
res = play_mailbox_owner(chan, context, dialcontext, cat, name, readext, fromappvm);
|
||||
switch (res) {
|
||||
case -1:
|
||||
/* user pressed '1' but extension does not exist, or
|
||||
* user hungup
|
||||
*/
|
||||
lastuserchoice = 0;
|
||||
breakout = 1;
|
||||
break;
|
||||
case '1':
|
||||
/* user pressed '1' and extensions exists;
|
||||
play_mailbox_owner will already have done
|
||||
a goto() on the channel
|
||||
*/
|
||||
lastuserchoice = res;
|
||||
breakout = 1;
|
||||
break;
|
||||
case '*':
|
||||
/* user pressed '*' to skip something found */
|
||||
lastuserchoice = res;
|
||||
breakout = 0;
|
||||
res = 0;
|
||||
break;
|
||||
default:
|
||||
breakout = 1;
|
||||
break;
|
||||
}
|
||||
free(conv);
|
||||
if (breakout)
|
||||
break;
|
||||
}
|
||||
else
|
||||
free(conv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lastuserchoice != '1') {
|
||||
res = ast_streamfile(chan, found ? "dir-nomore" : "dir-nomatch", chan->language);
|
||||
if (found)
|
||||
res = ast_streamfile(chan, "dir-nomore", chan->language);
|
||||
else
|
||||
res = ast_streamfile(chan, "dir-nomatch", chan->language);
|
||||
if (!res)
|
||||
res = 1;
|
||||
return res;
|
||||
@@ -573,96 +531,96 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, struct
|
||||
static int directory_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct ast_module_user *u;
|
||||
struct ast_config *cfg, *ucfg;
|
||||
struct localuser *u;
|
||||
struct ast_config *cfg;
|
||||
int last = 1;
|
||||
int readext = 0;
|
||||
int fromappvm = 0;
|
||||
const char *dirintro;
|
||||
char *parse;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(vmcontext);
|
||||
AST_APP_ARG(dialcontext);
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
char *context, *dialcontext, *dirintro, *options;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "Directory requires an argument (context[,dialcontext])\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
parse = ast_strdupa(data);
|
||||
context = ast_strdupa(data);
|
||||
dialcontext = strchr(context, '|');
|
||||
if (dialcontext) {
|
||||
*dialcontext = '\0';
|
||||
dialcontext++;
|
||||
options = strchr(dialcontext, '|');
|
||||
if (options) {
|
||||
*options = '\0';
|
||||
options++;
|
||||
if (strchr(options, 'f'))
|
||||
last = 0;
|
||||
if (strchr(options, 'v'))
|
||||
fromappvm = 1;
|
||||
}
|
||||
} else
|
||||
dialcontext = context;
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, parse);
|
||||
|
||||
if (args.options) {
|
||||
if (strchr(args.options, 'f'))
|
||||
last = 0;
|
||||
if (strchr(args.options, 'e'))
|
||||
readext = 1;
|
||||
if (strchr(args.options, 'v'))
|
||||
fromappvm = 1;
|
||||
}
|
||||
|
||||
if (ast_strlen_zero(args.dialcontext))
|
||||
args.dialcontext = args.vmcontext;
|
||||
|
||||
cfg = realtime_directory(args.vmcontext);
|
||||
cfg = realtime_directory(context);
|
||||
if (!cfg) {
|
||||
ast_log(LOG_ERROR, "Unable to read the configuration data!\n");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ucfg = ast_config_load("users.conf");
|
||||
|
||||
dirintro = ast_variable_retrieve(cfg, args.vmcontext, "directoryintro");
|
||||
dirintro = ast_variable_retrieve(cfg, context, "directoryintro");
|
||||
if (ast_strlen_zero(dirintro))
|
||||
dirintro = ast_variable_retrieve(cfg, "general", "directoryintro");
|
||||
if (ast_strlen_zero(dirintro))
|
||||
dirintro = last ? "dir-intro" : "dir-intro-fn";
|
||||
if (ast_strlen_zero(dirintro)) {
|
||||
if (last)
|
||||
dirintro = "dir-intro";
|
||||
else
|
||||
dirintro = "dir-intro-fn";
|
||||
}
|
||||
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
res = ast_answer(chan);
|
||||
|
||||
for (;;) {
|
||||
if (!res)
|
||||
res = ast_stream_and_wait(chan, dirintro, chan->language, AST_DIGIT_ANY);
|
||||
res = ast_streamfile(chan, dirintro, chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
if (!res)
|
||||
res = ast_waitfordigit(chan, 5000);
|
||||
if (res > 0) {
|
||||
res = do_directory(chan, cfg, ucfg, args.vmcontext, args.dialcontext, res, last, readext, fromappvm);
|
||||
res = do_directory(chan, cfg, context, dialcontext, res, last, fromappvm);
|
||||
if (res > 0) {
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
if (res >= 0)
|
||||
if (res >= 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (ucfg)
|
||||
ast_config_destroy(ucfg);
|
||||
ast_config_destroy(cfg);
|
||||
ast_module_user_remove(u);
|
||||
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)
|
||||
{
|
||||
#ifdef ODBC_STORAGE
|
||||
#ifdef USE_ODBC_STORAGE
|
||||
struct ast_config *cfg = ast_config_load(VOICEMAIL_CONFIG);
|
||||
const char *tmp;
|
||||
char *tmp;
|
||||
|
||||
if (cfg) {
|
||||
if ((tmp = ast_variable_retrieve(cfg, "general", "odbcstorage"))) {
|
||||
@@ -682,4 +640,19 @@ static int load_module(void)
|
||||
return ast_register_application(app, directory_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Extension Directory");
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
175
apps/app_disa.c
175
apps/app_disa.c
@@ -26,16 +26,16 @@
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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 "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
@@ -47,14 +47,15 @@ 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>]) or DISA(<filename>)\n"
|
||||
"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"
|
||||
@@ -70,7 +71,7 @@ static char *descrip =
|
||||
"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 allows specification\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"
|
||||
@@ -92,9 +93,11 @@ static char *descrip =
|
||||
"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. Also, if you set the 5th argument\n"
|
||||
"to 'NOANSWER', the DISA application will not answer initially.\n";
|
||||
"exists in the context, it will be used.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static void play_dialtone(struct ast_channel *chan, char *mailbox)
|
||||
{
|
||||
@@ -111,10 +114,10 @@ static void play_dialtone(struct ast_channel *chan, char *mailbox)
|
||||
|
||||
static int disa_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int i,j,k,x,did_ignore,special_noanswer;
|
||||
int i,j,k,x,did_ignore;
|
||||
int firstdigittimeout = 20000;
|
||||
int digittimeout = 10000;
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
char *tmp, exten[AST_MAX_EXTENSION],acctcode[20]="";
|
||||
char pwline[256];
|
||||
char ourcidname[256],ourcidnum[256];
|
||||
@@ -128,15 +131,14 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
AST_APP_ARG(context);
|
||||
AST_APP_ARG(cid);
|
||||
AST_APP_ARG(mailbox);
|
||||
AST_APP_ARG(noanswer);
|
||||
);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (chan->pbx) {
|
||||
firstdigittimeout = chan->pbx->rtimeout*1000;
|
||||
@@ -144,13 +146,13 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
|
||||
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);
|
||||
ast_module_user_remove(u);
|
||||
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);
|
||||
ast_module_user_remove(u);
|
||||
ast_log(LOG_WARNING, "Unable to set read format to Mu-law on %s\n",chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -158,6 +160,11 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
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);
|
||||
|
||||
@@ -168,15 +175,10 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
ast_log(LOG_DEBUG, "Mailbox: %s\n",args.mailbox);
|
||||
|
||||
|
||||
special_noanswer = 0;
|
||||
if ((!args.noanswer) || strcmp(args.noanswer,"NOANSWER"))
|
||||
{
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
/* answer */
|
||||
ast_answer(chan);
|
||||
}
|
||||
} else special_noanswer = 1;
|
||||
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;
|
||||
@@ -196,7 +198,8 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
for (;;) {
|
||||
/* if outa time, give em reorder */
|
||||
if (ast_tvdiff_ms(ast_tvnow(), lastdigittime) >
|
||||
((k&2) ? digittimeout : firstdigittimeout)) {
|
||||
((k&2) ? digittimeout : firstdigittimeout))
|
||||
{
|
||||
ast_log(LOG_DEBUG,"DISA %s entry timeout on chan %s\n",
|
||||
((k&1) ? "extension" : "password"),chan->name);
|
||||
break;
|
||||
@@ -207,68 +210,72 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
|
||||
f = ast_read(chan);
|
||||
if (f == NULL) {
|
||||
ast_module_user_remove(u);
|
||||
if (f == NULL)
|
||||
{
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
if ((f->frametype == AST_FRAME_CONTROL) &&
|
||||
(f->subclass == AST_CONTROL_HANGUP)) {
|
||||
(f->subclass == AST_CONTROL_HANGUP))
|
||||
{
|
||||
ast_frfree(f);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
ast_frfree(f);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if not DTMF, just do it again */
|
||||
if (f->frametype != AST_FRAME_DTMF) {
|
||||
/* 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 == 0) {
|
||||
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 */
|
||||
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,"%d",&j) < 1) { /* nope, it must be a filename */
|
||||
if (sscanf(args.passcode,"%30d",&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_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
pwline[0] = 0;
|
||||
while(fgets(pwline,sizeof(pwline) - 1,fp)) {
|
||||
if (!pwline[0])
|
||||
continue;
|
||||
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);
|
||||
|
||||
/* password must be in valid format (numeric) */
|
||||
if (sscanf(args.passcode,"%d", &j) < 1)
|
||||
continue;
|
||||
/* if we got it */
|
||||
/* password must be in valid format (numeric) */
|
||||
if (sscanf(args.passcode,"%30d",&j) < 1) continue;
|
||||
/* if we got it */
|
||||
if (!strcmp(exten,args.passcode)) {
|
||||
if (ast_strlen_zero(args.context))
|
||||
args.context = "disa";
|
||||
@@ -276,11 +283,12 @@ 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;
|
||||
|
||||
@@ -294,16 +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_log(LOG_DEBUG,"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;
|
||||
}
|
||||
}
|
||||
|
||||
exten[i++] = j; /* save digit */
|
||||
exten[i] = 0;
|
||||
if (!(k&1))
|
||||
continue; /* if getting password, continue doing it */
|
||||
/* if this exists */
|
||||
if (!(k&1)) continue; /* if getting password, continue doing it */
|
||||
/* if this exists */
|
||||
|
||||
if (ast_ignore_pattern(args.context, exten)) {
|
||||
play_dialtone(chan, "");
|
||||
@@ -314,7 +321,7 @@ 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;
|
||||
}
|
||||
@@ -334,18 +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);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -357,7 +364,8 @@ reorder:
|
||||
ast_indicate(chan,AST_CONTROL_CONGESTION);
|
||||
/* something is invalid, give em reorder for several seconds */
|
||||
time(&rstart);
|
||||
while(time(NULL) < rstart + 10) {
|
||||
while(time(NULL) < rstart + 10)
|
||||
{
|
||||
if (ast_waitfor(chan, -1) < 0)
|
||||
break;
|
||||
f = ast_read(chan);
|
||||
@@ -366,24 +374,39 @@ reorder:
|
||||
ast_frfree(f);
|
||||
}
|
||||
ast_playtones_stop(chan);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -22,21 +22,19 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief Application to dump channel variables
|
||||
*
|
||||
* \author Anthony Minessale <anthmct@yahoo.com>
|
||||
*
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -47,27 +45,30 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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";
|
||||
" 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;
|
||||
|
||||
@@ -85,12 +86,11 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
|
||||
"CallerID= %s\n"
|
||||
"CallerIDName= %s\n"
|
||||
"DNIDDigits= %s\n"
|
||||
"RDNIS= %s\n"
|
||||
"State= %s (%d)\n"
|
||||
"Rings= %d\n"
|
||||
"NativeFormat= %s\n"
|
||||
"WriteFormat= %s\n"
|
||||
"ReadFormat= %s\n"
|
||||
"NativeFormat= %d\n"
|
||||
"WriteFormat= %d\n"
|
||||
"ReadFormat= %d\n"
|
||||
"1stFileDescriptor= %d\n"
|
||||
"Framesin= %d %s\n"
|
||||
"Framesout= %d %s\n"
|
||||
@@ -105,20 +105,19 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
|
||||
"Data= %s\n"
|
||||
"Blocking_in= %s\n",
|
||||
c->name,
|
||||
c->tech->type,
|
||||
c->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->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,
|
||||
ast_getformatname_multiple(formatbuf, sizeof(formatbuf), c->nativeformats),
|
||||
ast_getformatname_multiple(formatbuf, sizeof(formatbuf), c->writeformat),
|
||||
ast_getformatname_multiple(formatbuf, sizeof(formatbuf), c->readformat),
|
||||
c->fds[0], c->fin & ~DEBUGCHAN_FLAG, (c->fin & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
|
||||
c->fout & ~DEBUGCHAN_FLAG, (c->fout & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "", (long)c->whentohangup,
|
||||
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,
|
||||
@@ -128,7 +127,7 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
|
||||
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)"),
|
||||
( c-> data ? (!ast_strlen_zero(c->data) ? c->data : "(Empty)") : "(None)"),
|
||||
(ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)"));
|
||||
|
||||
return 0;
|
||||
@@ -136,41 +135,59 @@ static int serialize_showchan(struct ast_channel *c, char *buf, size_t size)
|
||||
|
||||
static int dumpchan_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct ast_module_user *u;
|
||||
char vars[BUFSIZ * 4];
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char vars[1024];
|
||||
char info[1024];
|
||||
int level = 0;
|
||||
static char *line = "================================================================================";
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!ast_strlen_zero(data))
|
||||
if (!ast_strlen_zero(data)) {
|
||||
level = atoi(data);
|
||||
}
|
||||
|
||||
pbx_builtin_serialize_variables(chan, vars, sizeof(vars));
|
||||
serialize_showchan(chan, info, sizeof(info));
|
||||
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, line);
|
||||
ast_verbose("\nDumping Info For Channel: %s:\n%s\nInfo:\n%s\nVariables:\n%s%s\n",chan->name, line, info, vars, line);
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,21 +19,19 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief Echo application -- play back what you hear to evaluate latency
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -41,64 +39,85 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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";
|
||||
" 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;
|
||||
struct ast_module_user *u;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
|
||||
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);
|
||||
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:
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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
270
apps/app_enumlookup.c
Normal 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
127
apps/app_eval.c
Normal 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;
|
||||
}
|
||||
204
apps/app_exec.c
204
apps/app_exec.c
@@ -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,21 +19,20 @@
|
||||
*
|
||||
* \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 "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -45,177 +43,93 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
/* Maximum length of any variable */
|
||||
#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 =
|
||||
"Usage: 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 =
|
||||
"Usage: TryExec(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:\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 =
|
||||
"Usage: ExecIF (<expr>|<app>|<data>)\n"
|
||||
"If <expr> is true, execute and return the result of <app>(<data>).\n"
|
||||
"If <expr> is true, but <app> 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;
|
||||
struct ast_module_user *u;
|
||||
char *s, *appname, *endargs, args[MAXRESULT] = "";
|
||||
struct localuser *u;
|
||||
char *s, *appname, *endargs, args[MAXRESULT];
|
||||
struct ast_app *app;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
memset(args, 0, MAXRESULT);
|
||||
|
||||
/* Check and parse arguments */
|
||||
if (data) {
|
||||
s = ast_strdupa(data);
|
||||
appname = strsep(&s, "(");
|
||||
s = ast_strdupa((char *)data);
|
||||
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);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
|
||||
res = -1;
|
||||
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_ERROR, "Out of memory\n");
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int tryexec_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct ast_module_user *u;
|
||||
char *s, *appname, *endargs, args[MAXRESULT] = "";
|
||||
struct ast_app *app;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
|
||||
/* Check and parse arguments */
|
||||
if (data) {
|
||||
s = ast_strdupa(data);
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ast_module_user_remove(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int execif_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct ast_module_user *u;
|
||||
char *myapp = NULL;
|
||||
char *mydata = NULL;
|
||||
char *expr = NULL;
|
||||
struct ast_app *app = NULL;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
|
||||
expr = ast_strdupa(data);
|
||||
|
||||
if ((myapp = strchr(expr,'|'))) {
|
||||
*myapp = '\0';
|
||||
myapp++;
|
||||
if ((mydata = strchr(myapp,'|'))) {
|
||||
*mydata = '\0';
|
||||
mydata++;
|
||||
} else
|
||||
mydata = "";
|
||||
|
||||
if (pbx_checkcondition(expr)) {
|
||||
if ((app = pbx_findapp(myapp))) {
|
||||
res = pbx_exec(chan, app, mydata);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Count not find application! (%s)\n", myapp);
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_ERROR,"Invalid Syntax.\n");
|
||||
res = -1;
|
||||
}
|
||||
|
||||
ast_module_user_remove(u);
|
||||
|
||||
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);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -22,19 +22,10 @@
|
||||
/*! \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
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -42,6 +33,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
@@ -50,9 +45,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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";
|
||||
@@ -65,7 +61,7 @@ static const char *descrip =
|
||||
"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,9 +81,10 @@ 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;
|
||||
@@ -109,10 +107,12 @@ static void send_child_event(FILE *handle, const char event, const char *data,
|
||||
|
||||
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;
|
||||
@@ -141,7 +141,7 @@ static void gen_release(struct ast_channel *chan, void *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;
|
||||
@@ -173,7 +173,7 @@ 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))) {
|
||||
@@ -231,8 +231,10 @@ static struct ast_generator gen =
|
||||
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);
|
||||
@@ -242,7 +244,7 @@ static struct playlist_entry *make_entry(const char *filename)
|
||||
|
||||
static int app_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct ast_module_user *lu;
|
||||
struct localuser *u = NULL;
|
||||
struct playlist_entry *entry;
|
||||
const char *args = data;
|
||||
int child_stdin[2] = { 0,0 };
|
||||
@@ -257,28 +259,28 @@ static int app_exec(struct ast_channel *chan, void *data)
|
||||
FILE *child_commands = NULL;
|
||||
FILE *child_errors = NULL;
|
||||
FILE *child_events = NULL;
|
||||
struct ivr_localuser foo = {
|
||||
.playlist = AST_LIST_HEAD_INIT_VALUE,
|
||||
.finishlist = AST_LIST_HEAD_INIT_VALUE,
|
||||
};
|
||||
struct ivr_localuser *u = &foo;
|
||||
sigset_t fullset, oldset;
|
||||
|
||||
lu = ast_module_user_add(chan);
|
||||
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(args)) {
|
||||
ast_log(LOG_WARNING, "ExternalIVR requires a command to execute\n");
|
||||
ast_module_user_remove(lu);
|
||||
return -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
buf = ast_strdupa(data);
|
||||
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]));
|
||||
|
||||
@@ -320,7 +322,7 @@ static int app_exec(struct ast_channel *chan, void *data)
|
||||
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);
|
||||
@@ -554,25 +556,42 @@ static int app_exec(struct ast_channel *chan, void *data)
|
||||
while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list)))
|
||||
free(entry);
|
||||
|
||||
ast_module_user_remove(lu);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -19,16 +19,10 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief Connect to festival
|
||||
*
|
||||
* \author Christos Ricudis <ricudis@itc.auth.gr>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@@ -46,6 +40,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
@@ -59,6 +57,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#define FESTIVAL_CONFIG "festival.conf"
|
||||
|
||||
static char *tdesc = "Simple Festival Interface";
|
||||
|
||||
static char *app = "Festival";
|
||||
|
||||
static char *synopsis = "Say text to the user";
|
||||
@@ -68,6 +68,9 @@ static char *descrip =
|
||||
"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;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static char *socket_receive_file_to_buff(int fd,int *size)
|
||||
{
|
||||
@@ -82,10 +85,7 @@ static char *socket_receive_file_to_buff(int fd,int *size)
|
||||
char c;
|
||||
|
||||
bufflen = 1024;
|
||||
if (!(buff = ast_malloc(bufflen)))
|
||||
{
|
||||
/* TODO: Handle memory allocation failure */
|
||||
}
|
||||
buff = (char *)malloc(bufflen);
|
||||
*size=0;
|
||||
|
||||
for (k=0; file_stuff_key[k] != '\0';)
|
||||
@@ -95,10 +95,7 @@ static char *socket_receive_file_to_buff(int fd,int *size)
|
||||
if ((*size)+k+1 >= bufflen)
|
||||
{ /* +1 so you can add a NULL if you want */
|
||||
bufflen += bufflen/4;
|
||||
if (!(buff = ast_realloc(buff, bufflen)))
|
||||
{
|
||||
/* TODO: Handle memory allocation failure */
|
||||
}
|
||||
buff = (char *)realloc(buff,bufflen);
|
||||
}
|
||||
if (file_stuff_key[k] == c)
|
||||
k++;
|
||||
@@ -146,7 +143,7 @@ static int send_waveform_to_fd(char *waveform, int length, int fd) {
|
||||
if (x != fd)
|
||||
close(x);
|
||||
}
|
||||
if (ast_opt_high_priority)
|
||||
if (option_highpriority)
|
||||
ast_set_priority(0);
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
|
||||
@@ -178,9 +175,7 @@ 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, },
|
||||
};
|
||||
} myf;
|
||||
|
||||
if (pipe(fds)) {
|
||||
ast_log(LOG_WARNING, "Unable to create pipe\n");
|
||||
@@ -240,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;
|
||||
@@ -282,16 +278,16 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
{
|
||||
int usecache;
|
||||
int res=0;
|
||||
struct ast_module_user *u;
|
||||
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;
|
||||
char *host;
|
||||
char *cachedir;
|
||||
char *temp;
|
||||
char *festivalcommand;
|
||||
int port=1314;
|
||||
int n;
|
||||
char ack[4];
|
||||
@@ -314,19 +310,18 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
char *data;
|
||||
char *intstr;
|
||||
struct ast_config *cfg;
|
||||
char *newfestivalcommand;
|
||||
|
||||
if (ast_strlen_zero(vdata)) {
|
||||
ast_log(LOG_WARNING, "festival requires an argument (text)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
cfg = ast_config_load(FESTIVAL_CONFIG);
|
||||
if (!cfg) {
|
||||
ast_log(LOG_WARNING, "No such configuration file %s\n", FESTIVAL_CONFIG);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
if (!(host = ast_variable_retrieve(cfg, "general", "host"))) {
|
||||
@@ -347,25 +342,15 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
}
|
||||
if (!(festivalcommand = ast_variable_retrieve(cfg, "general", "festivalcommand"))) {
|
||||
festivalcommand = "(tts_textasterisk \"%s\" 'file)(quit)\n";
|
||||
} 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) + 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
|
||||
newfestivalcommand[j++] = festivalcommand[i];
|
||||
}
|
||||
newfestivalcommand[j] = '\0';
|
||||
festivalcommand = newfestivalcommand;
|
||||
}
|
||||
|
||||
data = ast_strdupa(vdata);
|
||||
if (!data) {
|
||||
ast_log(LOG_ERROR, "Out of memery\n");
|
||||
ast_config_destroy(cfg);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
intstr = strchr(data, '|');
|
||||
if (intstr) {
|
||||
@@ -383,7 +368,7 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
if (fd < 0) {
|
||||
ast_log(LOG_WARNING,"festival_client: can't get socket\n");
|
||||
ast_config_destroy(cfg);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
@@ -393,7 +378,7 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
if (serverhost == (struct hostent *)0) {
|
||||
ast_log(LOG_WARNING,"festival_client: gethostbyname failed\n");
|
||||
ast_config_destroy(cfg);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
memmove(&serv_addr.sin_addr,serverhost->h_addr, serverhost->h_length);
|
||||
@@ -404,7 +389,7 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
|
||||
ast_log(LOG_WARNING,"festival_client: connect to server failed\n");
|
||||
ast_config_destroy(cfg);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -496,7 +481,7 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
ast_log(LOG_WARNING,"Unable to read from cache/festival fd\n");
|
||||
close(fd);
|
||||
ast_config_destroy(cfg);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
n += read_data;
|
||||
@@ -523,31 +508,41 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
} while (strcmp(ack,"OK\n") != 0);
|
||||
close(fd);
|
||||
ast_config_destroy(cfg);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
int load_module(void)
|
||||
{
|
||||
struct ast_config *cfg = ast_config_load(FESTIVAL_CONFIG);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -19,26 +19,24 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief App to flash a zap trunk
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<depend>zaptel</depend>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <zaptel/zaptel.h>
|
||||
#ifdef __linux__
|
||||
#include <linux/zaptel.h>
|
||||
#else
|
||||
#include <zaptel.h>
|
||||
#endif /* __linux__ */
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
@@ -50,6 +48,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/image.h"
|
||||
#include "asterisk/options.h"
|
||||
|
||||
static char *tdesc = "Flash zap trunk application";
|
||||
|
||||
static char *app = "Flash";
|
||||
|
||||
static char *synopsis = "Flashes a Zap Trunk";
|
||||
@@ -59,6 +59,9 @@ static char *descrip =
|
||||
"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;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static inline int zt_wait_event(int fd)
|
||||
{
|
||||
@@ -74,10 +77,10 @@ static int flash_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = -1;
|
||||
int x;
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
struct zt_params ztp;
|
||||
u = ast_module_user_add(chan);
|
||||
if (!strcasecmp(chan->tech->type, "Zap")) {
|
||||
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) {
|
||||
@@ -100,25 +103,39 @@ static int flash_exec(struct ast_channel *chan, void *data)
|
||||
ast_log(LOG_WARNING, "Unable to get parameters of %s: %s\n", chan->name, strerror(errno));
|
||||
} else
|
||||
ast_log(LOG_WARNING, "%s is not a Zap channel\n", chan->name);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
1105
apps/app_followme.c
1105
apps/app_followme.c
File diff suppressed because it is too large
Load Diff
@@ -18,23 +18,19 @@
|
||||
/*! \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 "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -42,15 +38,21 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/cdr.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\n"
|
||||
"If the option 'v' is passed all cdr variables will be passed along also.\n";
|
||||
"If the option 'v' is passed all cdr variables will be passed along also.\n"
|
||||
"";
|
||||
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static void ast_cdr_fork(struct ast_channel *chan)
|
||||
{
|
||||
struct ast_cdr *cdr;
|
||||
@@ -77,38 +79,53 @@ static void ast_cdr_fork(struct ast_channel *chan)
|
||||
static int forkcdr_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
|
||||
if (!chan->cdr) {
|
||||
ast_log(LOG_WARNING, "Channel does not have a CDR\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!ast_strlen_zero(data))
|
||||
ast_set2_flag(chan->cdr, strchr(data, 'v'), AST_CDR_FLAG_KEEP_VARS);
|
||||
|
||||
ast_cdr_fork(chan);
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -19,21 +19,19 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief Get ADSI CPE ID
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -43,6 +41,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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";
|
||||
@@ -51,6 +51,9 @@ static char *descrip =
|
||||
" 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)
|
||||
{
|
||||
@@ -60,42 +63,43 @@ 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 ast_module_user *u;
|
||||
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];
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
|
||||
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;
|
||||
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) {
|
||||
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);
|
||||
@@ -104,15 +108,15 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
|
||||
}
|
||||
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)
|
||||
@@ -122,27 +126,42 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
|
||||
break;
|
||||
}
|
||||
}
|
||||
ast_adsi_unload_session(chan);
|
||||
adsi_unload_session(chan);
|
||||
}
|
||||
}
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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
338
apps/app_groupcount.c
Normal 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, "%30d", &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(®exbuf, 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(®exbuf, 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(®exbuf);
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Changes Copyright (c) 2004 - 2006 Todd Freeman <freeman@andrews.edu>
|
||||
* Changes Copyright (c) 2004 - 2005 Todd Freeman <freeman@andrews.edu>
|
||||
*
|
||||
* 95% based on HasNewVoicemail by:
|
||||
*
|
||||
@@ -24,18 +24,9 @@
|
||||
*
|
||||
* \brief HasVoicemail application
|
||||
*
|
||||
* \author Todd Freeman <freeman@andrews.edu>
|
||||
*
|
||||
* \note 95% based on HasNewVoicemail by
|
||||
* Tilghman Lesher <asterisk-hasnewvoicemail-app@the-tilghman.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -43,6 +34,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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"
|
||||
@@ -52,7 +47,14 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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 =
|
||||
@@ -63,8 +65,7 @@ static char *hasvoicemail_descrip =
|
||||
" '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"
|
||||
"\nThis application has been deprecated in favor of the VMCOUNT() function\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";
|
||||
@@ -76,13 +77,103 @@ static char *hasnewvoicemail_descrip =
|
||||
" '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"
|
||||
"\nThis application has been deprecated in favor of the VMCOUNT() function\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 ast_module_user *u;
|
||||
struct localuser *u;
|
||||
char *input, *varname = NULL, *vmbox, *context = "default";
|
||||
char *vmfolder;
|
||||
int vmcount = 0;
|
||||
@@ -105,16 +196,22 @@ static int hasvoicemail_exec(struct ast_channel *chan, void *data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
input = ast_strdupa(data);
|
||||
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);
|
||||
|
||||
vmbox = strsep(&args.vmbox, "@");
|
||||
|
||||
if (!ast_strlen_zero(args.vmbox))
|
||||
context = args.vmbox;
|
||||
if ((vmbox = strsep(&args.vmbox, "@")))
|
||||
if (!ast_strlen_zero(args.vmbox))
|
||||
context = args.vmbox;
|
||||
if (!vmbox)
|
||||
vmbox = args.vmbox;
|
||||
|
||||
vmfolder = strchr(vmbox, '/');
|
||||
if (vmfolder) {
|
||||
@@ -129,7 +226,7 @@ static int hasvoicemail_exec(struct ast_channel *chan, void *data)
|
||||
priority_jump = 1;
|
||||
}
|
||||
|
||||
vmcount = ast_app_messagecount(context, vmbox, vmfolder);
|
||||
vmcount = hasvoicemail_internal(context, vmbox, vmfolder);
|
||||
/* Set the count in the channel variable */
|
||||
if (varname) {
|
||||
snprintf(tmp, sizeof(tmp), "%d", vmcount);
|
||||
@@ -138,7 +235,7 @@ static int hasvoicemail_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
if (vmcount > 0) {
|
||||
/* Branch to the next extension */
|
||||
if (priority_jump || ast_opt_priority_jumping) {
|
||||
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);
|
||||
}
|
||||
@@ -147,42 +244,46 @@ static int hasvoicemail_exec(struct ast_channel *chan, void *data)
|
||||
snprintf(tmp, sizeof(tmp), "%d", vmcount);
|
||||
pbx_builtin_setvar_helper(chan, "HASVMSTATUS", tmp);
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acf_vmcount_exec(struct ast_channel *chan, char *cmd, char *argsstr, char *buf, size_t len)
|
||||
static char *acf_vmcount_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
|
||||
{
|
||||
struct ast_module_user *u;
|
||||
char *context;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(vmbox);
|
||||
AST_APP_ARG(folder);
|
||||
);
|
||||
struct localuser *u;
|
||||
char *args, *context, *box, *folder;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ACF_ADD(u);
|
||||
|
||||
buf[0] = '\0';
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, argsstr);
|
||||
args = ast_strdupa(data);
|
||||
if (!args) {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return buf;
|
||||
}
|
||||
|
||||
if (strchr(args.vmbox, '@')) {
|
||||
context = args.vmbox;
|
||||
args.vmbox = strsep(&context, "@");
|
||||
box = strsep(&args, "|");
|
||||
if (strchr(box, '@')) {
|
||||
context = box;
|
||||
box = strsep(&context, "@");
|
||||
} else {
|
||||
context = "default";
|
||||
}
|
||||
|
||||
if (ast_strlen_zero(args.folder)) {
|
||||
args.folder = "INBOX";
|
||||
if (args) {
|
||||
folder = args;
|
||||
} else {
|
||||
folder = "INBOX";
|
||||
}
|
||||
|
||||
snprintf(buf, len, "%d", ast_app_messagecount(context, args.vmbox, args.folder));
|
||||
snprintf(buf, len, "%d", hasvoicemail_internal(context, box, folder));
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
struct ast_custom_function acf_vmcount = {
|
||||
@@ -195,7 +296,32 @@ struct ast_custom_function acf_vmcount = {
|
||||
.read = acf_vmcount_exec,
|
||||
};
|
||||
|
||||
static int unload_module(void)
|
||||
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;
|
||||
|
||||
@@ -203,15 +329,15 @@ static int unload_module(void)
|
||||
res |= ast_unregister_application(app_hasvoicemail);
|
||||
res |= ast_unregister_application(app_hasnewvoicemail);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
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);
|
||||
@@ -219,4 +345,19 @@ static int load_module(void)
|
||||
return res;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Indicator for whether a voice mailbox has messages in a given folder.");
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -19,16 +19,10 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief Stream to an icecast server via ICES (see contrib/asterisk-ices.xml)
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
@@ -38,6 +32,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
@@ -51,6 +49,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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";
|
||||
|
||||
static char *synopsis = "Encode and stream using 'ices'";
|
||||
@@ -60,6 +60,9 @@ static char *descrip =
|
||||
"(available separately). A configuration file must be supplied\n"
|
||||
"for ices (see examples/asterisk-ices.conf). \n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int icesencode(char *filename, int fd)
|
||||
{
|
||||
@@ -82,7 +85,7 @@ static int icesencode(char *filename, int fd)
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
|
||||
|
||||
if (ast_opt_high_priority)
|
||||
if (option_highpriority)
|
||||
ast_set_priority(0);
|
||||
dup2(fd, STDIN_FILENO);
|
||||
for (x=STDERR_FILENO + 1;x<1024;x++) {
|
||||
@@ -102,7 +105,7 @@ static int icesencode(char *filename, int fd)
|
||||
static int ices_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
int fds[2];
|
||||
int ms = -1;
|
||||
int pid = -1;
|
||||
@@ -118,13 +121,13 @@ static int ices_exec(struct ast_channel *chan, void *data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
last = ast_tv(0, 0);
|
||||
|
||||
if (pipe(fds)) {
|
||||
ast_log(LOG_WARNING, "Unable to create pipe\n");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
flags = fcntl(fds[1], F_GETFL);
|
||||
@@ -139,7 +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");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -149,11 +152,11 @@ 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");
|
||||
ast_module_user_remove(u);
|
||||
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", (char *)ast_config_AST_CONFIG_DIR, (char *)data);
|
||||
/* Placeholder for options */
|
||||
@@ -199,25 +202,40 @@ static int ices_exec(struct ast_channel *chan, void *data)
|
||||
if (!res && oreadformat)
|
||||
ast_set_read_format(chan, oreadformat);
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -19,20 +19,18 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief App to transmit an image
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -44,6 +42,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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";
|
||||
@@ -59,11 +59,14 @@ static char *descrip =
|
||||
" 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 ast_module_user *u;
|
||||
struct localuser *u;
|
||||
char *parse;
|
||||
int priority_jump = 0;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
@@ -71,9 +74,13 @@ static int sendimage_exec(struct ast_channel *chan, void *data)
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
parse = ast_strdupa(data);
|
||||
if (!(parse = ast_strdupa(data))) {
|
||||
ast_log(LOG_WARNING, "Memory Error!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, parse);
|
||||
|
||||
@@ -89,10 +96,10 @@ static int sendimage_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
if (!ast_supports_images(chan)) {
|
||||
/* Does not support transport */
|
||||
if (priority_jump || ast_opt_priority_jumping)
|
||||
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");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -101,25 +108,40 @@ static int sendimage_exec(struct ast_channel *chan, void *data)
|
||||
if (!res)
|
||||
pbx_builtin_setvar_helper(chan, "SENDIMAGESTATUS", "OK");
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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
234
apps/app_intercom.c
Normal 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;
|
||||
}
|
||||
@@ -19,25 +19,19 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief IVR Demo application
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<defaultenabled>no</defaultenabled>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -88,18 +82,21 @@ 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 ast_module_user *u;
|
||||
struct localuser *u;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "skel requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Do our thing here */
|
||||
|
||||
@@ -108,25 +105,40 @@ static int skel_exec(struct ast_channel *chan, void *data)
|
||||
if (!res)
|
||||
res = ast_ivr_menu_run(chan, &ivr_demo, data);
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -20,20 +20,18 @@
|
||||
*
|
||||
* \brief App to lookup the callerid number, and see if it is blacklisted
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -47,6 +45,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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";
|
||||
@@ -59,52 +59,21 @@ static char *descrip =
|
||||
"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\n"
|
||||
"This application is deprecated and may be removed from a future release.\n"
|
||||
"Please use the dialplan function BLACKLIST() instead.\n";
|
||||
"Example: exten => 1234,1,LookupBlacklist()\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
static int blacklist_read(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
|
||||
{
|
||||
char blacklist[1];
|
||||
int bl = 0;
|
||||
|
||||
if (chan->cid.cid_num) {
|
||||
if (!ast_db_get("blacklist", chan->cid.cid_num, blacklist, sizeof (blacklist)))
|
||||
bl = 1;
|
||||
}
|
||||
if (chan->cid.cid_name) {
|
||||
if (!ast_db_get("blacklist", chan->cid.cid_name, blacklist, sizeof (blacklist)))
|
||||
bl = 1;
|
||||
}
|
||||
|
||||
snprintf(buf, len, "%d", bl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ast_custom_function blacklist_function = {
|
||||
.name = "BLACKLIST",
|
||||
.synopsis = "Check if the callerid is on the blacklist",
|
||||
.desc = "Uses astdb to check if the Caller*ID is in family 'blacklist'. Returns 1 or 0.\n",
|
||||
.syntax = "BLACKLIST()",
|
||||
.read = blacklist_read,
|
||||
};
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int
|
||||
lookupblacklist_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
char blacklist[1];
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
int bl = 0;
|
||||
int priority_jump = 0;
|
||||
static int dep_warning = 0;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
|
||||
if (!dep_warning) {
|
||||
dep_warning = 1;
|
||||
ast_log(LOG_WARNING, "LookupBlacklist is deprecated. Please use ${BLACKLIST()} instead.\n");
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!ast_strlen_zero(data)) {
|
||||
if (strchr(data, 'j'))
|
||||
@@ -127,34 +96,46 @@ lookupblacklist_exec (struct ast_channel *chan, void *data)
|
||||
}
|
||||
|
||||
if (bl) {
|
||||
if (priority_jump || ast_opt_priority_jumping)
|
||||
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");
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module (void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
res |= ast_custom_function_unregister(&blacklist_function);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
int load_module (void)
|
||||
{
|
||||
int res = ast_custom_function_register(&blacklist_function);
|
||||
res |= ast_register_application (app, lookupblacklist_exec, synopsis,descrip);
|
||||
return ast_register_application (app, lookupblacklist_exec, synopsis,descrip);
|
||||
}
|
||||
|
||||
char *description (void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount (void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT (res);
|
||||
return res;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Look up Caller*ID name/number from blacklist database");
|
||||
char *key ()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -19,20 +19,18 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief App to set callerid name from database, based on directory number
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -45,6 +43,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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";
|
||||
@@ -55,49 +55,66 @@ static char *descrip =
|
||||
"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\n"
|
||||
"LookupCIDName is deprecated. Please use ${DB(cidname/${CALLERID(num)})}\n"
|
||||
"instead.\n";
|
||||
"calls.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
static int lookupcidname_exec (struct ast_channel *chan, void *data)
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int
|
||||
lookupcidname_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
char dbname[64];
|
||||
struct ast_module_user *u;
|
||||
static int dep_warning = 0;
|
||||
char dbname[64];
|
||||
struct localuser *u;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
if (!dep_warning) {
|
||||
dep_warning = 1;
|
||||
ast_log(LOG_WARNING, "LookupCIDName is deprecated. Please use ${DB(cidname/${CALLERID(num)})} instead.\n");
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
ast_module_user_remove(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
LOCAL_USER_REMOVE (u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int
|
||||
unload_module (void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application (app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
int
|
||||
load_module (void)
|
||||
{
|
||||
return ast_register_application (app, lookupcidname_exec, synopsis, descrip);
|
||||
return ast_register_application (app, lookupcidname_exec, synopsis,
|
||||
descrip);
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Look up CallerID Name from local database");
|
||||
char *
|
||||
description (void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int
|
||||
usecount (void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT (res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *
|
||||
key ()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
171
apps/app_macro.c
171
apps/app_macro.c
@@ -19,22 +19,20 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief Dial plan macro Implementation
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -50,6 +48,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
/* special result value used to force macro exit */
|
||||
#define MACRO_EXIT_RESULT 1024
|
||||
|
||||
static char *tdesc = "Extension Macros";
|
||||
|
||||
static char *descrip =
|
||||
" Macro(macroname|arg1|arg2...): Executes a macro using the context\n"
|
||||
"'macro-<macroname>', jumping to the 's' extension of that context and\n"
|
||||
@@ -70,8 +70,8 @@ static char *descrip =
|
||||
" 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 macros\n"
|
||||
" could cause asterisk to crash earlier than this limit.\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"
|
||||
@@ -79,13 +79,6 @@ static char *if_descrip =
|
||||
"(otherwise <macroname_b> if provided)\n"
|
||||
"Arguments and return values as in application macro()\n";
|
||||
|
||||
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";
|
||||
|
||||
static char *exit_descrip =
|
||||
" MacroExit():\n"
|
||||
"Causes the currently running macro to exit as if it had\n"
|
||||
@@ -95,14 +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";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static struct ast_exten *find_matching_priority(struct ast_context *c, const char *exten, int priority, const char *callerid)
|
||||
{
|
||||
@@ -139,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;
|
||||
@@ -155,7 +148,7 @@ 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, dead = 0, inhangup = 0;
|
||||
@@ -164,34 +157,38 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
|
||||
char *save_macro_context;
|
||||
char *save_macro_priority;
|
||||
char *save_macro_offset;
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "Macro() requires arguments. See \"show application macro\" for help.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* does the user want a deeper rabbit hole? */
|
||||
s = pbx_builtin_getvar_helper(chan, "MACRO_RECURSION");
|
||||
if (s)
|
||||
sscanf(s, "%d", &maxdepth);
|
||||
sscanf(s, "%3d", &maxdepth);
|
||||
|
||||
/* Count how many levels deep the rabbit hole goes */
|
||||
s = pbx_builtin_getvar_helper(chan, "MACRO_DEPTH");
|
||||
if (s)
|
||||
sscanf(s, "%d", &depth);
|
||||
tmp = pbx_builtin_getvar_helper(chan, "MACRO_DEPTH");
|
||||
if (tmp) {
|
||||
sscanf(tmp, "%3d", &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, "%d", &inhangup);
|
||||
sscanf(inhangupc, "%3d", &inhangup);
|
||||
|
||||
if (depth >= maxdepth) {
|
||||
ast_log(LOG_ERROR, "Macro(): possible infinite loop detected. Returning early.\n");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
snprintf(depthc, sizeof(depthc), "%d", depth + 1);
|
||||
@@ -202,33 +199,18 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
|
||||
macro = strsep(&rest, "|");
|
||||
if (ast_strlen_zero(macro)) {
|
||||
ast_log(LOG_WARNING, "Invalid macro name specified\n");
|
||||
ast_module_user_remove(u);
|
||||
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_module_user_remove(u);
|
||||
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_log(LOG_DEBUG, "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);
|
||||
ast_module_user_remove(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
ast_autoservice_stop(chan);
|
||||
}
|
||||
|
||||
/* Save old info */
|
||||
oldpriority = chan->priority;
|
||||
@@ -242,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 */
|
||||
@@ -262,13 +252,12 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
|
||||
chan->priority = 1;
|
||||
|
||||
while((cur = strsep(&rest, "|")) && (argc < MAX_ARGS)) {
|
||||
const char *s;
|
||||
/* 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++;
|
||||
}
|
||||
@@ -320,14 +309,14 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
|
||||
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);
|
||||
else if (option_verbose > 1)
|
||||
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:
|
||||
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);
|
||||
else if (option_verbose > 1)
|
||||
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;
|
||||
@@ -408,6 +397,7 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
|
||||
snprintf(depthc, sizeof(depthc), "%d", depth);
|
||||
if (!dead) {
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc);
|
||||
|
||||
ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP);
|
||||
}
|
||||
|
||||
@@ -448,12 +438,11 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
|
||||
ast_copy_string(chan->context, oldcontext, sizeof(chan->context));
|
||||
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, "%d", &offset) == 1) {
|
||||
if (sscanf(offsets, "%30d", &offset) == 1) {
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + offset + 1, chan->cid.cid_num)) {
|
||||
chan->priority += offset;
|
||||
}
|
||||
@@ -466,41 +455,22 @@ static int _macro_exec(struct ast_channel *chan, void *data, int exclusive)
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset);
|
||||
if (save_macro_offset)
|
||||
free(save_macro_offset);
|
||||
|
||||
/* Unlock the macro */
|
||||
if (exclusive) {
|
||||
ast_log(LOG_DEBUG, "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_module_user_remove(u);
|
||||
|
||||
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 ast_module_user *u;
|
||||
struct localuser *u;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!(expr = ast_strdupa(data))) {
|
||||
ast_module_user_remove(u);
|
||||
expr = ast_strdupa(data);
|
||||
if (!expr) {
|
||||
ast_log(LOG_ERROR, "Out of Memory!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -512,13 +482,13 @@ static int macroif_exec(struct ast_channel *chan, void *data)
|
||||
label_b++;
|
||||
}
|
||||
if (pbx_checkcondition(expr))
|
||||
macro_exec(chan, label_a);
|
||||
res = macro_exec(chan, label_a);
|
||||
else if (label_b)
|
||||
macro_exec(chan, label_b);
|
||||
res = macro_exec(chan, label_b);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Invalid Syntax.\n");
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -528,30 +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);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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
298
apps/app_math.c
Normal 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, "%30f", &fnum1) != 1) {
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue1);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sscanf(mvalue2, "%30f", &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
205
apps/app_md5.c
Normal 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;
|
||||
}
|
||||
3864
apps/app_meetme.c
3864
apps/app_meetme.c
File diff suppressed because it is too large
Load Diff
@@ -19,29 +19,28 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief Digital Milliwatt Test
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
static char *tdesc = "Digital Milliwatt (mu-law) Test Application";
|
||||
|
||||
static char *app = "Milliwatt";
|
||||
|
||||
@@ -50,12 +49,19 @@ static char *synopsis = "Generate a Constant 1000Hz tone at 0dbm (mu-law)";
|
||||
static char *descrip =
|
||||
"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)
|
||||
@@ -66,30 +72,26 @@ static void milliwatt_release(struct ast_channel *chan, void *data)
|
||||
|
||||
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 = sizeof (buf) / sizeof (buf[0]);
|
||||
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++)
|
||||
{
|
||||
@@ -114,8 +116,8 @@ static struct ast_generator milliwattgen =
|
||||
static int milliwatt_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
|
||||
struct ast_module_user *u;
|
||||
u = ast_module_user_add(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)
|
||||
@@ -125,29 +127,44 @@ static int milliwatt_exec(struct ast_channel *chan, void *data)
|
||||
if (ast_activate_generator(chan,&milliwattgen,"milliwatt") < 0)
|
||||
{
|
||||
ast_log(LOG_WARNING,"Failed to activate generator on '%s'\n",chan->name);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
while(!ast_safe_sleep(chan, 10000));
|
||||
ast_deactivate_generator(chan);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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,26 +22,19 @@
|
||||
*/
|
||||
|
||||
/*! \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 "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -53,10 +46,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/linkedlists.h"
|
||||
#include "asterisk/utils.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 = ""
|
||||
@@ -80,15 +73,9 @@ 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\n"
|
||||
"Stops the audio recording that was started with a call to MixMonitor()\n"
|
||||
"on the current channel.\n"
|
||||
"";
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
struct module_symbols *me;
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static const char *mixmonitor_spy_type = "MixMonitor";
|
||||
|
||||
@@ -131,9 +118,9 @@ static int startmon(struct ast_channel *chan, struct ast_channel_spy *spy)
|
||||
if (!chan)
|
||||
return -1;
|
||||
|
||||
ast_channel_lock(chan);
|
||||
ast_mutex_lock(&chan->lock);
|
||||
res = ast_channel_spy_add(chan, spy);
|
||||
ast_channel_unlock(chan);
|
||||
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);
|
||||
@@ -151,7 +138,10 @@ static void *mixmonitor_thread(void *obj)
|
||||
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);
|
||||
|
||||
@@ -177,7 +167,7 @@ static void *mixmonitor_thread(void *obj)
|
||||
of frames if a queue flush was necessary, so process them
|
||||
*/
|
||||
for (; f; f = next) {
|
||||
next = AST_LIST_NEXT(f, frame_list);
|
||||
next = f->next;
|
||||
if (write && errflag == 0) {
|
||||
if (!fs) {
|
||||
/* Determine creation flags and filename plus extension for filestream */
|
||||
@@ -199,15 +189,15 @@ static void *mixmonitor_thread(void *obj)
|
||||
if (fs)
|
||||
ast_writestream(fs, f);
|
||||
}
|
||||
ast_frame_free(f, 0);
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ast_mutex_unlock(&mixmonitor->spy.lock);
|
||||
|
||||
ast_channel_spy_free(&mixmonitor->spy);
|
||||
|
||||
ast_channel_spy_free(&mixmonitor->spy);
|
||||
|
||||
if (option_verbose > 1)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "End MixMonitor Recording %s\n", mixmonitor->name);
|
||||
|
||||
@@ -222,6 +212,7 @@ static void *mixmonitor_thread(void *obj)
|
||||
|
||||
free(mixmonitor);
|
||||
|
||||
STANDARD_DECREMENT_USECOUNT;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -255,6 +246,7 @@ static void launch_monitor_thread(struct ast_channel *chan, const char *filename
|
||||
|
||||
/* Pre-allocate mixmonitor structure and spy */
|
||||
if (!(mixmonitor = calloc(1, len))) {
|
||||
ast_log(LOG_ERROR, "Memory Error!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -298,7 +290,7 @@ static void launch_monitor_thread(struct ast_channel *chan, const char *filename
|
||||
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
ast_pthread_create_background(&thread, &attr, mixmonitor_thread, mixmonitor);
|
||||
ast_pthread_create(&thread, &attr, mixmonitor_thread, mixmonitor);
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
}
|
||||
@@ -306,7 +298,7 @@ static void launch_monitor_thread(struct ast_channel *chan, const char *filename
|
||||
static int mixmonitor_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int x, readvol = 0, writevol = 0;
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
struct ast_flags flags = {0};
|
||||
char *parse;
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
@@ -320,15 +312,19 @@ static int mixmonitor_exec(struct ast_channel *chan, void *data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
parse = ast_strdupa(data);
|
||||
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");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -340,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], "%d", &x) != 1) || (x < -4) || (x > 4)) {
|
||||
} else if ((sscanf(opts[OPT_ARG_READVOLUME], "%2d", &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);
|
||||
@@ -350,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], "%d", &x) != 1) || (x < -4) || (x > 4)) {
|
||||
} else if ((sscanf(opts[OPT_ARG_WRITEVOLUME], "%2d", &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);
|
||||
@@ -360,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], "%d", &x) != 1) || (x < -4) || (x > 4)) {
|
||||
} else if ((sscanf(opts[OPT_ARG_VOLUME], "%2d", &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);
|
||||
@@ -380,22 +376,7 @@ static int mixmonitor_exec(struct ast_channel *chan, void *data)
|
||||
pbx_builtin_setvar_helper(chan, "MIXMONITOR_FILENAME", args.filename);
|
||||
launch_monitor_thread(chan, args.filename, flags.flags, readvol, writevol, args.post_process);
|
||||
|
||||
ast_module_user_remove(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stop_mixmonitor_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct ast_module_user *u;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
|
||||
ast_channel_lock(chan);
|
||||
ast_channel_spy_stop_by_type(chan, mixmonitor_spy_type);
|
||||
ast_channel_unlock(chan);
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -417,47 +398,57 @@ static int mixmonitor_cli(int fd, int argc, char **argv)
|
||||
else if (!strcasecmp(argv[1], "stop"))
|
||||
ast_channel_spy_stop_by_type(chan, mixmonitor_spy_type);
|
||||
|
||||
ast_channel_unlock(chan);
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static char *complete_mixmonitor_cli(const char *line, const char *word, int pos, int state)
|
||||
{
|
||||
return ast_complete_channels(line, word, pos, state, 2);
|
||||
}
|
||||
|
||||
static struct ast_cli_entry cli_mixmonitor[] = {
|
||||
{ { "mixmonitor", NULL, NULL },
|
||||
mixmonitor_cli, "Execute a MixMonitor command.",
|
||||
"mixmonitor <start|stop> <chan_name> [args]\n\n"
|
||||
"The optional arguments are passed to the\n"
|
||||
"MixMonitor application when the 'start' command is used.\n",
|
||||
complete_mixmonitor_cli },
|
||||
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);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,179 +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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.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/indications.h"
|
||||
|
||||
static char *app_morsecode = "Morsecode";
|
||||
|
||||
static char *morsecode_synopsis = "Plays morse code";
|
||||
|
||||
static char *morsecode_descrip =
|
||||
"Usage: 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;
|
||||
struct ast_module_user *u;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "Syntax: Morsecode(<string>) - no argument found\n");
|
||||
ast_module_user_remove(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use variable MORESEDITLEN, if set (else 80) */
|
||||
ditlenc = pbx_builtin_getvar_helper(chan, "MORSEDITLEN");
|
||||
if (ast_strlen_zero(ditlenc) || (sscanf(ditlenc, "%d", &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, "%d", &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);
|
||||
}
|
||||
|
||||
ast_module_user_remove(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app_morsecode);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
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");
|
||||
@@ -19,16 +19,10 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief Silly application to play an MP3 file -- uses mpg123
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
@@ -37,6 +31,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
@@ -50,6 +48,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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";
|
||||
@@ -59,6 +59,9 @@ static char *descrip =
|
||||
"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)
|
||||
{
|
||||
@@ -76,7 +79,7 @@ static int mp3play(char *filename, int fd)
|
||||
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
||||
return res;
|
||||
}
|
||||
if (ast_opt_high_priority)
|
||||
if (option_highpriority)
|
||||
ast_set_priority(0);
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
|
||||
@@ -125,7 +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 ast_module_user *u;
|
||||
struct localuser *u;
|
||||
int fds[2];
|
||||
int ms = -1;
|
||||
int pid = -1;
|
||||
@@ -144,11 +147,11 @@ static int mp3_exec(struct ast_channel *chan, void *data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (pipe(fds)) {
|
||||
ast_log(LOG_WARNING, "Unable to create pipe\n");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -158,7 +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");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -231,25 +234,40 @@ static int mp3_exec(struct ast_channel *chan, void *data)
|
||||
if (!res && owriteformat)
|
||||
ast_set_write_format(chan, owriteformat);
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -19,16 +19,10 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief Silly application to play an NBScat file -- uses nbscat8k
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
@@ -38,6 +32,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
@@ -55,6 +53,8 @@ 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";
|
||||
@@ -63,6 +63,9 @@ static char *descrip =
|
||||
" 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)
|
||||
{
|
||||
@@ -83,7 +86,7 @@ static int NBScatplay(int fd)
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);
|
||||
|
||||
if (ast_opt_high_priority)
|
||||
if (option_highpriority)
|
||||
ast_set_priority(0);
|
||||
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
@@ -116,7 +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 ast_module_user *u;
|
||||
struct localuser *u;
|
||||
int fds[2];
|
||||
int ms = -1;
|
||||
int pid = -1;
|
||||
@@ -129,11 +132,11 @@ static int NBScat_exec(struct ast_channel *chan, void *data)
|
||||
short frdata[160];
|
||||
} myf;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
|
||||
ast_log(LOG_WARNING, "Unable to create socketpair\n");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -143,7 +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");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -213,25 +216,40 @@ static int NBScat_exec(struct ast_channel *chan, void *data)
|
||||
if (!res && owriteformat)
|
||||
ast_set_write_format(chan, owriteformat);
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
1862
apps/app_osplookup.c
1862
apps/app_osplookup.c
File diff suppressed because it is too large
Load Diff
199
apps/app_page.c
199
apps/app_page.c
@@ -20,26 +20,19 @@
|
||||
*
|
||||
* \brief page() - Paging application
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<depend>zaptel</depend>
|
||||
<depend>app_meetme</depend>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -48,9 +41,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/chanvars.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/dial.h"
|
||||
#include "asterisk/devicestate.h"
|
||||
|
||||
|
||||
static const char *tdesc = "Page Multiple Phones";
|
||||
|
||||
static const char *app_page= "Page";
|
||||
|
||||
@@ -63,48 +56,121 @@ static const char *page_descrip =
|
||||
"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";
|
||||
" 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_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),
|
||||
});
|
||||
|
||||
#define MAX_DIALS 128
|
||||
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)
|
||||
{
|
||||
struct ast_module_user *u;
|
||||
char *options, *tech, *resource, *tmp;
|
||||
char meetmeopts[88], originator[AST_CHANNEL_NAME];
|
||||
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 *dials[MAX_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;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!(app = pbx_findapp("MeetMe"))) {
|
||||
ast_log(LOG_WARNING, "There is no MeetMe application available!\n");
|
||||
ast_module_user_remove(u);
|
||||
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, '-')))
|
||||
@@ -114,42 +180,19 @@ static int page_exec(struct ast_channel *chan, void *data)
|
||||
if (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");
|
||||
|
||||
/* Go through parsing/calling each device */
|
||||
while ((tech = strsep(&tmp, "&"))) {
|
||||
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;
|
||||
}
|
||||
|
||||
*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 */
|
||||
dials[pos++] = dial;
|
||||
}
|
||||
|
||||
if (!ast_test_flag(&flags, PAGE_QUIET)) {
|
||||
@@ -157,47 +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 = dials[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);
|
||||
}
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app_page);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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,23 +22,20 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief ParkAndAnnounce application for Asterisk
|
||||
*
|
||||
* \author Ben Miller <bgmiller@dccinc.com>
|
||||
* \arg With TONS of help from Mark!
|
||||
*
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -49,7 +46,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/say.h"
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
static char *tdesc = "Call Parking and Announce Application";
|
||||
|
||||
static char *app = "ParkAndAnnounce";
|
||||
|
||||
@@ -57,54 +55,57 @@ 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";
|
||||
"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=0;
|
||||
char *return_context;
|
||||
int lot, timeout = 0, dres;
|
||||
int l, lot, timeout = 0, dres;
|
||||
char *working, *context, *exten, *priority, *dial, *dialtech, *dialstr;
|
||||
char *template, *tpl_working, *tpl_current;
|
||||
char *tmp[100];
|
||||
char buf[13];
|
||||
int looptemp=0,i=0;
|
||||
char *s;
|
||||
char *s,*orig_s;
|
||||
|
||||
struct ast_channel *dchan;
|
||||
struct outgoing_helper oh;
|
||||
int outstate;
|
||||
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "ParkAndAnnounce requires arguments: (announce:template|timeout|dial|[return_context])\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
s = ast_strdupa(data);
|
||||
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);
|
||||
|
||||
template=strsep(&s,"|");
|
||||
if(! template) {
|
||||
ast_log(LOG_WARNING, "PARK: An announce template must be defined\n");
|
||||
ast_module_user_remove(u);
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -115,7 +116,8 @@ static int parkandannounce_exec(struct ast_channel *chan, void *data)
|
||||
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");
|
||||
ast_module_user_remove(u);
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
} else {
|
||||
dialtech=strsep(&dial, "/");
|
||||
@@ -147,15 +149,16 @@ static int parkandannounce_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
if(atoi(priority) < 0) {
|
||||
ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
|
||||
ast_module_user_remove(u);
|
||||
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)
|
||||
ast_copy_string(chan->exten, exten, sizeof(chan->exten));
|
||||
if (context)
|
||||
ast_copy_string(chan->context, context, sizeof(chan->context));
|
||||
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++;
|
||||
}
|
||||
@@ -178,10 +181,8 @@ static int parkandannounce_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
/* Now place the call to the extention */
|
||||
|
||||
snprintf(buf, sizeof(buf), "%d", lot);
|
||||
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, dialstr,30000, &outstate, chan->cid.cid_num, chan->cid.cid_name, &oh);
|
||||
|
||||
if(dchan) {
|
||||
@@ -193,12 +194,14 @@ static int parkandannounce_exec(struct ast_channel *chan, void *data)
|
||||
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);
|
||||
ast_module_user_remove(u);
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
|
||||
ast_module_user_remove(u);
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -234,27 +237,45 @@ static int parkandannounce_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
ast_stopstream(dchan);
|
||||
ast_hangup(dchan);
|
||||
free(orig_s);
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -19,20 +19,18 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief Trivial application to playback a sound file
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -43,9 +41,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/cli.h"
|
||||
#include "asterisk/localtime.h"
|
||||
#include "asterisk/say.h"
|
||||
|
||||
static char *tdesc = "Sound File Playback Application";
|
||||
|
||||
static char *app = "Playback";
|
||||
|
||||
@@ -67,325 +64,19 @@ static char *descrip =
|
||||
" SUCCESS | FAILED\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_log(LOG_WARNING, "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_log(LOG_WARNING, "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_log(LOG_WARNING, "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 <= 0 && (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 */
|
||||
memset(fn, 0, sizeof(fn)); /* XXX why isn't done in pbx_substitute_variables_helper! */
|
||||
pbx_substitute_variables_varshead(&head, x, fn, sizeof(fn));
|
||||
ast_log(LOG_WARNING, "doing [%s]\n", fn);
|
||||
|
||||
/* locate prefix and data, if any */
|
||||
fmt = index(fn, ':');
|
||||
if (!fmt || fmt == fn) { /* regular filename */
|
||||
ret = s_streamwait3(a, fn);
|
||||
continue;
|
||||
}
|
||||
fmt++;
|
||||
data = index(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 = index(fn2, '\'');
|
||||
if (!y) {
|
||||
p = data; /* invalid. prepare to end */
|
||||
break;
|
||||
}
|
||||
*y = '\0';
|
||||
ast_trim_blanks(fn2);
|
||||
p = index(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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 tm tm;
|
||||
say_args_t a = { chan, ints, lang, -1, -1 };
|
||||
if (format == NULL)
|
||||
format = "";
|
||||
|
||||
ast_localtime(&t, &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(int fd, int argc, char *argv[])
|
||||
{
|
||||
const char *old_mode = say_api_buf[0] ? say_new : say_old;
|
||||
char *mode;
|
||||
|
||||
if (argc == 2) {
|
||||
ast_cli(fd, "say mode is [%s]\n", old_mode);
|
||||
return RESULT_SUCCESS;
|
||||
} else if (argc != 3)
|
||||
return RESULT_SHOWUSAGE;
|
||||
mode = argv[2];
|
||||
|
||||
ast_log(LOG_WARNING, "init say.c from %s to %s\n", old_mode, mode);
|
||||
|
||||
if (!strcmp(mode, old_mode)) {
|
||||
ast_log(LOG_WARNING, "say mode is %s already\n", mode);
|
||||
} else if (!strcmp(mode, say_new)) {
|
||||
if (say_cfg == NULL)
|
||||
say_cfg = ast_config_load("say.conf");
|
||||
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 {
|
||||
ast_log(LOG_WARNING, "unrecognized mode %s\n", mode);
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static struct ast_cli_entry cli_playback[] = {
|
||||
{ { "say", "load", NULL },
|
||||
__say_init, "set/show the say mode",
|
||||
"say load new|old" },
|
||||
};
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int playback_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
int mres = 0;
|
||||
struct ast_module_user *u;
|
||||
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);
|
||||
@@ -396,16 +87,20 @@ static int playback_exec(struct ast_channel *chan, void *data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp = ast_strdupa(data);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
tmp = ast_strdupa(data);
|
||||
if (!tmp) {
|
||||
ast_log(LOG_ERROR, "Out of memory!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
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'))
|
||||
@@ -415,78 +110,72 @@ static int playback_exec(struct ast_channel *chan, void *data)
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
if (option_skip) {
|
||||
/* At the user's option, skip if the line is not up */
|
||||
goto done;
|
||||
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 || ast_opt_priority_jumping)
|
||||
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");
|
||||
ast_module_user_remove(u);
|
||||
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)
|
||||
{
|
||||
if (say_cfg) {
|
||||
ast_config_destroy(say_cfg);
|
||||
ast_log(LOG_NOTICE, "Reloading say.conf\n");
|
||||
}
|
||||
say_cfg = ast_config_load("say.conf");
|
||||
/*
|
||||
* 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));
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
|
||||
if (say_cfg)
|
||||
ast_config_destroy(say_cfg);
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
int load_module(void)
|
||||
{
|
||||
say_cfg = ast_config_load("say.conf");
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -19,20 +19,18 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief Block all calls without Caller*ID, require phone # to be entered
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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/utils.h"
|
||||
@@ -49,6 +47,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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";
|
||||
@@ -74,6 +74,11 @@ static char *descrip =
|
||||
" SUCCESS | FAILED \n"
|
||||
;
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
|
||||
|
||||
static int privacy_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
@@ -82,9 +87,9 @@ static int privacy_exec (struct ast_channel *chan, void *data)
|
||||
int maxretries = 3;
|
||||
int minlength = 10;
|
||||
int x = 0;
|
||||
const char *s;
|
||||
char *s;
|
||||
char phone[30];
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
struct ast_config *cfg = NULL;
|
||||
char *parse = NULL;
|
||||
int priority_jump = 0;
|
||||
@@ -94,8 +99,7 @@ static int privacy_exec (struct ast_channel *chan, void *data)
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
|
||||
LOCAL_USER_ADD (u);
|
||||
if (!ast_strlen_zero(chan->cid.cid_num)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "CallerID Present: Skipping\n");
|
||||
@@ -104,24 +108,30 @@ static int privacy_exec (struct ast_channel *chan, void *data)
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
res = ast_answer(chan);
|
||||
if (res) {
|
||||
ast_module_user_remove(u);
|
||||
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, "%d", &x) == 1)
|
||||
if (sscanf(args.maxretries, "%30d", &x) == 1)
|
||||
maxretries = x;
|
||||
else
|
||||
ast_log(LOG_WARNING, "Invalid max retries argument\n");
|
||||
}
|
||||
if (args.minlength) {
|
||||
if (sscanf(args.minlength, "%d", &x) == 1)
|
||||
if (sscanf(args.minlength, "%30d", &x) == 1)
|
||||
minlength = x;
|
||||
else
|
||||
ast_log(LOG_WARNING, "Invalid min length argument\n");
|
||||
@@ -138,14 +148,14 @@ static int privacy_exec (struct ast_channel *chan, void *data)
|
||||
cfg = ast_config_load(PRIV_CONFIG);
|
||||
|
||||
if (cfg && (s = ast_variable_retrieve(cfg, "general", "maxretries"))) {
|
||||
if (sscanf(s, "%d", &x) == 1)
|
||||
if (sscanf(s, "%30d", &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)
|
||||
if (sscanf(s, "%30d", &x) == 1)
|
||||
minlength = x;
|
||||
else
|
||||
ast_log(LOG_WARNING, "Invalid min length argument\n");
|
||||
@@ -200,7 +210,7 @@ static int privacy_exec (struct ast_channel *chan, void *data)
|
||||
}
|
||||
pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS");
|
||||
} else {
|
||||
if (priority_jump || ast_opt_priority_jumping)
|
||||
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");
|
||||
}
|
||||
@@ -208,25 +218,45 @@ static int privacy_exec (struct ast_channel *chan, void *data)
|
||||
ast_config_destroy(cfg);
|
||||
}
|
||||
|
||||
ast_module_user_remove(u);
|
||||
|
||||
return 0;
|
||||
LOCAL_USER_REMOVE (u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int
|
||||
unload_module (void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application (app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
2996
apps/app_queue.c
2996
apps/app_queue.c
File diff suppressed because it is too large
Load Diff
@@ -23,15 +23,15 @@
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -39,7 +39,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
|
||||
/*! \todo The Random() app should be removed from trunk following the release of 1.4 */
|
||||
static char *tdesc = "Random goto";
|
||||
|
||||
static char *app_random = "Random";
|
||||
|
||||
@@ -47,62 +47,80 @@ 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"
|
||||
"DEPRECATED: Use GotoIf($[${RAND(1,100)} > <number>]?<label>)\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 ast_module_user *u;
|
||||
struct localuser *u;
|
||||
|
||||
char *s;
|
||||
char *prob;
|
||||
int probint;
|
||||
static int deprecated = 0;
|
||||
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "Random requires an argument ([probability]:[[context|]extension|]priority)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
s = ast_strdupa(data);
|
||||
|
||||
prob = strsep(&s,":");
|
||||
if ((!prob) || (sscanf(prob, "%d", &probint) != 1))
|
||||
probint = 0;
|
||||
|
||||
if (!deprecated) {
|
||||
deprecated = 1;
|
||||
ast_log(LOG_WARNING, "Random is deprecated in Asterisk 1.4. Replace with GotoIf($[${RAND(0,99)} + %d >= 100]?%s)\n", probint, s);
|
||||
if (!s) {
|
||||
ast_log(LOG_ERROR, "Out of memory!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((ast_random() % 100) + probint >= 100) {
|
||||
prob = strsep(&s,":");
|
||||
if ((!prob) || (sscanf(prob, "%3d", &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);
|
||||
}
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app_random);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
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);
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Random goto");
|
||||
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;
|
||||
}
|
||||
|
||||
193
apps/app_read.c
193
apps/app_read.c
@@ -19,20 +19,18 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief Trivial application to read a variable
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -43,19 +41,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/indications.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";
|
||||
|
||||
@@ -65,131 +52,131 @@ static char *descrip =
|
||||
" 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 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 -- An integer number of seconds to wait for a digit response. If greater\n"
|
||||
" than 0, that value will override the default timeout.\n\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;
|
||||
struct ast_module_user *u;
|
||||
char tmp[256] = "";
|
||||
int maxdigits = 255;
|
||||
int tries = 1, to = 0, x = 0;
|
||||
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;
|
||||
struct ast_flags flags = {0};
|
||||
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);
|
||||
);
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "Read requires an argument (variable)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
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)) {
|
||||
to = atoi(arglist.timeout);
|
||||
if(timeout) {
|
||||
to = atoi(timeout);
|
||||
if (to <= 0)
|
||||
to = 0;
|
||||
else
|
||||
to *= 1000;
|
||||
}
|
||||
|
||||
if (ast_strlen_zero(arglist.filename)) {
|
||||
arglist.filename = NULL;
|
||||
}
|
||||
if (!ast_strlen_zero(arglist.maxdigits)) {
|
||||
maxdigits = atoi(arglist.maxdigits);
|
||||
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.variable)) {
|
||||
if (ast_strlen_zero(varname)) {
|
||||
ast_log(LOG_WARNING, "Invalid! Usage: Read(variable[|filename][|maxdigits][|option][|attempts][|timeout])\n\n");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
ts=NULL;
|
||||
if (ast_test_flag(&flags,OPT_INDICATION)) {
|
||||
if (!ast_strlen_zero(arglist.filename)) {
|
||||
ts = ast_get_indication_tone(chan->zone,arglist.filename);
|
||||
}
|
||||
}
|
||||
|
||||
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, "\0");
|
||||
ast_module_user_remove(u);
|
||||
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) {
|
||||
tmp[x]='\0';
|
||||
break;
|
||||
}
|
||||
tmp[x++] = res;
|
||||
if (tmp[x-1] == '#') {
|
||||
tmp[x-1] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = ast_app_getdata(chan, arglist.filename, tmp, maxdigits, to);
|
||||
}
|
||||
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)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User entered '%s'\n", tmp);
|
||||
@@ -205,30 +192,44 @@ static int read_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
res = 0;
|
||||
} else {
|
||||
pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User disconnected\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -20,20 +20,18 @@
|
||||
*
|
||||
* \brief ReadFile application -- Reads in a File for you.
|
||||
*
|
||||
* \author Matt O'Gorman <mogorman@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -42,6 +40,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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 = "ReadFile(varname=file,length)";
|
||||
@@ -52,11 +52,15 @@ static char *readfile_descrip =
|
||||
" 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 ast_module_user *u;
|
||||
struct localuser *u;
|
||||
char *s, *varname=NULL, *file=NULL, *length=NULL, *returnvar=NULL;
|
||||
int len=0;
|
||||
|
||||
@@ -65,9 +69,14 @@ static int readfile_exec(struct ast_channel *chan, void *data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
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, "|");
|
||||
@@ -75,12 +84,12 @@ static int readfile_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
if (!varname || !file) {
|
||||
ast_log(LOG_ERROR, "No file or variable specified!\n");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (length) {
|
||||
if ((sscanf(length, "%d", &len) != 1) || (len < 0)) {
|
||||
if ((sscanf(length, "%30d", &len) != 1) || (len < 0)) {
|
||||
ast_log(LOG_WARNING, "%s is not a positive number, defaulting length to max\n", length);
|
||||
len = 0;
|
||||
}
|
||||
@@ -96,25 +105,40 @@ static int readfile_exec(struct ast_channel *chan, void *data)
|
||||
pbx_builtin_setvar_helper(chan, varname, returnvar);
|
||||
free(returnvar);
|
||||
}
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app_readfile);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -20,22 +20,19 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief RealTime App
|
||||
*
|
||||
* \author Anthony Minessale <anthmct@yahoo.com>
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -49,27 +46,25 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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"
|
||||
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\n"
|
||||
"to the name. For example, a prefix of 'var_' would make the column 'name'\n"
|
||||
"become the variable ${var_name}. REALTIMECOUNT will be set with the number\n"
|
||||
"of values read.\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\n"
|
||||
"updated to <newval>. REALTIMECOUNT will be set with the number of rows\n"
|
||||
"updated or -1 if an error occurs.\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_realtime_load(int fd, int argc, char **argv)
|
||||
static int cli_load_realtime(int fd, int argc, char **argv)
|
||||
{
|
||||
char *header_format = "%30s %-30s\n";
|
||||
struct ast_variable *var=NULL;
|
||||
@@ -94,7 +89,7 @@ static int cli_realtime_load(int fd, int argc, char **argv)
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int cli_realtime_update(int fd, int argc, char **argv) {
|
||||
static int cli_update_realtime(int fd, int argc, char **argv) {
|
||||
int res = 0;
|
||||
|
||||
if(argc<7) {
|
||||
@@ -115,49 +110,45 @@ static int cli_realtime_update(int fd, int argc, char **argv) {
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static char cli_realtime_load_usage[] =
|
||||
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 char cli_realtime_update_usage[] =
|
||||
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_realtime[] = {
|
||||
{ { "realtime", "load", NULL, NULL },
|
||||
cli_realtime_load, "Used to print out RealTime variables.",
|
||||
cli_realtime_load_usage, NULL },
|
||||
|
||||
{ { "realtime", "update", NULL, NULL },
|
||||
cli_realtime_update, "Used to update RealTime variables.",
|
||||
cli_realtime_update_usage, NULL },
|
||||
};
|
||||
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 ast_module_user *u;
|
||||
int res = 0, count = 0;
|
||||
char countc[13];
|
||||
|
||||
ast_log(LOG_WARNING, "The RealTimeUpdate application has been deprecated in favor of the REALTIME dialplan function.\n");
|
||||
struct localuser *u;
|
||||
int res = 0;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_ERROR,"Invalid input: usage %s\n",UUSAGE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
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 = 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -165,13 +156,10 @@ static int realtime_update_exec(struct ast_channel *chan, void *data)
|
||||
ast_log(LOG_ERROR,"Invalid input: usage %s\n",UUSAGE);
|
||||
res = -1;
|
||||
} else {
|
||||
count = ast_update_realtime(family,colmatch,value,newcol,newval,NULL);
|
||||
ast_update_realtime(family,colmatch,value,newcol,newval,NULL);
|
||||
}
|
||||
|
||||
snprintf(countc, sizeof(countc), "%d", count);
|
||||
pbx_builtin_setvar_helper(chan, "REALTIMECOUNT", countc);
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -179,29 +167,27 @@ static int realtime_update_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
static int realtime_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0, count=0;
|
||||
struct ast_module_user *u;
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
struct ast_variable *var, *itt;
|
||||
char *family=NULL, *colmatch=NULL, *value=NULL, *prefix=NULL, *vname=NULL;
|
||||
char countc[13];
|
||||
size_t len;
|
||||
|
||||
ast_log(LOG_WARNING, "The RealTime application has been deprecated in favor of the REALTIME dialplan function.\n");
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_ERROR,"Invalid input: usage %s\n",USAGE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
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 = 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) ) {
|
||||
@@ -221,41 +207,56 @@ static int realtime_exec(struct ast_channel *chan, void *data)
|
||||
vname = itt->name;
|
||||
|
||||
pbx_builtin_setvar_helper(chan, vname, itt->value);
|
||||
count++;
|
||||
}
|
||||
ast_variables_destroy(var);
|
||||
} else if (option_verbose > 3)
|
||||
ast_verbose(VERBOSE_PREFIX_4"No Realtime Matches Found.\n");
|
||||
}
|
||||
snprintf(countc, sizeof(countc), "%d", count);
|
||||
pbx_builtin_setvar_helper(chan, "REALTIMECOUNT", countc);
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
ast_cli_unregister_multiple(cli_realtime, sizeof(cli_realtime) / sizeof(struct ast_cli_entry));
|
||||
res = ast_unregister_application(uapp);
|
||||
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);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
ast_cli_register_multiple(cli_realtime, sizeof(cli_realtime) / sizeof(struct ast_cli_entry));
|
||||
res = ast_register_application(uapp, realtime_update_exec, usynopsis, udesc);
|
||||
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;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Realtime Data Lookup/Rewrite");
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,19 +20,17 @@
|
||||
*
|
||||
* \brief Trivial application to record a sound file
|
||||
*
|
||||
* \author Matthew Fredrickson <creslin@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -45,6 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/app.h"
|
||||
|
||||
static char *tdesc = "Trivial Record Application";
|
||||
|
||||
static char *app = "Record";
|
||||
|
||||
@@ -63,17 +62,19 @@ static char *descrip =
|
||||
" '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";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int record_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
@@ -86,7 +87,7 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
char tmp[256];
|
||||
|
||||
struct ast_filestream *s = '\0';
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
struct ast_frame *f = NULL;
|
||||
|
||||
struct ast_dsp *sildet = NULL; /* silence detector dsp */
|
||||
@@ -112,10 +113,15 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* 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, "|");
|
||||
@@ -136,11 +142,11 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
if (!ext) {
|
||||
ast_log(LOG_WARNING, "No extension specified to filename!\n");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
if (silstr) {
|
||||
if ((sscanf(silstr, "%d", &i) == 1) && (i > -1)) {
|
||||
if ((sscanf(silstr, "%30d", &i) == 1) && (i > -1)) {
|
||||
silence = i * 1000;
|
||||
} else if (!ast_strlen_zero(silstr)) {
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid silence duration\n", silstr);
|
||||
@@ -148,7 +154,7 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
|
||||
if (maxstr) {
|
||||
if ((sscanf(maxstr, "%d", &i) == 1) && (i > -1))
|
||||
if ((sscanf(maxstr, "%30d", &i) == 1) && (i > -1))
|
||||
/* Convert duration to milliseconds */
|
||||
maxduration = i * 1000;
|
||||
else if (!ast_strlen_zero(maxstr))
|
||||
@@ -169,8 +175,6 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
option_append = 1;
|
||||
if (strchr(options, 't'))
|
||||
terminator = '*';
|
||||
if (strchr(options, 'x'))
|
||||
terminator = 0;
|
||||
if (strchr(options, 'q'))
|
||||
option_quiet = 1;
|
||||
}
|
||||
@@ -189,7 +193,8 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
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 */
|
||||
@@ -210,10 +215,10 @@ 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, filename, sizeof(tmp));
|
||||
strncpy(tmp, filename, sizeof(tmp)-1);
|
||||
/* end of routine mentioned */
|
||||
|
||||
|
||||
@@ -221,7 +226,7 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
if (option_skip) {
|
||||
/* At the user's option, skip if the line is not up */
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
} else if (!option_noanswer) {
|
||||
/* Otherwise answer unless we're supposed to record while on-hook */
|
||||
@@ -252,13 +257,13 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
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");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
sildet = ast_dsp_new();
|
||||
if (!sildet) {
|
||||
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
ast_dsp_set_threshold(sildet, 256);
|
||||
@@ -273,7 +278,7 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ast_opt_transmit_silence)
|
||||
if (option_transmit_silence_during_record)
|
||||
silgen = ast_channel_start_silence_generator(chan);
|
||||
|
||||
/* Request a video update */
|
||||
@@ -362,25 +367,40 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
ast_dsp_free(sildet);
|
||||
}
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
3137
apps/app_rpt.c
3137
apps/app_rpt.c
File diff suppressed because it is too large
Load Diff
@@ -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,21 +18,19 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief SayUnixTime application
|
||||
*
|
||||
* \author Tilghman Lesher <app_sayunixtime__200309@the-tilghman.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -41,7 +38,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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";
|
||||
@@ -65,55 +64,78 @@ static char *datetime_descrip =
|
||||
" 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;
|
||||
struct ast_module_user *u;
|
||||
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;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
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_STANDARD_APP_ARGS(args, parse);
|
||||
if (data) {
|
||||
s = data;
|
||||
s = ast_strdupa(s);
|
||||
if (s) {
|
||||
timec = strsep(&s,"|");
|
||||
if ((timec) && (*timec != '\0')) {
|
||||
long timein;
|
||||
if (sscanf(timec,"%30ld",&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");
|
||||
}
|
||||
}
|
||||
|
||||
ast_get_time_t(args.timeval, &unixtime, time(NULL), NULL);
|
||||
|
||||
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);
|
||||
|
||||
ast_module_user_remove(u);
|
||||
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);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
@@ -123,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;
|
||||
}
|
||||
|
||||
@@ -19,20 +19,18 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief App to send DTMF digits
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -43,7 +41,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/options.h"
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/app.h"
|
||||
#include "asterisk/manager.h"
|
||||
|
||||
static char *tdesc = "Send DTMF digits Application";
|
||||
|
||||
static char *app = "SendDTMF";
|
||||
|
||||
@@ -55,11 +54,14 @@ static char *descrip =
|
||||
" The application will either pass the assigned digits or terminate if it\n"
|
||||
" encounters an error.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int senddtmf_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
char *digits = NULL, *to = NULL;
|
||||
int timeout = 250;
|
||||
|
||||
@@ -68,9 +70,14 @@ static int senddtmf_exec(struct ast_channel *chan, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
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';
|
||||
@@ -78,66 +85,45 @@ static int senddtmf_exec(struct ast_channel *chan, void *data)
|
||||
timeout = atoi(to);
|
||||
}
|
||||
|
||||
if (timeout <= 0)
|
||||
if(timeout <= 0)
|
||||
timeout = 250;
|
||||
|
||||
res = ast_dtmf_stream(chan,NULL,digits,timeout);
|
||||
|
||||
ast_module_user_remove(u);
|
||||
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 (!digit) {
|
||||
astman_send_error(s, m, "No digit specified");
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ast_senddigit(chan, *digit);
|
||||
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
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");
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -19,22 +19,20 @@
|
||||
/*! \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 "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -46,6 +44,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#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";
|
||||
@@ -63,11 +63,14 @@ static const char *descrip =
|
||||
"'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 ast_module_user *u;
|
||||
struct localuser *u;
|
||||
char *status = "UNSUPPORTED";
|
||||
char *parse = NULL;
|
||||
int priority_jump = 0;
|
||||
@@ -76,14 +79,20 @@ static int sendtext_exec(struct ast_channel *chan, void *data)
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "SendText requires an argument (text[|options])\n");
|
||||
ast_module_user_remove(u);
|
||||
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);
|
||||
|
||||
@@ -92,39 +101,56 @@ static int sendtext_exec(struct ast_channel *chan, void *data)
|
||||
priority_jump = 1;
|
||||
}
|
||||
|
||||
ast_channel_lock(chan);
|
||||
ast_mutex_lock(&chan->lock);
|
||||
if (!chan->tech->send_text) {
|
||||
ast_channel_unlock(chan);
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
/* Does not support transport */
|
||||
if (priority_jump || ast_opt_priority_jumping)
|
||||
if (priority_jump || option_priority_jumping)
|
||||
ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
|
||||
ast_module_user_remove(u);
|
||||
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);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -19,20 +19,18 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief App to set callerid
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -47,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"
|
||||
@@ -66,25 +67,29 @@ static char *descrip2 =
|
||||
|
||||
static int setcallerid_pres_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
int pres = -1;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
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);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
chan->cid.cid_pres = pres;
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static char *tdesc = "Set CallerID Application";
|
||||
|
||||
static char *app = "SetCallerID";
|
||||
|
||||
static char *synopsis = "Set CallerID";
|
||||
@@ -99,24 +104,23 @@ static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
char *tmp = NULL;
|
||||
char name[256];
|
||||
char num[256];
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
char *opt;
|
||||
int anitoo = 0;
|
||||
static int dep_warning = 0;
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "SetCallerID requires an argument!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
|
||||
if (!dep_warning) {
|
||||
dep_warning = 1;
|
||||
ast_log(LOG_WARNING, "SetCallerID is deprecated. Please use Set(CALLERID(all)=...) or Set(CALLERID(ani)=...) instead.\n");
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -129,24 +133,24 @@ static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
ast_callerid_split(tmp, name, sizeof(name), num, sizeof(num));
|
||||
ast_set_callerid(chan, num, name, anitoo ? num : NULL);
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app2);
|
||||
res |= ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
@@ -156,4 +160,19 @@ static int load_module(void)
|
||||
return res;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Set CallerID Application");
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -19,20 +19,18 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief Applictions connected with CDR engine
|
||||
*
|
||||
* \author Justin Huff <jjhuff@mspin.net>
|
||||
*
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/cdr.h"
|
||||
#include "asterisk/module.h"
|
||||
@@ -43,6 +41,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
|
||||
static char *tdesc = "CDR user field apps";
|
||||
|
||||
static char *setcdruserfield_descrip =
|
||||
"[Synopsis]\n"
|
||||
"SetCDRUserField(value)\n\n"
|
||||
@@ -52,8 +52,7 @@ static char *setcdruserfield_descrip =
|
||||
" can use for data not stored anywhere else in the record.\n"
|
||||
" CDR records can be used for billing or storing other arbitrary data\n"
|
||||
" (I.E. telephone survey responses)\n"
|
||||
" Also see AppendCDRUserField().\n"
|
||||
"\nThis application is deprecated in favor of Set(CDR(userfield)=...)\n";
|
||||
" Also see AppendCDRUserField().\n";
|
||||
|
||||
|
||||
static char *setcdruserfield_app = "SetCDRUserField";
|
||||
@@ -68,19 +67,21 @@ static char *appendcdruserfield_descrip =
|
||||
" can use for data not stored anywhere else in the record.\n"
|
||||
" CDR records can be used for billing or storing other arbitrary data\n"
|
||||
" (I.E. telephone survey responses)\n"
|
||||
" Also see SetCDRUserField().\n"
|
||||
"\nThis application is deprecated in favor of Set(CDR(userfield)=...)\n";
|
||||
" Also see SetCDRUserField().\n";
|
||||
|
||||
static char *appendcdruserfield_app = "AppendCDRUserField";
|
||||
static char *appendcdruserfield_synopsis = "Append to the CDR user field";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
static int action_setcdruserfield(struct mansession *s, const struct message *m)
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int action_setcdruserfield(struct mansession *s, struct message *m)
|
||||
{
|
||||
struct ast_channel *c = NULL;
|
||||
const char *userfield = astman_get_header(m, "UserField");
|
||||
const char *channel = astman_get_header(m, "Channel");
|
||||
const char *append = astman_get_header(m, "Append");
|
||||
char *userfield = astman_get_header(m, "UserField");
|
||||
char *channel = astman_get_header(m, "Channel");
|
||||
char *append = astman_get_header(m, "Append");
|
||||
|
||||
if (ast_strlen_zero(channel)) {
|
||||
astman_send_error(s, m, "No Channel specified");
|
||||
@@ -106,49 +107,37 @@ static int action_setcdruserfield(struct mansession *s, const struct message *m)
|
||||
|
||||
static int setcdruserfield_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
int res = 0;
|
||||
static int dep_warning = 0;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (chan->cdr && data) {
|
||||
ast_cdr_setuserfield(chan, (char*)data);
|
||||
}
|
||||
|
||||
if (!dep_warning) {
|
||||
dep_warning = 1;
|
||||
ast_log(LOG_WARNING, "SetCDRUserField is deprecated. Please use CDR(userfield) instead.\n");
|
||||
}
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int appendcdruserfield_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
int res = 0;
|
||||
static int dep_warning = 0;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (chan->cdr && data) {
|
||||
ast_cdr_appenduserfield(chan, (char*)data);
|
||||
}
|
||||
|
||||
if (!dep_warning) {
|
||||
dep_warning = 1;
|
||||
ast_log(LOG_WARNING, "AppendCDRUserField is deprecated. Please use CDR(userfield) instead.\n");
|
||||
}
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
@@ -156,12 +145,12 @@ static int unload_module(void)
|
||||
res |= ast_unregister_application(appendcdruserfield_app);
|
||||
res |= ast_manager_unregister("SetCDRUserField");
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
@@ -172,4 +161,19 @@ static int load_module(void)
|
||||
return res;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "CDR user field apps");
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
132
apps/app_setcidname.c
Normal file
132
apps/app_setcidname.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* \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/callerid.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
static char *tdesc = "Set CallerID Name";
|
||||
|
||||
static char *app = "SetCIDName";
|
||||
|
||||
static char *synopsis = "Set CallerID Name";
|
||||
|
||||
static char *descrip =
|
||||
" SetCIDName(cname[|a]): Set Caller*ID Name on a call to a new\n"
|
||||
"value, while preserving the original Caller*ID number. This is\n"
|
||||
"useful for providing additional information to the called\n"
|
||||
"party. \n"
|
||||
"SetCIDName has been deprecated in favor of the function\n"
|
||||
"CALLERID(name)\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
char *tmp = NULL;
|
||||
struct localuser *u;
|
||||
char *opt;
|
||||
static int deprecation_warning = 0;
|
||||
|
||||
if (!deprecation_warning) {
|
||||
ast_log(LOG_WARNING, "SetCIDName is deprecated, please use Set(CALLERID(name)=value) instead.\n");
|
||||
deprecation_warning = 1;
|
||||
}
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_ERROR, "SetCIDName 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';
|
||||
}
|
||||
|
||||
ast_set_callerid(chan, NULL, tmp, NULL);
|
||||
|
||||
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, setcallerid_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
131
apps/app_setcidnum.c
Normal file
131
apps/app_setcidnum.c
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* Oliver Daudey <traveler@xs4all.nl>
|
||||
*
|
||||
* 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 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/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/translate.h"
|
||||
#include "asterisk/image.h"
|
||||
#include "asterisk/callerid.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
static char *tdesc = "Set CallerID Number";
|
||||
|
||||
static char *app = "SetCIDNum";
|
||||
|
||||
static char *synopsis = "Set CallerID Number";
|
||||
|
||||
static char *descrip =
|
||||
" SetCIDNum(cnum[|a]): Set Caller*ID Number on a call to a new\n"
|
||||
"value, while preserving the original Caller*ID name. This is\n"
|
||||
"useful for providing additional information to the called\n"
|
||||
"party. Sets ANI as well if a flag is used.\n"
|
||||
"SetCIDNum has been deprecated in favor of the function\n"
|
||||
"CALLERID(number)\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
char *opt;
|
||||
int anitoo = 0;
|
||||
char *tmp = NULL;
|
||||
static int deprecation_warning = 0;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!deprecation_warning) {
|
||||
ast_log(LOG_WARNING, "SetCIDNum is deprecated, please use Set(CALLERID(number)=value) instead.\n");
|
||||
deprecation_warning = 1;
|
||||
}
|
||||
|
||||
if (data)
|
||||
tmp = ast_strdupa(data);
|
||||
else
|
||||
tmp = "";
|
||||
|
||||
opt = strchr(tmp, '|');
|
||||
if (opt) {
|
||||
*opt = '\0';
|
||||
opt++;
|
||||
if (*opt == 'a')
|
||||
anitoo = 1;
|
||||
}
|
||||
|
||||
ast_set_callerid(chan, tmp, NULL, anitoo ? tmp : NULL);
|
||||
|
||||
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, setcallerid_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
132
apps/app_setrdnis.c
Normal file
132
apps/app_setrdnis.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 1999 - 2005, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* Oliver Daudey <traveler@xs4all.nl>
|
||||
*
|
||||
* 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 rdnis
|
||||
*
|
||||
* \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/callerid.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
static char *tdesc = "Set RDNIS Number";
|
||||
|
||||
static char *app = "SetRDNIS";
|
||||
|
||||
static char *synopsis = "Set RDNIS Number";
|
||||
|
||||
static char *descrip =
|
||||
" SetRDNIS(cnum): Set RDNIS Number on a call to a new\n"
|
||||
"value.\n"
|
||||
"SetRDNIS has been deprecated in favor of the function\n"
|
||||
"CALLERID(rdnis)\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int setrdnis_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
char *opt, *n, *l;
|
||||
char *tmp = NULL;
|
||||
static int deprecation_warning = 0;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (!deprecation_warning) {
|
||||
ast_log(LOG_WARNING, "SetRDNIS is deprecated, please use Set(CALLERID(rdnis)=value) instead.\n");
|
||||
deprecation_warning = 1;
|
||||
}
|
||||
|
||||
if (data)
|
||||
tmp = ast_strdupa(data);
|
||||
else
|
||||
tmp = "";
|
||||
|
||||
opt = strchr(tmp, '|');
|
||||
if (opt)
|
||||
*opt = '\0';
|
||||
|
||||
n = l = NULL;
|
||||
ast_callerid_parse(tmp, &n, &l);
|
||||
if (l) {
|
||||
ast_shrink_phone_number(l);
|
||||
ast_mutex_lock(&chan->lock);
|
||||
if (chan->cid.cid_rdnis)
|
||||
free(chan->cid.cid_rdnis);
|
||||
chan->cid.cid_rdnis = (l[0]) ? strdup(l) : NULL;
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
}
|
||||
|
||||
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, setrdnis_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
@@ -19,19 +19,17 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief App to set the ISDN Transfer Capability
|
||||
*
|
||||
* \author Frank Sautter - asterisk+at+sautter+dot+com
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/channel.h"
|
||||
#include "asterisk/pbx.h"
|
||||
@@ -44,6 +42,9 @@ static char *app = "SetTransferCapability";
|
||||
|
||||
static char *synopsis = "Set ISDN Transfer Capability";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static struct { int val; char *name; } transcaps[] = {
|
||||
{ AST_TRANS_CAP_SPEECH, "SPEECH" },
|
||||
@@ -64,27 +65,20 @@ static char *descrip =
|
||||
" RESTRICTED_DIGITAL : 0x09 - Restricted digital information\n"
|
||||
" 3K1AUDIO : 0x10 - 3.1kHz Audio (fax calls)\n"
|
||||
" DIGITAL_W_TONES : 0x11 - Unrestricted digital information with tones/announcements\n"
|
||||
" VIDEO : 0x18 - Video\n"
|
||||
" VIDEO : 0x18 - Video:\n"
|
||||
"\n"
|
||||
"This application is deprecated in favor of Set(CHANNEL(transfercapability)=...)\n"
|
||||
;
|
||||
|
||||
static int settransfercapability_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
char *tmp = NULL;
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
int x;
|
||||
char *opts;
|
||||
int transfercapability = -1;
|
||||
static int dep_warning = 0;
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
|
||||
if (!dep_warning) {
|
||||
dep_warning = 1;
|
||||
ast_log(LOG_WARNING, "SetTransferCapability is deprecated. Please use CHANNEL(transfercapability) instead.\n");
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (data)
|
||||
tmp = ast_strdupa(data);
|
||||
else
|
||||
@@ -102,7 +96,7 @@ static int settransfercapability_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
if (transfercapability < 0) {
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid transfer capability (see 'show application SetTransferCapability')\n", tmp);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -111,26 +105,41 @@ static int settransfercapability_exec(struct ast_channel *chan, void *data)
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Setting transfer capability to: 0x%.2x - %s.\n", transfercapability, tmp);
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, settransfercapability_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Set ISDN Transfer Capability");
|
||||
char *description(void)
|
||||
{
|
||||
return synopsis;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
116
apps/app_skel.c
116
apps/app_skel.c
@@ -19,26 +19,20 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief Skeleton application
|
||||
*
|
||||
* \author <Your Name Here> <<Your Email Here>>
|
||||
*
|
||||
* This is a skeleton for development of an Asterisk application
|
||||
* This is a skeleton for development of an Asterisk application
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<defaultenabled>no</defaultenabled>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -47,87 +41,109 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/app.h"
|
||||
|
||||
static char *tdesc = "Trivial skeleton Application";
|
||||
static char *app = "Skel";
|
||||
static char *synopsis =
|
||||
"Skeleton application.";
|
||||
static char *descrip = "This application is a template to build other applications from.\n"
|
||||
" It shows you the basic structure to create your own Asterisk applications.\n";
|
||||
|
||||
enum {
|
||||
OPTION_A = (1 << 0),
|
||||
OPTION_B = (1 << 1),
|
||||
OPTION_C = (1 << 2),
|
||||
} option_flags;
|
||||
|
||||
enum {
|
||||
OPTION_ARG_B = 0,
|
||||
OPTION_ARG_C = 1,
|
||||
/* This *must* be the last value in this enum! */
|
||||
OPTION_ARG_ARRAY_SIZE = 2,
|
||||
} option_args;
|
||||
#define OPTION_A (1 << 0) /* Option A */
|
||||
#define OPTION_B (1 << 1) /* Option B(n) */
|
||||
#define OPTION_C (1 << 2) /* Option C(str) */
|
||||
#define OPTION_NULL (1 << 3) /* Dummy Termination */
|
||||
|
||||
AST_APP_OPTIONS(app_opts,{
|
||||
AST_APP_OPTION('a', OPTION_A),
|
||||
AST_APP_OPTION_ARG('b', OPTION_B, OPTION_ARG_B),
|
||||
AST_APP_OPTION_ARG('c', OPTION_C, OPTION_ARG_C),
|
||||
['a'] = { OPTION_A },
|
||||
['b'] = { OPTION_B, 1 },
|
||||
['c'] = { OPTION_C, 2 }
|
||||
});
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int app_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct ast_flags flags;
|
||||
struct ast_module_user *u;
|
||||
char *parse, *opts[OPTION_ARG_ARRAY_SIZE];
|
||||
AST_DECLARE_APP_ARGS(args,
|
||||
AST_APP_ARG(dummy);
|
||||
AST_APP_ARG(options);
|
||||
);
|
||||
struct localuser *u;
|
||||
char *options=NULL;
|
||||
char *dummy = NULL;
|
||||
char *args;
|
||||
int argc = 0;
|
||||
char *opts[2];
|
||||
char *argv[2];
|
||||
|
||||
if (ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "%s requires an argument (dummy|[options])\n", app);
|
||||
ast_log(LOG_WARNING, "%s requires an argument (dummy|[options])\n",app);
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Do our thing here */
|
||||
|
||||
/* We need to make a copy of the input string if we are going to modify it! */
|
||||
parse = ast_strdupa(data);
|
||||
args = ast_strdupa(data);
|
||||
if (!args) {
|
||||
ast_log(LOG_ERROR, "Out of memory!\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
|
||||
dummy = argv[0];
|
||||
options = argv[1];
|
||||
ast_app_parse_options(app_opts, &flags, opts, options);
|
||||
}
|
||||
|
||||
AST_STANDARD_APP_ARGS(args, parse);
|
||||
|
||||
if (args.argc == 2)
|
||||
ast_app_parse_options(app_opts, &flags, opts, args.options);
|
||||
|
||||
if (!ast_strlen_zero(args.dummy))
|
||||
ast_log(LOG_NOTICE, "Dummy value is : %s\n", args.dummy);
|
||||
if (!ast_strlen_zero(dummy))
|
||||
ast_log(LOG_NOTICE, "Dummy value is : %s\n", dummy);
|
||||
|
||||
if (ast_test_flag(&flags, OPTION_A))
|
||||
ast_log(LOG_NOTICE, "Option A is set\n");
|
||||
|
||||
if (ast_test_flag(&flags, OPTION_B))
|
||||
ast_log(LOG_NOTICE, "Option B is set with : %s\n", opts[OPTION_ARG_B] ? opts[OPTION_ARG_B] : "<unspecified>");
|
||||
ast_log(LOG_NOTICE,"Option B is set with : %s\n", opts[0] ? opts[0] : "<unspecified>");
|
||||
|
||||
if (ast_test_flag(&flags, OPTION_C))
|
||||
ast_log(LOG_NOTICE, "Option C is set with : %s\n", opts[OPTION_ARG_C] ? opts[OPTION_ARG_C] : "<unspecified>");
|
||||
|
||||
ast_module_user_remove(u);
|
||||
ast_log(LOG_NOTICE,"Option C is set with : %s\n", opts[1] ? opts[1] : "<unspecified>");
|
||||
|
||||
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, app_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Skeleton (sample) Application");
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
126
apps/app_sms.c
126
apps/app_sms.c
@@ -18,14 +18,9 @@
|
||||
*
|
||||
* \brief SMS application - ETSI ES 201 912 protocol 1 implimentation
|
||||
* \ingroup applications
|
||||
*
|
||||
* \author Adrian Kennard
|
||||
*
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -36,6 +31,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/lock.h"
|
||||
#include "asterisk/file.h"
|
||||
#include "asterisk/logger.h"
|
||||
@@ -61,6 +60,8 @@ static volatile unsigned int seq; /* arbitrary message sequence number for
|
||||
static char log_file[255];
|
||||
static char spool_dir[255];
|
||||
|
||||
static char *tdesc = "SMS/PSTN handler";
|
||||
|
||||
static char *app = "SMS";
|
||||
|
||||
static char *synopsis = "Communicates with SMS service centres and SMS capable analogue phones";
|
||||
@@ -93,6 +94,9 @@ static signed short wave[] = {
|
||||
static unsigned char wavea[80];
|
||||
#endif
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
/* SMS 7 bit character mapping to UCS-2 */
|
||||
static const unsigned short defaultalphabet[] = {
|
||||
@@ -193,7 +197,7 @@ static void sms_release (struct ast_channel *chan, void *data)
|
||||
|
||||
static void sms_messagetx (sms_t * h);
|
||||
|
||||
/*! \brief copy number, skipping non digits apart from leading + */
|
||||
/*--- numcpy: copy number, skipping non digits apart from leading + */
|
||||
static void numcpy (char *d, char *s)
|
||||
{
|
||||
if (*s == '+')
|
||||
@@ -206,7 +210,7 @@ static void numcpy (char *d, char *s)
|
||||
*d = 0;
|
||||
}
|
||||
|
||||
/*! \brief static, return a date/time in ISO format */
|
||||
/*--- isodate: static, return a date/time in ISO format */
|
||||
static char * isodate (time_t t)
|
||||
{
|
||||
static char date[20];
|
||||
@@ -214,7 +218,7 @@ static char * isodate (time_t t)
|
||||
return date;
|
||||
}
|
||||
|
||||
/*! \brief reads next UCS character from null terminated UTF-8 string and advanced pointer */
|
||||
/*--- utf8decode: reads next UCS character from null terminated UTF-8 string and advanced pointer */
|
||||
/* for non valid UTF-8 sequences, returns character as is */
|
||||
/* Does not advance pointer for null termination */
|
||||
static long utf8decode (unsigned char **pp)
|
||||
@@ -260,7 +264,7 @@ static long utf8decode (unsigned char **pp)
|
||||
return *p; /* not sensible */
|
||||
}
|
||||
|
||||
/*! \brief takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using SMS 7 bit character codes */
|
||||
/*--- packsms7: takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using SMS 7 bit character codes */
|
||||
/* The return value is the number of septets packed in to o, which is internally limited to SMSLEN */
|
||||
/* o can be null, in which case this is used to validate or count only */
|
||||
/* if the input contains invalid characters then the return value is -1 */
|
||||
@@ -330,7 +334,7 @@ static int packsms7 (unsigned char *o, int udhl, unsigned char *udh, int udl, un
|
||||
return n;
|
||||
}
|
||||
|
||||
/*! \brief takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using 8 bit character codes */
|
||||
/*--- packsms8: takes a binary header (udhl bytes at udh) and UCS-2 message (udl characters at ud) and packs in to o using 8 bit character codes */
|
||||
/* The return value is the number of bytes packed in to o, which is internally limited to 140 */
|
||||
/* o can be null, in which case this is used to validate or count only */
|
||||
/* if the input contains invalid characters then the return value is -1 */
|
||||
@@ -362,7 +366,7 @@ static int packsms8 (unsigned char *o, int udhl, unsigned char *udh, int udl, un
|
||||
return p;
|
||||
}
|
||||
|
||||
/*! \brief takes a binary header (udhl bytes at udh) and UCS-2
|
||||
/*--- packsms16: takes a binary header (udhl bytes at udh) and UCS-2
|
||||
message (udl characters at ud) and packs in to o using 16 bit
|
||||
UCS-2 character codes
|
||||
The return value is the number of bytes packed in to o, which is
|
||||
@@ -399,7 +403,7 @@ static int packsms16 (unsigned char *o, int udhl, unsigned char *udh, int udl, u
|
||||
return p;
|
||||
}
|
||||
|
||||
/*! \brief general pack, with length and data,
|
||||
/*--- packsms: general pack, with length and data,
|
||||
returns number of bytes of target used */
|
||||
static int packsms (unsigned char dcs, unsigned char *base, unsigned int udhl, unsigned char *udh, int udl, unsigned short *ud)
|
||||
{
|
||||
@@ -431,7 +435,7 @@ static int packsms (unsigned char dcs, unsigned char *base, unsigned int udhl, u
|
||||
}
|
||||
|
||||
|
||||
/*! \brief pack a date and return */
|
||||
/*--- packdate: pack a date and return */
|
||||
static void packdate (unsigned char *o, time_t w)
|
||||
{
|
||||
struct tm *t = localtime (&w);
|
||||
@@ -452,7 +456,7 @@ static void packdate (unsigned char *o, time_t w)
|
||||
*o++ = ((z % 10) << 4) + z / 10;
|
||||
}
|
||||
|
||||
/*! \brief unpack a date and return */
|
||||
/*--- unpackdate: unpack a date and return */
|
||||
static time_t unpackdate (unsigned char *i)
|
||||
{
|
||||
struct tm t;
|
||||
@@ -470,7 +474,7 @@ static time_t unpackdate (unsigned char *i)
|
||||
return mktime (&t);
|
||||
}
|
||||
|
||||
/*! \brief unpacks bytes (7 bit encoding) at i, len l septets,
|
||||
/*--- unpacksms7: unpacks bytes (7 bit encoding) at i, len l septets,
|
||||
and places in udh and ud setting udhl and udl. udh not used
|
||||
if udhi not set */
|
||||
static void unpacksms7 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
|
||||
@@ -521,7 +525,7 @@ static void unpacksms7 (unsigned char *i, unsigned char l, unsigned char *udh, i
|
||||
*udl = (o - ud);
|
||||
}
|
||||
|
||||
/*! \brief unpacks bytes (8 bit encoding) at i, len l septets,
|
||||
/*--- unpacksms8: unpacks bytes (8 bit encoding) at i, len l septets,
|
||||
and places in udh and ud setting udhl and udl. udh not used
|
||||
if udhi not set */
|
||||
static void unpacksms8 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
|
||||
@@ -546,7 +550,7 @@ static void unpacksms8 (unsigned char *i, unsigned char l, unsigned char *udh, i
|
||||
*udl = (o - ud);
|
||||
}
|
||||
|
||||
/*! \brief unpacks bytes (16 bit encoding) at i, len l septets,
|
||||
/*--- unpacksms16: unpacks bytes (16 bit encoding) at i, len l septets,
|
||||
and places in udh and ud setting udhl and udl.
|
||||
udh not used if udhi not set */
|
||||
static void unpacksms16 (unsigned char *i, unsigned char l, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
|
||||
@@ -575,7 +579,7 @@ static void unpacksms16 (unsigned char *i, unsigned char l, unsigned char *udh,
|
||||
*udl = (o - ud);
|
||||
}
|
||||
|
||||
/*! \brief general unpack - starts with length byte (octet or septet) and returns number of bytes used, inc length */
|
||||
/*--- unpacksms: general unpack - starts with length byte (octet or septet) and returns number of bytes used, inc length */
|
||||
static int unpacksms (unsigned char dcs, unsigned char *i, unsigned char *udh, int *udhl, unsigned short *ud, int *udl, char udhi)
|
||||
{
|
||||
int l = *i++;
|
||||
@@ -589,7 +593,7 @@ static int unpacksms (unsigned char dcs, unsigned char *i, unsigned char *udh, i
|
||||
return l + 1;
|
||||
}
|
||||
|
||||
/*! \brief unpack an address from i, return byte length, unpack to o */
|
||||
/*--- unpackaddress: unpack an address from i, return byte length, unpack to o */
|
||||
static unsigned char unpackaddress (char *o, unsigned char *i)
|
||||
{
|
||||
unsigned char l = i[0],
|
||||
@@ -606,7 +610,7 @@ static unsigned char unpackaddress (char *o, unsigned char *i)
|
||||
return (l + 5) / 2;
|
||||
}
|
||||
|
||||
/*! \brief store an address at o, and return number of bytes used */
|
||||
/*--- packaddress: store an address at o, and return number of bytes used */
|
||||
static unsigned char packaddress (unsigned char *o, char *i)
|
||||
{
|
||||
unsigned char p = 2;
|
||||
@@ -631,7 +635,7 @@ static unsigned char packaddress (unsigned char *o, char *i)
|
||||
return p;
|
||||
}
|
||||
|
||||
/*! \brief Log the output, and remove file */
|
||||
/*--- sms_log: Log the output, and remove file */
|
||||
static void sms_log (sms_t * h, char status)
|
||||
{
|
||||
if (*h->oa || *h->da) {
|
||||
@@ -669,7 +673,7 @@ static void sms_log (sms_t * h, char status)
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief parse and delete a file */
|
||||
/*--- sms_readfile: parse and delete a file */
|
||||
static void sms_readfile (sms_t * h, char *fn)
|
||||
{
|
||||
char line[1000];
|
||||
@@ -690,8 +694,7 @@ static void sms_readfile (sms_t * h, char *fn)
|
||||
}
|
||||
while (fgets (line, sizeof (line), s))
|
||||
{ /* process line in file */
|
||||
char *p;
|
||||
void *pp = &p;
|
||||
unsigned char *p;
|
||||
for (p = line; *p && *p != '\n' && *p != '\r'; p++);
|
||||
*p = 0; /* strip eoln */
|
||||
p = line;
|
||||
@@ -711,7 +714,7 @@ static void sms_readfile (sms_t * h, char *fn)
|
||||
{ /* parse message (UTF-8) */
|
||||
unsigned char o = 0;
|
||||
while (*p && o < SMSLEN)
|
||||
h->ud[o++] = utf8decode(pp);
|
||||
h->ud[o++] = utf8decode((unsigned char **)&p);
|
||||
h->udl = o;
|
||||
if (*p)
|
||||
ast_log (LOG_WARNING, "UD too long in %s\n", fn);
|
||||
@@ -745,7 +748,7 @@ static void sms_readfile (sms_t * h, char *fn)
|
||||
H,
|
||||
M,
|
||||
S;
|
||||
if (sscanf (p, "%d-%d-%dT%d:%d:%d", &Y, &m, &d, &H, &M, &S) == 6)
|
||||
if (sscanf (p, "%4d-%2d-%2dT%2d:%2d:%2d", &Y, &m, &d, &H, &M, &S) == 6)
|
||||
{
|
||||
struct tm t;
|
||||
t.tm_year = Y - 1900;
|
||||
@@ -852,7 +855,7 @@ static void sms_readfile (sms_t * h, char *fn)
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief white a received text message to a file */
|
||||
/*--- sms_writefile: white a received text message to a file */
|
||||
static void sms_writefile (sms_t * h)
|
||||
{
|
||||
char fn[200] = "", fn2[200] = "";
|
||||
@@ -939,7 +942,7 @@ static void sms_writefile (sms_t * h)
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief read dir skipping dot files... */
|
||||
/*--- readdirqueue: read dir skipping dot files... */
|
||||
static struct dirent *readdirqueue (DIR * d, char *queue)
|
||||
{
|
||||
struct dirent *f;
|
||||
@@ -949,7 +952,7 @@ static struct dirent *readdirqueue (DIR * d, char *queue)
|
||||
return f;
|
||||
}
|
||||
|
||||
/*! \brief handle the incoming message */
|
||||
/*--- sms_handleincoming: handle the incoming message */
|
||||
static unsigned char sms_handleincoming (sms_t * h)
|
||||
{
|
||||
unsigned char p = 3;
|
||||
@@ -1020,7 +1023,8 @@ static unsigned char sms_handleincoming (sms_t * h)
|
||||
#define NAME_MAX 1024
|
||||
#endif
|
||||
|
||||
/*! \brief find and fill in next message, or send a REL if none waiting */
|
||||
/*--- sms_nextoutgoing: find and fill in next message,
|
||||
or send a REL if none waiting */
|
||||
static void sms_nextoutgoing (sms_t * h)
|
||||
{
|
||||
char fn[100 + NAME_MAX] = "";
|
||||
@@ -1174,7 +1178,7 @@ static void sms_messagetx(sms_t * h)
|
||||
static int sms_generate (struct ast_channel *chan, void *data, int len, int samples)
|
||||
{
|
||||
struct ast_frame f = { 0 };
|
||||
#define MAXSAMPLES (800)
|
||||
#define MAXSAMPLES 800
|
||||
#ifdef OUTALAW
|
||||
unsigned char *buf;
|
||||
#else
|
||||
@@ -1195,10 +1199,11 @@ static int sms_generate (struct ast_channel *chan, void *data, int len, int samp
|
||||
f.frametype = AST_FRAME_VOICE;
|
||||
#ifdef OUTALAW
|
||||
f.subclass = AST_FORMAT_ALAW;
|
||||
f.datalen = samples;
|
||||
#else
|
||||
f.subclass = AST_FORMAT_SLINEAR;
|
||||
f.datalen = samples * 2;
|
||||
#endif
|
||||
f.datalen = samples * SAMPLE2LEN;
|
||||
f.offset = AST_FRIENDLY_OFFSET;
|
||||
f.mallocd = 0;
|
||||
f.data = buf;
|
||||
@@ -1250,8 +1255,6 @@ static int sms_generate (struct ast_channel *chan, void *data, int len, int samp
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#undef SAMPLE2LEN
|
||||
#undef MAXSAMPLES
|
||||
}
|
||||
|
||||
static void sms_process (sms_t * h, int samples, signed short *data)
|
||||
@@ -1357,17 +1360,17 @@ static struct ast_generator smsgen = {
|
||||
static int sms_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = -1;
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
struct ast_frame *f;
|
||||
sms_t h = { 0 };
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
h.ipc0 = h.ipc1 = 20; /* phase for cosine */
|
||||
h.dcs = 0xF1; /* default */
|
||||
if (!data) {
|
||||
ast_log (LOG_ERROR, "Requires queue name at least\n");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1380,20 +1383,20 @@ static int sms_exec (struct ast_channel *chan, void *data)
|
||||
answer = 0;
|
||||
if (!*d || *d == '|') {
|
||||
ast_log (LOG_ERROR, "Requires queue name\n");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
for (p = d; *p && *p != '|'; p++);
|
||||
if (p - d >= sizeof (h.queue)) {
|
||||
ast_log (LOG_ERROR, "Queue name too long\n");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
strncpy(h.queue, (char *)d, p - d);
|
||||
strncpy (h.queue, d, p - d);
|
||||
if (*p == '|')
|
||||
p++;
|
||||
d = p;
|
||||
for (p = (unsigned char *)h.queue; *p; p++)
|
||||
for (p = h.queue; *p; p++)
|
||||
if (!isalnum (*p))
|
||||
*p = '-'; /* make very safe for filenames */
|
||||
while (*d && *d != '|') {
|
||||
@@ -1425,20 +1428,20 @@ static int sms_exec (struct ast_channel *chan, void *data)
|
||||
}
|
||||
if (*d == '|') {
|
||||
/* submitting a message, not taking call. */
|
||||
/* deprecated, use smsq instead */
|
||||
/* depricated, use smsq instead */
|
||||
d++;
|
||||
h.scts = time (0);
|
||||
for (p = d; *p && *p != '|'; p++);
|
||||
if (*p)
|
||||
*p++ = 0;
|
||||
if (strlen ((char *)d) >= sizeof (h.oa)) {
|
||||
if (strlen (d) >= sizeof (h.oa)) {
|
||||
ast_log (LOG_ERROR, "Address too long %s\n", d);
|
||||
return 0;
|
||||
}
|
||||
if (h.smsc) {
|
||||
ast_copy_string (h.oa, (char *)d, sizeof (h.oa));
|
||||
ast_copy_string (h.oa, d, sizeof (h.oa));
|
||||
} else {
|
||||
ast_copy_string (h.da, (char *)d, sizeof (h.da));
|
||||
ast_copy_string (h.da, d, sizeof (h.da));
|
||||
}
|
||||
if (!h.smsc)
|
||||
ast_copy_string (h.oa, h.cli, sizeof (h.oa));
|
||||
@@ -1455,7 +1458,7 @@ static int sms_exec (struct ast_channel *chan, void *data)
|
||||
h.rx = 0; /* sent message */
|
||||
h.mr = -1;
|
||||
sms_writefile (&h);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1479,13 +1482,13 @@ static int sms_exec (struct ast_channel *chan, void *data)
|
||||
res = ast_set_read_format (chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
ast_log (LOG_ERROR, "Unable to set to linear mode, giving up\n");
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE (u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ast_activate_generator (chan, &smsgen, &h) < 0) {
|
||||
ast_log (LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name);
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE (u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1504,22 +1507,22 @@ static int sms_exec (struct ast_channel *chan, void *data)
|
||||
|
||||
sms_log (&h, '?'); /* log incomplete message */
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE (u);
|
||||
return (h.err);
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module (void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application (app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
int load_module (void)
|
||||
{
|
||||
#ifdef OUTALAW
|
||||
{
|
||||
@@ -1533,4 +1536,19 @@ static int load_module(void)
|
||||
return ast_register_application (app, sms_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SMS/PSTN handler");
|
||||
char *description (void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount (void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT (res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key ()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
@@ -19,22 +19,20 @@
|
||||
/*! \file
|
||||
*
|
||||
* \brief SoftHangup application
|
||||
*
|
||||
* \author Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* \ingroup applications
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#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"
|
||||
@@ -44,6 +42,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
static char *synopsis = "Soft Hangup Application";
|
||||
|
||||
static char *tdesc = "Hangs up the requested channel";
|
||||
|
||||
static char *desc = " SoftHangup(Technology/resource|options)\n"
|
||||
"Hangs up the requested channel. If there are no channels to hangup,\n"
|
||||
"the application will report it.\n"
|
||||
@@ -52,10 +52,13 @@ static char *desc = " SoftHangup(Technology/resource|options)\n"
|
||||
|
||||
static char *app = "SoftHangup";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int softhangup_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct ast_module_user *u;
|
||||
struct localuser *u;
|
||||
struct ast_channel *c=NULL;
|
||||
char *options, *cut, *cdata, *match;
|
||||
char name[AST_CHANNEL_NAME] = "";
|
||||
@@ -66,7 +69,7 @@ static int softhangup_exec(struct ast_channel *chan, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
u = ast_module_user_add(chan);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
cdata = ast_strdupa(data);
|
||||
match = strsep(&cdata, "|");
|
||||
@@ -74,12 +77,12 @@ static int softhangup_exec(struct ast_channel *chan, void *data)
|
||||
all = options && strchr(options,'a');
|
||||
c = ast_channel_walk_locked(NULL);
|
||||
while (c) {
|
||||
ast_copy_string(name, c->name, sizeof(name));
|
||||
strncpy(name, c->name, sizeof(name)-1);
|
||||
ast_mutex_unlock(&c->lock);
|
||||
/* XXX watch out, i think it is wrong to access c-> after unlocking! */
|
||||
if (all) {
|
||||
/* CAPI is set up like CAPI[foo/bar]/clcnt */
|
||||
if (!strcmp(c->tech->type, "CAPI"))
|
||||
if (!strcmp(c->type,"CAPI"))
|
||||
cut = strrchr(name,'/');
|
||||
/* Basically everything else is Foo/Bar-Z */
|
||||
else
|
||||
@@ -97,25 +100,40 @@ static int softhangup_exec(struct ast_channel *chan, void *data)
|
||||
c = ast_channel_walk_locked(c);
|
||||
}
|
||||
|
||||
ast_module_user_remove(u);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = ast_unregister_application(app);
|
||||
|
||||
ast_module_user_hangup_all();
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, softhangup_exec, synopsis, desc);
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Hangs up the requested channel");
|
||||
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
Reference in New Issue
Block a user