mirror of
https://github.com/asterisk/asterisk.git
synced 2026-03-12 15:37:58 +00:00
Compare commits
2786 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c23e7645fd | ||
|
|
00d6d3233f | ||
|
|
a7bea083ee | ||
|
|
7c322a0d90 | ||
|
|
4c710cd189 | ||
|
|
1700f24dd3 | ||
|
|
aa2e435d82 | ||
|
|
2fc5fed79e | ||
|
|
efd42d2d5c | ||
|
|
2ff6a84a16 | ||
|
|
01c0938ddf | ||
|
|
fda8fa2367 | ||
|
|
998ef5948c | ||
|
|
cbc39f7d71 | ||
|
|
802a44a15b | ||
|
|
efbb88225c | ||
|
|
30d264ebda | ||
|
|
bf4ca23372 | ||
|
|
9ecfd9f33e | ||
|
|
255ce93616 | ||
|
|
4ffa6c246f | ||
|
|
a9db074776 | ||
|
|
7b10240bc3 | ||
|
|
9812bcc03c | ||
|
|
fb6e840213 | ||
|
|
2a896e5d3c | ||
|
|
ab67420c37 | ||
|
|
07a6cd4592 | ||
|
|
762cd4621d | ||
|
|
a23534c4e2 | ||
|
|
1597114535 | ||
|
|
aea667c7c8 | ||
|
|
e0f335a4eb | ||
|
|
78531a0f32 | ||
|
|
a2297d6776 | ||
|
|
ef889d6672 | ||
|
|
291ce3e839 | ||
|
|
42806dc1ac | ||
|
|
45a157ec0e | ||
|
|
49389bd690 | ||
|
|
a638a19ea2 | ||
|
|
199ec4356a | ||
|
|
5dad6f4319 | ||
|
|
27e4a2ee57 | ||
|
|
d7fb7e9ed7 | ||
|
|
528cf89739 | ||
|
|
b96abb803c | ||
|
|
574d3785ab | ||
|
|
d1be79cce2 | ||
|
|
9d8c71ee86 | ||
|
|
877f1f64c2 | ||
|
|
a9f5393bfe | ||
|
|
038cd054ae | ||
|
|
e228c88d2a | ||
|
|
4824ee8b20 | ||
|
|
0da1f7593d | ||
|
|
8fae88d368 | ||
|
|
5c32080a0c | ||
|
|
610d52b054 | ||
|
|
0aa4c95a89 | ||
|
|
d2385517ac | ||
|
|
3fc2609468 | ||
|
|
0eec8c8318 | ||
|
|
bdc00dae0e | ||
|
|
a1442538b5 | ||
|
|
ce68497243 | ||
|
|
9a387e5a7a | ||
|
|
c4aa1dadbd | ||
|
|
556f27ecf1 | ||
|
|
ef2cd744cf | ||
|
|
f5b1c6c27e | ||
|
|
5f93d06cf8 | ||
|
|
952a5e6dd9 | ||
|
|
238b9d24c6 | ||
|
|
7457c51bc2 | ||
|
|
a4437b1362 | ||
|
|
45b91a90e1 | ||
|
|
3cb1d7843b | ||
|
|
4d6b943ea4 | ||
|
|
d8aff59a9e | ||
|
|
e9dbd238c8 | ||
|
|
89447a99ec | ||
|
|
e499028440 | ||
|
|
2f82498995 | ||
|
|
71df4d92da | ||
|
|
ac1e884328 | ||
|
|
e31d4ee777 | ||
|
|
cc30079edd | ||
|
|
b76252d68e | ||
|
|
ce868ed5f5 | ||
|
|
8283811633 | ||
|
|
00f227a684 | ||
|
|
a6e748e491 | ||
|
|
8a12240f73 | ||
|
|
815318b12f | ||
|
|
5e0b84633e | ||
|
|
aa2a8ed77c | ||
|
|
9e96cb612b | ||
|
|
f54c287c73 | ||
|
|
14e1fe4795 | ||
|
|
81df8343d3 | ||
|
|
388ca07547 | ||
|
|
b3fdacf9cc | ||
|
|
cb896da998 | ||
|
|
879c401544 | ||
|
|
c6025e41c6 | ||
|
|
52647db120 | ||
|
|
5adfdcba1e | ||
|
|
550e8e56ba | ||
|
|
8d457d07c4 | ||
|
|
b3333ebc2e | ||
|
|
3454b5927f | ||
|
|
54e81f5ca0 | ||
|
|
c1e14143fa | ||
|
|
97904aee06 | ||
|
|
24e902d2a4 | ||
|
|
0da197d593 | ||
|
|
6b2e3f29f9 | ||
|
|
64b9a563f2 | ||
|
|
a703e927b1 | ||
|
|
8d0d386970 | ||
|
|
dc542971df | ||
|
|
8fb1ddeb5d | ||
|
|
e94fa076cb | ||
|
|
f83715ce9c | ||
|
|
b0970b9e33 | ||
|
|
f4b60a5c65 | ||
|
|
e7908a50e8 | ||
|
|
789c4f4587 | ||
|
|
19be63c4c3 | ||
|
|
04a9441769 | ||
|
|
a2da1f08bd | ||
|
|
eb57ea95d6 | ||
|
|
1e2db0e885 | ||
|
|
d77ae42896 | ||
|
|
2a2d65541b | ||
|
|
fd7577eed2 | ||
|
|
93818c761b | ||
|
|
bc72d7584a | ||
|
|
b813a5f3fa | ||
|
|
d952c7ed71 | ||
|
|
07166e63a3 | ||
|
|
9888487f9c | ||
|
|
3c7ab1ca5e | ||
|
|
08a8632ac7 | ||
|
|
4b2877834e | ||
|
|
344ec00439 | ||
|
|
082f628401 | ||
|
|
3cf360ae44 | ||
|
|
0c39d6de8e | ||
|
|
53262335c8 | ||
|
|
380b9a40a3 | ||
|
|
f6109b7b94 | ||
|
|
1db964ad95 | ||
|
|
416079db61 | ||
|
|
49ca05642a | ||
|
|
7d88098555 | ||
|
|
82db278716 | ||
|
|
cfb711bf57 | ||
|
|
471df8f512 | ||
|
|
9f1562a599 | ||
|
|
e2fe8ef485 | ||
|
|
4a19a2644f | ||
|
|
066a53df8a | ||
|
|
2a108b9b06 | ||
|
|
6749f1b8b5 | ||
|
|
8ff9c0d1b9 | ||
|
|
b48987922c | ||
|
|
5259155e52 | ||
|
|
2f753040ef | ||
|
|
bd7ca6bb69 | ||
|
|
0f88c702df | ||
|
|
28e5320ab4 | ||
|
|
47f8883942 | ||
|
|
4c133e47da | ||
|
|
0cf6b2ba31 | ||
|
|
7fffa6e20a | ||
|
|
ccdd86775f | ||
|
|
91d2e58d1b | ||
|
|
1327846518 | ||
|
|
11b1e81197 | ||
|
|
616780b64e | ||
|
|
90a497c3b8 | ||
|
|
de1d9a90dd | ||
|
|
516cd1ba8d | ||
|
|
c7541bd672 | ||
|
|
c3c13114fb | ||
|
|
2863202bed | ||
|
|
cab4557006 | ||
|
|
f1be7d7ffc | ||
|
|
c22fdb7232 | ||
|
|
bd1c5ac3cf | ||
|
|
fa814abe05 | ||
|
|
03cd30b746 | ||
|
|
7ede296efd | ||
|
|
264fead207 | ||
|
|
e5ad308a2b | ||
|
|
f31a210cb2 | ||
|
|
b27c9f26fe | ||
|
|
0ffa958fc4 | ||
|
|
e8483c021b | ||
|
|
5596c6a5da | ||
|
|
0a6f41cdf2 | ||
|
|
4219bdc2b4 | ||
|
|
fa9c265ce7 | ||
|
|
6d447004ea | ||
|
|
091c6c36b9 | ||
|
|
1f34a1dab4 | ||
|
|
ba55e8ae64 | ||
|
|
461596d9b1 | ||
|
|
0e3fc6a4fe | ||
|
|
6a589d5630 | ||
|
|
b8c18d6176 | ||
|
|
4210fd6ad9 | ||
|
|
1ddd0afe36 | ||
|
|
230d4b38a3 | ||
|
|
1afd98d916 | ||
|
|
60707a4172 | ||
|
|
f2dcfca9c4 | ||
|
|
d8436708c0 | ||
|
|
de3528f0be | ||
|
|
d0ab0358aa | ||
|
|
4f9f6df42c | ||
|
|
ed20af4517 | ||
|
|
3ca96a1317 | ||
|
|
3bcff2d2f9 | ||
|
|
3e85e4b82c | ||
|
|
299b26ae4a | ||
|
|
bbbbcaf73f | ||
|
|
37e789fd79 | ||
|
|
27f3c530ed | ||
|
|
534e44c599 | ||
|
|
1587fd6b84 | ||
|
|
ce51451ca6 | ||
|
|
3385ecc112 | ||
|
|
5d589eb866 | ||
|
|
039aad9ff4 | ||
|
|
a0b8879af4 | ||
|
|
e1c9ebc5b9 | ||
|
|
02ffc0eec8 | ||
|
|
a560227ccb | ||
|
|
87a7a3aaff | ||
|
|
6723ea3afb | ||
|
|
3ff53cd50b | ||
|
|
94f18868f1 | ||
|
|
e85d440f88 | ||
|
|
6910fd79f2 | ||
|
|
c14b405974 | ||
|
|
0125ed120f | ||
|
|
be2d39a1a5 | ||
|
|
cbe0264949 | ||
|
|
96e2c3a3aa | ||
|
|
7216081447 | ||
|
|
7acee329e1 | ||
|
|
916566ac11 | ||
|
|
785eaf01b3 | ||
|
|
ccbc7a6835 | ||
|
|
6193bc31b8 | ||
|
|
698820f4e3 | ||
|
|
34e40a3a59 | ||
|
|
a21e295c96 | ||
|
|
082d7ee4b8 | ||
|
|
bdd9753f1e | ||
|
|
0df4b4eb64 | ||
|
|
2ee29be0e8 | ||
|
|
172a45d603 | ||
|
|
27d0ebc686 | ||
|
|
be02813c26 | ||
|
|
85a15b4fc9 | ||
|
|
c16542c1d0 | ||
|
|
1de05fb7da | ||
|
|
a2e82071c5 | ||
|
|
cfba600eab | ||
|
|
99f901f065 | ||
|
|
f074b92823 | ||
|
|
07f349766c | ||
|
|
892b06e282 | ||
|
|
f3522b6c01 | ||
|
|
437f625786 | ||
|
|
8b364485a0 | ||
|
|
345dff63e9 | ||
|
|
76913125d8 | ||
|
|
f195e423f4 | ||
|
|
5abc3ecb56 | ||
|
|
87787b05ae | ||
|
|
4f2b8f8e9a | ||
|
|
c8170cf360 | ||
|
|
358ff9f7d6 | ||
|
|
e094bf07dc | ||
|
|
05e338ce75 | ||
|
|
fbe6024753 | ||
|
|
4d3f4f719a | ||
|
|
b240128ed4 | ||
|
|
70b3ab34a8 | ||
|
|
27e3cd9ca8 | ||
|
|
13a45232fa | ||
|
|
c4bfcdeec5 | ||
|
|
cfcc58d96e | ||
|
|
096feeeddd | ||
|
|
2de01f7b7e | ||
|
|
0369242c4c | ||
|
|
a70d444333 | ||
|
|
79a00a33f9 | ||
|
|
c542576190 | ||
|
|
725c352e94 | ||
|
|
64e1166e6f | ||
|
|
57b6515d82 | ||
|
|
e786eae3cd | ||
|
|
a322c6f411 | ||
|
|
943133953e | ||
|
|
f6717c92b2 | ||
|
|
9b0b4bf041 | ||
|
|
183fb08ee6 | ||
|
|
760bc42049 | ||
|
|
3329f8154e | ||
|
|
b4f6d91eda | ||
|
|
0f93207cda | ||
|
|
43866cf0d9 | ||
|
|
deb02a000f | ||
|
|
baef4818d2 | ||
|
|
bf70a01da6 | ||
|
|
5733f64bdd | ||
|
|
a57ad69b53 | ||
|
|
7b52e19b6d | ||
|
|
728e55e697 | ||
|
|
71f41a06dc | ||
|
|
e90022767d | ||
|
|
a395d75a91 | ||
|
|
42837cde4c | ||
|
|
1394a78bd6 | ||
|
|
e4d4c93bd8 | ||
|
|
00f3bf560b | ||
|
|
5bd8cf6cde | ||
|
|
9e789de703 | ||
|
|
d1ad2a695d | ||
|
|
d0c1882cf7 | ||
|
|
0abd9ec096 | ||
|
|
25afd9876c | ||
|
|
eb718e597d | ||
|
|
1bfdd45fca | ||
|
|
d189993f15 | ||
|
|
6f5eb3b8fa | ||
|
|
4eedf0cd2e | ||
|
|
630ca201d6 | ||
|
|
bf17aa1eca | ||
|
|
5ed7dc3590 | ||
|
|
0fc1ef8c9d | ||
|
|
d89ed4ab5f | ||
|
|
0905b587cf | ||
|
|
35ffb12ae8 | ||
|
|
4dba976a7f | ||
|
|
d3499da6fd | ||
|
|
a1531e0ae3 | ||
|
|
7f234dbc4e | ||
|
|
1a3ec0536c | ||
|
|
832da92bdc | ||
|
|
e85731555d | ||
|
|
7ab67c9fba | ||
|
|
0afbb8bcbf | ||
|
|
bb75fcc4db | ||
|
|
0bb8d95674 | ||
|
|
405d0be9fe | ||
|
|
b5ad8c24be | ||
|
|
e252af2152 | ||
|
|
a59c1d2ac4 | ||
|
|
e49aae74d0 | ||
|
|
c87d1f6309 | ||
|
|
a23fa08274 | ||
|
|
24a5704798 | ||
|
|
d3397cd37d | ||
|
|
f8594ac304 | ||
|
|
ed42d3074d | ||
|
|
eb80683222 | ||
|
|
5808760bf4 | ||
|
|
404485711e | ||
|
|
daf76979ca | ||
|
|
73f91fcc44 | ||
|
|
8a4967294f | ||
|
|
dc60239686 | ||
|
|
b600cf2232 | ||
|
|
d9be9eb5a8 | ||
|
|
449bef5a36 | ||
|
|
b53507021e | ||
|
|
463444b391 | ||
|
|
a1cf0fbd43 | ||
|
|
2f2122875a | ||
|
|
569b95352a | ||
|
|
ab7cd94b60 | ||
|
|
57217916f1 | ||
|
|
de4188df06 | ||
|
|
f10148d3e3 | ||
|
|
b1e841edab | ||
|
|
68070c82d0 | ||
|
|
823f4559c9 | ||
|
|
f202a8dbb3 | ||
|
|
09c3679e2d | ||
|
|
6b8ecfa35f | ||
|
|
3abd26bfdf | ||
|
|
03b1d1ea8c | ||
|
|
b1d55878a7 | ||
|
|
d5c614397a | ||
|
|
eac29e9814 | ||
|
|
bba1faf910 | ||
|
|
78117423fa | ||
|
|
5de01235b6 | ||
|
|
e167cc89f8 | ||
|
|
05d3d9c25f | ||
|
|
957782627c | ||
|
|
6e9d4faf61 | ||
|
|
0a4a5483ae | ||
|
|
bab6f6bdf2 | ||
|
|
fa0ca01ffe | ||
|
|
044ad2e2e7 | ||
|
|
9cd917c42a | ||
|
|
1b9251ad14 | ||
|
|
2f1c9c690f | ||
|
|
0c6b76f7c2 | ||
|
|
2a9d43407b | ||
|
|
8ed49644a6 | ||
|
|
872685d088 | ||
|
|
4d32c46126 | ||
|
|
4290558ec0 | ||
|
|
9b08305eae | ||
|
|
f78179c374 | ||
|
|
e42c11905e | ||
|
|
3fdbac912a | ||
|
|
3ba284094e | ||
|
|
634521b59b | ||
|
|
423fd40090 | ||
|
|
058f20179b | ||
|
|
dd293ed6fe | ||
|
|
3c7300d145 | ||
|
|
fb3f2062fa | ||
|
|
9e0e3799bf | ||
|
|
f107562f75 | ||
|
|
602d616726 | ||
|
|
611da9b699 | ||
|
|
34ed331f82 | ||
|
|
7ca6f85a41 | ||
|
|
069d045513 | ||
|
|
7c97de2611 | ||
|
|
11ee0b6a41 | ||
|
|
a40e6c115f | ||
|
|
4113c814c7 | ||
|
|
8426e454de | ||
|
|
c5e44cc3cb | ||
|
|
c793ab62ff | ||
|
|
decd0771ee | ||
|
|
68dd66c46d | ||
|
|
568ba9c398 | ||
|
|
e3d12a2ab2 | ||
|
|
c4a633a87b | ||
|
|
b5780eda44 | ||
|
|
65fc87b245 | ||
|
|
12b3b6c86e | ||
|
|
8ebfe337a7 | ||
|
|
28076a9c68 | ||
|
|
851fce9568 | ||
|
|
91a7960ad5 | ||
|
|
216fd6e249 | ||
|
|
18844270c3 | ||
|
|
fd9b6d13e6 | ||
|
|
5fa70e63a0 | ||
|
|
432bb121f3 | ||
|
|
52549b25cd | ||
|
|
fba5172e8a | ||
|
|
155d84a979 | ||
|
|
a7d2842beb | ||
|
|
70c530630a | ||
|
|
a722b0462e | ||
|
|
f63d46097d | ||
|
|
75d4369dfc | ||
|
|
3697f7dbcc | ||
|
|
9de6aed36b | ||
|
|
2e5873cb5d | ||
|
|
d2f22c57fe | ||
|
|
b1d9a040d4 | ||
|
|
fb8ebe6365 | ||
|
|
201849fb42 | ||
|
|
8e2e53c987 | ||
|
|
bd7418b625 | ||
|
|
3cf3edb14f | ||
|
|
3e2806114b | ||
|
|
2f911dfba6 | ||
|
|
64439e0692 | ||
|
|
b94f5ca495 | ||
|
|
1f1c915fea | ||
|
|
7be9c6e469 | ||
|
|
60ad539878 | ||
|
|
9b32ff1eeb | ||
|
|
074f8d9378 | ||
|
|
4b5f53d6a0 | ||
|
|
34208f76a5 | ||
|
|
e7bd1ce7b9 | ||
|
|
a8d8221357 | ||
|
|
ee4a248e6b | ||
|
|
4d0dd2775a | ||
|
|
eb6b35b75f | ||
|
|
9a478cb855 | ||
|
|
457528ae86 | ||
|
|
733c167528 | ||
|
|
f97df161f4 | ||
|
|
5bb0c3786d | ||
|
|
6195ae7453 | ||
|
|
779140b94c | ||
|
|
196112076c | ||
|
|
30910d48bc | ||
|
|
408ead2dda | ||
|
|
baa46147a5 | ||
|
|
3d0e3d3c0f | ||
|
|
560068617a | ||
|
|
ef0128ec41 | ||
|
|
5fec7176e0 | ||
|
|
a11c4965b7 | ||
|
|
b283a02a7d | ||
|
|
09c41b415d | ||
|
|
9b6bd35ed3 | ||
|
|
eb9adf42d6 | ||
|
|
6f0a7f7a15 | ||
|
|
614d878b04 | ||
|
|
a9da004305 | ||
|
|
88eede5218 | ||
|
|
9127ab071b | ||
|
|
05110e85d3 | ||
|
|
ca75adf9cb | ||
|
|
54dcc9bf56 | ||
|
|
ca7fc00ad5 | ||
|
|
df2394af02 | ||
|
|
c3af8944af | ||
|
|
b140eef0aa | ||
|
|
88bcbb2368 | ||
|
|
d9ed36059c | ||
|
|
1af31f2c64 | ||
|
|
b76935b95c | ||
|
|
03fbf171a7 | ||
|
|
3db853b428 | ||
|
|
a30ae193db | ||
|
|
a466fdbc40 | ||
|
|
2fb8ad79c2 | ||
|
|
9ab74af94f | ||
|
|
c9f168ed0f | ||
|
|
dbea1448bd | ||
|
|
e6de64a5a9 | ||
|
|
fe4b2401bd | ||
|
|
d37b6dd459 | ||
|
|
0a059f8ce1 | ||
|
|
80c9620612 | ||
|
|
2f421a55da | ||
|
|
42ad569376 | ||
|
|
bdbed69984 | ||
|
|
1d473f25dd | ||
|
|
b0972b8d1f | ||
|
|
f6f67727c6 | ||
|
|
8ef1f1ea2e | ||
|
|
df93792f9c | ||
|
|
08ac005489 | ||
|
|
27bb1601d3 | ||
|
|
da49f53b66 | ||
|
|
e9f2a805b9 | ||
|
|
74fdefdf1e | ||
|
|
68248b91f0 | ||
|
|
6729301b4d | ||
|
|
5e36feac27 | ||
|
|
7a363d3d17 | ||
|
|
2187465cae | ||
|
|
0f6db9f939 | ||
|
|
a03db324dd | ||
|
|
3f9c34f415 | ||
|
|
024f486810 | ||
|
|
f5c18f62a1 | ||
|
|
8801247d76 | ||
|
|
45ee2978cd | ||
|
|
f5de717d6e | ||
|
|
5546e32355 | ||
|
|
2f4a0dc3f5 | ||
|
|
652e085d0f | ||
|
|
8b2b0278c9 | ||
|
|
e66aef0c05 | ||
|
|
9cb185e126 | ||
|
|
2bd13db091 | ||
|
|
551e3ad719 | ||
|
|
df4ea0cec4 | ||
|
|
3ccf8627e0 | ||
|
|
aa63104784 | ||
|
|
2efcb2e331 | ||
|
|
76fe489c86 | ||
|
|
ec3f9d5041 | ||
|
|
7b0160ee51 | ||
|
|
b0991ab170 | ||
|
|
8c4cacbd58 | ||
|
|
502e74e5db | ||
|
|
b168dcdddf | ||
|
|
585afa7e8e | ||
|
|
737e9b2458 | ||
|
|
2ee28d0ccf | ||
|
|
bbe5ff18c2 | ||
|
|
ef4d9eb5b7 | ||
|
|
491e5d941c | ||
|
|
b72227e845 | ||
|
|
70167380a3 | ||
|
|
347f32ab97 | ||
|
|
3b3a042cef | ||
|
|
a054fec8ef | ||
|
|
bc9e475d6e | ||
|
|
18fef6deb1 | ||
|
|
133120aa38 | ||
|
|
e32c8f1ebe | ||
|
|
19d5ae6e8d | ||
|
|
3932d756d4 | ||
|
|
f75a3079e0 | ||
|
|
d11177774a | ||
|
|
e5629ea138 | ||
|
|
4f72a1da77 | ||
|
|
095b971fc6 | ||
|
|
2d78f0d53c | ||
|
|
4a4e1e348d | ||
|
|
702b8a96b0 | ||
|
|
dd4aba8022 | ||
|
|
e3c58c8ebe | ||
|
|
fdf586e416 | ||
|
|
88aec64bce | ||
|
|
db8da3c376 | ||
|
|
7538cee13b | ||
|
|
be9d4b4333 | ||
|
|
b3b931fab9 | ||
|
|
8fa9d75365 | ||
|
|
1f4eadaf6a | ||
|
|
ada1e768c4 | ||
|
|
7255d8797c | ||
|
|
46303772e5 | ||
|
|
d0e532a070 | ||
|
|
6c9b510d5d | ||
|
|
dc7ceb7fd8 | ||
|
|
d88a461764 | ||
|
|
db8da85266 | ||
|
|
bc80b3130d | ||
|
|
001623fa0a | ||
|
|
c53e76528d | ||
|
|
ee664e6ccd | ||
|
|
427be16475 | ||
|
|
5b9cab6c13 | ||
|
|
f70b57352b | ||
|
|
bec994b037 | ||
|
|
3cf5ea7383 | ||
|
|
d208532e6e | ||
|
|
800ad7f727 | ||
|
|
fd70e7920e | ||
|
|
d030752f72 | ||
|
|
319011b0e3 | ||
|
|
9e3a90e249 | ||
|
|
439e5eeeb4 | ||
|
|
1b23fce2bd | ||
|
|
a3355d9fe2 | ||
|
|
c359ec8f5c | ||
|
|
31b39fe85e | ||
|
|
c51934cd70 | ||
|
|
481a59e92e | ||
|
|
1bc96b7aab | ||
|
|
bad7cc9c14 | ||
|
|
c96b39a960 | ||
|
|
758f246390 | ||
|
|
b1a658f57e | ||
|
|
8800bd6b1f | ||
|
|
a53d260d5f | ||
|
|
3ef099dede | ||
|
|
1794aac9e1 | ||
|
|
de57be6bbd | ||
|
|
a23c43cefa | ||
|
|
727abcdec7 | ||
|
|
c96046b6c2 | ||
|
|
f105351643 | ||
|
|
5ae7b48700 | ||
|
|
8c2bc79b77 | ||
|
|
d3fd49f2cf | ||
|
|
68c45465c8 | ||
|
|
ad49896f6b | ||
|
|
8995f5d810 | ||
|
|
22de310e04 | ||
|
|
9bd9958722 | ||
|
|
dff7c80952 | ||
|
|
a14ba4f1b5 | ||
|
|
994c0a5573 | ||
|
|
a9b5a6cbb0 | ||
|
|
8699103fa1 | ||
|
|
469c7d6de9 | ||
|
|
9c42fa75a4 | ||
|
|
0f2e75a257 | ||
|
|
e115566669 | ||
|
|
65d5921dde | ||
|
|
e325aa312f | ||
|
|
7b7dbfb855 | ||
|
|
cc36c3d475 | ||
|
|
a550016fd6 | ||
|
|
df9b7608a9 | ||
|
|
b9d81ae6ad | ||
|
|
32ecea7b8c | ||
|
|
746d2e7f67 | ||
|
|
27578642b8 | ||
|
|
63b280e97c | ||
|
|
0062fe9588 | ||
|
|
103bb4a334 | ||
|
|
aa2795cc46 | ||
|
|
269507ad59 | ||
|
|
ca0c646539 | ||
|
|
8cc1ffe2ab | ||
|
|
dc7e5f5f03 | ||
|
|
799b876aa0 | ||
|
|
8f5498177e | ||
|
|
8f9ace9228 | ||
|
|
5a9ab574de | ||
|
|
ea2b6241fd | ||
|
|
ea70485e7b | ||
|
|
37ae3cd701 | ||
|
|
b6beb440cd | ||
|
|
bc86e5de2a | ||
|
|
2587e6faa4 | ||
|
|
ce82bfa75a | ||
|
|
31e427d775 | ||
|
|
a435f135b5 | ||
|
|
36b87b3b33 | ||
|
|
8164972e34 | ||
|
|
49257bafbc | ||
|
|
9286f2c6d3 | ||
|
|
fdcf41cef0 | ||
|
|
66fae27e3a | ||
|
|
c66bf9a326 | ||
|
|
8968d50976 | ||
|
|
b0f9569b5c | ||
|
|
514acf8dfc | ||
|
|
89561c6a29 | ||
|
|
c47538a24b | ||
|
|
5ee4f3048c | ||
|
|
0f5ed60d51 | ||
|
|
5ef2ef8a1d | ||
|
|
d34639a601 | ||
|
|
bf2ec2d6d0 | ||
|
|
f30d55fbf6 | ||
|
|
8136198e53 | ||
|
|
fa9a8d158a | ||
|
|
cc698e15cf | ||
|
|
4926908616 | ||
|
|
a2cc6b01be | ||
|
|
63074875d6 | ||
|
|
04887bcc3e | ||
|
|
5b53760717 | ||
|
|
ff2ba012d2 | ||
|
|
e446f4ca81 | ||
|
|
4d1706d05f | ||
|
|
4f5ddbc374 | ||
|
|
96117402b1 | ||
|
|
2cd1eb39b1 | ||
|
|
03cb980dc2 | ||
|
|
b820fd0075 | ||
|
|
cf57ba2310 | ||
|
|
fc7593e594 | ||
|
|
54780434a6 | ||
|
|
ec14976ac3 | ||
|
|
fdb8ffe20d | ||
|
|
f7a7158f3f | ||
|
|
b4a2ee6104 | ||
|
|
728cceca7e | ||
|
|
7baf86bc8b | ||
|
|
9432a1c19f | ||
|
|
1b5d2d4667 | ||
|
|
682913a1f3 | ||
|
|
82b3a5f417 | ||
|
|
8f9e2b6633 | ||
|
|
8161efd26a | ||
|
|
1799dd3641 | ||
|
|
1147ed1e8c | ||
|
|
0f966565af | ||
|
|
2cc7d3e8db | ||
|
|
67b3ab9ee5 | ||
|
|
7dee677799 | ||
|
|
9dbb2ef08c | ||
|
|
0e1e513d5a | ||
|
|
588801931f | ||
|
|
e3ad88c784 | ||
|
|
af69f68359 | ||
|
|
3377298b06 | ||
|
|
15b86b3afb | ||
|
|
776497fb6b | ||
|
|
9082b027ef | ||
|
|
bbce72c316 | ||
|
|
d7ba067af6 | ||
|
|
1798abd909 | ||
|
|
4b5f7f0ef6 | ||
|
|
5273e43919 | ||
|
|
316bffd061 | ||
|
|
ba264f8158 | ||
|
|
cf24f7ff7e | ||
|
|
5e29d3a518 | ||
|
|
25ca4c854c | ||
|
|
50449d5c87 | ||
|
|
740243552f | ||
|
|
9f14461cb7 | ||
|
|
194fe2a4a5 | ||
|
|
e300367ad8 | ||
|
|
15b2f1f635 | ||
|
|
47133fda31 | ||
|
|
a0486afb83 | ||
|
|
ad67680ed3 | ||
|
|
93da37619a | ||
|
|
0284bc4b99 | ||
|
|
7f1117a71f | ||
|
|
0004e8a4be | ||
|
|
41c995dd18 | ||
|
|
89dbeddcfc | ||
|
|
6195dd35e0 | ||
|
|
e1b72cf020 | ||
|
|
b1462cd593 | ||
|
|
868fec3692 | ||
|
|
a105455487 | ||
|
|
0882f61a8e | ||
|
|
eff9477388 | ||
|
|
fc6a82fcb8 | ||
|
|
2bc871a62e | ||
|
|
61ce929656 | ||
|
|
67e1c59427 | ||
|
|
3f6896acd3 | ||
|
|
17aeeda774 | ||
|
|
143b73ee7b | ||
|
|
260fcde6e2 | ||
|
|
ce55c480e9 | ||
|
|
5738da5225 | ||
|
|
457f4caf6f | ||
|
|
34347418e3 | ||
|
|
5d9aa86efa | ||
|
|
ff5851c685 | ||
|
|
7976579ef6 | ||
|
|
36f888e06e | ||
|
|
a73524874c | ||
|
|
1c445d44c5 | ||
|
|
a54a0e5ecb | ||
|
|
e0ab451084 | ||
|
|
2310261cbe | ||
|
|
99876da380 | ||
|
|
76a22457ce | ||
|
|
e36ed02083 | ||
|
|
1f506e55d0 | ||
|
|
a80bce7e58 | ||
|
|
4b56cf02f0 | ||
|
|
668f8161ab | ||
|
|
d117f2258f | ||
|
|
1a81758f1c | ||
|
|
655bce9e1f | ||
|
|
9242c5c05e | ||
|
|
adc4fbe921 | ||
|
|
95ef751780 | ||
|
|
e2dd1cc3da | ||
|
|
2dfb2d723f | ||
|
|
1feaac6a54 | ||
|
|
4fc75f6559 | ||
|
|
e37c73ef97 | ||
|
|
3c50e18f46 | ||
|
|
ed443d08cf | ||
|
|
3794c9bfef | ||
|
|
1081dc05c2 | ||
|
|
72ca19339d | ||
|
|
83c46fb83e | ||
|
|
b8190d0e92 | ||
|
|
103034acf2 | ||
|
|
2742f2ca72 | ||
|
|
f222665d1d | ||
|
|
70007e6095 | ||
|
|
694c1c0c9c | ||
|
|
d146b72e53 | ||
|
|
4d1137ded4 | ||
|
|
2293ad0b1f | ||
|
|
f59f077d27 | ||
|
|
28c55ae8e3 | ||
|
|
7254cca9f3 | ||
|
|
50b637d1f9 | ||
|
|
023939d65f | ||
|
|
83a8b6745f | ||
|
|
baeb134536 | ||
|
|
c1b3b1d5b1 | ||
|
|
beae1fb946 | ||
|
|
6b0805633b | ||
|
|
c9d3a81c3a | ||
|
|
dbb7b83ecc | ||
|
|
ed01d3b366 | ||
|
|
88fa72f892 | ||
|
|
1aba1bbca4 | ||
|
|
10c25aa6d9 | ||
|
|
34e400fe2b | ||
|
|
a7818fb1be | ||
|
|
e753e1a460 | ||
|
|
fb80a4a397 | ||
|
|
964565519c | ||
|
|
960c01e4c6 | ||
|
|
87e3b8b2ad | ||
|
|
230eb50e96 | ||
|
|
1bc23d416c | ||
|
|
4b84c43811 | ||
|
|
22243ee9ae | ||
|
|
2d8c703fa0 | ||
|
|
6ead43beb1 | ||
|
|
62eef7c695 | ||
|
|
f2e0152108 | ||
|
|
25b07915d6 | ||
|
|
811f5cff35 | ||
|
|
c00550f3ae | ||
|
|
8ef3b1544b | ||
|
|
3e3642433b | ||
|
|
aff78a98cf | ||
|
|
d2a4408930 | ||
|
|
9740f51d00 | ||
|
|
812b527dd8 | ||
|
|
297e62b8be | ||
|
|
3189e70baa | ||
|
|
dca37d634e | ||
|
|
29718a5001 | ||
|
|
0ce20fea8a | ||
|
|
46b24e8a27 | ||
|
|
66b96f417c | ||
|
|
b974395573 | ||
|
|
1057e70da0 | ||
|
|
1d7c058f08 | ||
|
|
36911830dd | ||
|
|
2fbee61fff | ||
|
|
76adf66390 | ||
|
|
c94e23b2f6 | ||
|
|
28f4e820f7 | ||
|
|
6f9829fa5e | ||
|
|
6d280193d6 | ||
|
|
bb8d1dbb3a | ||
|
|
f1d0d949dc | ||
|
|
efc8c74b9a | ||
|
|
5f2dc3fe14 | ||
|
|
05a87a441c | ||
|
|
9c5c609de2 | ||
|
|
ab3c603b1c | ||
|
|
be1efdbf89 | ||
|
|
960f681dec | ||
|
|
995468ea0a | ||
|
|
ecbd983648 | ||
|
|
2bda857bf7 | ||
|
|
6f3dd86f22 | ||
|
|
cc1da2eb5b | ||
|
|
cc9ffa5ac1 | ||
|
|
9cc62f6461 | ||
|
|
6ac10272bc | ||
|
|
19a080ddd7 | ||
|
|
fdec9012eb | ||
|
|
67c11acbbf | ||
|
|
a5ad1269ef | ||
|
|
958668f001 | ||
|
|
5acaa777b8 | ||
|
|
9bb1b64d48 | ||
|
|
cf0659f7af | ||
|
|
e158ab2fe9 | ||
|
|
5098302f2f | ||
|
|
e8ed258aa4 | ||
|
|
b4a674e0ac | ||
|
|
d4c439c61d | ||
|
|
9c683b7423 | ||
|
|
ca2069a246 | ||
|
|
07a40f5141 | ||
|
|
3b3674807b | ||
|
|
bbaf536f6a | ||
|
|
b50ecc25b2 | ||
|
|
f2ccbc81d9 | ||
|
|
5537e1ad17 | ||
|
|
0e89f839e1 | ||
|
|
131a8c8f53 | ||
|
|
603511ea6f | ||
|
|
ded7dae112 | ||
|
|
8c05e4677e | ||
|
|
73b389da6c | ||
|
|
09eeb42315 | ||
|
|
e05b6242a5 | ||
|
|
c3c38eeeaf | ||
|
|
6cdbd6903c | ||
|
|
503dbb3d8a | ||
|
|
35ca4404f0 | ||
|
|
ee0532702a | ||
|
|
44de97d496 | ||
|
|
9d1e203b3d | ||
|
|
cb59df7bed | ||
|
|
70d5cd0210 | ||
|
|
3c134b6549 | ||
|
|
511816a56d | ||
|
|
3ad6ed3e92 | ||
|
|
9144ad4883 | ||
|
|
00c2c1b70e | ||
|
|
307168cc0f | ||
|
|
58a42e51e2 | ||
|
|
5b34d11ce9 | ||
|
|
1dbc8e3f0e | ||
|
|
3d775d9286 | ||
|
|
faaef0fbe3 | ||
|
|
ff7f09ecc7 | ||
|
|
0a457907fe | ||
|
|
73b62ab0f6 | ||
|
|
0122a3ea08 | ||
|
|
c432265ab7 | ||
|
|
b773853b03 | ||
|
|
3d16691c9e | ||
|
|
770796275d | ||
|
|
a717d81cea | ||
|
|
ec6644c146 | ||
|
|
93fd179b4c | ||
|
|
a3803a3c93 | ||
|
|
489656458f | ||
|
|
30e9661919 | ||
|
|
3e48f862a7 | ||
|
|
722f92e834 | ||
|
|
d106797a26 | ||
|
|
6f9df58afe | ||
|
|
66498eee0b | ||
|
|
1f21ca187a | ||
|
|
c7df3b4b22 | ||
|
|
da010f1600 | ||
|
|
709e526ad9 | ||
|
|
cd788e2ab9 | ||
|
|
01f39a3e51 | ||
|
|
1622c57f07 | ||
|
|
a46999cf0d | ||
|
|
b34020d5a6 | ||
|
|
4f51ef7ab7 | ||
|
|
ec8a80b070 | ||
|
|
5192a1a054 | ||
|
|
7e79c52808 | ||
|
|
314877e155 | ||
|
|
da8f6a9acf | ||
|
|
e5059cb891 | ||
|
|
ebba5fd9af | ||
|
|
e6b464ed23 | ||
|
|
33faf463a0 | ||
|
|
ceb572a280 | ||
|
|
8ace87616e | ||
|
|
ffe885b21f | ||
|
|
b18913b338 | ||
|
|
fd9d8ca43b | ||
|
|
882411586a | ||
|
|
90a331f7a5 | ||
|
|
478474bcb1 | ||
|
|
19064660d2 | ||
|
|
0fe6d16e89 | ||
|
|
7ca96ea7e5 | ||
|
|
5f71712b8b | ||
|
|
6cbc92b760 | ||
|
|
286d0656e2 | ||
|
|
f34b684e0e | ||
|
|
f9226cd9cd | ||
|
|
7596de9ac8 | ||
|
|
5385ca0a0e | ||
|
|
f4b55b802c | ||
|
|
0d048dee56 | ||
|
|
6726488e48 | ||
|
|
3b64c4830f | ||
|
|
add7cf7ded | ||
|
|
6b55f06a23 | ||
|
|
2b5a352840 | ||
|
|
2a3fc7b8ea | ||
|
|
1511750650 | ||
|
|
cce37f8d32 | ||
|
|
69f5623a03 | ||
|
|
7567113e71 | ||
|
|
9c13bd8884 | ||
|
|
30a7162bd9 | ||
|
|
f85d0713cf | ||
|
|
64c9e859e0 | ||
|
|
ed360fcf57 | ||
|
|
c924d1a322 | ||
|
|
ce44c6ec41 | ||
|
|
459fda5e44 | ||
|
|
435e55958f | ||
|
|
0eca3cf384 | ||
|
|
b9604cde6c | ||
|
|
470f226d9d | ||
|
|
8a411edf9f | ||
|
|
243a3df832 | ||
|
|
90778ada6d | ||
|
|
7bf0c1bc45 | ||
|
|
f9aef7098f | ||
|
|
ba078042ba | ||
|
|
3534419f14 | ||
|
|
025ae183eb | ||
|
|
6534f4d668 | ||
|
|
0d9adb7294 | ||
|
|
d851db3cee | ||
|
|
a640df56e6 | ||
|
|
17563e2929 | ||
|
|
12bcd39583 | ||
|
|
e30e0c5135 | ||
|
|
d3f9887589 | ||
|
|
ca493a14e1 | ||
|
|
250c1d2068 | ||
|
|
65c3fe8b33 | ||
|
|
fe9255a816 | ||
|
|
0f3f7eee9a | ||
|
|
22411494aa | ||
|
|
fcf07fce61 | ||
|
|
87e84064d2 | ||
|
|
0134d2cc85 | ||
|
|
c984a64f3e | ||
|
|
f864caba2f | ||
|
|
0709926b82 | ||
|
|
8f86c8409d | ||
|
|
ef89a2709a | ||
|
|
c96b093a58 | ||
|
|
b54d2b2c38 | ||
|
|
50edb67fc4 | ||
|
|
776a66f5db | ||
|
|
8a7f4bcd7a | ||
|
|
8e0f9147b2 | ||
|
|
a84bb950fa | ||
|
|
e9ea9975de | ||
|
|
7a8ec5bea4 | ||
|
|
98533cbccc | ||
|
|
36a13f931a | ||
|
|
295ce9fc8d | ||
|
|
e7f819bed1 | ||
|
|
34e415222e | ||
|
|
d8a6763be4 | ||
|
|
2d232c4c57 | ||
|
|
1487d749fe | ||
|
|
74de37e81e | ||
|
|
ec6d3b535a | ||
|
|
698b0b090b | ||
|
|
a3d9d7b58b | ||
|
|
de51a91db3 | ||
|
|
97dd838cda | ||
|
|
02287658f7 | ||
|
|
083d9c8039 | ||
|
|
5ebb0b8c15 | ||
|
|
64d509a931 | ||
|
|
9cb2272494 | ||
|
|
d3f45d14b3 | ||
|
|
7ed519ba84 | ||
|
|
c512310934 | ||
|
|
e15b5a83d5 | ||
|
|
fec02c20a9 | ||
|
|
63702b9a78 | ||
|
|
a8fb88516a | ||
|
|
694cacc93d | ||
|
|
d2019972f7 | ||
|
|
f2ee5d3a80 | ||
|
|
43d7359221 | ||
|
|
ae07b8ee83 | ||
|
|
fcf76b36aa | ||
|
|
639438836b | ||
|
|
cbd5a0e6bb | ||
|
|
9cb145c44c | ||
|
|
4d7386fc5f | ||
|
|
8f591d1b71 | ||
|
|
e9c65d0c08 | ||
|
|
1b2dc7ef75 | ||
|
|
0f2bcccaba | ||
|
|
6cde9d87a3 | ||
|
|
61ff225f1d | ||
|
|
50edc08001 | ||
|
|
0b2a9dc297 | ||
|
|
f7b250f963 | ||
|
|
78641613c7 | ||
|
|
42034844dc | ||
|
|
d45addcc7a | ||
|
|
df9089d3f8 | ||
|
|
6938bb6109 | ||
|
|
5a2c606d94 | ||
|
|
a3d396b11b | ||
|
|
a1ffc320e4 | ||
|
|
512583709a | ||
|
|
13bca43aa8 | ||
|
|
d0037ea2fd | ||
|
|
6b09ce4336 | ||
|
|
584936aa9b | ||
|
|
672e3e49fb | ||
|
|
1d8f780f45 | ||
|
|
d3bcf405c2 | ||
|
|
426bf55df2 | ||
|
|
1bbf0d2cf6 | ||
|
|
8cfed866d3 | ||
|
|
852422f4ab | ||
|
|
528c513602 | ||
|
|
1cf4ea2eb3 | ||
|
|
70dfab8be0 | ||
|
|
f897350521 | ||
|
|
b5da1073b0 | ||
|
|
dc383a7ee7 | ||
|
|
09e0fc2074 | ||
|
|
940a5deb2e | ||
|
|
aacc5e108b | ||
|
|
1cf0d5ad9d | ||
|
|
9f726fce46 | ||
|
|
d051e2da43 | ||
|
|
94279f00c1 | ||
|
|
ef1f39d29e | ||
|
|
9c7ffa265e | ||
|
|
9cc3adbdd9 | ||
|
|
d42f7886ab | ||
|
|
e2b0f32c18 | ||
|
|
52f13283ea | ||
|
|
7d2624dd3c | ||
|
|
7ae1d61120 | ||
|
|
39c9375eef | ||
|
|
cdb1b1dba3 | ||
|
|
3d61f5f20e | ||
|
|
59859d8cc2 | ||
|
|
b285cd40b2 | ||
|
|
3415434e04 | ||
|
|
36a8fb3e4d | ||
|
|
a925c1b306 | ||
|
|
7f6b9ccb5b | ||
|
|
3cedced29a | ||
|
|
1d53342b18 | ||
|
|
1e87c2aa48 | ||
|
|
fbc5be2426 | ||
|
|
4b02c78aaa | ||
|
|
71e80e5f62 | ||
|
|
8b5bbe4673 | ||
|
|
c89cbd916d | ||
|
|
3c70509e9b | ||
|
|
e1112c64c9 | ||
|
|
8dec8d3632 | ||
|
|
722babe8d1 | ||
|
|
3e9c337946 | ||
|
|
2c0d0d836c | ||
|
|
dbbf64fdd4 | ||
|
|
1ccab64d86 | ||
|
|
4b234476bb | ||
|
|
6ce8fc0b15 | ||
|
|
9fca20acc1 | ||
|
|
eeb2ca5b26 | ||
|
|
4b4c55e328 | ||
|
|
3ee43dd572 | ||
|
|
a222dbe8c7 | ||
|
|
2ff5d7de53 | ||
|
|
c6aaaf438e | ||
|
|
fb0af47761 | ||
|
|
211afe3a4b | ||
|
|
ea1c68b666 | ||
|
|
82bf2663e3 | ||
|
|
638684636c | ||
|
|
3ec7218ffb | ||
|
|
96c7fb890e | ||
|
|
efd7427f33 | ||
|
|
b43c1f054b | ||
|
|
f8b04c4bb6 | ||
|
|
bb8b00dad8 | ||
|
|
8279f0eac5 | ||
|
|
61d1fd9a0e | ||
|
|
4f72330f5c | ||
|
|
3b6c8b3f77 | ||
|
|
a05ef35ca8 | ||
|
|
359430871f | ||
|
|
747a18f65d | ||
|
|
598d7963e5 | ||
|
|
484484ce89 | ||
|
|
6e15f28d6a | ||
|
|
b5d452b1c7 | ||
|
|
b46d67e301 | ||
|
|
3107d6d03b | ||
|
|
67af82457e | ||
|
|
2a16a0a30c | ||
|
|
b19cb95257 | ||
|
|
dc41c40eba | ||
|
|
71eafcf3da | ||
|
|
7555e69cdc | ||
|
|
284a5b3465 | ||
|
|
25d74e0334 | ||
|
|
c1c704c042 | ||
|
|
3f5277d57b | ||
|
|
98b59da9ad | ||
|
|
a8bbe997d2 | ||
|
|
893ed27f5b | ||
|
|
97c5b2b7d7 | ||
|
|
730ca5f9b1 | ||
|
|
7c35f68e29 | ||
|
|
79668f0624 | ||
|
|
4ba3ced42f | ||
|
|
21d31939d1 | ||
|
|
68e767078f | ||
|
|
ff9621e279 | ||
|
|
de20d2a179 | ||
|
|
6fb5ebfedb | ||
|
|
7132570353 | ||
|
|
92f6d077fd | ||
|
|
1498cc552f | ||
|
|
32bde5b009 | ||
|
|
af6016cfd0 | ||
|
|
f3d440a16f | ||
|
|
47b6495e9b | ||
|
|
7192fbfae7 | ||
|
|
be59053650 | ||
|
|
c36ec4f9d7 | ||
|
|
5191a04055 | ||
|
|
9ef542b3cb | ||
|
|
2414aeb4dd | ||
|
|
cd8bc46a15 | ||
|
|
b79b6aba5d | ||
|
|
fa308aa83b | ||
|
|
b90a103e22 | ||
|
|
0ddcb1f666 | ||
|
|
785ac43c84 | ||
|
|
7075b58ee1 | ||
|
|
a386f01a7c | ||
|
|
ce9e964c5f | ||
|
|
2524d2c413 | ||
|
|
687b0ebe6e | ||
|
|
8c232e1dbb | ||
|
|
bc2a510fb7 | ||
|
|
130c64e5d9 | ||
|
|
264bfb7121 | ||
|
|
d3b2cb19e4 | ||
|
|
e7ecf6accb | ||
|
|
4c06525432 | ||
|
|
bf5d593e71 | ||
|
|
29b7818ebf | ||
|
|
ce88c6dd08 | ||
|
|
1b05e77127 | ||
|
|
726d3cba43 | ||
|
|
b690dc13aa | ||
|
|
b0d28cedf7 | ||
|
|
b3f94c4c00 | ||
|
|
0753ca66ab | ||
|
|
e02fae664a | ||
|
|
2a75bbb711 | ||
|
|
9223055df1 | ||
|
|
4b0d26c93d | ||
|
|
0e90480d6b | ||
|
|
c30ff0935d | ||
|
|
200ae67551 | ||
|
|
89c55fe46c | ||
|
|
f997f9f139 | ||
|
|
0852f5a930 | ||
|
|
9e83daa3bb | ||
|
|
ea92b714f2 | ||
|
|
aa2bdcc078 | ||
|
|
7989800674 | ||
|
|
9d8952f3a8 | ||
|
|
51f004494a | ||
|
|
044aa4fa60 | ||
|
|
17e2416f68 | ||
|
|
8750f1c05f | ||
|
|
afab3c4151 | ||
|
|
3a2f0750cb | ||
|
|
4efa995ae1 | ||
|
|
f1330f7efd | ||
|
|
1e8ea5eece | ||
|
|
12a8e15227 | ||
|
|
a082f8d8c7 | ||
|
|
39c60235f8 | ||
|
|
f12928f700 | ||
|
|
8812409528 | ||
|
|
6406e07a79 | ||
|
|
6741234ec9 | ||
|
|
c0ef6a5d1b | ||
|
|
18b3da6bab | ||
|
|
fac46c078a | ||
|
|
21832436ec | ||
|
|
6c6bd28308 | ||
|
|
d298a73aab | ||
|
|
f82797006f | ||
|
|
6f0d8022d1 | ||
|
|
3edb8bfc21 | ||
|
|
f986561b62 | ||
|
|
d971478d75 | ||
|
|
b1718d715e | ||
|
|
674d81ce27 | ||
|
|
0d5dcf7358 | ||
|
|
653b86fa48 | ||
|
|
3461b2f5bb | ||
|
|
f2b52d46d0 | ||
|
|
d9359f8249 | ||
|
|
146469ab19 | ||
|
|
fa4ed416c7 | ||
|
|
7f2e23bb50 | ||
|
|
d97cc460b0 | ||
|
|
2bc6301e39 | ||
|
|
c07a37b91d | ||
|
|
94f3b5751a | ||
|
|
e42e998f76 | ||
|
|
5bf9b86aa4 | ||
|
|
1b37f94737 | ||
|
|
82a2a8b7eb | ||
|
|
359160d8a1 | ||
|
|
a1d8701369 | ||
|
|
b4ea3725da | ||
|
|
595049117c | ||
|
|
a51ca42b18 | ||
|
|
fa7454688b | ||
|
|
657056b114 | ||
|
|
16d9e65b32 | ||
|
|
9e21bc74ac | ||
|
|
0a103544e4 | ||
|
|
80904fddcf | ||
|
|
550785ba29 | ||
|
|
1f691912e1 | ||
|
|
bff0a94507 | ||
|
|
806bb3c63f | ||
|
|
534e78b372 | ||
|
|
4653b4bb79 | ||
|
|
e67f8a50f9 | ||
|
|
d260293f62 | ||
|
|
22b56f13cc | ||
|
|
6d799e9ff8 | ||
|
|
e141e7311c | ||
|
|
96e3d08787 | ||
|
|
b82aa22442 | ||
|
|
9d5fe279b6 | ||
|
|
231dbeea61 | ||
|
|
40ec19961c | ||
|
|
4cd13f4ebf | ||
|
|
5fafcdd73c | ||
|
|
7409bc052d | ||
|
|
8f73da1f79 | ||
|
|
4de0a2e30e | ||
|
|
32a11a2b20 | ||
|
|
a9d042db2c | ||
|
|
4160dfa6e1 | ||
|
|
b32c690175 | ||
|
|
064d7ffdb2 | ||
|
|
6a73e70663 | ||
|
|
5f68a5f70d | ||
|
|
ade75fecae | ||
|
|
43d758e630 | ||
|
|
0f111e2d3a | ||
|
|
a232d8e060 | ||
|
|
cf854246fa | ||
|
|
548d6bb6c0 | ||
|
|
6a0bc27b35 | ||
|
|
a303a83b92 | ||
|
|
e8c21dfe67 | ||
|
|
3439c08170 | ||
|
|
133748f004 | ||
|
|
35f3f86df4 | ||
|
|
462cfbe8ae | ||
|
|
38198d8cb3 | ||
|
|
500ebad7aa | ||
|
|
6de8d14b29 | ||
|
|
853ead07d4 | ||
|
|
8bfe5e86b4 | ||
|
|
ff976ce055 | ||
|
|
96abbad91d | ||
|
|
6023b736d9 | ||
|
|
066212158e | ||
|
|
2a9044d607 | ||
|
|
23eaf5c442 | ||
|
|
39a358ef56 | ||
|
|
f62061aa78 | ||
|
|
406e4283fd | ||
|
|
1f33e8b807 | ||
|
|
a23c89dd75 | ||
|
|
d1cb6a3aa9 | ||
|
|
d53b0d0643 | ||
|
|
a06b48ccc6 | ||
|
|
c278f09897 | ||
|
|
e08247218e | ||
|
|
84cbebcf17 | ||
|
|
d03dbf91a6 | ||
|
|
90594b5fc8 | ||
|
|
de6910a6b6 | ||
|
|
ce8778c01b | ||
|
|
6724dd1597 | ||
|
|
79500cdb9f | ||
|
|
0b8234edb4 | ||
|
|
b2a648b4da | ||
|
|
48496a930c | ||
|
|
43e312bd62 | ||
|
|
fb96473eb0 | ||
|
|
89c76a80f2 | ||
|
|
f285c61830 | ||
|
|
cc894e6100 | ||
|
|
e2ecedfa70 | ||
|
|
a1c6ac945d | ||
|
|
509e9a4d4e | ||
|
|
c28a51899f | ||
|
|
9028579d84 | ||
|
|
2cbef73a27 | ||
|
|
dbe3dea363 | ||
|
|
df987c2086 | ||
|
|
2655e5c7b9 | ||
|
|
52be37dd37 | ||
|
|
8a6dc0d0b4 | ||
|
|
7907a37002 | ||
|
|
4b26ec2372 | ||
|
|
2a31c91136 | ||
|
|
f49d75994e | ||
|
|
864fe70e35 | ||
|
|
98391c1324 | ||
|
|
e83acf8658 | ||
|
|
bac2215fb6 | ||
|
|
7cdb6d36f4 | ||
|
|
2671e3d9bb | ||
|
|
29571cfcb1 | ||
|
|
260072954e | ||
|
|
077975cba7 | ||
|
|
e1df8c9082 | ||
|
|
02f99cb631 | ||
|
|
ae4adad5c4 | ||
|
|
cf4825233d | ||
|
|
82e18770bc | ||
|
|
0dd66bd2e9 | ||
|
|
8baa1ed52e | ||
|
|
ba3b53d64a | ||
|
|
02858c574c | ||
|
|
1e4b334321 | ||
|
|
9a7374faf0 | ||
|
|
3f69c1b62d | ||
|
|
4bef006566 | ||
|
|
860f35a7ab | ||
|
|
9bd6034f9b | ||
|
|
694058ccb1 | ||
|
|
78602e0966 | ||
|
|
1a225306f8 | ||
|
|
2c9585e9f6 | ||
|
|
bc06fe3b51 | ||
|
|
5bb289262e | ||
|
|
8c339b9d63 | ||
|
|
904027f25f | ||
|
|
0068b8c823 | ||
|
|
d3ab1d50b5 | ||
|
|
9c2f131b66 | ||
|
|
1e3c163233 | ||
|
|
28d980de3d | ||
|
|
e2dddf3532 | ||
|
|
12934e17e6 | ||
|
|
87f28fa6dd | ||
|
|
83344af1c2 | ||
|
|
c7f703c476 | ||
|
|
48748b8f9a | ||
|
|
c33c9283f1 | ||
|
|
0cadef62c1 | ||
|
|
fc7311e94c | ||
|
|
068fd1d839 | ||
|
|
81cf763a97 | ||
|
|
2ad3e1428d | ||
|
|
9286665be5 | ||
|
|
c7f175309d | ||
|
|
917f50e737 | ||
|
|
15ba1fe530 | ||
|
|
ccf510188f | ||
|
|
eb97ef73fa | ||
|
|
8dbbc0e72b | ||
|
|
695422d698 | ||
|
|
c0eb1e6bfe | ||
|
|
32e131862d | ||
|
|
1c838758c3 | ||
|
|
f5c3a23a75 | ||
|
|
cf036062c4 | ||
|
|
c5deb0a325 | ||
|
|
aa4f316c14 | ||
|
|
b53e81786a | ||
|
|
80f23eb97d | ||
|
|
e7f46a4251 | ||
|
|
39f0e4b207 | ||
|
|
1b3e733e1c | ||
|
|
78e57f29bc | ||
|
|
1d02548e4a | ||
|
|
2078c0d1bf | ||
|
|
662e7238ef | ||
|
|
8face6c67c | ||
|
|
f2bb840936 | ||
|
|
01d62f822d | ||
|
|
0efa5c562a | ||
|
|
785da17231 | ||
|
|
a9b3a77cda | ||
|
|
e60848a65f | ||
|
|
1455d0211b | ||
|
|
1499f1e480 | ||
|
|
dbe6828978 | ||
|
|
4fa609e2be | ||
|
|
8d80f9c624 | ||
|
|
e26d9ae75e | ||
|
|
92aba71fb5 | ||
|
|
4393076c6c | ||
|
|
6a6814379f | ||
|
|
c23ffc045d | ||
|
|
8abe6ccb64 | ||
|
|
4718c784af | ||
|
|
616e31f795 | ||
|
|
dd96991005 | ||
|
|
fa0c31b864 | ||
|
|
a7154d73fe | ||
|
|
de08da1003 | ||
|
|
c6fb650a62 | ||
|
|
821643f30b | ||
|
|
3d40b1c03f | ||
|
|
e993855421 | ||
|
|
8a8b2d0684 | ||
|
|
94fe1c8b26 | ||
|
|
5f23eba1b0 | ||
|
|
036cb819d6 | ||
|
|
94da5ac1e8 | ||
|
|
e2db31c94b | ||
|
|
de6d4f266e | ||
|
|
69c84b4c28 | ||
|
|
c44e6130cc | ||
|
|
81b1cb9caa | ||
|
|
3f0a3cc6c0 | ||
|
|
cf41cc2ec2 | ||
|
|
b3ab1cbe73 | ||
|
|
1c60de9c6b | ||
|
|
929f24602e | ||
|
|
508cb3d34a | ||
|
|
a4cc03ffd9 | ||
|
|
74aea6680a | ||
|
|
35a1ef8198 | ||
|
|
3b4935ad97 | ||
|
|
7f2fdcc2bf | ||
|
|
8fb24677a4 | ||
|
|
337d7f6884 | ||
|
|
54478c3a0a | ||
|
|
00fff0dbc1 | ||
|
|
e46d9edc98 | ||
|
|
e88fdae17d | ||
|
|
b3d1d22317 | ||
|
|
3817133d4f | ||
|
|
dade45942c | ||
|
|
057f297bfd | ||
|
|
40bd0e0ec1 | ||
|
|
51bac49a91 | ||
|
|
9e980fde5f | ||
|
|
d181abbab8 | ||
|
|
b1488a63ef | ||
|
|
b9d9f86770 | ||
|
|
9c1844a927 | ||
|
|
4f9f4c44d1 | ||
|
|
4a558d611b | ||
|
|
226ec5bd25 | ||
|
|
3340239733 | ||
|
|
c5dcbb9901 | ||
|
|
8c83933000 | ||
|
|
8298664e1c | ||
|
|
0f4379d111 | ||
|
|
4231743209 | ||
|
|
64bd104b64 | ||
|
|
93567dffb6 | ||
|
|
dcbd70fc54 | ||
|
|
2786bc27be | ||
|
|
3db5846f8f | ||
|
|
424b4be5c6 | ||
|
|
aa03b29d77 | ||
|
|
d4af3ee3b6 | ||
|
|
7a39517c94 | ||
|
|
c060d39cca | ||
|
|
a39f993cd4 | ||
|
|
9e1bae7bad | ||
|
|
d319206566 | ||
|
|
5273ddbbdd | ||
|
|
8a731e502d | ||
|
|
b103bfdb8b | ||
|
|
0c6adc08fc | ||
|
|
e08cce6b6b | ||
|
|
92f261cf3b | ||
|
|
171865492f | ||
|
|
ee342cc3b8 | ||
|
|
5520872def | ||
|
|
00f8683fc0 | ||
|
|
cf6a85ba65 | ||
|
|
adb41a5685 | ||
|
|
8fa4149a37 | ||
|
|
fcfd867c25 | ||
|
|
b9bd0c6fe1 | ||
|
|
50fe0ee0b3 | ||
|
|
5d6c0a66b4 | ||
|
|
f582495d75 | ||
|
|
071ea96fbd | ||
|
|
248350a9a5 | ||
|
|
b0649afc37 | ||
|
|
b7e53c695f | ||
|
|
3a5f932648 | ||
|
|
673814eac5 | ||
|
|
f102ce6f26 | ||
|
|
c26e3b15ac | ||
|
|
6b5c11548e | ||
|
|
1e3bd03b92 | ||
|
|
f6d7d4d020 | ||
|
|
2eaddaca67 | ||
|
|
06d2506544 | ||
|
|
9e3c926730 | ||
|
|
275f0ed037 | ||
|
|
da6648f3c9 | ||
|
|
9b960f3555 | ||
|
|
ed72e0e169 | ||
|
|
389d089ecc | ||
|
|
459d19823e | ||
|
|
68d2aa2491 | ||
|
|
91f3a18d33 | ||
|
|
718d215046 | ||
|
|
4042e0f832 | ||
|
|
365bacfea6 | ||
|
|
3ccb9c1c31 | ||
|
|
3135a5e01f | ||
|
|
168242c841 | ||
|
|
f020200c2c | ||
|
|
c54405c270 | ||
|
|
9c116b4d4d | ||
|
|
be056ad723 | ||
|
|
1a0797e6bd | ||
|
|
02196c2c68 | ||
|
|
6ae49b9ccd | ||
|
|
548860bce0 | ||
|
|
e8622a660a | ||
|
|
564c1c8fa7 | ||
|
|
6b6ff098eb | ||
|
|
3f0477868a | ||
|
|
5bd726380c | ||
|
|
2e3400f899 | ||
|
|
81fd2f29de | ||
|
|
571c8be2de | ||
|
|
861ed9a339 | ||
|
|
0cd9e10d2d | ||
|
|
5a0ef67644 | ||
|
|
2d8a1765eb | ||
|
|
d06dcc74b4 | ||
|
|
d3c388db9c | ||
|
|
5fc7f417da | ||
|
|
ce44ad5019 | ||
|
|
d9de4806b0 | ||
|
|
6f21ad6d86 | ||
|
|
12186e981c | ||
|
|
d86261dc2b | ||
|
|
0448f34aff | ||
|
|
22b3dd8c17 | ||
|
|
3470e79f83 | ||
|
|
772b6b66b1 | ||
|
|
3eef7bf9ab | ||
|
|
452b07a6c2 | ||
|
|
efc9862836 | ||
|
|
73f26fd3b9 | ||
|
|
ee480fecae | ||
|
|
b4141f7e91 | ||
|
|
d1641a7cd0 | ||
|
|
b0fe498112 | ||
|
|
e7d8b197f3 | ||
|
|
f0774e7a6c | ||
|
|
9697652c0a | ||
|
|
c3b8ab76a5 | ||
|
|
19b7e41fda | ||
|
|
d4b69a2f24 | ||
|
|
d0a7e585d7 | ||
|
|
152eeec7a7 | ||
|
|
9be31cd944 | ||
|
|
58c1a92bc4 | ||
|
|
148edfcf26 | ||
|
|
b7bd21bc0a | ||
|
|
e9186caa33 | ||
|
|
8abff30849 | ||
|
|
5dc45a0046 | ||
|
|
91ef46755f | ||
|
|
a8d8f70335 | ||
|
|
ecc015889c | ||
|
|
3827fbc302 | ||
|
|
5bc570d449 | ||
|
|
f1676593d0 | ||
|
|
ddf7bc57d3 | ||
|
|
d2b596f108 | ||
|
|
d3bf33f9aa | ||
|
|
ef6973087b | ||
|
|
0ae915c0f6 | ||
|
|
f96c0762ff | ||
|
|
9e996ceef8 | ||
|
|
83c63206c1 | ||
|
|
fd0c9f6c2d | ||
|
|
a2418cd15d | ||
|
|
40b77a4661 | ||
|
|
60d1f9cf45 | ||
|
|
a41fc6bbf9 | ||
|
|
fb3d6a049f | ||
|
|
8b557dfd30 | ||
|
|
843ae2cc2c | ||
|
|
6fb9ea4ea5 | ||
|
|
1a603dd365 | ||
|
|
25ebd8de49 | ||
|
|
41d9f563a8 | ||
|
|
1540cd05a9 | ||
|
|
c3b80c117f | ||
|
|
5dd1310ac6 | ||
|
|
2f69b332d8 | ||
|
|
23cfe10d94 | ||
|
|
72e21db66a | ||
|
|
b3af980c46 | ||
|
|
a5e6cf5003 | ||
|
|
64e4031fb7 | ||
|
|
a91dc75020 | ||
|
|
7a714fa8c3 | ||
|
|
2b30f6aa04 | ||
|
|
1451a407ac | ||
|
|
0f2bdc6d0a | ||
|
|
2fe1bc2e71 | ||
|
|
368377375d | ||
|
|
64d595c1c0 | ||
|
|
cb161e634c | ||
|
|
3e6c5132de | ||
|
|
e8a355e872 | ||
|
|
eab0dfc66b | ||
|
|
d94279554c | ||
|
|
9270beada5 | ||
|
|
37f1885152 | ||
|
|
7e38be5470 | ||
|
|
09573266da | ||
|
|
fac7eaffa9 | ||
|
|
26411c1021 | ||
|
|
da34cf8fd6 | ||
|
|
bbbf123fcf | ||
|
|
3d776a2da2 | ||
|
|
6b45687df2 | ||
|
|
af19291e01 | ||
|
|
1740f71793 | ||
|
|
4518e7d1f0 | ||
|
|
1525d7f901 | ||
|
|
8f276e00c5 | ||
|
|
3171dea6ef | ||
|
|
5b13ea0278 | ||
|
|
08c7c4be31 | ||
|
|
b3e9086d5d | ||
|
|
dec9f318a8 | ||
|
|
e6e73e7c94 | ||
|
|
b497faff84 | ||
|
|
3526997670 | ||
|
|
f42b2aaeef | ||
|
|
8a4d7dd913 | ||
|
|
9b97ea8983 | ||
|
|
4468124abd | ||
|
|
e1f471f89c | ||
|
|
9ccfcb3d24 | ||
|
|
efc61fe709 | ||
|
|
7d74bcd7bc | ||
|
|
37f33c4346 | ||
|
|
d4fe6cf255 | ||
|
|
6a7ddeb222 | ||
|
|
d6d3585c03 | ||
|
|
e45e601c35 | ||
|
|
f367a8bd33 | ||
|
|
343b784d6c | ||
|
|
66d2f2de66 | ||
|
|
8b7dd0193e | ||
|
|
ca1504db04 | ||
|
|
3cfe7e6e25 | ||
|
|
55beaa4d47 | ||
|
|
541568fbb6 | ||
|
|
171b29fd4c | ||
|
|
2154f62f51 | ||
|
|
73b98c7500 | ||
|
|
250e28aaf4 | ||
|
|
143b3de606 | ||
|
|
e0544c3eb5 | ||
|
|
d547cbee4e | ||
|
|
aa68c67537 | ||
|
|
1d08a35f18 | ||
|
|
967871d4b8 | ||
|
|
d4c9f37994 | ||
|
|
bfb27d0836 | ||
|
|
dc17a4c1c8 | ||
|
|
e6e02ac002 | ||
|
|
6d32c64100 | ||
|
|
50a4441a6f | ||
|
|
d31be07a25 | ||
|
|
669e957291 | ||
|
|
8bcee712e0 | ||
|
|
e09ed4f612 | ||
|
|
54ae8fcd9e | ||
|
|
502e18c0d0 | ||
|
|
cd0e1c9780 | ||
|
|
a16e5d577c | ||
|
|
626d85b1bd | ||
|
|
1ceb43f77f | ||
|
|
69bef6678a | ||
|
|
e30e685ee1 | ||
|
|
bb2bb1d083 | ||
|
|
3d4c7fd9dd | ||
|
|
02121840c1 | ||
|
|
6da153e69c | ||
|
|
e406f72564 | ||
|
|
538dec2390 | ||
|
|
dae1a4e6df | ||
|
|
e3b0a66805 | ||
|
|
6f9da41a6c | ||
|
|
2850b4962f | ||
|
|
265d0a060c | ||
|
|
6f6ff1a673 | ||
|
|
ae77308b3f | ||
|
|
ada8ccbb14 | ||
|
|
e7626bb3ce | ||
|
|
f6c230ebcb | ||
|
|
64c02a2174 | ||
|
|
5f0e314fe5 | ||
|
|
9d244cb4ce | ||
|
|
fe98390fe0 | ||
|
|
d886e2a557 | ||
|
|
acf41ac2df | ||
|
|
c71d9d53ff | ||
|
|
08b0a2e4e2 | ||
|
|
dbb09a65fe | ||
|
|
484e1fae4e | ||
|
|
4195115d60 | ||
|
|
d21c6b7c13 | ||
|
|
270c8e3746 | ||
|
|
38ea72559b | ||
|
|
9d2c55e62a | ||
|
|
6955b7cda1 | ||
|
|
3a3722eb90 | ||
|
|
078022fa64 | ||
|
|
f7b3b78414 | ||
|
|
a2303e3d0f | ||
|
|
5865f43a79 | ||
|
|
027d5bbf30 | ||
|
|
f6e02bc306 | ||
|
|
5904fc0ed0 | ||
|
|
ec06e092ff | ||
|
|
ccb2b96262 | ||
|
|
9175d0a1ee | ||
|
|
d3850ae0e7 | ||
|
|
795767ee49 | ||
|
|
b0f482d9b3 | ||
|
|
d48b05d8ab | ||
|
|
9f110a3b81 | ||
|
|
f4cafc5041 | ||
|
|
f305473af5 | ||
|
|
a8e01c95f8 | ||
|
|
81339d3c3c | ||
|
|
6cd4d3c008 | ||
|
|
2705394aeb | ||
|
|
47b3c0ec82 | ||
|
|
fe46a4c9d3 | ||
|
|
994d37c441 | ||
|
|
f391225968 | ||
|
|
f518e71f76 | ||
|
|
f70f05ca35 | ||
|
|
952faabb04 | ||
|
|
b5ec8ef1d9 | ||
|
|
98166ff081 | ||
|
|
019d707dc2 | ||
|
|
d7df92d71b | ||
|
|
89aadcec48 | ||
|
|
2768a55b02 | ||
|
|
d387ca7779 | ||
|
|
fa45f2e6ba | ||
|
|
e255fe1685 | ||
|
|
1e95c3a4ac | ||
|
|
7ec16a6af7 | ||
|
|
0c5ee9486b | ||
|
|
4d5b31e943 | ||
|
|
8284ea8b46 | ||
|
|
ec8d4cfdcc | ||
|
|
840e27bd41 | ||
|
|
0827fe8bc1 | ||
|
|
da93b54687 | ||
|
|
0519fde656 | ||
|
|
71dd98a22e | ||
|
|
0de223a1ee | ||
|
|
251e70953e | ||
|
|
3d994d0b6c | ||
|
|
6e445e39a1 | ||
|
|
c420eb06ea | ||
|
|
4ce283ff18 | ||
|
|
cd5bbf0f35 | ||
|
|
5d32badfee | ||
|
|
a1d9de0613 | ||
|
|
bc7b8ef41e | ||
|
|
a40f00bee9 | ||
|
|
4d0e046a06 | ||
|
|
e425ba6c0e | ||
|
|
77003fea94 | ||
|
|
b5bcecce5d | ||
|
|
c6569f5177 | ||
|
|
37ff334508 | ||
|
|
765bc4a66c | ||
|
|
67d2608db9 | ||
|
|
9e7084c024 | ||
|
|
8cd853a1c8 | ||
|
|
dd5a2c44a5 | ||
|
|
a1fe10de33 | ||
|
|
7d4e0b32e1 | ||
|
|
85bf34eb5e | ||
|
|
d9d8746b06 | ||
|
|
adb1122f72 | ||
|
|
ada63fbb4f | ||
|
|
c5efc24b53 | ||
|
|
ff6e7df51a | ||
|
|
a6b382fa40 | ||
|
|
8ea87da749 | ||
|
|
46c8f9282e | ||
|
|
df3bb5d4ef | ||
|
|
524c10a4c5 | ||
|
|
82d87fe9cc | ||
|
|
5e25770a83 | ||
|
|
de28fa60cf | ||
|
|
1692747009 | ||
|
|
bc69cfe5a4 | ||
|
|
c0d8f10a42 | ||
|
|
20760f83da | ||
|
|
13b7b73b08 | ||
|
|
d5b54e4b7f | ||
|
|
084ce330ff | ||
|
|
f59f259586 | ||
|
|
a32f02162b | ||
|
|
aada3ee156 | ||
|
|
2bf8b38383 | ||
|
|
a10a120c99 | ||
|
|
274ce67572 | ||
|
|
6615fcee6e | ||
|
|
c8a93d08eb | ||
|
|
1682b2ced8 | ||
|
|
4966cfa119 | ||
|
|
f537e2e0ec | ||
|
|
7198e00097 | ||
|
|
1b19a2b1de | ||
|
|
ea4aeb0c67 | ||
|
|
55637d3de5 | ||
|
|
0f007abd86 | ||
|
|
4e1fa1bbb9 | ||
|
|
d86015f6b7 | ||
|
|
ceb8d1ccb8 | ||
|
|
daf8899e5c | ||
|
|
dd96bea16c | ||
|
|
9efec3dff4 | ||
|
|
285d3a4497 | ||
|
|
1343c2638c | ||
|
|
07e971e7c2 | ||
|
|
f5a68e9839 | ||
|
|
9cb95aad26 | ||
|
|
a5e6d130fd | ||
|
|
d79518ec0e | ||
|
|
357e60ffdc | ||
|
|
f7f5b56b0a | ||
|
|
e4b8d32001 | ||
|
|
3892a7162a | ||
|
|
03e8e4a18e | ||
|
|
3b49a87972 | ||
|
|
b016beaeb1 | ||
|
|
b239d0de27 | ||
|
|
c0dde4ac5b | ||
|
|
cacfd42960 | ||
|
|
8cd100de39 | ||
|
|
16ae57d222 | ||
|
|
9e68716e0e | ||
|
|
d3e0c54f7d | ||
|
|
80f05b38b0 | ||
|
|
694d3435e1 | ||
|
|
7db0e60486 | ||
|
|
19ef8e56ef | ||
|
|
740e8469da | ||
|
|
3bbf429ac0 | ||
|
|
b9643771af | ||
|
|
b64094d528 | ||
|
|
a97186b2f1 | ||
|
|
50ecdfc27e | ||
|
|
a2126b635f | ||
|
|
229f4abf93 | ||
|
|
4fe5b6f516 | ||
|
|
0bf4bf3f54 | ||
|
|
7bf42218fe | ||
|
|
f1c0d4683b | ||
|
|
f02ca8f2e9 | ||
|
|
a2c9772f3c | ||
|
|
df0c9bee94 | ||
|
|
f6c0dd8c4d | ||
|
|
55e664cb00 | ||
|
|
78b6e77a95 | ||
|
|
d3369ceb9b | ||
|
|
7d1dd00794 | ||
|
|
eca42807c3 | ||
|
|
78be0c2b5c | ||
|
|
4b08d2b86c | ||
|
|
cb4fccfd5d | ||
|
|
249eef49d6 | ||
|
|
372bb483c5 | ||
|
|
41cafc5042 | ||
|
|
b455108961 | ||
|
|
43ad5e5129 | ||
|
|
0399d007f3 | ||
|
|
d48612ee3d | ||
|
|
b14e6b526b | ||
|
|
55512a7328 | ||
|
|
8d4b8f164c | ||
|
|
02fa2dab28 | ||
|
|
c6d3583e08 | ||
|
|
9eb75e0e3e | ||
|
|
c514e681e7 | ||
|
|
be64ea63b1 | ||
|
|
153c3c3f99 | ||
|
|
45f21ff66b | ||
|
|
83e9734908 | ||
|
|
9a49c07cf3 | ||
|
|
273e1b07d6 | ||
|
|
403f27e5b9 | ||
|
|
cfe24ba7e9 | ||
|
|
b54c5c7561 | ||
|
|
29d2a6d9d2 | ||
|
|
c545cd3cf7 | ||
|
|
a83662beda | ||
|
|
7c59caf852 | ||
|
|
27787e21ec | ||
|
|
27294b83d2 | ||
|
|
a2ee614628 | ||
|
|
dc3d7eb38c | ||
|
|
b0500e1945 | ||
|
|
320a52e5f5 | ||
|
|
f2e2b29c3c | ||
|
|
4ac2cab962 | ||
|
|
6dfc67d078 | ||
|
|
7af5d948da | ||
|
|
0644267b41 | ||
|
|
90f6d836ee | ||
|
|
233591ddc5 | ||
|
|
a2894c1114 | ||
|
|
4e13099add | ||
|
|
d77b1791d8 | ||
|
|
79ecd05a02 | ||
|
|
6be8c6b6bf | ||
|
|
d6f33f273d | ||
|
|
26fdbec56f | ||
|
|
02222bc6c1 | ||
|
|
c3174c0319 | ||
|
|
c165196f71 | ||
|
|
a4c9fa34d9 | ||
|
|
d28bc810a3 | ||
|
|
d6ba77a74b | ||
|
|
b745ba8380 | ||
|
|
00b83639fd | ||
|
|
c1c5fcd426 | ||
|
|
56f915e783 | ||
|
|
c511b967ed | ||
|
|
faeb2e28f2 | ||
|
|
fd4bc1398d | ||
|
|
86278dfb1f | ||
|
|
3bd044c236 | ||
|
|
5a894711eb | ||
|
|
4828759ab8 | ||
|
|
3672619e13 | ||
|
|
78ef0d0ebe | ||
|
|
884381d54d | ||
|
|
08079c6863 | ||
|
|
ac19ba51bd | ||
|
|
c874416036 | ||
|
|
69d2a4917c | ||
|
|
76b99bb025 | ||
|
|
14dd5077a9 | ||
|
|
441be8c4d7 | ||
|
|
979dc97f36 | ||
|
|
479a67e629 | ||
|
|
1e19f72077 | ||
|
|
541a3eb0b1 | ||
|
|
328897248a | ||
|
|
059b57438b | ||
|
|
ebae0a11be | ||
|
|
7b8a61c9a7 | ||
|
|
8785c02365 | ||
|
|
d488a8c522 | ||
|
|
d4c55fbdb5 | ||
|
|
6e8a074912 | ||
|
|
fb1c18e6fd | ||
|
|
c80158ce30 | ||
|
|
687a0e76b5 | ||
|
|
e42d5a20fd | ||
|
|
ef1632a591 | ||
|
|
bb0fba0974 | ||
|
|
9c12f6b550 | ||
|
|
9f1fc03a58 | ||
|
|
d104c1d73d | ||
|
|
28ade8e879 | ||
|
|
4974960882 | ||
|
|
c0f4fbf6ad | ||
|
|
6d2e62cda0 | ||
|
|
204f6c2f0c | ||
|
|
52c2755347 | ||
|
|
884c178142 | ||
|
|
f12366ffc7 | ||
|
|
6d3f2dbae3 | ||
|
|
7893c6b188 | ||
|
|
d855c2855a | ||
|
|
193f6631be | ||
|
|
03373895c2 | ||
|
|
43fdbc4b63 | ||
|
|
c22a72fc65 | ||
|
|
a44c2e4636 | ||
|
|
b12730866a | ||
|
|
0faa3c1baf | ||
|
|
79a5692764 | ||
|
|
2fbf9c9e16 | ||
|
|
f14004abfd | ||
|
|
3ee27a8a89 | ||
|
|
01882fa17e | ||
|
|
c6d42e9779 | ||
|
|
77a6aa9327 | ||
|
|
c3882de991 | ||
|
|
e46cb9d09a | ||
|
|
e5732d1743 | ||
|
|
00f701aa87 | ||
|
|
771c1e867f | ||
|
|
a257ce71d1 | ||
|
|
01f66003a4 | ||
|
|
578b394236 | ||
|
|
e46cefeb4b | ||
|
|
aaf83cc86f | ||
|
|
1434714b58 | ||
|
|
44e6a8619e | ||
|
|
e89a2bcd5c | ||
|
|
822d556924 | ||
|
|
194998be61 | ||
|
|
0857d4255d | ||
|
|
174af33085 | ||
|
|
4f944c0e3d | ||
|
|
eeceb89d31 | ||
|
|
5c19df841a | ||
|
|
6c1f176438 | ||
|
|
1d7e348b8f | ||
|
|
dcb9b8f9a2 | ||
|
|
2d9561427e | ||
|
|
f148fe7e4f | ||
|
|
2dd53c0bba | ||
|
|
384072d44c | ||
|
|
730d7655c7 | ||
|
|
d6cfcc994d | ||
|
|
8d4afb9c19 | ||
|
|
4c1686f194 | ||
|
|
5a25985a00 | ||
|
|
1f628fe5f9 | ||
|
|
6b8998b8ec | ||
|
|
bc46ece67f | ||
|
|
438ed9e5f8 | ||
|
|
46059b0714 | ||
|
|
ddb5ae08e8 | ||
|
|
2421bea611 | ||
|
|
7d8d7837b4 | ||
|
|
aa7997427a | ||
|
|
f3b5e16672 | ||
|
|
783fddaede | ||
|
|
3f2e9d2e0d | ||
|
|
436f02d38a | ||
|
|
4b1baccb2e | ||
|
|
51895a907e | ||
|
|
a869aae156 | ||
|
|
2cedb10fa7 | ||
|
|
202f44e45a | ||
|
|
7c7806d768 | ||
|
|
b79a237186 | ||
|
|
e280cb5f96 | ||
|
|
63373352e5 | ||
|
|
eb22964898 | ||
|
|
913a5331b7 | ||
|
|
f50b20df7a | ||
|
|
eefb17607c | ||
|
|
b938de4ea7 | ||
|
|
312760c381 | ||
|
|
55d8ae6caa | ||
|
|
704f806df6 | ||
|
|
789a8be699 | ||
|
|
326456653b | ||
|
|
52095246a6 | ||
|
|
e492a6ef88 | ||
|
|
d3bdd36e46 | ||
|
|
f148cc891b | ||
|
|
2eda7699de | ||
|
|
04ca3568cb | ||
|
|
fa073b7330 | ||
|
|
1ab3f636cc | ||
|
|
caffbd564d | ||
|
|
a66020eda9 | ||
|
|
91e3e209bf | ||
|
|
8d5c7dd566 | ||
|
|
f3a4294a11 | ||
|
|
9140063401 | ||
|
|
5f5e75de6e | ||
|
|
e71e9b07a8 | ||
|
|
5ff7c338f2 | ||
|
|
36795a34a2 | ||
|
|
341c78552d | ||
|
|
c3d0f7e463 | ||
|
|
7089f24156 | ||
|
|
fff9b4ecba | ||
|
|
e5f7fd404e | ||
|
|
79bbadc3c4 | ||
|
|
36508bc31a | ||
|
|
e4a8e3fd9e | ||
|
|
5774f469c0 | ||
|
|
9ced4a373b | ||
|
|
1fc8a6ca14 | ||
|
|
501c800c5a | ||
|
|
6fc89a80d1 | ||
|
|
4e82233874 | ||
|
|
6be62cdb7a | ||
|
|
858ad8ca64 | ||
|
|
ec3d5a0c43 | ||
|
|
738fe3d529 | ||
|
|
3e211c91a2 | ||
|
|
6aa3efe185 | ||
|
|
eb72c49bd2 | ||
|
|
37b7bccc61 | ||
|
|
a9414a6e2a | ||
|
|
ae886f5c2b | ||
|
|
28f69488c6 | ||
|
|
0e56b81f4c | ||
|
|
7264ffaabb | ||
|
|
4c17496489 | ||
|
|
c7eef6e141 | ||
|
|
c9998ac0e2 | ||
|
|
5aab786c35 | ||
|
|
1b1917f4b3 | ||
|
|
46171bc538 | ||
|
|
bca487f709 | ||
|
|
9edf987b94 | ||
|
|
8e5659a7e8 | ||
|
|
2edde8f5a4 | ||
|
|
78daafd161 | ||
|
|
c21550022e | ||
|
|
981b58ae55 | ||
|
|
5047f6f219 | ||
|
|
5b3ad85c96 | ||
|
|
933f70cf5d | ||
|
|
67fb880dfb | ||
|
|
006e49982e | ||
|
|
465a7518cc | ||
|
|
66252c0f4b | ||
|
|
d91f72fd5f | ||
|
|
e35371be2b | ||
|
|
1bb58646de | ||
|
|
4a396046fe | ||
|
|
6d59eee9e3 | ||
|
|
c032902159 | ||
|
|
f230bc9d12 | ||
|
|
62ed498468 | ||
|
|
e4c58b025f | ||
|
|
71fd88b931 | ||
|
|
4fbe072aa4 | ||
|
|
e85c9cbc45 | ||
|
|
e9f725b418 | ||
|
|
655f60e567 | ||
|
|
e4614cf487 | ||
|
|
1695ca0ce8 | ||
|
|
50af63e1d2 | ||
|
|
7fa4d658e3 | ||
|
|
fe73c5fc95 | ||
|
|
b5fb02dc70 | ||
|
|
0e2190687f | ||
|
|
886cf4f227 | ||
|
|
5dc7640d74 | ||
|
|
d2e8557038 | ||
|
|
af6128c44b | ||
|
|
b12891297f | ||
|
|
680e851452 | ||
|
|
45bdf40534 | ||
|
|
785958db53 | ||
|
|
385647af43 | ||
|
|
c82e412d32 | ||
|
|
f37a567e8c | ||
|
|
51b800f40a | ||
|
|
be647641bb | ||
|
|
5a0a0ff8dd | ||
|
|
d21648495a | ||
|
|
29802d2ff5 | ||
|
|
1d12de4da6 | ||
|
|
c5155d54c6 | ||
|
|
fac1fb13da | ||
|
|
e13c4fac01 | ||
|
|
c10477c152 | ||
|
|
9f51b3590d | ||
|
|
01fcb9779a | ||
|
|
58022ed110 | ||
|
|
5e39502200 | ||
|
|
e0369d78c9 | ||
|
|
826fe52a8a | ||
|
|
d7754393bb | ||
|
|
6ca53fde12 | ||
|
|
f778fb89a5 | ||
|
|
b7d9b6702e | ||
|
|
2711c7aed9 | ||
|
|
75fbecf831 | ||
|
|
7f886b4c53 | ||
|
|
601df24372 | ||
|
|
cd5a6fd5d8 | ||
|
|
e707a89e63 | ||
|
|
1d0858f08e | ||
|
|
f4985479d2 | ||
|
|
1fb2eaabf3 | ||
|
|
7ab4290896 | ||
|
|
895b4077d1 | ||
|
|
0484eac549 | ||
|
|
fd62e99c23 | ||
|
|
697993ef35 | ||
|
|
ebe8fb518a | ||
|
|
e217072b8b | ||
|
|
5fc9d43a99 | ||
|
|
56f1a46121 | ||
|
|
d407e8e25e | ||
|
|
184c7ab61f | ||
|
|
663e7feea2 | ||
|
|
5ea641b2d3 | ||
|
|
21b6696e8b | ||
|
|
c8edb6ab5d | ||
|
|
7a6ec6b25a | ||
|
|
34b28107e2 | ||
|
|
fbada4d85a | ||
|
|
19f4f3c36c | ||
|
|
57d8ea696c | ||
|
|
3119961e8c | ||
|
|
e2ca759d56 | ||
|
|
6b3938f2f2 | ||
|
|
43d532519f | ||
|
|
27d3190aa2 | ||
|
|
7a594ca15d | ||
|
|
70f306e8d8 | ||
|
|
b03498907b | ||
|
|
ecf50fcee8 | ||
|
|
159de43db3 | ||
|
|
4cb0fe78ba | ||
|
|
bb187d73e4 | ||
|
|
91f9ec998a | ||
|
|
a085980b22 | ||
|
|
f1ed7d40c1 | ||
|
|
6bb88bdcc0 | ||
|
|
d218619e35 | ||
|
|
4a2a281c32 | ||
|
|
b0b27ae007 | ||
|
|
5ca00863fb | ||
|
|
0b7e57f8b8 | ||
|
|
4aacf51f4d | ||
|
|
9f7b1269b7 | ||
|
|
3f1d92ad68 | ||
|
|
f561107add | ||
|
|
9fd6ce9eba | ||
|
|
27b54b8d01 | ||
|
|
3fabe90067 | ||
|
|
a948d041fe | ||
|
|
da17bb3e97 | ||
|
|
f2d573fe85 | ||
|
|
7fa873f2b2 | ||
|
|
c05524beb1 | ||
|
|
e4ef5fc7fc | ||
|
|
53fab94828 | ||
|
|
2984b40bc9 | ||
|
|
cd16a399e5 | ||
|
|
c9d68a3a2b | ||
|
|
aa45923166 | ||
|
|
4386d3b764 | ||
|
|
acb58deb48 | ||
|
|
09a80571a5 | ||
|
|
546e9d3ecc | ||
|
|
1521e09083 | ||
|
|
f4341a13d0 | ||
|
|
c6a3f83e83 | ||
|
|
529b08c3a3 | ||
|
|
fb1aeaa66c | ||
|
|
cbd33586ac | ||
|
|
37f1d9add6 | ||
|
|
94f7087311 | ||
|
|
4e6c02b6ad | ||
|
|
936baa4dfa | ||
|
|
d0e69f8c6e | ||
|
|
29aeb9d959 | ||
|
|
9023f99c52 | ||
|
|
c9472cabee | ||
|
|
5a82b043d0 | ||
|
|
c11f4d9df6 | ||
|
|
e74c5226f3 | ||
|
|
26fab30972 | ||
|
|
4285e650af | ||
|
|
cf5a44f1e3 | ||
|
|
f88d485e38 | ||
|
|
a5a9db828e | ||
|
|
3b84a3f8a4 | ||
|
|
7de3a7fcb0 | ||
|
|
6d3f4243c1 | ||
|
|
4ec902aab5 | ||
|
|
fd1ca04d76 | ||
|
|
c2ad77b27f | ||
|
|
5a4e282ae8 | ||
|
|
3201291b32 | ||
|
|
485db41457 | ||
|
|
748c909e7b | ||
|
|
1b473c2ef0 | ||
|
|
72d36d9c27 | ||
|
|
6b3f1c2e99 | ||
|
|
db2ec82162 | ||
|
|
20af2eb571 | ||
|
|
a0f9b1a2ed | ||
|
|
3bd078e428 | ||
|
|
b66f9e2579 | ||
|
|
e9cffc55a7 | ||
|
|
81fc3f26fa | ||
|
|
6a19e66d00 | ||
|
|
16b14c8945 | ||
|
|
65ed20b4f4 | ||
|
|
cbe865df7a | ||
|
|
e78cef0d9f | ||
|
|
f7f30d8c63 | ||
|
|
6fb26bad22 | ||
|
|
746c335bcd | ||
|
|
9b0526bb46 | ||
|
|
40e4cfe458 | ||
|
|
97fc11c244 | ||
|
|
2a3888bfac | ||
|
|
813531edd4 | ||
|
|
8a20115615 | ||
|
|
817fc344e7 | ||
|
|
9c9ee7c952 | ||
|
|
3b78918878 | ||
|
|
9befc69684 | ||
|
|
f5e13431a5 | ||
|
|
71c9cbb2b1 | ||
|
|
f945ae2122 | ||
|
|
e7a1bdc90c | ||
|
|
3a83b65a88 | ||
|
|
1e7da835b8 | ||
|
|
97bbd2381b | ||
|
|
733f251743 | ||
|
|
0bcf4e2787 | ||
|
|
01e8718ad5 | ||
|
|
10183deadb | ||
|
|
7540c30f54 | ||
|
|
f6d219cb18 | ||
|
|
250b80eaf7 | ||
|
|
0e46787829 | ||
|
|
74a4fde52e | ||
|
|
cd2d5400ce | ||
|
|
ff7e6bda27 | ||
|
|
842b885e3c | ||
|
|
4331bbcc1a | ||
|
|
f3e493de49 | ||
|
|
4c021fb727 | ||
|
|
a5cee9d917 | ||
|
|
da6bceb5a7 | ||
|
|
cf43ccdfde | ||
|
|
3654cba018 | ||
|
|
d562c7c228 | ||
|
|
2685819181 | ||
|
|
ada0d0504c | ||
|
|
60f13d2625 | ||
|
|
b2796a0d46 | ||
|
|
b95777507e | ||
|
|
fb101603f0 | ||
|
|
7625719654 | ||
|
|
0c23127aae | ||
|
|
b04542e11e | ||
|
|
226e31d86d | ||
|
|
3664ca0cbb | ||
|
|
9706fc6bac | ||
|
|
5d6ede1055 | ||
|
|
8a2e7f50d7 | ||
|
|
cfe1d50b1a | ||
|
|
615a463e23 | ||
|
|
fc8d3631b4 | ||
|
|
819668f839 | ||
|
|
6407936c27 | ||
|
|
fc12d8258b | ||
|
|
5b7ef7bfa3 | ||
|
|
51973e530b | ||
|
|
c680adba74 | ||
|
|
731dccfccc | ||
|
|
79c8c611db | ||
|
|
f08922f6b7 | ||
|
|
71633c9523 | ||
|
|
521e6eece4 | ||
|
|
d30a9acc68 | ||
|
|
a13bf9ab7a | ||
|
|
1cb4cc98ab | ||
|
|
eca9614457 | ||
|
|
8458723ef2 | ||
|
|
1ba2edcfb2 | ||
|
|
f24eba5c44 | ||
|
|
d52ac4259b | ||
|
|
81a770b93f | ||
|
|
047bc4bd88 | ||
|
|
11325940c8 | ||
|
|
ed04393d27 | ||
|
|
d6e3f866bc | ||
|
|
a03406e91f | ||
|
|
37d41292bb | ||
|
|
b27b9b09c6 | ||
|
|
8082927ba3 | ||
|
|
139db65acf | ||
|
|
24457fa523 | ||
|
|
acc40fafeb | ||
|
|
38c28eb6cb | ||
|
|
921ffb5dd7 | ||
|
|
bc75095a9a | ||
|
|
d82c9db4c8 | ||
|
|
3693410426 | ||
|
|
cee8ab8dc0 | ||
|
|
208f167090 | ||
|
|
4c29324050 | ||
|
|
bc973fb1d0 | ||
|
|
3e6d45aebe | ||
|
|
878db20a92 | ||
|
|
2f6b25c4fb | ||
|
|
e888d3d393 | ||
|
|
e5e82459c6 | ||
|
|
1d22c714ce | ||
|
|
a342626920 | ||
|
|
bbdb142d2e | ||
|
|
26926ffcfa | ||
|
|
a4f55d7fd7 | ||
|
|
1dbd21dc61 | ||
|
|
28e58d7df2 | ||
|
|
e7b5056769 | ||
|
|
0ceeeafa41 | ||
|
|
b531a37942 | ||
|
|
21e9421c4b | ||
|
|
166f1120c8 | ||
|
|
cd3f2c48c0 | ||
|
|
b0760f8006 | ||
|
|
f345e8a77c | ||
|
|
b4429b287a | ||
|
|
df27f744df | ||
|
|
7c2d9a9302 | ||
|
|
7a506337e6 | ||
|
|
377303a391 | ||
|
|
0ad12d0e0b | ||
|
|
978733388c | ||
|
|
4f5c46fb20 | ||
|
|
8f27350e65 | ||
|
|
8e280ab712 | ||
|
|
1d3cdc6b11 | ||
|
|
2b67a9e709 | ||
|
|
783919611b | ||
|
|
10376c0c61 | ||
|
|
7ec55a027f | ||
|
|
6642fb0688 | ||
|
|
af47f4a497 | ||
|
|
847f8207f7 | ||
|
|
2a0036e496 | ||
|
|
412cf715a7 | ||
|
|
5e8102a304 | ||
|
|
48647bfc08 | ||
|
|
40c4e1f8c4 | ||
|
|
21524d6652 | ||
|
|
ba9786d714 | ||
|
|
85accd0169 | ||
|
|
fff27f4683 | ||
|
|
e0458e4c27 | ||
|
|
75113c58ef | ||
|
|
f5fe6c81ee | ||
|
|
8ee8f1e057 | ||
|
|
11ee28639d | ||
|
|
3f16af5a44 | ||
|
|
425ab889d6 | ||
|
|
d593a70bbf | ||
|
|
7a37c73b8e | ||
|
|
bd8f307677 | ||
|
|
bbe2d4668e | ||
|
|
687b0543c8 | ||
|
|
067eae567c | ||
|
|
5aa87dbfa7 | ||
|
|
814d7db11a | ||
|
|
5e26db0a5d | ||
|
|
94c3b35271 | ||
|
|
06101a43c8 | ||
|
|
5e019a3df5 | ||
|
|
e34e97ef86 | ||
|
|
27ba5b8b62 | ||
|
|
4228090f88 | ||
|
|
51cc98e6f2 | ||
|
|
c31ecfba93 | ||
|
|
3b0d12d986 | ||
|
|
f6f32e60d5 | ||
|
|
db43c5e732 | ||
|
|
eb2ba42eaa | ||
|
|
50e9f66257 | ||
|
|
26e0fbbeb5 | ||
|
|
73c22d0d50 | ||
|
|
fa44c77c6f | ||
|
|
3051f1edd9 | ||
|
|
7b517e7131 | ||
|
|
5a5b4b41c0 | ||
|
|
1a3cd8e6ad | ||
|
|
fda8b94bdf | ||
|
|
5806a08168 | ||
|
|
f83d5e5be8 | ||
|
|
01a79e3adc | ||
|
|
b7e5181f8e | ||
|
|
7fe77f16a7 | ||
|
|
8b257ef3b6 | ||
|
|
f3b8441cc7 | ||
|
|
8162607c58 | ||
|
|
fe7038fb2d | ||
|
|
fba6a02260 | ||
|
|
163898dae7 | ||
|
|
f0d069772c | ||
|
|
47da76ae48 | ||
|
|
d77613aaba | ||
|
|
475fc3de54 | ||
|
|
b7dcee9370 | ||
|
|
6abb9f6415 | ||
|
|
b32daa0ed7 | ||
|
|
835c162442 | ||
|
|
4981335c1d | ||
|
|
d7216653df | ||
|
|
0e451c786e | ||
|
|
07dfb3d5f2 | ||
|
|
f7e921313e | ||
|
|
9ba4867e64 | ||
|
|
278d8a7319 | ||
|
|
e4c20dbe87 | ||
|
|
c58934fd46 | ||
|
|
be6da9b8ea | ||
|
|
2aba17e440 | ||
|
|
711d99a23c | ||
|
|
80e0c565cd | ||
|
|
36028564f8 | ||
|
|
209a6d00f3 | ||
|
|
5526000ece | ||
|
|
7babc7c8cd | ||
|
|
67623b0801 | ||
|
|
d73839b733 | ||
|
|
c6179991b8 | ||
|
|
29ac09a2aa | ||
|
|
59488458b0 | ||
|
|
f6764f4722 | ||
|
|
493cba1f80 | ||
|
|
05b1559275 | ||
|
|
6eeee2496b | ||
|
|
b9d6efa20e | ||
|
|
20e1b92862 | ||
|
|
a54678d7fa | ||
|
|
0a9130bb4b | ||
|
|
6e3fdcffa6 | ||
|
|
3cf4974cfe | ||
|
|
ba1639e1f7 | ||
|
|
791c0bf970 | ||
|
|
5987504e82 | ||
|
|
4602d19afd | ||
|
|
829e4e749f | ||
|
|
0f453631c4 | ||
|
|
cdbc2f2b9e | ||
|
|
562fc888b5 | ||
|
|
b0506b3e4b | ||
|
|
c75324a1a4 | ||
|
|
b3543499f0 | ||
|
|
ddf2e8a342 | ||
|
|
67aa337ee7 | ||
|
|
6eb85b943b | ||
|
|
75e98ab6d1 | ||
|
|
8feb0d8bb6 | ||
|
|
e6472033b1 | ||
|
|
82082c0a35 | ||
|
|
c4225d255e | ||
|
|
a71b49f405 | ||
|
|
89e0dd94a2 | ||
|
|
f5652e5d4e | ||
|
|
1302c48d8e | ||
|
|
7d1c585587 | ||
|
|
d19769f687 | ||
|
|
c6ff40e6aa | ||
|
|
08979fc8ff | ||
|
|
907980f17d | ||
|
|
0e09ca68a5 | ||
|
|
df565c2ccb | ||
|
|
82b01cca71 | ||
|
|
9cb7619730 | ||
|
|
beaab96cdf | ||
|
|
5d3958b794 | ||
|
|
0dee7f521b | ||
|
|
833d11aeb2 | ||
|
|
a03e42860f | ||
|
|
dea29b88c5 | ||
|
|
4a90412468 | ||
|
|
53eabdf513 | ||
|
|
f2245eff85 | ||
|
|
732c8b2a00 | ||
|
|
2e449cd972 | ||
|
|
a1486ff1b1 | ||
|
|
f01788bff9 | ||
|
|
dffda7e8c7 | ||
|
|
d2c9cc6e2b | ||
|
|
f37357f371 | ||
|
|
5d4c51eeb9 | ||
|
|
e16a3e6f74 | ||
|
|
edf612581f | ||
|
|
d855fee050 | ||
|
|
154334a414 | ||
|
|
40fe8aa533 | ||
|
|
7ba7ec9c97 | ||
|
|
df085816fc | ||
|
|
0cfae29887 | ||
|
|
c4da749362 | ||
|
|
dbe00ec2d2 | ||
|
|
41129c57bd | ||
|
|
3fddf10c3e | ||
|
|
4fef1b32cd | ||
|
|
21dd479a6b | ||
|
|
e6c2b58b2b | ||
|
|
ca5ebe78cd | ||
|
|
8d2dcf3a32 | ||
|
|
523d20a573 | ||
|
|
aae534130b | ||
|
|
7b6912fd28 | ||
|
|
665e5bfee1 | ||
|
|
1cdcc857d9 | ||
|
|
2cf87c7c50 | ||
|
|
ac16b57304 | ||
|
|
979de9323a |
@@ -1,4 +0,0 @@
|
||||
asterisk
|
||||
build.h
|
||||
ast_expr.c
|
||||
.version
|
||||
59
BUGS
Executable file → Normal file
59
BUGS
Executable file → Normal file
@@ -1,48 +1,23 @@
|
||||
* EVERYTHING MARKED WITH "XXX" IN THE SOURCE REPRESENTS A BUG! Sometimes
|
||||
these bugs are in asterisk, and sometimes they relate to the products
|
||||
that asterisk uses.
|
||||
Asterisk 1.0-RC-1 Known Major Bugs
|
||||
==================================
|
||||
* Some people still have issues with H.323
|
||||
* QuickNet driver still not entirely stable
|
||||
|
||||
* In general Asterisk is a very new program, and there are liable to be
|
||||
many bugs yet to be discovered, so if you think you've found one, please
|
||||
be sure to report it.
|
||||
Asterisk Bug Tracking Information
|
||||
=================================
|
||||
|
||||
* When you flip to call waiting on a tormenta channel while you have a
|
||||
three way call up, the parties in the three way cannot hear one another
|
||||
in the general case.
|
||||
To learn about and report Asterisk bugs or make feature
|
||||
requests, please visit the official Asterisk Bug Tracker
|
||||
at:
|
||||
|
||||
* No auto-reload in chan_zap yet
|
||||
http://bugs.digium.com
|
||||
|
||||
* Must be able to call park with flash-hook transfer
|
||||
For more information on using the bug tracker, or to
|
||||
learn how you can contribute by acting as a bug marshal
|
||||
please see:
|
||||
|
||||
======================================================================
|
||||
Short report on the voicemail system
|
||||
======================================================================
|
||||
Stuff We Need:
|
||||
http://www.digium.com/bugtracker.html
|
||||
|
||||
-Date/Time (conversion on the fly for different locales)
|
||||
-A more fleshed/emphasized Main Menu
|
||||
-Mailbox Options
|
||||
-useful for allowing user to set certain options
|
||||
-Notification of new vs. old messages
|
||||
-Notification of first and last messages (old and new)
|
||||
and a return to the Main Menu @ the end
|
||||
**-Better handling of lack of user input, specifically...
|
||||
infinite loops...
|
||||
currently found in: vm-instructions
|
||||
vm-msginstruct
|
||||
System MUST disconnect user for inactivity
|
||||
-Mid message menu w/
|
||||
pause/unpause
|
||||
seeking
|
||||
callback option
|
||||
option to get caller's number if available
|
||||
option to leave message directly on caller's voicemail
|
||||
if he/she has account on system
|
||||
-Also redesign the End Of Message Menu
|
||||
-Efficienty Question...
|
||||
Better to always rename msgs to being @ 0001
|
||||
or...
|
||||
Better to append new msgs numerically @ the
|
||||
end and use software to traverse them in
|
||||
order...saving cpu cycles on renaming files
|
||||
..could get messy w/ lots of users
|
||||
Thank you!
|
||||
|
||||
Mark
|
||||
|
||||
267
CHANGES
267
CHANGES
@@ -1,267 +0,0 @@
|
||||
Asterisk 0.4.0
|
||||
-- Merge and edit Nick's FXO dial support
|
||||
-- Reengineer SIP registration (outbound)
|
||||
-- Support call pickup on SIP and compatibly with ZAP
|
||||
-- Support 302 Redirect on SIP
|
||||
-- Management interface improvements
|
||||
-- Add "hint" support
|
||||
-- Improve call forwarding using new "Local" channel driver.
|
||||
-- Add "Local" channel
|
||||
-- Substantial SIP enhancements including retransmissions
|
||||
-- Enforce case sensitivity on extension/context names
|
||||
-- Add monitor support (Thanks, Mahmut)
|
||||
-- Add experimental "trunk" option to IAX2 for high density VoIP
|
||||
-- Add experimental "debug channel" command
|
||||
-- Add 'C' flag to dial command to reset call detail record (handy for calling cards)
|
||||
-- Add NAT and dynamic support to MGCP
|
||||
-- Allow selection of in-band, out-of-band, or INFO based DTMF
|
||||
-- Add contributed "*80" support to blacklist numbers (Thanks James!)
|
||||
-- Add "NAT" option to sip user, peer, friend
|
||||
-- Add experimental "IAX2" protocol
|
||||
-- Change special variable "EXTEN-n" to "EXTEN:n" to follow Bash syntax
|
||||
-- Add "Enhanced" AGI with audio pass-through (voice recognition anyone?)
|
||||
-- Choose best priority from codec from allow/disallow
|
||||
-- Reject SIP calls to self
|
||||
-- Allow SIP registration to provide an alternative contact
|
||||
-- Make HOLD on SIP make use of asterisk MOH
|
||||
-- Add supervised transfer (tested with Pingtel only)
|
||||
-- Allow maxexpirey and defaultexpirey to be runtime configurable for SIP
|
||||
-- Preliminary codec 13 support (RFC3389)
|
||||
-- Add app_authenticate for general purpose authentication
|
||||
-- Optimize RTP and smoother
|
||||
-- Create special variable "EXTEN-n" where it is extension stripped by n MSD
|
||||
-- Fix uninitialized frame pointer in channel.c
|
||||
-- Add global variables support under [globals] of extensions.conf
|
||||
-- Add macro support (show application Macro)
|
||||
-- Allow [123-5] etc in extensions
|
||||
-- Allow format of App(arg1,arg2,...) instead of just App,arg1|arg2 in dialplan
|
||||
-- Add message waiting indicator to SIP
|
||||
-- Fix double free bug in channel.c
|
||||
Asterisk 0.3.0
|
||||
-- Add fastfoward, rewind, seek, and truncate functions to streams
|
||||
-- Support registration
|
||||
-- Add G729 format
|
||||
-- Permit applications to return a digit indicating new extension
|
||||
-- Change "SHUTDOWN" to "STOP" in commands
|
||||
-- SIP "Hold" fixes and VXML URI support
|
||||
-- New chan_zap with 160 sample chunk size
|
||||
-- Add DTMF, MF, and Fax tone detector to dsp routines
|
||||
-- Allow overlap dialing (inbound) on PRI
|
||||
-- Enable tone detection with PRI
|
||||
-- Add special information tone detection
|
||||
-- Add Asterisk DB support
|
||||
-- Add pulse dialing
|
||||
-- Re-record all system prompts
|
||||
-- Change "timelen" to samples for better accuracy
|
||||
-- Move to editline, eliminating readline dependency
|
||||
-- Add peer "poke" support to SIP and IAX
|
||||
-- Add experimental call progress detection
|
||||
-- Add SIP authentication (digest)
|
||||
-- Add RDNIS
|
||||
-- Reroute faxes to "fax" extension
|
||||
-- Create ISDN/modem group concept
|
||||
-- Centralize indication
|
||||
-- Add initial MGCP support
|
||||
-- SIP debugging cleanup
|
||||
-- SIP reload
|
||||
-- SIP commands (show channels, etc)
|
||||
-- Add optional busy detection
|
||||
-- Add Visual Message Waiting Indicator (MDMF and SDMF)
|
||||
-- Add ambiguous extension matching
|
||||
-- Add *69
|
||||
-- Major SIP enhancements from SIPit
|
||||
-- Rewrite of ZAP CLASS features using subchannels
|
||||
-- Enhanced call parking
|
||||
-- Add extended outgoing spool support (pbx_spool)
|
||||
Asterisk 0.2.0
|
||||
-- Outbound origination API
|
||||
-- Call management improvements
|
||||
-- Add Do Not Disturb (*78, *79)
|
||||
-- Add agents
|
||||
-- Document variables
|
||||
-- Add transfer capability on the console
|
||||
-- Add SpeeX codec translator
|
||||
-- Add call queues
|
||||
-- Add setcallerid functionality (AGI, application)
|
||||
-- Add special variables ${CALLERID}, ${EXTEN}, ${CONTEXT}, ${PRIORITY}
|
||||
-- Don't echo cancel on pure TDM connections by default
|
||||
-- Implement Async GOTO
|
||||
-- Differentiate softhangups
|
||||
-- Add date/time
|
||||
Asterisk 0.1.12
|
||||
-- Fix for Big Endian machines
|
||||
-- MySQL CDR Engine
|
||||
-- Various SIP fixes and enhancements
|
||||
-- Add "zapateller application and arbitrary tone pairs
|
||||
-- Don't always start at "s"
|
||||
-- Separate linear mode for pseudo and real
|
||||
-- Add initial RTP and SIP support (no jitter buffer yet, unknown stability)
|
||||
-- Add 'h' extension, executed on hangup
|
||||
-- Add duration timer to message info
|
||||
-- Add web based voicemail checking ("make webvmail")
|
||||
-- Add ast_queue_frame function and eliminate frame pipes in most drivers
|
||||
-- Centralize host access (and possibly future ACL's)
|
||||
-- Add Caller*ID on PhoneJack (Thanks Nathan)
|
||||
-- Add "safe_asterisk" wrapper script to auto-restart Asterisk
|
||||
-- Indicate ringback on chan_phone
|
||||
-- Add answer confirmation (press '#' to confirm answer)
|
||||
-- Add distinctive ring support (e.g. Dial,Zap/4r2)
|
||||
-- Add ANSI/vt100 color support
|
||||
-- Make parking configurable through parking.conf
|
||||
-- Fix the empty voicemail problem
|
||||
-- Add Music On Hold
|
||||
-- Add ADSI Compiler (app_adsiprog)
|
||||
-- Extensive DISA re-work to improve tone generation
|
||||
-- Reset all idle channels every 10 minutes on a PRI
|
||||
-- Reset channels which are hungup with "channel in use"
|
||||
-- Implement VNAK support in chan_iax
|
||||
-- Fix chan_oss to support proper hangups and autoanswer
|
||||
-- Make shutdown properly hangup channels
|
||||
-- Add idling capability to chan_zap for idle-net
|
||||
-- Add "MeetMe" conferencing app (app_meetme)
|
||||
-- Add timing information to include
|
||||
Asterisk 0.1.11
|
||||
-- Add ISDN RAS capability
|
||||
-- Add stutter dialtone to Chan Zap
|
||||
-- Add "#include" capability to config files.
|
||||
-- Add call-forward variable to Chan Zap (*72, *73)
|
||||
-- Optimize IAX flow when transfer isn't possible
|
||||
-- Allow transmission of ANI over IAX
|
||||
Asterisk 0.1.10
|
||||
-- Make ast_readstring parameter be the max # of digits, not the max size with \0
|
||||
-- Make up any missing messages on the fly
|
||||
-- Add support for specific DTMF interruption to saying numbers
|
||||
-- Add new "u" and "b" options to condense busy/unavail handling
|
||||
-- Add support for RSA authentication on IAX calls
|
||||
-- Add support for ADSI compatible CPE
|
||||
-- Outgoing call queue
|
||||
-- Remote dialplan fixes for Quicknet
|
||||
-- Added AGI commands supporting TDD functions (RECEIVE CHAR & TDD MODE)
|
||||
-- Added TDD support (send/receive text in chan_zap)
|
||||
-- Fix all strncpy references
|
||||
-- Implement CSV CDR backend
|
||||
-- Implement Call Detail Records
|
||||
Asterisk 0.1.9
|
||||
-- Implement IAX quelching
|
||||
-- Allow Caller*ID to be overridden and suggested
|
||||
-- Configure defaults to use IAXTEL
|
||||
-- Allow remote dialplan polling via IAX
|
||||
-- Eliminate ast_longest_extension
|
||||
-- Implement dialplan request/reply
|
||||
-- Let peers have allow/disallow for codecs
|
||||
-- Change allow/deny to permit/deny in IAX
|
||||
-- Allow dialplan entries to match Caller*ID as well
|
||||
-- Added AGI (Asterisk Gateway Interface) scripting interface (app_agi)
|
||||
-- Added chan_zap for zapata telephony kernel interface, removed chan_tor
|
||||
-- Add convenience functions
|
||||
-- Fix race condition in channel hangup
|
||||
-- Fix memory leaks in both asterisk and iax frame allocations
|
||||
-- Add "iax show stats" command and -DTRACE_FRAMES (for frame tracing)
|
||||
-- Add DISA application (Thanks to Jim Dixon)
|
||||
-- Add IAX transfer support
|
||||
-- Add URL and HTML transmission
|
||||
-- Add application for sending images
|
||||
-- Add RedHat RPM spec file and build capability
|
||||
-- Fix GSM WAV file format bug
|
||||
-- Move ignorepat to main dialplan
|
||||
-- Add ability to specificy TOS bits in IAX
|
||||
-- Allow username:password in IAX strings
|
||||
-- Updates to PhoneJack interface
|
||||
-- Allow "servermail" in voicemail.conf to override e-mail in "from" line
|
||||
-- Add 'skip' option to app_playback
|
||||
-- Reject IAX calls on unknown extensions
|
||||
-- Fix version stuff
|
||||
Asterisk 0.1.8
|
||||
-- Keep track of version information
|
||||
-- Add -f to cause Asterisk not to fork
|
||||
-- Keep important information in voicemail .txt file
|
||||
-- Adtran Voice over Frame Relay updates
|
||||
-- Implement option setting/querying of channel drivers
|
||||
-- IAX performance improvements and protocol fixes
|
||||
-- Substantial enhancement of console channel driver
|
||||
-- Add IAX registration. Now IAX can dynamically register
|
||||
-- Add flash-hook transfer on tormenta channels
|
||||
-- Added Three Way Calling on tormenta channels
|
||||
-- Start on concept of zombie channel
|
||||
-- Add Call Waiting CallerID
|
||||
-- Keep track of who registeres contexts, includes, and extensions
|
||||
-- Added Call Waiting(tm), *67, *70, and *82 codes
|
||||
-- Move parked calls into "parkedcalls" context by default
|
||||
-- Allow dialplan to be displayed
|
||||
-- Allow "=>" instead of just "=" to make instantiation clearer
|
||||
-- Asterisk forks if called with no arguments
|
||||
-- Add remote control by running asterisk -vvvc
|
||||
-- Adjust verboseness with "set verbose" now
|
||||
-- No longer requires libaudiofile
|
||||
-- Install beep
|
||||
-- Make PBX Config module reload extensions on SIGHUP
|
||||
-- Allow modules to be reloaded when SIGHUP is received
|
||||
-- Variables now contain line numbers
|
||||
-- Make dialer send in band signalling
|
||||
-- Add record application
|
||||
-- Added PRI signalling to Tormenta driver
|
||||
-- Allow use of BYEXTENSION in "Goto"
|
||||
-- Allow adjustment of gains on tormenta channels
|
||||
-- Added raw PCM file format support
|
||||
-- Add U-law translator
|
||||
-- Fix DTMF handling in bridge code
|
||||
-- Fix access control with IAX
|
||||
* Asterisk 0.1.7
|
||||
-- Update configuration files and add some missing sounds
|
||||
-- Added ability to include one context in another
|
||||
-- Rewrite of PBX switching
|
||||
-- Major mods to dialler application
|
||||
-- Added Caller*ID spill reception
|
||||
-- Added Dialogic VOX file format support
|
||||
-- Added ADPCM Codec
|
||||
-- Add Tormenta driver (RBS signalling)
|
||||
-- Add Caller*ID spill creation
|
||||
-- Rewrite of translation layer entirely
|
||||
-- Add ability to run PBX without additional thread
|
||||
* Asterisk 0.1.6
|
||||
-- Make app_dial handle a lack of translators smoothly
|
||||
-- Add ISDN4Linux support -- dtmf is weird...
|
||||
-- Minor bug fixes
|
||||
* Asterisk 0.1.5
|
||||
-- Fix a small mistake in IAX
|
||||
-- Fix the QuickNet driver to work with newer cards
|
||||
* Asterisk 0.1.4
|
||||
-- Update VoFR some more
|
||||
-- Fix the QuickNet driver to work with LineJack
|
||||
-- Add ability to pass images for IAX.
|
||||
* Asterisk 0.1.3
|
||||
-- Update VoFR for latest sangoma code
|
||||
-- Update QuickNet Driver
|
||||
-- Add text message handling
|
||||
-- Fix transfers to use "default" if not in current context
|
||||
-- Add call parking
|
||||
-- Improve format/content negotiation
|
||||
-- Added support for multiple languages
|
||||
-- Bug fixes, as always...
|
||||
* Asterisk 0.1.2
|
||||
-- Updated README file with a "Getting Started" section
|
||||
-- Added sample sounds and configuration files.
|
||||
-- Added LPC10 very low bandwidth (low quality) compression
|
||||
-- Enhanced translation selection mechanism.
|
||||
-- Enhanced IAX jitter buffer, improved reliability
|
||||
-- Support echo cancelation on PhoneJack
|
||||
-- Updated PhoneJack driver to std. Telephony interface
|
||||
-- Added app_echo for evaluating VoIP latency
|
||||
-- Added app_system to execute arbitrary programs
|
||||
-- Updated sample configuration files
|
||||
-- Added OSS channel driver (full duplex only)
|
||||
-- Added IAX implementation
|
||||
-- Fixed some deadlocks.
|
||||
-- A whole bunch of bug fixes
|
||||
* Asterisk 0.1.1
|
||||
-- Revised translator, fixed some general race conditions throughout *
|
||||
-- Made dialer somewhat more aware of incompatible voice channels
|
||||
-- Added Voice Modem driver and A/Open Modem Driver stub
|
||||
-- Added MP3 decoder channel
|
||||
-- Added Microsoft WAV49 support
|
||||
-- Revised License -- Pure GPL, nothing else
|
||||
-- Modified Copyright statement since code is still currently owned by author
|
||||
-- Added RAW GSM headerless data format
|
||||
-- Innumerable bug fixes
|
||||
* Asterisk 0.1.0
|
||||
-- Initial Release
|
||||
23
CREDITS
Executable file → Normal file
23
CREDITS
Executable file → Normal file
@@ -5,12 +5,16 @@ Asterisk:
|
||||
|
||||
Pilosoft, Inc. - for supporting ADSI development in Asterisk
|
||||
|
||||
Asterlink, Inc. - for supporting broad Asterisk development
|
||||
|
||||
GFS - for supporting ALSA development
|
||||
|
||||
Telesthetic - for supporting SIP development
|
||||
|
||||
Christos Ricudis - for substantial code contributions
|
||||
|
||||
Paul Bagyenda, Digital Solutions - for initial Voicetronix driver development
|
||||
|
||||
=== WISHLIST CONTRIBUTERS ===
|
||||
Jeremy McNamara - SpeeX support
|
||||
Nick Seraphin - RDNIS support
|
||||
@@ -22,6 +26,8 @@ Wasim - Hangup detect
|
||||
PhoneJack and Linejack card to the project. (http://www.quicknet.net)
|
||||
|
||||
=== MISCELLANEOUS PATCHES ===
|
||||
Anthony Minessale - Countless big and small fixes, and relentless forward push
|
||||
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
|
||||
@@ -30,6 +36,8 @@ 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 enhancmenets to Voicemail
|
||||
wjordan@vonage.com
|
||||
Jac Kersing - Various fixes
|
||||
Steven Critchfield - Seek and Trunc functions for playback and recording
|
||||
critch@basesys.com
|
||||
@@ -40,10 +48,25 @@ 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 - - Route lookup code; ast_localtime(), ast_say_date_with_format();
|
||||
GotoIfTime, Random, SayUnixTime, HasNewVoicemail, and Cut applications,
|
||||
along with various other patches. 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, various other
|
||||
bugs. tholo@sigmasoft.com
|
||||
Brian West - ODBC support and Bug Marshaling
|
||||
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
|
||||
|
||||
=== OTHER CONTRIBUTIONS ===
|
||||
John Todd - Monkey sounds and associated teletorture prompt
|
||||
|
||||
=== HOLD MUSIC ===
|
||||
Music provided by www.opsound.org
|
||||
|
||||
=== OTHER SOURCE CODE IN ASTERISK ===
|
||||
|
||||
I did not implement the codecs in asterisk. Here is the copyright on the
|
||||
|
||||
640
ChangeLog
Normal file
640
ChangeLog
Normal file
@@ -0,0 +1,640 @@
|
||||
NOTE: Corrections or additions to the ChangeLog may be submitted to
|
||||
http://bugs.digium.com. Documentation and formatting fixes are not
|
||||
not listed here. A complete listing of changes is available through
|
||||
the Asterisk-CVS mailing list hosted at http://lists.digium.com.
|
||||
|
||||
Asterisk 1.0.10
|
||||
|
||||
-- chan_local
|
||||
-- In releases 1.0.8 and 1.0.9, the Local channels that are created would
|
||||
not be masqueraded into the new channel type. This has now been fixed.
|
||||
-- chan_sip
|
||||
-- The 'insecure' options have been changed to support matching peersby IP
|
||||
only, not requiring authentication on incoming invites, or both. Before,
|
||||
to not require authentication on incoming invites also required matching
|
||||
peers based on IP only.
|
||||
-- chan_zap
|
||||
-- Before, call waiting could occur during the initial ringing on the line.
|
||||
This has now been fixed.
|
||||
-- app_disa
|
||||
-- We will now not set the accountcode if one is not supplied.
|
||||
-- app_meetme
|
||||
-- If the first caller into a conference hangs up while being prompted for
|
||||
the conference pin number, the conference will no longer be held open.
|
||||
-- app_userevent
|
||||
-- Events created with this application were indicated as a "call" event
|
||||
instead of a "user" event. This made the "user" event permissions
|
||||
not work correctly.
|
||||
-- app_voicemail
|
||||
-- When using the externpass option for voicemail, the password will be
|
||||
immediately updated in memory as well, instead of having to wait for
|
||||
the next time the configuration is reloaded.
|
||||
-- app_zapras
|
||||
-- We now ensure buffer policy is restored after RAS is done with a channel.
|
||||
This could cause audio problems on the channel after zapras is done
|
||||
with it.
|
||||
-- res_agi
|
||||
-- We now unmask the SIGHUP signal before executing an AGI script. This
|
||||
fixes problems where some AGI scripts would continue running long after
|
||||
the call is over.
|
||||
-- extensions
|
||||
-- A potential crash has been fixed when calling LEN() to get the length of
|
||||
a string that was 80 characters or larger.
|
||||
-- logger
|
||||
-- The Asterisk logger will automatically detect when a log file needs to
|
||||
be rotated. However, this feature could put Asterisk in a nasty loop
|
||||
that would result in a crash.
|
||||
-- general
|
||||
-- Added man pages for astgenkey, autosupport, and safe_asterisk
|
||||
|
||||
Asterisk 1.0.9
|
||||
|
||||
-- fix bug in callerid matching in the dialplan that was introduced in 1.0.8
|
||||
|
||||
Asterisk 1.0.8
|
||||
|
||||
-- chan_zap
|
||||
-- Asterisk will now also look in the regular context for the fax extension
|
||||
while executing a macro. Previously, for this to work, the fax extension
|
||||
would have to be included in the macro definition.
|
||||
-- On some systems, ALERTING will be sent after PROCEEDING, so code has been
|
||||
added to account for this case.
|
||||
-- If no extension is specified on an overlap call, the 's' extension will
|
||||
be used.
|
||||
-- chan_sip
|
||||
-- We no longer send a "to" tag on "100 Trying" messages, as it is
|
||||
inappropriate to do so.
|
||||
-- We now respond correctly to an invite for T.38 with a "488 Not acceptable
|
||||
here"
|
||||
-- We now discard saved tags on 401/407 responses in case the provider we're
|
||||
talking to tries to pull a dirty trick on us and change it.
|
||||
-- rtptimeout options will now be correctly set on a peer basis rather than
|
||||
only global
|
||||
-- chan_mgcp
|
||||
-- Fixed setting of accountcode
|
||||
-- Fixed where *67 to block callerid only worked for first call
|
||||
-- chan_agent
|
||||
-- We now will not pass audio until the agent has acked the call if the
|
||||
configuration
|
||||
is set up for the agent to do so.
|
||||
-- chan_alsa
|
||||
-- Fixed problems with the unloading of this module
|
||||
-- res_agi
|
||||
-- A fix has been added to prevent calls from being hung up when more than
|
||||
one call is executing an AGI script calling the GET DATA command.
|
||||
-- AGI scripts will now continue to run even if a file was not found with
|
||||
the GET DATA command.
|
||||
-- When calling SAY NUMBER with a number like 09, we will now say "nine"
|
||||
instead of "zero"
|
||||
-- app_dial
|
||||
-- There was a problem where text frames would not be forwarded before the
|
||||
channel has been answered.
|
||||
-- app_disa
|
||||
-- Fixed the timeout used when no password is set
|
||||
-- app_queue
|
||||
-- Distinctive ring has been fixed to work for queue members
|
||||
-- rtp
|
||||
-- Fixed a logic error when setting the "rtpchecksums" option
|
||||
-- say.c
|
||||
-- A problem has been fixed with saying the date in Spanish.
|
||||
-- Makefile
|
||||
-- A line was missing for the autosupport script that caused "make rpm" to
|
||||
fail
|
||||
-- format_wav_gsm
|
||||
-- Fixed a problem with wav formatting that prevented files from being
|
||||
played in some media players
|
||||
-- pbx_spool
|
||||
-- Fixed if the last line of text in a file for the call spool did not
|
||||
contain a new line, it would not be processed
|
||||
-- logger
|
||||
-- Fixed the logger so that color escape sequences wouldn't be sent to the
|
||||
logs
|
||||
-- format_sln
|
||||
-- A lot of changes were made to correctly handle signed linear format on
|
||||
big endian machines
|
||||
-- asterisk.conf
|
||||
-- fix 'highpriority' option for asterisk.conf
|
||||
|
||||
Asterisk 1.0.7
|
||||
|
||||
-- chan_sip
|
||||
-- The fix for some codec availibility issues in 1.0.6 caused music on hold
|
||||
problems, but has now been fixed.
|
||||
-- chan_skinny
|
||||
-- A check has been added to avoid a crash.
|
||||
-- chan_iax2
|
||||
-- A feature has been added to CVS head to have the option of sending
|
||||
timestamps with trunk frames. It is not supported in 1.0, but a change
|
||||
has been made so that it will at least not choke if sent trunk
|
||||
timestamps.
|
||||
-- app_voicemail
|
||||
-- Some checks have been added to avoid a crash.
|
||||
-- speex
|
||||
-- The path /usr/include/speex has been added for a place to look for the
|
||||
speex header.
|
||||
|
||||
Asterisk 1.0.6
|
||||
|
||||
-- chan_iax2:
|
||||
-- Fixed a bug dealing with a division by zero that could cause a crash
|
||||
-- chan_sip:
|
||||
-- Behavior was changed so that when a registration fails due to DNS
|
||||
resolution issues, a retry will be attempted in 20 seconds.
|
||||
-- Peer settings were not reset to null values when reloading the
|
||||
configuration file. Behavior has been changed so that these values are
|
||||
now cleared.
|
||||
-- 'restrictcid' now properly works on MySQL peers.
|
||||
-- Only use the default callerid if it has been specified.
|
||||
-- Asterisk was not sending the same From: line in SIP messages during
|
||||
certain times. Fixed to make sure it stays the same. This makes some
|
||||
providers happier, to a working state.
|
||||
-- Certain circumstances involving a blank callerid caused asterisk to
|
||||
segmentation fault.
|
||||
-- There was a problem incorrectly matching codec availablity when global
|
||||
preferences were different from that of the user. To fix this,
|
||||
processing of SDP data has been moved to after determining who the call
|
||||
is coming from.
|
||||
-- Asterisk would run out of RTP ports while waiting for SUBSCRIBE's to
|
||||
expire even though an RTP port isn't needed in this case. This has been
|
||||
fixed by releasing the ports early.
|
||||
-- chan_zap:
|
||||
-- During a certain scenario when using flash and '#' transfers you would
|
||||
hear the other person and the music they were hearing. This has been
|
||||
fixed.
|
||||
-- A fix for a compilation issue with gcc4 was added.
|
||||
-- chan_modem_bestdata:
|
||||
-- A fix for a compilation issue with gcc4 was added.
|
||||
-- format_g729:
|
||||
-- Treat a 10-byte read as an end of file indication instead of an error.
|
||||
Some G729 encoders like to put 10-bytes at the end to indicate this.
|
||||
-- res_features:
|
||||
-- During certain situations when parking a call, both endpoints would get
|
||||
musiconhold. This has been fixed so the individual who parked the call
|
||||
will hear the digits and not musiconhold.
|
||||
-- app_dial:
|
||||
-- DIALEDPEERNUMBER is now being set, so if you attempted to use it in the
|
||||
past and failed, it should work now.
|
||||
-- A callerid change caused many headaches, this has been reversed to the
|
||||
original 1.0 behavior.
|
||||
-- A crash caused with the combination of the 'g' option and # transfer was
|
||||
fixed.
|
||||
-- app_voicemail:
|
||||
-- If two people hit the voicemail system at the same time, and were leaving
|
||||
a message the second message was overwriting the first. This has been
|
||||
fixed so that each one is distinct and will not overwrite eachother.
|
||||
-- cdr_tds:
|
||||
-- If the server you were using was going down, it had the potential to
|
||||
bring your asterisk server down with it. Extra stuff has been added so
|
||||
as to bring in more error/connection checking.
|
||||
-- cdr_pgsql:
|
||||
-- This will now attempt to reconnect after a connection problem.
|
||||
-- IAXY firmware:
|
||||
-- This has been updated to version 23. It includes a fix for lost
|
||||
registrations.
|
||||
-- internals
|
||||
-- Behavior was changed for 'show codec <number>' to make it more intuitive.
|
||||
-- DNS failures and asterisk do not get along too well, this is not totally
|
||||
the case anymore.
|
||||
-- Asterisk will now handle DNS failures at startup more gracefully, and
|
||||
won't crash and burn
|
||||
-- Choosing to append to a wave file would render the outputted wave file
|
||||
corrupt. Appending now works again.
|
||||
-- If you failed to define certain keys, asterisk had the potential to crash
|
||||
when seeing if you had used them.
|
||||
-- Attempting to use such things as ${EXTEN:-1} gave a wrong return value.
|
||||
However, this was never a documented feature...
|
||||
|
||||
Asterisk 1.0.5
|
||||
|
||||
-- chan_zap
|
||||
-- fix a callerid bug introduced in 1.0.4
|
||||
-- app_queue
|
||||
-- fix some penalty behavior
|
||||
|
||||
Asterisk 1.0.4
|
||||
|
||||
-- general
|
||||
-- fix memory leak evident with extensive use of variables
|
||||
-- update IAXy firmware to version 22
|
||||
-- enable some special write protection
|
||||
-- enable outbound DTMF
|
||||
-- fix seg fault with incorrect usage of SetVar
|
||||
-- other minor fixes including typos and doc updates
|
||||
-- chan_sip
|
||||
-- fix codecs to not be case sensitive
|
||||
-- Re-use auth credentials
|
||||
-- fix MWI when using type=friend
|
||||
-- fix global NAT option
|
||||
-- chan_agent / chan_local
|
||||
-- fix incorrect use count
|
||||
-- chan_zap
|
||||
-- Allow CID rings to be configured in zapata.conf
|
||||
-- no more patching needed for UK CID
|
||||
-- app_macro
|
||||
-- allow Macros to exit with '*' or '#' like regular extension processing
|
||||
-- app_voicemail
|
||||
-- don't allow '#' as a password
|
||||
-- add option to save voicemail before going to the operator
|
||||
-- fix global operator=yes
|
||||
-- app_read
|
||||
-- return 0 instead of -1 if user enters nothing
|
||||
-- res_agi
|
||||
-- don't exit AGI when file not found to stream
|
||||
-- send script parameter when using FastAGI
|
||||
|
||||
Asterisk 1.0.3
|
||||
|
||||
-- chan_zap
|
||||
-- fix seg fault when doing *0 to flash a trunk
|
||||
-- rtp
|
||||
-- seg fault fix
|
||||
-- chan_sip
|
||||
-- fix to prevent seg fault when attempting a transfer
|
||||
-- fix bug with supervised transfers
|
||||
-- fix codec preferences
|
||||
-- chan_h323
|
||||
-- fix compilation problem
|
||||
-- chan_iax2
|
||||
-- avoid a deadlock related to a static config of a BUNCH of peers
|
||||
-- cdr_pgsql
|
||||
-- fix memory leak when reading config
|
||||
-- Numerous other minor bug fixes
|
||||
|
||||
Asterisk 1.0.2
|
||||
|
||||
-- Major bugfix release
|
||||
|
||||
Asterisk 1.0.1
|
||||
|
||||
-- Added AGI over TCP support
|
||||
-- Add ability to purge callers from queue if no agents are logged in
|
||||
-- Fix inband PRI indication detection
|
||||
-- Fix for MGCP - always request digits if no RTP stream
|
||||
-- Fixed seg fault for ast_control_streamfile
|
||||
-- Make pick-up extension configurable via features.conf
|
||||
-- Numerous other bug fixes
|
||||
|
||||
Asterisk 1.0.0
|
||||
-- Use Q.931 standard cause codes for asterisk cause codes
|
||||
-- Bug fixes from the bug tracker
|
||||
Asterisk 1.0-RC2
|
||||
-- Additional CDR backends
|
||||
-- Allow muted to reconnect
|
||||
-- Call parking improvements (including SIP parking support)
|
||||
-- Added licensed hold music from opsound.org
|
||||
-- GR-303 and Zap improvements
|
||||
-- More bug fixes from the bug tracker
|
||||
-- Improved FreeBSD/OpenBSD/MacOS X support
|
||||
Asterisk 1.0-RC1
|
||||
-- Innumerable bug fixes and features from the bug tracker
|
||||
-- Added Open Settlement Protocol (OSP) support
|
||||
-- Added Non-facility Associated Signalling (NFAS) Support
|
||||
-- Added alarm Monitoring support
|
||||
-- Added new MeetMe options
|
||||
-- Added GR-303 Support
|
||||
-- Added trunk groups
|
||||
-- ADPCM Standardization
|
||||
-- Numerous bug fixes
|
||||
-- Add IAX2 Firmware Support
|
||||
-- Add G.726 support
|
||||
-- Add ices/icecast support
|
||||
-- Numerous bug fixes
|
||||
Asterisk 0.7.2
|
||||
-- Countless small bug fixes from bug tracker
|
||||
-- DSP Fixes
|
||||
-- Fix unloading of Zaptel
|
||||
-- Pass Caller*ID/ANI properly on call forwarding
|
||||
-- Add indication for Italy
|
||||
Asterisk 0.7.1
|
||||
-- Fixed timed include context's and GotoIfTime
|
||||
-- Fixed chan_h323 it now gets remote ip properly instead of 127.0.0.1
|
||||
Asterisk 0.7.0
|
||||
-- Removed MP3 format and codec
|
||||
-- Can now load and unload SIP,IAX,IAX2,H323 channels without core
|
||||
-- Fixed various compiler warnings and clean up source tree
|
||||
-- Preliminary AES Support
|
||||
-- Fix SIP REINVITE
|
||||
-- Outbound SIP registration behind NAT using externip
|
||||
-- More CLI documentation and clean up
|
||||
-- Pin numbers on MeeMe
|
||||
-- Dynamic MeetMe conferences are more consistent with static conferences
|
||||
-- Added channel variables ${HANGUPCAUSE}, ${SIPDOMAIN}, ${TIMESTAMP}, ${ACCONTCODE}
|
||||
-- ODBC support for logging CDRs
|
||||
-- Indications for Norway and New Zeland
|
||||
-- Major redesign of app_voicemail
|
||||
-- Syslog support
|
||||
-- Reload logfiles with CLI command 'logger reload' and rotate logs with "logger rotate'
|
||||
-- Configurable DEBUG, NOTICE, WARNING, ERROR and ast_verbose messages now appear on remote console
|
||||
-- Properly reaping any zombie processes
|
||||
-- Added applications SayUnixTime, SetCDRUserField, HasNewVoicemail, ZapScan, Random, ResetCDR, NoCDR
|
||||
-- Make PRI Hangup Cause available to the dialplan
|
||||
-- Verify included contexts in extensions.conf
|
||||
-- Add DESTDIR support for building RPMs and packages
|
||||
-- Do route lookups on OpenBSD
|
||||
-- Add support for building on FreeBSD and OS X
|
||||
-- Add support for PostgreSQL in Voicemail
|
||||
-- Translate SIP hangup cause to PRI hangup cause where needed
|
||||
-- Better support for MOH in IAX2
|
||||
-- Fix SIP problem where channels were not removed on BYE
|
||||
-- Display codecs by name
|
||||
-- Remove MySQL and put PGSql instead for licensing reasons
|
||||
-- Better capability matching in SIP
|
||||
-- Full IBR4 compliance for chan_zap
|
||||
-- More flexible CDR handling
|
||||
-- Distinguish between BUSY and FAILURE on outbound calls
|
||||
-- Add initial support for SCCP via chan_skinny
|
||||
-- Better support for Future Group B signaling
|
||||
Asterisk 0.5.0
|
||||
-- Retain IAX2 and SIP registrations past shutdown/crash and restart
|
||||
-- True data mode bridging when possible
|
||||
-- H.323 build improvements
|
||||
-- Agent Callback-login support
|
||||
-- RFC2833 Improvements
|
||||
-- Add thread debugging
|
||||
-- Add optional pedantic SIP checking for Pingtel
|
||||
-- Allow extension names, include context, switch to use global vars.
|
||||
-- Allow variables in extensions.conf to reference previously defined ones
|
||||
-- Merge voicemail enhancements (app_voicemail2)
|
||||
-- Add multiple queueing strategies
|
||||
-- Merge support for 'T'
|
||||
-- Allow pending agent calling (Agent/:1)
|
||||
-- Add groupings to agents.conf
|
||||
-- Add video support to IAX2
|
||||
-- Zaptel optimize playback
|
||||
-- Add video support to SIP
|
||||
-- Make RTP ports configurable
|
||||
-- Add RDNIS support to SIP and IAX2
|
||||
-- Add transfer app (implement in SIP and IAX2)
|
||||
-- Make voicemail segmentable by context (app_voicemail2)
|
||||
-- Major restructuring of voicemail (app_voicemail2)
|
||||
-- Add initial ENUM support
|
||||
-- Add malloc debugging support
|
||||
-- Add preliminary Voicetronix support
|
||||
-- Add iLBC codec
|
||||
Asterisk 0.4.0
|
||||
-- Merge and edit Nick's FXO dial support
|
||||
-- Reengineer SIP registration (outbound)
|
||||
-- Support call pickup on SIP and compatibly with ZAP
|
||||
-- Support 302 Redirect on SIP
|
||||
-- Management interface improvements
|
||||
-- Add "hint" support
|
||||
-- Improve call forwarding using new "Local" channel driver.
|
||||
-- Add "Local" channel
|
||||
-- Substantial SIP enhancements including retransmissions
|
||||
-- Enforce case sensitivity on extension/context names
|
||||
-- Add monitor support (Thanks, Mahmut)
|
||||
-- Add experimental "trunk" option to IAX2 for high density VoIP
|
||||
-- Add experimental "debug channel" command
|
||||
-- Add 'C' flag to dial command to reset call detail record (handy for calling cards)
|
||||
-- Add NAT and dynamic support to MGCP
|
||||
-- Allow selection of in-band, out-of-band, or INFO based DTMF
|
||||
-- Add contributed "*80" support to blacklist numbers (Thanks James!)
|
||||
-- Add "NAT" option to sip user, peer, friend
|
||||
-- Add experimental "IAX2" protocol
|
||||
-- Change special variable "EXTEN-n" to "EXTEN:n" to follow Bash syntax
|
||||
-- Add "Enhanced" AGI with audio pass-through (voice recognition anyone?)
|
||||
-- Choose best priority from codec from allow/disallow
|
||||
-- Reject SIP calls to self
|
||||
-- Allow SIP registration to provide an alternative contact
|
||||
-- Make HOLD on SIP make use of asterisk MOH
|
||||
-- Add supervised transfer (tested with Pingtel only)
|
||||
-- Allow maxexpirey and defaultexpirey to be runtime configurable for SIP
|
||||
-- Preliminary codec 13 support (RFC3389)
|
||||
-- Add app_authenticate for general purpose authentication
|
||||
-- Optimize RTP and smoother
|
||||
-- Create special variable "EXTEN-n" where it is extension stripped by n MSD
|
||||
-- Fix uninitialized frame pointer in channel.c
|
||||
-- Add global variables support under [globals] of extensions.conf
|
||||
-- Add macro support (show application Macro)
|
||||
-- Allow [123-5] etc in extensions
|
||||
-- Allow format of App(arg1,arg2,...) instead of just App,arg1|arg2 in dialplan
|
||||
-- Add message waiting indicator to SIP
|
||||
-- Fix double free bug in channel.c
|
||||
Asterisk 0.3.0
|
||||
-- Add fastfoward, rewind, seek, and truncate functions to streams
|
||||
-- Support registration
|
||||
-- Add G729 format
|
||||
-- Permit applications to return a digit indicating new extension
|
||||
-- Change "SHUTDOWN" to "STOP" in commands
|
||||
-- SIP "Hold" fixes and VXML URI support
|
||||
-- New chan_zap with 160 sample chunk size
|
||||
-- Add DTMF, MF, and Fax tone detector to dsp routines
|
||||
-- Allow overlap dialing (inbound) on PRI
|
||||
-- Enable tone detection with PRI
|
||||
-- Add special information tone detection
|
||||
-- Add Asterisk DB support
|
||||
-- Add pulse dialing
|
||||
-- Re-record all system prompts
|
||||
-- Change "timelen" to samples for better accuracy
|
||||
-- Move to editline, eliminating readline dependency
|
||||
-- Add peer "poke" support to SIP and IAX
|
||||
-- Add experimental call progress detection
|
||||
-- Add SIP authentication (digest)
|
||||
-- Add RDNIS
|
||||
-- Reroute faxes to "fax" extension
|
||||
-- Create ISDN/modem group concept
|
||||
-- Centralize indication
|
||||
-- Add initial MGCP support
|
||||
-- SIP debugging cleanup
|
||||
-- SIP reload
|
||||
-- SIP commands (show channels, etc)
|
||||
-- Add optional busy detection
|
||||
-- Add Visual Message Waiting Indicator (MDMF and SDMF)
|
||||
-- Add ambiguous extension matching
|
||||
-- Add *69
|
||||
-- Major SIP enhancements from SIPit
|
||||
-- Rewrite of ZAP CLASS features using subchannels
|
||||
-- Enhanced call parking
|
||||
-- Add extended outgoing spool support (pbx_spool)
|
||||
Asterisk 0.2.0
|
||||
-- Outbound origination API
|
||||
-- Call management improvements
|
||||
-- Add Do Not Disturb (*78, *79)
|
||||
-- Add agents
|
||||
-- Document variables
|
||||
-- Add transfer capability on the console
|
||||
-- Add SpeeX codec translator
|
||||
-- Add call queues
|
||||
-- Add setcallerid functionality (AGI, application)
|
||||
-- Add special variables ${CALLERID}, ${EXTEN}, ${CONTEXT}, ${PRIORITY}
|
||||
-- Don't echo cancel on pure TDM connections by default
|
||||
-- Implement Async GOTO
|
||||
-- Differentiate softhangups
|
||||
-- Add date/time
|
||||
Asterisk 0.1.12
|
||||
-- Fix for Big Endian machines
|
||||
-- MySQL CDR Engine
|
||||
-- Various SIP fixes and enhancements
|
||||
-- Add "zapateller application and arbitrary tone pairs
|
||||
-- Don't always start at "s"
|
||||
-- Separate linear mode for pseudo and real
|
||||
-- Add initial RTP and SIP support (no jitter buffer yet, unknown stability)
|
||||
-- Add 'h' extension, executed on hangup
|
||||
-- Add duration timer to message info
|
||||
-- Add web based voicemail checking ("make webvmail")
|
||||
-- Add ast_queue_frame function and eliminate frame pipes in most drivers
|
||||
-- Centralize host access (and possibly future ACL's)
|
||||
-- Add Caller*ID on PhoneJack (Thanks Nathan)
|
||||
-- Add "safe_asterisk" wrapper script to auto-restart Asterisk
|
||||
-- Indicate ringback on chan_phone
|
||||
-- Add answer confirmation (press '#' to confirm answer)
|
||||
-- Add distinctive ring support (e.g. Dial,Zap/4r2)
|
||||
-- Add ANSI/vt100 color support
|
||||
-- Make parking configurable through parking.conf
|
||||
-- Fix the empty voicemail problem
|
||||
-- Add Music On Hold
|
||||
-- Add ADSI Compiler (app_adsiprog)
|
||||
-- Extensive DISA re-work to improve tone generation
|
||||
-- Reset all idle channels every 10 minutes on a PRI
|
||||
-- Reset channels which are hungup with "channel in use"
|
||||
-- Implement VNAK support in chan_iax
|
||||
-- Fix chan_oss to support proper hangups and autoanswer
|
||||
-- Make shutdown properly hangup channels
|
||||
-- Add idling capability to chan_zap for idle-net
|
||||
-- Add "MeetMe" conferencing app (app_meetme)
|
||||
-- Add timing information to include
|
||||
Asterisk 0.1.11
|
||||
-- Add ISDN RAS capability
|
||||
-- Add stutter dialtone to Chan Zap
|
||||
-- Add "#include" capability to config files.
|
||||
-- Add call-forward variable to Chan Zap (*72, *73)
|
||||
-- Optimize IAX flow when transfer isn't possible
|
||||
-- Allow transmission of ANI over IAX
|
||||
Asterisk 0.1.10
|
||||
-- Make ast_readstring parameter be the max # of digits, not the max size with \0
|
||||
-- Make up any missing messages on the fly
|
||||
-- Add support for specific DTMF interruption to saying numbers
|
||||
-- Add new "u" and "b" options to condense busy/unavail handling
|
||||
-- Add support for RSA authentication on IAX calls
|
||||
-- Add support for ADSI compatible CPE
|
||||
-- Outgoing call queue
|
||||
-- Remote dialplan fixes for Quicknet
|
||||
-- Added AGI commands supporting TDD functions (RECEIVE CHAR & TDD MODE)
|
||||
-- Added TDD support (send/receive text in chan_zap)
|
||||
-- Fix all strncpy references
|
||||
-- Implement CSV CDR backend
|
||||
-- Implement Call Detail Records
|
||||
Asterisk 0.1.9
|
||||
-- Implement IAX quelching
|
||||
-- Allow Caller*ID to be overridden and suggested
|
||||
-- Configure defaults to use IAXTEL
|
||||
-- Allow remote dialplan polling via IAX
|
||||
-- Eliminate ast_longest_extension
|
||||
-- Implement dialplan request/reply
|
||||
-- Let peers have allow/disallow for codecs
|
||||
-- Change allow/deny to permit/deny in IAX
|
||||
-- Allow dialplan entries to match Caller*ID as well
|
||||
-- Added AGI (Asterisk Gateway Interface) scripting interface (app_agi)
|
||||
-- Added chan_zap for zapata telephony kernel interface, removed chan_tor
|
||||
-- Add convenience functions
|
||||
-- Fix race condition in channel hangup
|
||||
-- Fix memory leaks in both asterisk and iax frame allocations
|
||||
-- Add "iax show stats" command and -DTRACE_FRAMES (for frame tracing)
|
||||
-- Add DISA application (Thanks to Jim Dixon)
|
||||
-- Add IAX transfer support
|
||||
-- Add URL and HTML transmission
|
||||
-- Add application for sending images
|
||||
-- Add RedHat RPM spec file and build capability
|
||||
-- Fix GSM WAV file format bug
|
||||
-- Move ignorepat to main dialplan
|
||||
-- Add ability to specificy TOS bits in IAX
|
||||
-- Allow username:password in IAX strings
|
||||
-- Updates to PhoneJack interface
|
||||
-- Allow "servermail" in voicemail.conf to override e-mail in "from" line
|
||||
-- Add 'skip' option to app_playback
|
||||
-- Reject IAX calls on unknown extensions
|
||||
-- Fix version stuff
|
||||
Asterisk 0.1.8
|
||||
-- Keep track of version information
|
||||
-- Add -f to cause Asterisk not to fork
|
||||
-- Keep important information in voicemail .txt file
|
||||
-- Adtran Voice over Frame Relay updates
|
||||
-- Implement option setting/querying of channel drivers
|
||||
-- IAX performance improvements and protocol fixes
|
||||
-- Substantial enhancement of console channel driver
|
||||
-- Add IAX registration. Now IAX can dynamically register
|
||||
-- Add flash-hook transfer on tormenta channels
|
||||
-- Added Three Way Calling on tormenta channels
|
||||
-- Start on concept of zombie channel
|
||||
-- Add Call Waiting CallerID
|
||||
-- Keep track of who registeres contexts, includes, and extensions
|
||||
-- Added Call Waiting(tm), *67, *70, and *82 codes
|
||||
-- Move parked calls into "parkedcalls" context by default
|
||||
-- Allow dialplan to be displayed
|
||||
-- Allow "=>" instead of just "=" to make instantiation clearer
|
||||
-- Asterisk forks if called with no arguments
|
||||
-- Add remote control by running asterisk -vvvc
|
||||
-- Adjust verboseness with "set verbose" now
|
||||
-- No longer requires libaudiofile
|
||||
-- Install beep
|
||||
-- Make PBX Config module reload extensions on SIGHUP
|
||||
-- Allow modules to be reloaded when SIGHUP is received
|
||||
-- Variables now contain line numbers
|
||||
-- Make dialer send in band signalling
|
||||
-- Add record application
|
||||
-- Added PRI signalling to Tormenta driver
|
||||
-- Allow use of BYEXTENSION in "Goto"
|
||||
-- Allow adjustment of gains on tormenta channels
|
||||
-- Added raw PCM file format support
|
||||
-- Add U-law translator
|
||||
-- Fix DTMF handling in bridge code
|
||||
-- Fix access control with IAX
|
||||
* Asterisk 0.1.7
|
||||
-- Update configuration files and add some missing sounds
|
||||
-- Added ability to include one context in another
|
||||
-- Rewrite of PBX switching
|
||||
-- Major mods to dialler application
|
||||
-- Added Caller*ID spill reception
|
||||
-- Added Dialogic VOX file format support
|
||||
-- Added ADPCM Codec
|
||||
-- Add Tormenta driver (RBS signalling)
|
||||
-- Add Caller*ID spill creation
|
||||
-- Rewrite of translation layer entirely
|
||||
-- Add ability to run PBX without additional thread
|
||||
* Asterisk 0.1.6
|
||||
-- Make app_dial handle a lack of translators smoothly
|
||||
-- Add ISDN4Linux support -- dtmf is weird...
|
||||
-- Minor bug fixes
|
||||
* Asterisk 0.1.5
|
||||
-- Fix a small mistake in IAX
|
||||
-- Fix the QuickNet driver to work with newer cards
|
||||
* Asterisk 0.1.4
|
||||
-- Update VoFR some more
|
||||
-- Fix the QuickNet driver to work with LineJack
|
||||
-- Add ability to pass images for IAX.
|
||||
* Asterisk 0.1.3
|
||||
-- Update VoFR for latest sangoma code
|
||||
-- Update QuickNet Driver
|
||||
-- Add text message handling
|
||||
-- Fix transfers to use "default" if not in current context
|
||||
-- Add call parking
|
||||
-- Improve format/content negotiation
|
||||
-- Added support for multiple languages
|
||||
-- Bug fixes, as always...
|
||||
* Asterisk 0.1.2
|
||||
-- Updated README file with a "Getting Started" section
|
||||
-- Added sample sounds and configuration files.
|
||||
-- Added LPC10 very low bandwidth (low quality) compression
|
||||
-- Enhanced translation selection mechanism.
|
||||
-- Enhanced IAX jitter buffer, improved reliability
|
||||
-- Support echo cancelation on PhoneJack
|
||||
-- Updated PhoneJack driver to std. Telephony interface
|
||||
-- Added app_echo for evaluating VoIP latency
|
||||
-- Added app_system to execute arbitrary programs
|
||||
-- Updated sample configuration files
|
||||
-- Added OSS channel driver (full duplex only)
|
||||
-- Added IAX implementation
|
||||
-- Fixed some deadlocks.
|
||||
-- A whole bunch of bug fixes
|
||||
* Asterisk 0.1.1
|
||||
-- Revised translator, fixed some general race conditions throughout *
|
||||
-- Made dialer somewhat more aware of incompatible voice channels
|
||||
-- Added Voice Modem driver and A/Open Modem Driver stub
|
||||
-- Added MP3 decoder channel
|
||||
-- Added Microsoft WAV49 support
|
||||
-- Revised License -- Pure GPL, nothing else
|
||||
-- Modified Copyright statement since code is still currently owned by author
|
||||
-- Added RAW GSM headerless data format
|
||||
-- Innumerable bug fixes
|
||||
* Asterisk 0.1.0
|
||||
-- Initial Release
|
||||
12
HARDWARE
Executable file → Normal file
12
HARDWARE
Executable file → Normal file
@@ -16,11 +16,11 @@ Zaptel compatible hardware
|
||||
* Wildcard X100P - Single FXO interface connects to Loopstart phone
|
||||
line
|
||||
|
||||
* Wildcard T400P - Quad T1 interface connects to four T1/PRI
|
||||
* Wildcard T400P (obsolete) - Quad T1 interface connects to four T1/PRI
|
||||
interfaces. Supports RBS and PRI voice and PPP, FR, and HDLC data.
|
||||
|
||||
* Wildcard E400P - Quad E1 interface connects to four E1/PRI (or PRA)
|
||||
interfaces. Supports PRA/PRI, EuroISDN voice and PPP, FR, HDLC data.
|
||||
* Wildcard E400P (obsolete)- Quad E1 interface connects to four E1/PRI
|
||||
(or PRA) interfaces. Supports PRA/PRI, EuroISDN voice and data.
|
||||
|
||||
* Wildcard T100P - Single T1 interface connects to a single T1/PRI
|
||||
interface. Supports RBS and PRI voice and PPP, FR, and HDLC data.
|
||||
@@ -31,6 +31,12 @@ Zaptel compatible hardware
|
||||
* Wildcard S100U - Single FXS interface connects to a standard analog
|
||||
telephone.
|
||||
|
||||
* Wildcard TDM400P - Quad Modular FXS interface connects to standard
|
||||
analog telephones.
|
||||
|
||||
* Wildcard TE410P - Quad T1/E1 switchable interface. Supports PRI and
|
||||
RBS signalling, as well as PPP, FR, and HDLC data modes.
|
||||
|
||||
Non-zaptel compatible hardware
|
||||
==============================
|
||||
|
||||
|
||||
458
Makefile
Executable file → Normal file
458
Makefile
Executable file → Normal file
@@ -13,36 +13,104 @@
|
||||
|
||||
.EXPORT_ALL_VARIABLES:
|
||||
|
||||
# Create OPTIONS variable
|
||||
OPTIONS=
|
||||
|
||||
OSARCH=$(shell uname -s)
|
||||
|
||||
ifeq (${OSARCH},Linux)
|
||||
PROC=$(shell uname -m)
|
||||
ifeq ($(PROC),x86_64)
|
||||
# You must have GCC 3.4 to use k8, otherwise use athlon
|
||||
PROC=k8
|
||||
#PROC=athlon
|
||||
OPTIONS+=-m64
|
||||
endif
|
||||
ifeq ($(PROC),sparc64)
|
||||
#The problem with sparc is the best stuff is in newer versions of gcc (post 3.0) only.
|
||||
#This works for even old (2.96) versions of gcc and provides a small boost either way.
|
||||
#A ultrasparc cpu is really v9 but the stock debian stable 3.0 gcc doesn't support it.
|
||||
#So we go lowest common available by gcc and go a step down, still a step up from
|
||||
#the default as we now have a better instruction set to work with. - Belgarath
|
||||
PROC=ultrasparc
|
||||
OPTIONS+=$(shell if $(CC) -mtune=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-mtune=$(PROC)"; fi)
|
||||
OPTIONS+=$(shell if $(CC) -mcpu=v8 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-mcpu=v8"; fi)
|
||||
OPTIONS+=-fomit-frame-pointer
|
||||
endif
|
||||
|
||||
MPG123TARG=linux
|
||||
endif
|
||||
|
||||
ifeq ($(findstring BSD,${OSARCH}),BSD)
|
||||
PROC=$(shell uname -m)
|
||||
endif
|
||||
|
||||
# Pentium Pro Optimize
|
||||
#PROC=i686
|
||||
# Pentium Optimize
|
||||
|
||||
# Pentium & VIA processors optimize
|
||||
#PROC=i586
|
||||
|
||||
#PROC=k6
|
||||
#PROC=ppc
|
||||
PROC=$(shell uname -m)
|
||||
|
||||
PWD=$(shell pwd)
|
||||
|
||||
######### 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
|
||||
#K6OPT = -DK6OPT
|
||||
|
||||
#Tell gcc to optimize the asterisk's code
|
||||
OPTIMIZE=-O6
|
||||
OPTIMIZE+=-O6
|
||||
|
||||
#Include debug symbols in the executables (-g) and profiling info (-pg)
|
||||
DEBUG=-g #-pg
|
||||
|
||||
# If you are running a radio application, define RADIO_RELAX so that the DTMF
|
||||
# will be received more reliably
|
||||
#OPTIONS += -DRADIO_RELAX
|
||||
|
||||
# If you don't have a lot of memory (e.g. embedded Asterisk), uncomment the
|
||||
# following to reduce the size of certain static buffers
|
||||
#OPTIONS += -DLOW_MEMORY
|
||||
|
||||
# Optional debugging parameters
|
||||
DEBUG_THREADS = #-DDO_CRASH -DDEBUG_THREADS
|
||||
DEBUG_THREADS = #-DDEBUG_THREADS #-DDO_CRASH
|
||||
|
||||
# Uncomment next one to enable ast_frame tracing (for debugging)
|
||||
TRACE_FRAMES = #-DTRACE_FRAMES
|
||||
|
||||
# Uncomment next one to enable malloc debugging
|
||||
# You can view malloc debugging with:
|
||||
# *CLI> show memory allocations [filename]
|
||||
# *CLI> show memory summary [filename]
|
||||
#
|
||||
MALLOC_DEBUG = #-include $(PWD)/include/asterisk/astmm.h
|
||||
|
||||
# Where to install asterisk after compiling
|
||||
# Default -> leave empty
|
||||
INSTALL_PREFIX=
|
||||
|
||||
# Staging directory
|
||||
# Files are copied here temporarily during the install process
|
||||
# For example, make DESTDIR=/tmp/asterisk woud put things in
|
||||
# /tmp/asterisk/etc/asterisk
|
||||
DESTDIR=
|
||||
|
||||
# Original busydetect routine
|
||||
BUSYDETECT = #-DBUSYDETECT
|
||||
|
||||
# Improved busydetect routine, comment the previous one if you use this one
|
||||
BUSYDETECT+= -DBUSYDETECT_MARTIN
|
||||
# Detect the busy signal looking only at tone lengths
|
||||
# For example if you have 3 beeps 100ms tone, 100ms silence separated by 500 ms of silence
|
||||
BUSYDETECT+= #-DBUSYDETECT_TONEONLY
|
||||
# Inforce the detection of busy singal (get rid of false hangups)
|
||||
# Don't use together with -DBUSYDETECT_TONEONLY
|
||||
BUSYDETECT+= #-DBUSYDETECT_COMPARE_TONE_AND_SILENCE
|
||||
|
||||
ASTLIBDIR=$(INSTALL_PREFIX)/usr/lib/asterisk
|
||||
ASTVARLIBDIR=$(INSTALL_PREFIX)/var/lib/asterisk
|
||||
ASTETCDIR=$(INSTALL_PREFIX)/etc/asterisk
|
||||
@@ -53,7 +121,7 @@ ASTCONFPATH=$(ASTETCDIR)/asterisk.conf
|
||||
ASTBINDIR=$(INSTALL_PREFIX)/usr/bin
|
||||
ASTSBINDIR=$(INSTALL_PREFIX)/usr/sbin
|
||||
ASTVARRUNDIR=$(INSTALL_PREFIX)/var/run
|
||||
|
||||
ASTMANDIR=$(INSTALL_PREFIX)/usr/share/man
|
||||
|
||||
MODULES_DIR=$(ASTLIBDIR)/modules
|
||||
AGI_DIR=$(ASTVARLIBDIR)/agi-bin
|
||||
@@ -61,12 +129,42 @@ AGI_DIR=$(ASTVARLIBDIR)/agi-bin
|
||||
INCLUDE=-Iinclude -I../include
|
||||
CFLAGS=-pipe -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(DEBUG) $(INCLUDE) -D_REENTRANT -D_GNU_SOURCE #-DMAKE_VALGRIND_HAPPY
|
||||
CFLAGS+=$(OPTIMIZE)
|
||||
|
||||
ifneq ($(PROC),ultrasparc)
|
||||
CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi)
|
||||
endif
|
||||
|
||||
CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi)
|
||||
CFLAGS+=$(shell if [ -f /usr/include/osp/osp.h ]; then echo "-DOSP_SUPPORT -I/usr/include/osp" ; fi)
|
||||
|
||||
ifeq (${OSARCH},FreeBSD)
|
||||
OSVERSION=$(shell make -V OSVERSION -f /usr/share/mk/bsd.port.subdir.mk)
|
||||
CFLAGS+=$(shell if test ${OSVERSION} -lt 500016 ; then echo "-D_THREAD_SAFE"; fi)
|
||||
LIBS+=$(shell if test ${OSVERSION} -lt 502102 ; then echo "-lc_r"; else echo "-pthread"; fi)
|
||||
INCLUDE+=-I/usr/local/include
|
||||
CFLAGS+=$(shell if [ -d /usr/local/include/spandsp ]; then echo "-I/usr/local/include/spandsp"; fi)
|
||||
MPG123TARG=freebsd
|
||||
endif # FreeBSD
|
||||
|
||||
ifeq (${OSARCH},NetBSD)
|
||||
CFLAGS+=-pthread
|
||||
INCLUDE+=-I/usr/local/include -I/usr/pkg/include
|
||||
MPG123TARG=netbsd
|
||||
endif
|
||||
|
||||
ifeq (${OSARCH},OpenBSD)
|
||||
CFLAGS+=-pthread
|
||||
endif
|
||||
|
||||
#Uncomment this to use the older DSP routines
|
||||
#CFLAGS+=-DOLD_DSP_ROUTINES
|
||||
|
||||
CFLAGS+=$(shell if [ -f /usr/include/linux/zaptel.h ]; then echo "-DZAPTEL_OPTIMIZATIONS"; fi)
|
||||
CFLAGS+=$(shell if [ -f /usr/local/include/zaptel.h ]; then echo "-DZAPTEL_OPTIMIZATIONS"; fi)
|
||||
|
||||
LIBEDIT=editline/libedit.a
|
||||
|
||||
ASTERISKVERSION=$(shell if [ -f .version ]; then cat .version; fi)
|
||||
ASTERISKVERSION=$(shell if [ -f .version ]; then cat .version; else if [ -d CVS ]; then if [ -f CVS/Tag ] ; then echo "CVS-`sed 's/^T//g' CVS/Tag`-`date +"%D-%T"`"; else echo "CVS-HEAD-`date +"%D-%T"`"; fi; fi; fi)
|
||||
HTTPDIR=$(shell if [ -d /var/www ]; then echo "/var/www"; else echo "/home/httpd"; fi)
|
||||
RPMVERSION=$(shell if [ -f .version ]; then sed 's/[-\/:]/_/g' .version; else echo "unknown" ; fi)
|
||||
CFLAGS+=-DASTERISK_VERSION=\"$(ASTERISKVERSION)\"
|
||||
@@ -83,14 +181,58 @@ CFLAGS+=-DASTAGIDIR=\"$(AGI_DIR)\"
|
||||
|
||||
CFLAGS+= $(DEBUG_THREADS)
|
||||
CFLAGS+= $(TRACE_FRAMES)
|
||||
CFLAGS+= $(MALLOC_DEBUG)
|
||||
CFLAGS+= $(BUSYDETECT)
|
||||
CFLAGS+= $(OPTIONS)
|
||||
CFLAGS+=# -fomit-frame-pointer
|
||||
SUBDIRS=res channels pbx apps codecs formats agi cdr astman
|
||||
LIBS=-ldl -lpthread -lncurses -lm #-lnjamd
|
||||
SUBDIRS=res channels pbx apps codecs formats agi cdr astman stdtime
|
||||
ifeq (${OSARCH},Linux)
|
||||
LIBS=-ldl -lpthread
|
||||
endif
|
||||
LIBS+=-lncurses -lm
|
||||
ifeq (${OSARCH},Linux)
|
||||
LIBS+=-lresolv #-lnjamd
|
||||
endif
|
||||
ifeq (${OSARCH},Darwin)
|
||||
LIBS+=-lresolv
|
||||
endif
|
||||
ifeq (${OSARCH},FreeBSD)
|
||||
LIBS+=-lcrypto
|
||||
endif
|
||||
ifeq (${OSARCH},NetBSD)
|
||||
LIBS+=-lpthread -lcrypto -lm -L/usr/local/lib -L/usr/pkg/lib -lncurses
|
||||
endif
|
||||
ifeq (${OSARCH},OpenBSD)
|
||||
LIBS=-lcrypto -lpthread -lm -lncurses
|
||||
endif
|
||||
LIBS+=-lssl
|
||||
OBJS=io.o sched.o logger.o frame.o loader.o config.o channel.o \
|
||||
translate.o file.o say.o pbx.o cli.o md5.o term.o \
|
||||
ulaw.o alaw.o callerid.o fskmodem.o image.o app.o \
|
||||
cdr.o tdd.o acl.o rtp.o manager.o asterisk.o ast_expr.o \
|
||||
dsp.o chanvars.o indications.o autoservice.o db.o privacy.o
|
||||
dsp.o chanvars.o indications.o autoservice.o db.o privacy.o \
|
||||
astmm.o enum.o srv.o dns.o aescrypt.o aestab.o aeskey.o \
|
||||
utils.o
|
||||
ifeq (${OSARCH},Darwin)
|
||||
ASTLINK=-Wl,-dynamic
|
||||
SOLINK=-dynamic -bundle -undefined suppress -force_flat_namespace
|
||||
OBJS+= poll.o
|
||||
CFLAGS+=-DPOLLCOMPAT
|
||||
else
|
||||
ASTLINK=-Wl,-E
|
||||
SOLINK=-shared -Xlinker -x
|
||||
endif
|
||||
|
||||
ifeq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/sys/poll.h),)
|
||||
OBJS+= poll.o
|
||||
CFLAGS+=-DPOLLCOMPAT
|
||||
endif
|
||||
|
||||
ifeq ($(wildcard $(CROSS_COMPILE_TARGET)/usr/include/dlfcn.h),)
|
||||
OBJS+= dhfcn.o
|
||||
CFLAGS+=-DDLFCNCOMPAT
|
||||
endif
|
||||
|
||||
CC=gcc
|
||||
INSTALL=install
|
||||
|
||||
@@ -100,32 +242,34 @@ _all: all
|
||||
@echo " + cannot be run before being installed by +"
|
||||
@echo " + running: +"
|
||||
@echo " + +"
|
||||
@echo " + make install +"
|
||||
@echo " + $(MAKE) install +"
|
||||
@echo " +-------------------------------------------+"
|
||||
|
||||
all: asterisk subdirs
|
||||
all: depend asterisk subdirs
|
||||
|
||||
editline/config.h:
|
||||
@if [ -d editline ]; then \
|
||||
cd editline && unset CFLAGS LIBS && ./configure ; \
|
||||
else \
|
||||
echo "You need to do a cvs update -d not just cvs update"; \
|
||||
exit 1; \
|
||||
fi
|
||||
cd editline && unset CFLAGS LIBS && ./configure ; \
|
||||
|
||||
editline/libedit.a: editline/config.h
|
||||
make -C editline libedit.a
|
||||
editline/libedit.a: FORCE
|
||||
cd editline && unset CFLAGS LIBS && test -f config.h || ./configure
|
||||
$(MAKE) -C editline libedit.a
|
||||
|
||||
db1-ast/libdb1.a:
|
||||
db1-ast/libdb1.a: FORCE
|
||||
@if [ -d db1-ast ]; then \
|
||||
make -C db1-ast libdb1.a ; \
|
||||
$(MAKE) -C db1-ast libdb1.a ; \
|
||||
else \
|
||||
echo "You need to do a cvs update -d not just cvs update"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
ifneq ($(wildcard .depend),)
|
||||
include .depend
|
||||
endif
|
||||
|
||||
.PHONY: _version
|
||||
|
||||
_version:
|
||||
if [ -d CVS ] && ! [ -f .version ]; then echo "CVS-`date +"%D-%T"`" > .version; fi
|
||||
if [ -d CVS ] && ! [ -f .version ]; then echo $(ASTERISKVERSION) > .version; fi
|
||||
|
||||
.version: _version
|
||||
|
||||
@@ -134,79 +278,152 @@ _version:
|
||||
|
||||
ast_expr.o: ast_expr.c
|
||||
|
||||
cli.o: cli.c build.h
|
||||
|
||||
asterisk.o: asterisk.c build.h
|
||||
|
||||
manpage: asterisk.8.gz
|
||||
|
||||
asterisk.8.gz: asterisk.sgml
|
||||
rm -f asterisk.8
|
||||
docbook2man asterisk.sgml
|
||||
mv ./*.8 asterisk.8
|
||||
gzip asterisk.8
|
||||
|
||||
ifneq ($(strip $(ASTERISKVERSION)),)
|
||||
build.h: .version
|
||||
./make_build_h
|
||||
else
|
||||
build.h:
|
||||
./make_build_h
|
||||
endif
|
||||
|
||||
asterisk: .version build.h editline/libedit.a db1-ast/libdb1.a $(OBJS)
|
||||
gcc -o asterisk -rdynamic $(OBJS) $(LIBS) $(LIBEDIT) db1-ast/libdb1.a
|
||||
stdtime/libtime.a: FORCE
|
||||
@if [ -d stdtime ]; then \
|
||||
$(MAKE) -C stdtime libtime.a ; \
|
||||
else \
|
||||
echo "You need to do a cvs update -d not just cvs update"; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
asterisk: editline/libedit.a db1-ast/libdb1.a stdtime/libtime.a $(OBJS)
|
||||
$(CC) $(DEBUG) -o asterisk $(ASTLINK) $(OBJS) $(LIBEDIT) db1-ast/libdb1.a stdtime/libtime.a $(LIBS)
|
||||
|
||||
muted: muted.o
|
||||
$(CC) -o muted muted.o
|
||||
|
||||
subdirs:
|
||||
for x in $(SUBDIRS); do $(MAKE) -C $$x || exit 1 ; done
|
||||
|
||||
clean:
|
||||
for x in $(SUBDIRS); do $(MAKE) -C $$x clean || exit 1 ; done
|
||||
rm -f *.o *.so asterisk
|
||||
rm -f *.o *.so asterisk .depend
|
||||
rm -f build.h
|
||||
rm -f ast_expr.c
|
||||
@if [ -e editline/Makefile ]; then make -C editline clean ; fi
|
||||
make -C db1-ast clean
|
||||
@if [ -e editline/Makefile ]; then $(MAKE) -C editline distclean ; fi
|
||||
@if [ -d mpg123-0.59r ]; then $(MAKE) -C mpg123-0.59r clean; fi
|
||||
$(MAKE) -C db1-ast clean
|
||||
$(MAKE) -C stdtime clean
|
||||
|
||||
datafiles: all
|
||||
mkdir -p $(ASTVARLIBDIR)/sounds/digits
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/digits
|
||||
for x in sounds/digits/*.gsm; do \
|
||||
if grep -q "^%`basename $$x`%" sounds.txt; then \
|
||||
install $$x $(ASTVARLIBDIR)/sounds/digits ; \
|
||||
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds/digits ; \
|
||||
else \
|
||||
echo "No description for $$x"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-* sounds/conf-* sounds/agent-* sounds/invalid* sounds/tt-* sounds/auth-* sounds/privacy-*; do \
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/letters
|
||||
for x in sounds/letters/*.gsm; do \
|
||||
if grep -q "^%`basename $$x`%" sounds.txt; then \
|
||||
install $$x $(ASTVARLIBDIR)/sounds ; \
|
||||
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds/letters ; \
|
||||
else \
|
||||
echo "No description for $$x"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
mkdir -p $(ASTVARLIBDIR)/mohmp3
|
||||
mkdir -p $(ASTVARLIBDIR)/images
|
||||
for x in images/*.jpg; do \
|
||||
install $$x $(ASTVARLIBDIR)/images ; \
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/phonetic
|
||||
for x in sounds/phonetic/*.gsm; do \
|
||||
if grep -q "^%`basename $$x`%" sounds.txt; then \
|
||||
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds/phonetic ; \
|
||||
else \
|
||||
echo "No description for $$x"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
mkdir -p $(AGI_DIR)
|
||||
for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-* sounds/conf-* sounds/agent-* sounds/invalid* sounds/tt-* sounds/auth-* sounds/privacy-* sounds/queue-* sounds/hello-*; do \
|
||||
if grep -q "^%`basename $$x`%" sounds.txt; then \
|
||||
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds ; \
|
||||
else \
|
||||
echo "No description for $$x"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/mohmp3
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/images
|
||||
for x in images/*.jpg; do \
|
||||
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/images ; \
|
||||
done
|
||||
mkdir -p $(DESTDIR)$(AGI_DIR)
|
||||
|
||||
update:
|
||||
@if [ -d CVS ]; then \
|
||||
echo "Updating from CVS..." ; \
|
||||
cvs update -d; \
|
||||
cvs -q -z3 update -Pd; \
|
||||
rm -f .version; \
|
||||
else \
|
||||
echo "Not CVS"; \
|
||||
fi
|
||||
|
||||
bininstall: all
|
||||
mkdir -p $(MODULES_DIR)
|
||||
mkdir -p $(ASTSBINDIR)
|
||||
mkdir -p $(ASTETCDIR)
|
||||
mkdir -p $(ASTBINDIR)
|
||||
mkdir -p $(ASTSBINDIR)
|
||||
mkdir -p $(ASTVARRUNDIR)
|
||||
install -m 755 asterisk $(ASTSBINDIR)/
|
||||
install -m 755 astgenkey $(ASTSBINDIR)/
|
||||
install -m 755 safe_asterisk $(ASTSBINDIR)/
|
||||
mkdir -p $(DESTDIR)$(MODULES_DIR)
|
||||
mkdir -p $(DESTDIR)$(ASTSBINDIR)
|
||||
mkdir -p $(DESTDIR)$(ASTETCDIR)
|
||||
mkdir -p $(DESTDIR)$(ASTBINDIR)
|
||||
mkdir -p $(DESTDIR)$(ASTSBINDIR)
|
||||
mkdir -p $(DESTDIR)$(ASTVARRUNDIR)
|
||||
mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/voicemail
|
||||
mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/tmp
|
||||
install -m 755 asterisk $(DESTDIR)$(ASTSBINDIR)/
|
||||
install -m 755 contrib/scripts/astgenkey $(DESTDIR)$(ASTSBINDIR)/
|
||||
install -m 755 contrib/scripts/autosupport $(DESTDIR)$(ASTSBINDIR)/
|
||||
if [ ! -f $(DESTDIR)$(ASTSBINDIR)/safe_asterisk ]; then \
|
||||
install -m 755 contrib/scripts/safe_asterisk $(DESTDIR)$(ASTSBINDIR)/ ;\
|
||||
fi
|
||||
for x in $(SUBDIRS); do $(MAKE) -C $$x install || exit 1 ; done
|
||||
install -d $(ASTHEADERDIR)
|
||||
install include/asterisk/*.h $(ASTHEADERDIR)
|
||||
rm -f $(ASTVARLIBDIR)/sounds/vm
|
||||
mkdir -p $(ASTSPOOLDIR)/vm
|
||||
rm -f $(ASTMODULESDIR)/chan_ixj.so
|
||||
rm -f $(ASTMODULESDIR)/chan_tor.so
|
||||
mkdir -p $(ASTVARLIBDIR)/sounds
|
||||
mkdir -p $(ASTLOGDIR)/cdr-csv
|
||||
mkdir -p $(ASTVARLIBDIR)/keys
|
||||
install -m 644 keys/iaxtel.pub $(ASTVARLIBDIR)/keys
|
||||
( cd $(ASTVARLIBDIR)/sounds ; ln -s $(ASTSPOOLDIR)/vm . )
|
||||
install -d $(DESTDIR)$(ASTHEADERDIR)
|
||||
install -m 644 include/asterisk/*.h $(DESTDIR)$(ASTHEADERDIR)
|
||||
rm -f $(DESTDIR)$(ASTVARLIBDIR)/sounds/vm
|
||||
rm -f $(DESTDIR)$(ASTVARLIBDIR)/sounds/voicemail
|
||||
if [ ! -h $(DESTDIR)$(ASTSPOOLDIR)/vm ] && [ -d $(DESTDIR)$(ASTSPOOLDIR)/vm ]; then \
|
||||
mv $(DESTDIR)$(ASTSPOOLDIR)/vm $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default; \
|
||||
else \
|
||||
mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default; \
|
||||
rm -f $(DESTDIR)$(ASTSPOOLDIR)/vm; \
|
||||
fi
|
||||
ln -s $(ASTSPOOLDIR)/voicemail/default $(DESTDIR)$(ASTSPOOLDIR)/vm
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds
|
||||
mkdir -p $(DESTDIR)$(ASTLOGDIR)/cdr-csv
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/keys
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/firmware
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/firmware/iax
|
||||
mkdir -p $(DESTDIR)$(ASTMANDIR)/man8
|
||||
install -m 644 keys/iaxtel.pub $(DESTDIR)$(ASTVARLIBDIR)/keys
|
||||
install -m 644 keys/freeworlddialup.pub $(DESTDIR)$(ASTVARLIBDIR)/keys
|
||||
install -m 644 asterisk.8.gz $(DESTDIR)$(ASTMANDIR)/man8
|
||||
install -m 644 contrib/scripts/astgenkey.8 $(DESTDIR)$(ASTMANDIR)/man8
|
||||
install -m 644 contrib/scripts/autosupport.8 $(DESTDIR)$(ASTMANDIR)/man8
|
||||
install -m 644 contrib/scripts/safe_asterisk.8 $(DESTDIR)$(ASTMANDIR)/man8
|
||||
if [ -d contrib/firmware/iax ]; then \
|
||||
install -m 644 contrib/firmware/iax/iaxy.bin $(DESTDIR)$(ASTVARLIBDIR)/firmware/iax/iaxy.bin; \
|
||||
else \
|
||||
echo "You need to do cvs update -d not just cvs update" ; \
|
||||
fi
|
||||
( cd $(DESTDIR)$(ASTVARLIBDIR)/sounds ; ln -s $(ASTSPOOLDIR)/vm . )
|
||||
( cd $(DESTDIR)$(ASTVARLIBDIR)/sounds ; ln -s $(ASTSPOOLDIR)/voicemail . )
|
||||
if [ -f mpg123-0.59r/mpg123 ]; then $(MAKE) -C mpg123-0.59r install; fi
|
||||
@echo " +---- Asterisk Installation Complete -------+"
|
||||
@echo " + +"
|
||||
@echo " + YOU MUST READ THE SECURITY DOCUMENT +"
|
||||
@@ -216,76 +433,90 @@ bininstall: all
|
||||
@echo " + configuration files (overwriting any +"
|
||||
@echo " + existing config files), run: +"
|
||||
@echo " + +"
|
||||
@echo " + make samples +"
|
||||
@echo " + $(MAKE) samples +"
|
||||
@echo " + +"
|
||||
@echo " +----------------- or ---------------------+"
|
||||
@echo " + +"
|
||||
@echo " + You can go ahead and install the asterisk +"
|
||||
@echo " + program documentation now or later run: +"
|
||||
@echo " + +"
|
||||
@echo " + make progdocs +"
|
||||
@echo " + $(MAKE) progdocs +"
|
||||
@echo " + +"
|
||||
@echo " + **Note** This requires that you have +"
|
||||
@echo " + doxygen installed on your local system +"
|
||||
@echo " +-------------------------------------------+"
|
||||
@echo " + +"
|
||||
@echo " + ** NOTE FOR DOWNGRADING FROM CVS HEAD ** +"
|
||||
@echo " + +"
|
||||
@echo " + If you are downgrading from CVS HEAD to +"
|
||||
@echo " + a stable release, remember to delete +"
|
||||
@echo " + everything from your asterisk modules +"
|
||||
@echo " + directory (/usr/lib/asterisk/modules/) +"
|
||||
@echo " + and the asterisk header directory +"
|
||||
@echo " + (/usr/include/asterisk/) +"
|
||||
@echo " + before doing a '$(MAKE) install'. +"
|
||||
@echo " + +"
|
||||
@echo " +-------------------------------------------+"
|
||||
|
||||
|
||||
install: all datafiles bininstall
|
||||
|
||||
upgrade: all bininstall
|
||||
|
||||
adsi: all
|
||||
mkdir -p $(ASTETCDIR)
|
||||
mkdir -p $(DESTDIR)$(ASTETCDIR)
|
||||
for x in configs/*.adsi; do \
|
||||
if ! [ -f $(ASTETCDIRX)/$$x ]; then \
|
||||
install -m 644 $$x $(ASTETCDIR)/`basename $$x` ; \
|
||||
if ! [ -f $(DESTDIR)$(ASTETCDIRX)/$$x ]; then \
|
||||
install -m 644 $$x $(DESTDIR)$(ASTETCDIR)/`basename $$x` ; \
|
||||
fi ; \
|
||||
done
|
||||
|
||||
samples: all datafiles adsi
|
||||
mkdir -p $(ASTETCDIR)
|
||||
mkdir -p $(DESTDIR)$(ASTETCDIR)
|
||||
for x in configs/*.sample; do \
|
||||
if [ -f $(ASTETCDIR)/`basename $$x .sample` ]; then \
|
||||
mv -f $(ASTETCDIR)/`basename $$x .sample` $(ASTETCDIR)/`basename $$x .sample`.old ; \
|
||||
if [ -f $(DESTDIR)$(ASTETCDIR)/`basename $$x .sample` ]; then \
|
||||
mv -f $(DESTDIR)$(ASTETCDIR)/`basename $$x .sample` $(DESTDIR)$(ASTETCDIR)/`basename $$x .sample`.old ; \
|
||||
fi ; \
|
||||
install $$x $(ASTETCDIR)/`basename $$x .sample` ;\
|
||||
install -m 644 $$x $(DESTDIR)$(ASTETCDIR)/`basename $$x .sample` ;\
|
||||
done
|
||||
echo "[directories]" > $(ASTETCDIR)/asterisk.conf
|
||||
echo "astetcdir => $(ASTETCDIR)" >> $(ASTETCDIR)/asterisk.conf
|
||||
echo "astmoddir => $(MODULES_DIR)" >> $(ASTETCDIR)/asterisk.conf
|
||||
echo "astvarlibdir => $(ASTVARLIBDIR)" >> $(ASTETCDIR)/asterisk.conf
|
||||
echo "astagidir => $(AGI_DIR)" >> $(ASTETCDIR)/asterisk.conf
|
||||
echo "astspooldir => $(ASTSPOOLDIR)" >> $(ASTETCDIR)/asterisk.conf
|
||||
echo "astrundir => $(ASTVARRUNDIR)" >> $(ASTETCDIR)/asterisk.conf
|
||||
echo "astlogdir => $(ASTLOGDIR)" >> $(ASTETCDIR)/asterisk.conf
|
||||
echo "[directories]" > $(DESTDIR)$(ASTETCDIR)/asterisk.conf
|
||||
echo "astetcdir => $(ASTETCDIR)" >> $(DESTDIR)$(ASTETCDIR)/asterisk.conf
|
||||
echo "astmoddir => $(MODULES_DIR)" >> $(DESTDIR)$(ASTETCDIR)/asterisk.conf
|
||||
echo "astvarlibdir => $(ASTVARLIBDIR)" >> $(DESTDIR)$(ASTETCDIR)/asterisk.conf
|
||||
echo "astagidir => $(AGI_DIR)" >> $(DESTDIR)$(ASTETCDIR)/asterisk.conf
|
||||
echo "astspooldir => $(ASTSPOOLDIR)" >> $(DESTDIR)$(ASTETCDIR)/asterisk.conf
|
||||
echo "astrundir => $(ASTVARRUNDIR)" >> $(DESTDIR)$(ASTETCDIR)/asterisk.conf
|
||||
echo "astlogdir => $(ASTLOGDIR)" >> $(DESTDIR)$(ASTETCDIR)/asterisk.conf
|
||||
for x in sounds/demo-*; do \
|
||||
if grep -q "^%`basename $$x`%" sounds.txt; then \
|
||||
install $$x $(ASTVARLIBDIR)/sounds ; \
|
||||
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds ; \
|
||||
else \
|
||||
echo "No description for $$x"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
for x in sounds/*.mp3; do \
|
||||
install $$x $(ASTVARLIBDIR)/mohmp3 ; \
|
||||
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/mohmp3 ; \
|
||||
done
|
||||
mkdir -p $(ASTSPOOLDIR)/vm/1234/INBOX
|
||||
:> $(ASTVARLIBDIR)/sounds/vm/1234/unavail.gsm
|
||||
rm -f $(DESTDIR)$(ASTVARLIBDIR)/mohmp3/sample-hold.mp3
|
||||
mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/INBOX
|
||||
:> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/unavail.gsm
|
||||
for x in vm-theperson digits/1 digits/2 digits/3 digits/4 vm-isunavail; do \
|
||||
cat $(ASTVARLIBDIR)/sounds/$$x.gsm >> $(ASTVARLIBDIR)/sounds/vm/1234/unavail.gsm ; \
|
||||
cat $(DESTDIR)$(ASTVARLIBDIR)/sounds/$$x.gsm >> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/unavail.gsm ; \
|
||||
done
|
||||
:> $(ASTVARLIBDIR)/sounds/vm/1234/busy.gsm
|
||||
:> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/busy.gsm
|
||||
for x in vm-theperson digits/1 digits/2 digits/3 digits/4 vm-isonphone; do \
|
||||
cat $(ASTVARLIBDIR)/sounds/$$x.gsm >> $(ASTVARLIBDIR)/sounds/vm/1234/busy.gsm ; \
|
||||
cat $(DESTDIR)$(ASTVARLIBDIR)/sounds/$$x.gsm >> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/busy.gsm ; \
|
||||
done
|
||||
|
||||
webvmail:
|
||||
@[ -d $(HTTPDIR) ] || ( echo "No HTTP directory" && exit 1 )
|
||||
@[ -d $(HTTPDIR)/html ] || ( echo "No http directory" && exit 1 )
|
||||
@[ -d $(HTTPDIR)/cgi-bin ] || ( echo "No cgi-bin directory" && exit 1 )
|
||||
install -m 4755 -o root -g root vmail.cgi $(HTTPDIR)/cgi-bin/vmail.cgi
|
||||
mkdir -p $(HTTPDIR)/html/_asterisk
|
||||
@[ -d $(DESTDIR)$(HTTPDIR) ] || ( echo "No HTTP directory" && exit 1 )
|
||||
@[ -d $(DESTDIR)$(HTTPDIR)/html ] || ( echo "No http directory" && exit 1 )
|
||||
@[ -d $(DESTDIR)$(HTTPDIR)/cgi-bin ] || ( echo "No cgi-bin directory" && exit 1 )
|
||||
install -m 4755 -o root -g root contrib/scripts/vmail.cgi $(DESTDIR)$(HTTPDIR)/cgi-bin/vmail.cgi
|
||||
mkdir -p $(DESTDIR)$(HTTPDIR)/html/_asterisk
|
||||
for x in images/*.gif; do \
|
||||
install -m 644 $$x $(HTTPDIR)/html/_asterisk/; \
|
||||
install -m 644 $$x $(DESTDIR)$(HTTPDIR)/html/_asterisk/; \
|
||||
done
|
||||
@echo " +--------- Asterisk Web Voicemail ----------+"
|
||||
@echo " + +"
|
||||
@@ -297,38 +528,61 @@ webvmail:
|
||||
@echo " +-------------------------------------------+"
|
||||
|
||||
mailbox:
|
||||
./addmailbox
|
||||
|
||||
./contrib/scripts/addmailbox
|
||||
|
||||
rpm: __rpm
|
||||
|
||||
__rpm: _version
|
||||
rm -rf /tmp/asterisk ; \
|
||||
mkdir -p /tmp/asterisk/redhat/RPMS/i386 ; \
|
||||
make INSTALL_PREFIX=/tmp/asterisk install ; \
|
||||
make INSTALL_PREFIX=/tmp/asterisk samples ; \
|
||||
$(MAKE) DESTDIR=/tmp/asterisk install ; \
|
||||
$(MAKE) DESTDIR=/tmp/asterisk samples ; \
|
||||
mkdir -p /tmp/asterisk/etc/rc.d/init.d ; \
|
||||
cp -f redhat/asterisk /tmp/asterisk/etc/rc.d/init.d/ ; \
|
||||
cp -f redhat/rpmrc /tmp/asterisk/ ; \
|
||||
cp -f redhat/rpmmacros /tmp/asterisk/ ; \
|
||||
sed "s/Version:/Version: $(RPMVERSION)/g" redhat/asterisk.spec > /tmp/asterisk/asterisk.spec ; \
|
||||
rpm --rcfile /usr/lib/rpm/rpmrc:/tmp/asterisk/rpmrc -bb /tmp/asterisk/asterisk.spec ; \
|
||||
mv /tmp/asterisk/redhat/RPMS/i386/asterisk* ./ ; \
|
||||
rm -rf /tmp/asterisk
|
||||
sed "s/^Version:.*/Version: $(RPMVERSION)/g" redhat/asterisk.spec > asterisk.spec ; \
|
||||
rpmbuild --rcfile /usr/lib/rpm/rpmrc:redhat/rpmrc -bb asterisk.spec
|
||||
|
||||
progdocs:
|
||||
doxygen asterisk-ng-doxygen
|
||||
doxygen contrib/asterisk-ng-doxygen
|
||||
|
||||
mpg123:
|
||||
@wget -V >/dev/null || (echo "You need wget" ; false )
|
||||
[ -f mpg123-0.59r.tar.gz ] || wget http://www.mpg123.de/mpg123/mpg123-0.59r.tar.gz
|
||||
[ -d mpg123-0.59r ] || tar xfz mpg123-0.59r.tar.gz
|
||||
$(MAKE) -C mpg123-0.59r $(MPG123TARG)
|
||||
|
||||
config:
|
||||
if [ -d /etc/rc.d/init.d ]; then \
|
||||
install -m 755 init.asterisk /etc/rc.d/init.d/asterisk; \
|
||||
install -m 755 contrib/init.d/rc.redhat.asterisk /etc/rc.d/init.d/asterisk; \
|
||||
/sbin/chkconfig --add asterisk; \
|
||||
elif [ -d /etc/init.d ]; then \
|
||||
install -m 755 init.asterisk /etc/init.d/asterisk; \
|
||||
fi
|
||||
|
||||
|
||||
dont-optimize:
|
||||
make OPTIMIZE= K6OPT= install
|
||||
$(MAKE) OPTIMIZE= K6OPT= install
|
||||
|
||||
valgrind: dont-optimize
|
||||
|
||||
depend: .depend
|
||||
for x in $(SUBDIRS); do $(MAKE) -C $$x depend || exit 1 ; done
|
||||
|
||||
.depend:
|
||||
@if ! which mpg123 &>/dev/null ; then \
|
||||
echo "*** You don't have mpg123 installed. You're going to need ***";\
|
||||
echo "*** it if you want MusicOnHold ***";\
|
||||
elif ! mpg123 --longhelp 2>&1 | grep .59r &>/dev/null ; then \
|
||||
echo "*************************************************************";\
|
||||
echo "*** You have the WRONG version of mpg123... you need .59r ***";\
|
||||
echo "*** Use 'make mpg123' to get the right verison ***";\
|
||||
echo "*************************************************************";\
|
||||
fi
|
||||
./mkdep ${CFLAGS} `ls *.c`
|
||||
|
||||
FORCE:
|
||||
|
||||
%_env:
|
||||
$(MAKE) -C $(shell echo $@ | sed "s/_env//g") env
|
||||
|
||||
env:
|
||||
env
|
||||
|
||||
112
README
Executable file → Normal file
112
README
Executable file → Normal file
@@ -1,6 +1,6 @@
|
||||
The Asterisk Open Source PBX
|
||||
by Mark Spencer <markster@linux-support.net>
|
||||
Copyright (C) 2001, Linux Support Services, Inc.
|
||||
by Mark Spencer <markster@digium.com>
|
||||
Copyright (C) 2001-2004 Digium
|
||||
================================================================
|
||||
* SECURITY
|
||||
It is imperative that you read and fully understand the contents of
|
||||
@@ -12,54 +12,61 @@ sense, middleware between Internet and telephony channels on the bottom,
|
||||
and Internet and telephony applications at the top. For more information
|
||||
on the project itself, please visit the Asterisk home page at:
|
||||
|
||||
http://www.asteriskpbx.com
|
||||
http://www.asterisk.org
|
||||
|
||||
In addition you'll find lot's of information compiled by the Asterisk
|
||||
community on this Wiki:
|
||||
|
||||
http://www.voip-info.org/wiki-Asterisk
|
||||
|
||||
* LICENSING
|
||||
Asterisk is distributed under GNU General Public License. The GPL also
|
||||
must apply to all loadable modules as well, except as defined below.
|
||||
|
||||
Linux Support Services, Inc. retains copyright to all of the core
|
||||
Asterisk system, and therefore can grant, at its sole discression, the
|
||||
ability for companies, individuals, or organizations to create proprietary
|
||||
Digium, Inc. (formerly Linux Support Services) retains copyright to all
|
||||
of the core Asterisk system, and therefore can grant, at its sole discretion,
|
||||
the ability for companies, individuals, or organizations to create proprietary
|
||||
or Open Source (but non-GPL'd) modules which may be dynamically linked at
|
||||
runtime with the portions of Asterisk which fall under our copyright
|
||||
umbrella, or are distributed under more flexible licenses than GPL. At
|
||||
this time (5/21/2001) the only component of Asterisk which is covered
|
||||
under GPL and not under our Copyright is the Xing MP3 decoder.
|
||||
umbrella, or are distributed under more flexible licenses than GPL.
|
||||
|
||||
|
||||
If you wish to use our code in other GPL programs, don't worry -- there
|
||||
is no requirement that you provide the same exemption in your GPL'd
|
||||
products (although if you've written a module for Asterisk we would
|
||||
strongly encourage you to make the same excemption that we do).
|
||||
strongly encourage you to make the same exemption that we do).
|
||||
|
||||
Specific permission is also granted to OpenSSL and OpenH323 to link to
|
||||
Asterisk.
|
||||
|
||||
If you have any questions, whatsoever, regarding our licensing policy,
|
||||
please contact us.
|
||||
|
||||
Modules that are GPL-licensed and not available under Digium's
|
||||
licensing scheme are added to the Asterisk-addons CVS module.
|
||||
|
||||
* REQUIRED COMPONENTS
|
||||
|
||||
== Linux ==
|
||||
Currently, the Asterisk Open Source PBX is only known to run on the
|
||||
Linux OS, although it may be portable to other UNIX-like operating systems
|
||||
as well.
|
||||
(like FreeBSD) as well.
|
||||
|
||||
|
||||
* GETTING STARTED
|
||||
|
||||
First, be sure you've got supported hardware. To use Asterisk right now,
|
||||
you will need one of the following:
|
||||
First, be sure you've got supported hardware (but note that you don't need ANY hardware, not even a soundcard) to install and run Asterisk. Supported are:
|
||||
|
||||
* All Wildcard (tm) products from LSS (www.linux-support.net)
|
||||
* All Wildcard (tm) products from Digium (www.digium.com)
|
||||
* QuickNet Internet PhoneJack and LineJack (http://www.quicknet.net)
|
||||
* Full Duplex Sound Card supported by Linux
|
||||
* Adtran Atlas 800 Plus
|
||||
* ISDN4Linux compatible ISDN card
|
||||
* Tormenta Dual T1 card (www.bsdtelephony.com.mx)
|
||||
|
||||
Assuming you have one of these (most likely the third) you're ready to
|
||||
proceed:
|
||||
Hint: CAPI compatible ISDN cards can be run using the add-on channel chan_capi.
|
||||
|
||||
So let's proceed:
|
||||
|
||||
1) Run "make"
|
||||
2) Run "make install"
|
||||
@@ -69,7 +76,7 @@ the sample PBX, with demonstration extensions, etc. If so, run:
|
||||
|
||||
"make samples"
|
||||
|
||||
Doing so will overwrite any existing config files you have.
|
||||
Doing so will overwrite any existing config files you have. If you are lacking a soundcard you won't be able to use the DIAL command on the console, though.
|
||||
|
||||
Finally, you can launch Asterisk with:
|
||||
|
||||
@@ -129,9 +136,78 @@ parameters. For example, the line "channel => 25-47" creates objects for
|
||||
the channels 25 through 47 of the tormenta card, obtaining the settings
|
||||
from the variables specified above.
|
||||
|
||||
* SPECIAL NOTE ON TIME
|
||||
|
||||
Those using SIP phones should be aware the Asterisk is sensitive to
|
||||
large jumps in time. Manually changing the system time using date(1)
|
||||
(or other similar commands) may cause SIP registrations and other
|
||||
internal processes to fail. If your system cannot keep accurate time
|
||||
by itself use NTP (http://www.ntp.org/) to keep the system clock
|
||||
synchronized to "real time". NTP is designed to keep the system clock
|
||||
synchronized by speeding up or slowing down the system clock until it
|
||||
is synchronized to "real time" rather than by jumping the time and
|
||||
causing discontinuities. Most Linux distributions include precompiled
|
||||
versions of NTP. Beware of some time synchronization methods that get
|
||||
the correct real time periodically and then manually set the system
|
||||
clock.
|
||||
|
||||
Apparent time changes due to daylight savings time are just that,
|
||||
apparent. The use of daylight savings time in a Linux system is
|
||||
purely a user interface issue and does not affect the operation of the
|
||||
Linux kernel or Asterisk. The system clock on Linux kernels operates
|
||||
on UTC. UTC does not use daylight savings time.
|
||||
|
||||
Also note that this issue is separate from the clocking of TDM
|
||||
channels, and is known to at least affect SIP registrations.
|
||||
|
||||
* FILE DESCRIPTORS
|
||||
|
||||
Depending on the size of your system and your configuration,
|
||||
Asterisk can consume a large number of file descriptors. In UNIX,
|
||||
file descriptors are used for more than just files on disk. File
|
||||
descriptors are also used for handling network communication
|
||||
(e.g. SIP, IAX2, or H.323 calls) and hardware access (e.g. analog and
|
||||
digital trunk hardware). Asterisk accesses many on-disk files for
|
||||
everything from configuration information to voicemail storage.
|
||||
|
||||
Most systems limit the number of file descriptors that Asterisk can
|
||||
have open at one time. This can limit the number of simultaneous
|
||||
calls that your system can handle. For example, if the limit is set
|
||||
at 1024 (a common default value) Asterisk can handle approxiately 150
|
||||
SIP calls simultaneously. To change the number of file descriptors
|
||||
follow the instructions for your system below:
|
||||
|
||||
== PAM-based Linux System ==
|
||||
|
||||
If your system uses PAM (Pluggable Authentication Modules) edit
|
||||
/etc/security/limits.conf. Add these lines to the bottom of the file:
|
||||
|
||||
root soft nofile 4096
|
||||
root hard nofile 8196
|
||||
asterisk soft nofile 4096
|
||||
asterisk hard nofile 8196
|
||||
|
||||
(adjust the numbers to taste). You may need to reboot the system for
|
||||
these changes to take effect.
|
||||
|
||||
== Generic UNIX System ==
|
||||
|
||||
If there are no instructions specifically adapted to your system
|
||||
above you can try adding the command "ulimit -n 8192" to the script
|
||||
that starts Asterisk.
|
||||
|
||||
|
||||
* MORE INFORMATION
|
||||
|
||||
See the doc directory for more documentation.
|
||||
|
||||
Finally, you may wish to visit the web site and join the mailing list if
|
||||
you're interested in getting more information.
|
||||
|
||||
Mark
|
||||
http://www.asterisk.org/index.php?menu=support
|
||||
|
||||
Welcome to the growing worldwide community of Asterisk users!
|
||||
|
||||
Mark Spencer
|
||||
|
||||
|
||||
|
||||
14
README.cdr
14
README.cdr
@@ -1,14 +0,0 @@
|
||||
Asterisk now generates Call Detail Records. See include/asterisk/cdr.h for
|
||||
all the fields which are recorded. By default, records in comma-separated
|
||||
values will be created in /var/log/asterisk/cdr-csv. You can specify
|
||||
account codes and AMA (Automated Machine Accounting) flags on a per-channel
|
||||
(Zaptel et al) or per-user (IAX) basis to help with accounting. Look
|
||||
at the top of cdr/cdr_csv.c to see the format for the records.
|
||||
|
||||
ONE IMPORTANT NOTE: If you are trying to collect records on IAX to IAX calls
|
||||
you need to be aware that by default, IAX will attempt to transfer calls
|
||||
in this situation (if DTMF is not required). When the transfer is completed
|
||||
the call is dumped from the middle machine and thus the call detail records
|
||||
will report a short call time. If you want detailed records you must
|
||||
turn off IAX transfer, but unless your servers are very close together, you
|
||||
will definitely get a latency hit from doing so.
|
||||
@@ -1,22 +0,0 @@
|
||||
|
||||
app_festival is an application that allows one to send text-to-speech commands
|
||||
to a background festival server, and to obtain the resulting waveform which
|
||||
gets sent down to the respective channel. app_festival also employs a waveform
|
||||
cache, so invariant text-to-speech strings ("Please press 1 for instructions")
|
||||
do not need to be dynamically generated all the time.
|
||||
|
||||
You need :
|
||||
|
||||
1) festival, patched to produce 8khz waveforms on output. Patch for Festival
|
||||
1.4.2 RELEASE are included. The patch adds a new command to festival
|
||||
(asterisk_tts).
|
||||
|
||||
2) My patches to asterisk that provide variable substitution and quoting to
|
||||
the Asterisk Extension Logic. This is not really a requirement, but without
|
||||
this, app_festival is mostly useless (you could very well use prerecorded
|
||||
voices for static information).
|
||||
|
||||
3) Before running asterisk, you have to run festival-server with a command
|
||||
like :
|
||||
|
||||
/usr/local/festival/bin/festival --server > /dev/null 2>&1 &
|
||||
326
README.iax
326
README.iax
@@ -1,326 +0,0 @@
|
||||
Inter-Asterisk eXchange Protocol
|
||||
================================
|
||||
|
||||
INTRODUCTION
|
||||
------------
|
||||
|
||||
This document is intended as an introduction to the Inter-Asterisk
|
||||
eXchange (or simply IAX) protocol. It provides both a theoretical
|
||||
background and practical information on its use.
|
||||
|
||||
WHY IAX
|
||||
-------
|
||||
The first question most people are thinking at this point is "Why do you
|
||||
need another VoIP protocol? Why didn't you just use SIP or H.323?"
|
||||
|
||||
Well, the answer is a fairly complicated one, but in a nutshell it's like
|
||||
this... Asterisk is intended as a very flexible and powerful
|
||||
communications tool. As such, the primary feature we need from a VoIP
|
||||
protocol is the ability to meet our own goals with Asterisk, and one with
|
||||
enough flexibility that we could use it as a kind of laboratory for
|
||||
inventing and implementing new concepts in the field. Neither H.323 or
|
||||
SIP fit the roles we needed, so we developed our own protocol, which,
|
||||
while not standards based, provides a number of advantages over both SIP
|
||||
and H.323, some of which are:
|
||||
|
||||
* Interoperability with NAT/PAT/Masquerade firewalls
|
||||
IAX seamlessly interoperates through all sorts of NAT and PAT
|
||||
and other firewalls, including the ability to place and
|
||||
receive calls, and transfer calls to other stations.
|
||||
|
||||
* High performance, low overhead protocol
|
||||
When running on low-bandwidth connections, or when running
|
||||
large numbers of calls, optimized bandwidth utilization is
|
||||
imperitive. IAX uses only 4 bytes of overhead
|
||||
|
||||
* Internationalization support
|
||||
IAX transmits language information, so that remote PBX
|
||||
content can be delivered in the native language of the
|
||||
calling party.
|
||||
|
||||
* Remote dialplan polling
|
||||
IAX allows a PBX or IP phone to poll the availability of a
|
||||
number from a remote server. This allows PBX dialplans to
|
||||
be centralized.
|
||||
|
||||
* Flexible authentication
|
||||
IAX supports cleartext, md5, and RSA authentication,
|
||||
providing flexible security models for outgoing calls and
|
||||
registration services.
|
||||
|
||||
* Multimedia protocol
|
||||
IAX supports the transmission of voice, video, images, text,
|
||||
HTML, DTMF, and URL's. Voice menus can be presented in both
|
||||
audibly and visually.
|
||||
|
||||
* Call statistic gathering
|
||||
IAX gathers statistics about network performance (including
|
||||
latency and jitter, as well as providing end-to-end latency
|
||||
measurement.
|
||||
|
||||
* Call parameter communication
|
||||
Caller*ID, requested extension, requested context, etc are
|
||||
all communicated through the call.
|
||||
|
||||
* Single socket design
|
||||
IAX's single socket design allows up to 32768 calls to be
|
||||
multiplexed.
|
||||
|
||||
While we value the importance of standards based (i.e. SIP) call handling,
|
||||
hopefully this will provide a reasonable explanation of why we developed
|
||||
IAX rather than starting with SIP.
|
||||
|
||||
CONFIG FILE CONVENTIONS
|
||||
-----------------------
|
||||
Lines beginning with '>' represent lines which might appear in an actual
|
||||
configuration file. The '>' is used to help separate them from the
|
||||
descriptive text and should not actually be included in the file itself.
|
||||
|
||||
Lines within []'s by themselves represent section labels within the
|
||||
configuration file. like this:
|
||||
|
||||
> [mysection]
|
||||
|
||||
Options are set using the "=" sign, for example
|
||||
|
||||
> myoption = value
|
||||
|
||||
Sometimes an option will have a number of discrete values which it can
|
||||
take. In that case, in the documentation, the options will be listed
|
||||
within square brackets (the "[" and "]" ones) separated by the pipe symbol
|
||||
("|"). For example:
|
||||
|
||||
> myoption = [value1|value2|value3]
|
||||
|
||||
means the option "myoption" can be assigned a value of "value1", "value2",
|
||||
or "value3".
|
||||
|
||||
Objects, or pseudo-objects are instantiated using the "=>" construct. For
|
||||
example:
|
||||
|
||||
> myobject => parameter
|
||||
|
||||
creates an object called "myobject" with some parameter whose definition
|
||||
would be specific to that object. Note that the config file parser
|
||||
considers "=>" and "=" to be equivalent and their use is purely to make
|
||||
configuration files more readable and easier to "humanly parse".
|
||||
|
||||
The comment character in Asterisk configuration files is the semicolon
|
||||
";". The reason it is not "#" is because the "#" symbol can be used as
|
||||
parts of extensions and it didn't seem like a good idea to have to escape
|
||||
it.
|
||||
|
||||
IAX CONFIGURATION IN ASTERISK
|
||||
-----------------------------
|
||||
|
||||
Like everything else in Asterisk, IAX's configuration lies in
|
||||
/etc/asterisk -- specifically /etc/asterisk/iax.conf
|
||||
|
||||
The IAX configuration file is a collection of sections, each of which
|
||||
(with the exception of the "general" section) represents an entity within
|
||||
the IAX scope.
|
||||
|
||||
------------
|
||||
|
||||
The first section is typically the "general" section. In this area,
|
||||
a number of parameters which affect the entire system are configured.
|
||||
Specifically, the default codecs, port and address, jitter behavior, TOS
|
||||
bits, and registrations.
|
||||
|
||||
The first line of the "general" section is always:
|
||||
|
||||
> [general]
|
||||
|
||||
Following the first line are a number of other possibilities:
|
||||
|
||||
> port = <portnum>
|
||||
|
||||
This sets the port that IAX will bind to. The default IAX port number is
|
||||
5036. It is recommended that this value not be altered in general.
|
||||
|
||||
> bindaddr = <ipaddr>
|
||||
|
||||
This allows you to bind IAX to a specific local IP address instead of
|
||||
binding to all addresses. This could be used to enhance security if, for
|
||||
example, you only wanted IAX to be available to users on your LAN.
|
||||
|
||||
> bandwidth = [low|medium|high]
|
||||
|
||||
The bandwidth selection initializes the codec selection to appropriate
|
||||
values for given bandwidths. The "high" selection enables all codecs and
|
||||
is recommended only for 10Mbps or higher connections. The "medium"
|
||||
bandwidth eliminates signed linear, Mu-law and A-law codecs, leaving only
|
||||
the codecs which are 32kbps and smaller (with MP3 as a special case). It
|
||||
can be used with broadband connections if desired. "low" eliminates ADPCM
|
||||
and MP3 formats, leaving only the G.723.1, GSM, and LPC10.
|
||||
|
||||
> allow = [gsm|lpc10|g723.1|adpcm|ulaw|alaw|mp3|slinear|all]
|
||||
> disallow = [gsm|lpc10|g723.1|adpcm|ulaw|alaw|mp3|slinear|all]
|
||||
|
||||
The "allow" and "disallow" allow you to fine tune the codec selection
|
||||
beyond the initial bandwidth selection on a codec-by-codec basis.
|
||||
|
||||
The recommended configuration is to select "low" bandwidth and then
|
||||
disallow the LPC10 codec just because it doesn't sound very good.
|
||||
|
||||
> jitterbuffer = [yes|no]
|
||||
> dropcount = <dropamount>
|
||||
> maxjitterbuffer = <max>
|
||||
> maxexcessbuffer = <max>
|
||||
|
||||
These parameters control the operation of the jitter buffer. The
|
||||
jitterbuffer should always be enabled unless you expect all your
|
||||
connections to be over a LAN. The drop count is the maximum number of
|
||||
voice packets to allow to drop (out of 100). Useful values are 3-10. The
|
||||
maxjitterbuffer is the maximum amount of jitter buffer to permit to be
|
||||
used. The "maxexcessbuffer" is the maximum amount of excess jitter buffer
|
||||
that is permitted before the jitter buffer is slowly shrunk to eliminate
|
||||
latency.
|
||||
|
||||
> accountcode = <code>
|
||||
> amaflags = [default|omit|billing|documentation]
|
||||
|
||||
These parameters affect call detail record generation. The first sets the
|
||||
account code for records received with IAX. The account code can be
|
||||
overridden on a per-user basis for incoming calls (see below). The
|
||||
amaflags controls how the record is labeled ("omit" causes no record to be
|
||||
written. "billing" and "documentation" label the records as billing or
|
||||
documentation records respectively, and "default" selects the system
|
||||
default.
|
||||
|
||||
> tos = [lowdelay|throughput|reliability|mincost|none]
|
||||
|
||||
IAX can optionally set the TOS (Type of Service) bits to specified values
|
||||
to help improve performance in routing. The recommended value is
|
||||
"lowdelay", which many routers (including any Linux routers with 2.4
|
||||
kernels that have not been altered with ip tables) will give priority to
|
||||
these packets, improving voice quality.
|
||||
|
||||
> register => <name>[:<secret>]@<host>[:port]
|
||||
|
||||
Any number of registery entries may be instantiated in the general
|
||||
section. Registration allows Asterisk to notify a remote Asterisk server
|
||||
(with a fixed address) what our current address is. In order for
|
||||
registration to work, the remote Asterisk server will need to have a
|
||||
dynamic peer entry with the same name (and secret if provided).
|
||||
|
||||
The name is a required field, and is the remote peer name that we wish to
|
||||
identify ourselves as. A secret may be provided as well. The secret is
|
||||
generally a shared password between the local server and the remote
|
||||
server. However, if the secret is in square brackets ([]'s) then it is
|
||||
interpreted as the name of a key to use. In that case, the local Asterisk
|
||||
server must have the *private* key (/var/lib/asterisk/keys/<name>.key) and
|
||||
the remote server will have to have the corresponding public key.
|
||||
|
||||
The "host" is a required field and is the hostname or IP address of the
|
||||
remote Asterisk server. The port specification is optional and is by
|
||||
default 5036 if not specified.
|
||||
|
||||
-------------
|
||||
|
||||
The following sections, after "general" define either users, peers or
|
||||
friends. A "user" is someone who connects to us. A "peer" is someone
|
||||
that we connect to. A "friend" is simply shorthand for creating a "user"
|
||||
and "peer" with identical parameters (i.e. someone who can contact us and
|
||||
who we contact).
|
||||
|
||||
> [identifier]
|
||||
|
||||
The section begins with the identifier in square brackets. The identifier
|
||||
should be an alphanumeric string.
|
||||
|
||||
> type = [user|peer|friend]
|
||||
|
||||
This line tells Asterisk how to interpret this entity. Users are things
|
||||
that connect to us, while peers are people we connect to, and a friend is
|
||||
shorthand for creating a user and a peer with identical information
|
||||
|
||||
----------------
|
||||
User fields:
|
||||
|
||||
> context = <context>
|
||||
|
||||
One or more context lines may be specified in a user, thus giving the user
|
||||
access to place calls in the given contexts. Contexts are used by
|
||||
Asterisk to divide dialing plans into logical units each with the ability
|
||||
to have numbers interpreted differently, have their own security model,
|
||||
auxilliary switch handling, and include other contexts. Most users are
|
||||
given access to the default context. Trusted users could be given access
|
||||
to the local context for example.
|
||||
|
||||
> permit = <ipaddr>/<netmask>
|
||||
> deny = <ipaddr>/<netmask>
|
||||
|
||||
Permit and deny rules may be applied to users, allowing them to connect
|
||||
from certain IP addresses and not others. The permit and deny rules are
|
||||
interpreted in sequence and all are evaluated on a given IP address, with
|
||||
the final result being the decision. For example:
|
||||
|
||||
> permit = 0.0.0.0/0.0.0.0
|
||||
> deny = 192.168.0.0/255.255.255.0
|
||||
|
||||
would deny anyone in 192.168.0.0 with a netmask of 24 bits (class C),
|
||||
whereas:
|
||||
|
||||
> deny = 192.168.0.0/255.255.255.0
|
||||
> permit = 0.0.0.0/0.0.0.0
|
||||
|
||||
would not deny anyone since the final rule would permit anyone, thsu
|
||||
overriding the denial.
|
||||
|
||||
If no permit/deny rules are listed, it is assumed that someone may connect
|
||||
from anywhere.
|
||||
|
||||
> callerid = <callerid>
|
||||
|
||||
You may override the Caller*ID information passed by a user to you (if
|
||||
they choose to send it) in order that it always be accurate from the
|
||||
perspective of your server.
|
||||
|
||||
> auth = [md5|plaintext|rsa]
|
||||
|
||||
You may select which authentication methods are permitted to be used by
|
||||
the user to authenticate to us. Multiple methods may be specified,
|
||||
separated by commas. If md5 or plaintext authentication is selected, a
|
||||
secret must be provided. If RSA authentication is specified, then one or
|
||||
more key names must be specifed with "inkeys"
|
||||
|
||||
If no secret is specified and no authentication method is specified, then
|
||||
no authentication will be required.
|
||||
|
||||
> secret = <secret>
|
||||
|
||||
The "secret" line specifies the shared secret for md5 and plaintext
|
||||
authentication methods. It is never suggested to use plaintext except in
|
||||
some cases for debugging.
|
||||
|
||||
> inkeys = key1[:key2...]
|
||||
|
||||
The "inkeys" line specifies which keys we can use to authenticate the
|
||||
remote peer. If the peer's challenge passes with any of the given keys,
|
||||
then we accept its authentication. The key files live in
|
||||
/var/lib/asterisk/keys/<name>.pub and are *public keys*. Public keys are
|
||||
not typically DES3 encrypted and thus do not usually need initialization.
|
||||
|
||||
---------------
|
||||
Peer configuration
|
||||
|
||||
> allow = [gsm|lpc10|g723.1|adpcm|ulaw|alaw|mp3|slinear|all]
|
||||
> disallow = [gsm|lpc10|g723.1|adpcm|ulaw|alaw|mp3|slinear|all]
|
||||
|
||||
The "allow" and "disallow" may be used to enable or disable specific codec
|
||||
support on a per-peer basis.
|
||||
|
||||
> host = [<ipaddr>|dynamic]
|
||||
|
||||
The host line specifies the hostname or IP address of the remote host, or
|
||||
may be the word "dynamic" signifying that the host will register with us
|
||||
(see register => in the general section above).
|
||||
|
||||
> defaultip = <ipaddr>
|
||||
|
||||
If the host uses dynamic registration, Asterisk may still be given a
|
||||
default IP address to use when dynamic registration has not been performed
|
||||
or has timed out.
|
||||
|
||||
|
||||
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
|
||||
138
README.variables
138
README.variables
@@ -1,138 +0,0 @@
|
||||
GENERAL ENCHANCEMENTS TO EXTENSION LOGIC :
|
||||
|
||||
QUOTING:
|
||||
|
||||
exten => s,5,BackGround,blabla
|
||||
|
||||
The parameter (blabla) can be quoted ("blabla"). In this case, a
|
||||
comma does not terminate the field.
|
||||
|
||||
Also, characters special to variable substitution, expression evaluation, etc
|
||||
(see below), can be quoted. For example, to literally use a $ on the
|
||||
string "$1231", quote it with a preceeding \. Special characters that must
|
||||
be quoted to be used, are [ ] $ " \. (to write \ itself, use \\).
|
||||
|
||||
VARIABLES:
|
||||
|
||||
Parameter strings can include variables. Variable names are arbitrary strings.
|
||||
They are stored in the respective channel structure.
|
||||
|
||||
To set a variable to a particular value, do :
|
||||
|
||||
;exten => 1,2,SetVar,varname=value
|
||||
|
||||
You can substitute the value of a variable everywhere using ${variablename}.
|
||||
For example, to stringwise append $lala to $blabla and store result in $koko,
|
||||
do:
|
||||
|
||||
;exten => 1,2,SetVar,koko=${blabla}${lala}
|
||||
|
||||
There are also the following special variables:
|
||||
|
||||
${CALLERID} Caller ID
|
||||
${CALLERIDNAME} Caller ID Name only
|
||||
${CALLERIDNUM} Caller ID Number only
|
||||
${EXTEN} Current extension
|
||||
${CONTEXT} Current context
|
||||
${PRIORITY} Current priority
|
||||
${CHANNEL} Current channel name
|
||||
|
||||
There are two reference modes - reference by value and reference by name.
|
||||
To refer to a variable with its name (as an argument to a function that
|
||||
requires a variable), just write the name. To refer to the variable's value,
|
||||
enclose it inside ${}. For example, SetVar takes as the first argument
|
||||
(before the =) a variable name, so:
|
||||
|
||||
;exten => 1,2,SetVar,koko=lala
|
||||
;exten => 1,3,SetVar,${koko}=blabla
|
||||
|
||||
stores to the variable "koko" the value "lala" and to variable "lala" the
|
||||
value "blabla".
|
||||
|
||||
In fact, everything contained ${here} is just replaced with the value of
|
||||
the variable "here".
|
||||
|
||||
EXPRESSIONS:
|
||||
|
||||
Everything contained inside a bracket pair prefixed by a $ (like $[this]) is
|
||||
considered as an expression and it is evaluated. Evaluation works similar to
|
||||
(but is done on a later stage than) variable substitution: the expression
|
||||
(including the square brackets) is replaced by the result of the expression
|
||||
evaluation. The arguments and operands of the expression MUST BE separated
|
||||
with spaces (take care NOT to leave ANY spaces between opening and closing
|
||||
square brackets and the first and last arguments).
|
||||
|
||||
For example, after the sequence:
|
||||
|
||||
exten => 1,1,SetVar,"lala=$[1 + 2]";
|
||||
exten => 1,2,SetVar,"koko=$[2 * ${lala}]";
|
||||
|
||||
the value of variable koko is "6".
|
||||
|
||||
Operators are listed below in order of increasing precedence. Operators
|
||||
with equal precedence are grouped within { } symbols.
|
||||
|
||||
expr1 | expr2
|
||||
Return the evaluation of expr1 if it is neither an empty string
|
||||
nor zero; otherwise, returns the evaluation of expr2.
|
||||
|
||||
expr1 & expr2
|
||||
Return the evaluation of expr1 if neither expression evaluates to
|
||||
an empty string or zero; otherwise, returns zero.
|
||||
|
||||
expr1 {=, >, >=, <, <=, !=} expr2
|
||||
Return the results of integer comparison if both arguments are
|
||||
integers; otherwise, returns the results of string comparison
|
||||
using the locale-specific collation sequence. The result of each
|
||||
comparison is 1 if the specified relation is true, or 0 if the
|
||||
relation is false.
|
||||
|
||||
expr1 {+, -} expr2
|
||||
Return the results of addition or subtraction of integer-valued
|
||||
arguments.
|
||||
|
||||
expr1 {*, /, %} expr2
|
||||
Return the results of multiplication, integer division, or
|
||||
remainder of integer-valued arguments.
|
||||
|
||||
expr1 : expr2
|
||||
The `:' operator matches expr1 against expr2, which must be a
|
||||
regular expression. The regular expression is anchored to the
|
||||
beginning of the string with an implicit `^'.
|
||||
|
||||
If the match succeeds and the pattern contains at least one regu-
|
||||
lar expression subexpression `\(...\)', the string correspond-
|
||||
ing to `\1' is returned; otherwise the matching operator
|
||||
returns the number of characters matched. If the match fails and
|
||||
the pattern contains a regular expression subexpression the null
|
||||
string is returned; otherwise 0.
|
||||
|
||||
Parentheses are used for grouping in the usual manner.
|
||||
|
||||
The parser must be parsed with bison (bison is REQUIRED - yacc cannot
|
||||
produce pure parsers, which are reentrant)
|
||||
|
||||
CONDITIONALS
|
||||
|
||||
There is one conditional operator - the conditional goto :
|
||||
|
||||
;exten => 1,2,gotoif,condition?label1:label2
|
||||
|
||||
If condition is true go to label1, else go to label2. Labels are interpreted
|
||||
exactly as in the normal goto command.
|
||||
|
||||
"condition" is just a string. If the string is empty or "0", the condition
|
||||
is considered to be false, if it's anything else, the condition is true.
|
||||
This is designed to be used together with the expression syntax described
|
||||
above, eg :
|
||||
|
||||
exten => 1,2,gotoif,$[${CALLERID} = 123456]?2|1:3|1
|
||||
|
||||
|
||||
Example of use :
|
||||
|
||||
exten => s,2,SetVar,"vara=1"
|
||||
exten => s,3,SetVar,"varb=$[${vara} + 2]"
|
||||
exten => s,4,SetVar,"varc=$[${varb} * 2]"
|
||||
exten => s,5,GotoIf,"$[${varc} = 6]?99|1:s|6";
|
||||
|
||||
6
SECURITY
Executable file → Normal file
6
SECURITY
Executable file → Normal file
@@ -25,15 +25,15 @@ the "default" context within other private contexts by using:
|
||||
in the appropriate section. A well designed PBX might look like this:
|
||||
|
||||
[longdistance]
|
||||
exten => _91NXXNXXXXXX,1,Dial,Tor/g2/BYEXTENSION
|
||||
exten => _91NXXNXXXXXX,1,Dial(Zap/g2/${EXTEN:1})
|
||||
include => local
|
||||
|
||||
[local]
|
||||
exten => _9NXXNXXX,1,Dial,Tor/g2/BYEXTENSION
|
||||
exten => _9NXXNXXX,1,Dial(Zap/g2/${EXTEN:1})
|
||||
include => default
|
||||
|
||||
[default]
|
||||
exten => 6123,Dial,Tor/1
|
||||
exten => 6123,Dial(Zap/1)
|
||||
|
||||
|
||||
DON'T FORGET TO TAKE THE DEMO CONTEXT OUT OF YOUR DEFAULT CONTEXT. There
|
||||
|
||||
326
acl.c
Executable file → Normal file
326
acl.c
Executable file → Normal file
@@ -13,7 +13,6 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
@@ -21,12 +20,23 @@
|
||||
#include <unistd.h>
|
||||
#include <asterisk/acl.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/ioctl.h>
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
|
||||
#include <fcntl.h>
|
||||
#include <net/route.h>
|
||||
|
||||
AST_MUTEX_DEFINE_STATIC(routeseq_lock);
|
||||
#endif
|
||||
|
||||
#define AST_SENSE_DENY 0
|
||||
#define AST_SENSE_ALLOW 1
|
||||
|
||||
struct ast_ha {
|
||||
/* Host access rule */
|
||||
@@ -36,6 +46,15 @@ struct ast_ha {
|
||||
struct ast_ha *next;
|
||||
};
|
||||
|
||||
/* Default IP - if not otherwise set, don't breathe garbage */
|
||||
static struct in_addr __ourip = { 0x00000000 };
|
||||
|
||||
struct my_ifreq {
|
||||
char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "eth0", "ppp0", etc. */
|
||||
struct sockaddr_in ifru_addr;
|
||||
};
|
||||
|
||||
/* Free HA structure */
|
||||
void ast_free_ha(struct ast_ha *ha)
|
||||
{
|
||||
struct ast_ha *hal;
|
||||
@@ -46,33 +65,89 @@ void ast_free_ha(struct ast_ha *ha)
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy HA structure */
|
||||
static void ast_copy_ha(struct ast_ha *from, struct ast_ha *to)
|
||||
{
|
||||
memcpy(&to->netaddr, &from->netaddr, sizeof(from->netaddr));
|
||||
memcpy(&to->netmask, &from->netmask, sizeof(from->netmask));
|
||||
to->sense = from->sense;
|
||||
}
|
||||
|
||||
/* Create duplicate of ha structure */
|
||||
static struct ast_ha *ast_duplicate_ha(struct ast_ha *original)
|
||||
{
|
||||
struct ast_ha *new_ha = malloc(sizeof(struct ast_ha));
|
||||
|
||||
/* Copy from original to new object */
|
||||
ast_copy_ha(original, new_ha);
|
||||
|
||||
return(new_ha);
|
||||
|
||||
}
|
||||
|
||||
/* Create duplicate HA link list */
|
||||
/* Used in chan_sip2 templates */
|
||||
struct ast_ha *ast_duplicate_ha_list(struct ast_ha *original)
|
||||
{
|
||||
struct ast_ha *start=original;
|
||||
struct ast_ha *ret = NULL;
|
||||
struct ast_ha *link,*prev=NULL;
|
||||
|
||||
while(start) {
|
||||
link = ast_duplicate_ha(start); /* Create copy of this object */
|
||||
if (prev)
|
||||
prev->next = link; /* Link previous to this object */
|
||||
|
||||
if (!ret)
|
||||
ret = link; /* Save starting point */
|
||||
|
||||
start = start->next; /* Go to next object */
|
||||
prev = link; /* Save pointer to this object */
|
||||
}
|
||||
return (ret); /* Return start of list */
|
||||
}
|
||||
|
||||
struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
|
||||
{
|
||||
struct ast_ha *ha = malloc(sizeof(struct ast_ha));
|
||||
char *nm;
|
||||
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) {
|
||||
char *stringp=NULL;
|
||||
stringp=stuff;
|
||||
strsep(&stringp, "/");
|
||||
nm = strsep(&stringp, "/");
|
||||
strncpy(tmp, stuff, sizeof(tmp) - 1);
|
||||
nm = strchr(tmp, '/');
|
||||
if (!nm)
|
||||
nm = "255.255.255.255";
|
||||
if (!inet_aton(stuff, &ha->netaddr)) {
|
||||
ast_log(LOG_WARNING, "%s not a valid IP\n", stuff);
|
||||
free(ha);
|
||||
return NULL;
|
||||
else {
|
||||
*nm = '\0';
|
||||
nm++;
|
||||
}
|
||||
if (!inet_aton(nm, &ha->netmask)) {
|
||||
if (!strchr(nm, '.')) {
|
||||
if ((sscanf(nm, "%i", &x) == 1) && (x >= 0) && (x <= 32)) {
|
||||
y = 0;
|
||||
for (z=0;z<x;z++) {
|
||||
y >>= 1;
|
||||
y |= 0x80000000;
|
||||
}
|
||||
ha->netmask.s_addr = htonl(y);
|
||||
}
|
||||
} else if (!inet_aton(nm, &ha->netmask)) {
|
||||
ast_log(LOG_WARNING, "%s not a valid netmask\n", nm);
|
||||
free(ha);
|
||||
return NULL;
|
||||
return path;
|
||||
}
|
||||
if (!inet_aton(tmp, &ha->netaddr)) {
|
||||
ast_log(LOG_WARNING, "%s not a valid IP\n", tmp);
|
||||
free(ha);
|
||||
return path;
|
||||
}
|
||||
ha->netaddr.s_addr &= ha->netmask.s_addr;
|
||||
if (!strncasecmp(sense, "p", 1)) {
|
||||
@@ -86,7 +161,8 @@ struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
|
||||
else
|
||||
ret = ha;
|
||||
}
|
||||
return NULL;
|
||||
ast_log(LOG_DEBUG, "%s/%s appended to acl for peer\n",stuff, nm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
|
||||
@@ -94,6 +170,13 @@ int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
|
||||
/* Start optimistic */
|
||||
int res = AST_SENSE_ALLOW;
|
||||
while(ha) {
|
||||
char iabuf[INET_ADDRSTRLEN];
|
||||
char iabuf2[INET_ADDRSTRLEN];
|
||||
/* DEBUG */
|
||||
ast_log(LOG_DEBUG,
|
||||
"##### Testing %s with %s\n",
|
||||
ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr),
|
||||
ast_inet_ntoa(iabuf2, sizeof(iabuf2), ha->netaddr));
|
||||
/* For each rule, if this address and the netmask = the net address
|
||||
apply the current rule */
|
||||
if ((sin->sin_addr.s_addr & ha->netmask.s_addr) == (ha->netaddr.s_addr))
|
||||
@@ -106,7 +189,8 @@ int ast_apply_ha(struct ast_ha *ha, struct sockaddr_in *sin)
|
||||
int ast_get_ip(struct sockaddr_in *sin, char *value)
|
||||
{
|
||||
struct hostent *hp;
|
||||
hp = gethostbyname(value);
|
||||
struct ast_hostent ahp;
|
||||
hp = ast_gethostbyname(value, &ahp);
|
||||
if (hp) {
|
||||
memcpy(&sin->sin_addr, hp->h_addr, sizeof(sin->sin_addr));
|
||||
} else {
|
||||
@@ -116,8 +200,210 @@ int ast_get_ip(struct sockaddr_in *sin, char *value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int inaddrcmp(struct sockaddr_in *sin1, struct sockaddr_in *sin2)
|
||||
{
|
||||
return ((sin1->sin_addr.s_addr != sin2->sin_addr.s_addr )
|
||||
|| (sin1->sin_port != sin2->sin_port));
|
||||
/* iface is the interface (e.g. eth0); address is the return value */
|
||||
int ast_lookup_iface(char *iface, struct in_addr *address) {
|
||||
int mysock, res = 0;
|
||||
struct my_ifreq ifreq;
|
||||
|
||||
memset(&ifreq, 0, sizeof(ifreq));
|
||||
strncpy(ifreq.ifrn_name,iface,sizeof(ifreq.ifrn_name) - 1);
|
||||
|
||||
mysock = socket(PF_INET,SOCK_DGRAM,IPPROTO_IP);
|
||||
res = ioctl(mysock,SIOCGIFADDR,&ifreq);
|
||||
|
||||
close(mysock);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to get IP of %s: %s\n", iface, strerror(errno));
|
||||
memcpy((char *)address,(char *)&__ourip,sizeof(__ourip));
|
||||
return -1;
|
||||
} else {
|
||||
memcpy((char *)address,(char *)&ifreq.ifru_addr.sin_addr,sizeof(ifreq.ifru_addr.sin_addr));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
|
||||
{
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
|
||||
struct sockaddr_in *sin;
|
||||
struct sockaddr *sa;
|
||||
struct {
|
||||
struct rt_msghdr m_rtm;
|
||||
char m_space[512];
|
||||
} m_rtmsg;
|
||||
char iabuf[INET_ADDRSTRLEN];
|
||||
char *cp, *p;
|
||||
int i, l, s, seq, flags;
|
||||
pid_t pid = getpid();
|
||||
static int routeseq; /* Protected by "routeseq_lock" mutex */
|
||||
|
||||
p = ast_strdupa(ast_inet_ntoa(iabuf, sizeof(iabuf), *them));
|
||||
memset(us, 0, sizeof(struct in_addr));
|
||||
|
||||
memset(&m_rtmsg, 0, sizeof(m_rtmsg));
|
||||
m_rtmsg.m_rtm.rtm_type = RTM_GET;
|
||||
m_rtmsg.m_rtm.rtm_version = RTM_VERSION;
|
||||
ast_mutex_lock(&routeseq_lock);
|
||||
seq = ++routeseq;
|
||||
ast_mutex_unlock(&routeseq_lock);
|
||||
m_rtmsg.m_rtm.rtm_seq = seq;
|
||||
m_rtmsg.m_rtm.rtm_addrs = RTA_DST | RTA_IFA;
|
||||
m_rtmsg.m_rtm.rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in);
|
||||
sin = (struct sockaddr_in *)m_rtmsg.m_space;
|
||||
sin->sin_family = AF_INET;
|
||||
sin->sin_len = sizeof(struct sockaddr_in);
|
||||
sin->sin_addr = *them;
|
||||
|
||||
if ((s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC)) < 0) {
|
||||
ast_log(LOG_ERROR, "Error opening routing socket\n");
|
||||
return -1;
|
||||
}
|
||||
flags = fcntl(s, F_GETFL);
|
||||
fcntl(s, F_SETFL, flags | O_NONBLOCK);
|
||||
if (write(s, (char *)&m_rtmsg, m_rtmsg.m_rtm.rtm_msglen) < 0) {
|
||||
ast_log(LOG_ERROR, "Error writing to routing socket: %s\n", strerror(errno));
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
do {
|
||||
l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
|
||||
} while (l > 0 && (m_rtmsg.m_rtm.rtm_seq != seq || m_rtmsg.m_rtm.rtm_pid != pid));
|
||||
if (l < 0) {
|
||||
if (errno != EAGAIN)
|
||||
ast_log(LOG_ERROR, "Error reading from routing socket\n");
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
close(s);
|
||||
|
||||
if (m_rtmsg.m_rtm.rtm_version != RTM_VERSION) {
|
||||
ast_log(LOG_ERROR, "Unsupported route socket protocol version\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (m_rtmsg.m_rtm.rtm_msglen != l)
|
||||
ast_log(LOG_WARNING, "Message length mismatch, in packet %d, returned %d\n",
|
||||
m_rtmsg.m_rtm.rtm_msglen, l);
|
||||
|
||||
if (m_rtmsg.m_rtm.rtm_errno) {
|
||||
ast_log(LOG_ERROR, "RTM_GET got %s (%d)\n",
|
||||
strerror(m_rtmsg.m_rtm.rtm_errno), m_rtmsg.m_rtm.rtm_errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cp = (char *)m_rtmsg.m_space;
|
||||
if (m_rtmsg.m_rtm.rtm_addrs)
|
||||
for (i = 1; i; i <<= 1)
|
||||
if (m_rtmsg.m_rtm.rtm_addrs & i) {
|
||||
sa = (struct sockaddr *)cp;
|
||||
if (i == RTA_IFA && sa->sa_family == AF_INET) {
|
||||
sin = (struct sockaddr_in *)sa;
|
||||
*us = sin->sin_addr;
|
||||
ast_log(LOG_DEBUG, "Found route to %s, output from our address %s.\n", p, ast_inet_ntoa(iabuf, sizeof(iabuf), *us));
|
||||
return 0;
|
||||
}
|
||||
cp += sa->sa_len > 0 ?
|
||||
(1 + ((sa->sa_len - 1) | (sizeof(long) - 1))) :
|
||||
sizeof(long);
|
||||
}
|
||||
|
||||
ast_log(LOG_DEBUG, "No route found for address %s!\n", p);
|
||||
return -1;
|
||||
#else
|
||||
FILE *PROC;
|
||||
unsigned int remote_ip;
|
||||
int res = 1;
|
||||
char line[256];
|
||||
remote_ip = them->s_addr;
|
||||
|
||||
PROC = fopen("/proc/net/route","r");
|
||||
if (!PROC) {
|
||||
bzero(us,sizeof(struct in_addr));
|
||||
return -1;
|
||||
}
|
||||
/* First line contains headers */
|
||||
fgets(line,sizeof(line),PROC);
|
||||
|
||||
while (!feof(PROC)) {
|
||||
char iface[256];
|
||||
unsigned int dest, gateway, mask;
|
||||
int i,fieldnum;
|
||||
char *fields[40];
|
||||
|
||||
fgets(line,sizeof(line),PROC);
|
||||
|
||||
fieldnum = 0;
|
||||
for (i=0;i<sizeof(line);i++) {
|
||||
char *offset;
|
||||
|
||||
fields[fieldnum++] = line + i;
|
||||
offset = strchr(line + i,'\t');
|
||||
if (offset == NULL) {
|
||||
/* Exit loop */
|
||||
break;
|
||||
} else if (fieldnum >= 9) {
|
||||
/* Short-circuit: can't break at 8, since the end of field 7 is figured when fieldnum=8 */
|
||||
break;
|
||||
} else {
|
||||
*offset = '\0';
|
||||
i = offset - line;
|
||||
}
|
||||
}
|
||||
if (fieldnum >= 8) {
|
||||
|
||||
sscanf(fields[0],"%s",iface);
|
||||
sscanf(fields[1],"%x",&dest);
|
||||
sscanf(fields[2],"%x",&gateway);
|
||||
sscanf(fields[7],"%x",&mask);
|
||||
#if 0
|
||||
{ char iabuf[INET_ADDRSTRLEN];
|
||||
printf("Addr: %s %08x Dest: %08x Mask: %08x\n", ast_inet_ntoa(iabuf, sizeof(iabuf), *them), remote_ip, dest, mask); }
|
||||
#endif
|
||||
/* Looks simple, but here is the magic */
|
||||
if (((remote_ip & mask) ^ dest) == 0) {
|
||||
res = ast_lookup_iface(iface,us);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(PROC);
|
||||
if (res == 1) {
|
||||
ast_log(LOG_WARNING, "Yikes! No default route?!!\n");
|
||||
bzero(us,sizeof(struct in_addr));
|
||||
return -2;
|
||||
} else if (res) {
|
||||
/* We've already warned in subroutine */
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ast_find_ourip(struct in_addr *ourip, struct sockaddr_in bindaddr)
|
||||
{
|
||||
char ourhost[MAXHOSTNAMELEN]="";
|
||||
struct ast_hostent ahp;
|
||||
struct hostent *hp;
|
||||
struct in_addr saddr;
|
||||
|
||||
/* just use the bind address if it is nonzero */
|
||||
if (ntohl(bindaddr.sin_addr.s_addr)) {
|
||||
memcpy(ourip, &bindaddr.sin_addr, sizeof(*ourip));
|
||||
return 0;
|
||||
}
|
||||
/* try to use our hostname */
|
||||
if (gethostname(ourhost, sizeof(ourhost)-1)) {
|
||||
ast_log(LOG_WARNING, "Unable to get hostname\n");
|
||||
} else {
|
||||
hp = ast_gethostbyname(ourhost, &ahp);
|
||||
if (hp) {
|
||||
memcpy(ourip, hp->h_addr, sizeof(*ourip));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* A.ROOT-SERVERS.NET. */
|
||||
if (inet_aton("198.41.0.4", &saddr) && !ast_ouraddrfor(&saddr, ourip))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
20
addmailbox
20
addmailbox
@@ -1,20 +0,0 @@
|
||||
#!/bin/sh
|
||||
VMHOME=/var/spool/asterisk/vm
|
||||
SNDHOME=/var/lib/asterisk/sounds
|
||||
echo -n "Enter mailbox number: "
|
||||
read mailbox
|
||||
mkdir -p ${VMHOME}/${mailbox}
|
||||
mkdir -p ${VMHOME}/${mailbox}/INBOX
|
||||
cat ${SNDHOME}/vm-theperson.gsm > ${VMHOME}/${mailbox}/unavail.gsm
|
||||
cat ${SNDHOME}/vm-theperson.gsm > ${VMHOME}/${mailbox}/busy.gsm
|
||||
cat ${SNDHOME}/vm-extension.gsm > ${VMHOME}/${mailbox}/greet.gsm
|
||||
nums=`echo $mailbox | sed 's/./ \0/g'`
|
||||
for x in $nums; do
|
||||
cat ${SNDHOME}/digits/${x}.gsm >> ${VMHOME}/${mailbox}/unavail.gsm
|
||||
cat ${SNDHOME}/digits/${x}.gsm >> ${VMHOME}/${mailbox}/busy.gsm
|
||||
cat ${SNDHOME}/digits/${x}.gsm >> ${VMHOME}/${mailbox}/greet.gsm
|
||||
done
|
||||
|
||||
cat ${SNDHOME}/vm-isunavail.gsm >> ${VMHOME}/${mailbox}/unavail.gsm
|
||||
cat ${SNDHOME}/vm-isonphone.gsm >> ${VMHOME}/${mailbox}/busy.gsm
|
||||
|
||||
311
aescrypt.c
Normal file
311
aescrypt.c
Normal file
@@ -0,0 +1,311 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 2003, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
|
||||
All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The free distribution and use of this software in both source and binary
|
||||
form is allowed (with or without changes) provided that:
|
||||
|
||||
1. distributions of this source code include the above copyright
|
||||
notice, this list of conditions and the following disclaimer;
|
||||
|
||||
2. distributions in binary form include the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other associated materials;
|
||||
|
||||
3. the copyright holder's name is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
ALTERNATIVELY, provided that this notice is retained in full, this product
|
||||
may be distributed under the terms of the GNU General Public License (GPL),
|
||||
in which case the provisions of the GPL apply INSTEAD OF those given above.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 26/08/2003
|
||||
|
||||
This file contains the code for implementing encryption and decryption
|
||||
for AES (Rijndael) for block and key sizes of 16, 24 and 32 bytes. It
|
||||
can optionally be replaced by code written in assembler using NASM. For
|
||||
further details see the file aesopt.h
|
||||
*/
|
||||
|
||||
#include "aesopt.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c])
|
||||
#define so(y,x,c) word_out(y, c, s(x,c))
|
||||
|
||||
#if defined(ARRAYS)
|
||||
#define locals(y,x) x[4],y[4]
|
||||
#else
|
||||
#define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3
|
||||
#endif
|
||||
|
||||
#define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \
|
||||
s(y,2) = s(x,2); s(y,3) = s(x,3);
|
||||
#define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3)
|
||||
#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
|
||||
#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)
|
||||
|
||||
#if defined(ENCRYPTION) && !defined(AES_ASM)
|
||||
|
||||
/* Visual C++ .Net v7.1 provides the fastest encryption code when using
|
||||
Pentium optimiation with small code but this is poor for decryption
|
||||
so we need to control this with the following VC++ pragmas
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma optimize( "s", on )
|
||||
#endif
|
||||
|
||||
/* Given the column (c) of the output state variable, the following
|
||||
macros give the input state variables which are needed in its
|
||||
computation for each row (r) of the state. All the alternative
|
||||
macros give the same end values but expand into different ways
|
||||
of calculating these values. In particular the complex macro
|
||||
used for dynamically variable block sizes is designed to expand
|
||||
to a compile time constant whenever possible but will expand to
|
||||
conditional clauses on some branches (I am grateful to Frank
|
||||
Yellin for this construction)
|
||||
*/
|
||||
|
||||
#define fwd_var(x,r,c)\
|
||||
( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
|
||||
: r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\
|
||||
: r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
|
||||
: ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2)))
|
||||
|
||||
#if defined(FT4_SET)
|
||||
#undef dec_fmvars
|
||||
#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c))
|
||||
#elif defined(FT1_SET)
|
||||
#undef dec_fmvars
|
||||
#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c))
|
||||
#else
|
||||
#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c)))
|
||||
#endif
|
||||
|
||||
#if defined(FL4_SET)
|
||||
#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c))
|
||||
#elif defined(FL1_SET)
|
||||
#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c))
|
||||
#else
|
||||
#define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c))
|
||||
#endif
|
||||
|
||||
aes_rval aes_encrypt(const void *in_blk, void *out_blk, const aes_encrypt_ctx cx[1])
|
||||
{ aes_32t locals(b0, b1);
|
||||
const aes_32t *kp = cx->ks;
|
||||
#ifdef dec_fmvars
|
||||
dec_fmvars; /* declare variables for fwd_mcol() if needed */
|
||||
#endif
|
||||
|
||||
aes_32t nr = (kp[45] ^ kp[52] ^ kp[53] ? kp[52] : 14);
|
||||
|
||||
#ifdef AES_ERR_CHK
|
||||
if( (nr != 10 || !(kp[0] | kp[3] | kp[4]))
|
||||
&& (nr != 12 || !(kp[0] | kp[5] | kp[6]))
|
||||
&& (nr != 14 || !(kp[0] | kp[7] | kp[8])) )
|
||||
return aes_error;
|
||||
#endif
|
||||
|
||||
state_in(b0, in_blk, kp);
|
||||
|
||||
#if (ENC_UNROLL == FULL)
|
||||
|
||||
switch(nr)
|
||||
{
|
||||
case 14:
|
||||
round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
|
||||
round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
|
||||
kp += 2 * N_COLS;
|
||||
case 12:
|
||||
round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
|
||||
round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
|
||||
kp += 2 * N_COLS;
|
||||
case 10:
|
||||
round(fwd_rnd, b1, b0, kp + 1 * N_COLS);
|
||||
round(fwd_rnd, b0, b1, kp + 2 * N_COLS);
|
||||
round(fwd_rnd, b1, b0, kp + 3 * N_COLS);
|
||||
round(fwd_rnd, b0, b1, kp + 4 * N_COLS);
|
||||
round(fwd_rnd, b1, b0, kp + 5 * N_COLS);
|
||||
round(fwd_rnd, b0, b1, kp + 6 * N_COLS);
|
||||
round(fwd_rnd, b1, b0, kp + 7 * N_COLS);
|
||||
round(fwd_rnd, b0, b1, kp + 8 * N_COLS);
|
||||
round(fwd_rnd, b1, b0, kp + 9 * N_COLS);
|
||||
round(fwd_lrnd, b0, b1, kp +10 * N_COLS);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if (ENC_UNROLL == PARTIAL)
|
||||
{ aes_32t rnd;
|
||||
for(rnd = 0; rnd < (nr >> 1) - 1; ++rnd)
|
||||
{
|
||||
kp += N_COLS;
|
||||
round(fwd_rnd, b1, b0, kp);
|
||||
kp += N_COLS;
|
||||
round(fwd_rnd, b0, b1, kp);
|
||||
}
|
||||
kp += N_COLS;
|
||||
round(fwd_rnd, b1, b0, kp);
|
||||
#else
|
||||
{ aes_32t rnd;
|
||||
for(rnd = 0; rnd < nr - 1; ++rnd)
|
||||
{
|
||||
kp += N_COLS;
|
||||
round(fwd_rnd, b1, b0, kp);
|
||||
l_copy(b0, b1);
|
||||
}
|
||||
#endif
|
||||
kp += N_COLS;
|
||||
round(fwd_lrnd, b0, b1, kp);
|
||||
}
|
||||
#endif
|
||||
|
||||
state_out(out_blk, b0);
|
||||
#ifdef AES_ERR_CHK
|
||||
return aes_good;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(DECRYPTION) && !defined(AES_ASM)
|
||||
|
||||
/* Visual C++ .Net v7.1 provides the fastest encryption code when using
|
||||
Pentium optimiation with small code but this is poor for decryption
|
||||
so we need to control this with the following VC++ pragmas
|
||||
*/
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma optimize( "t", on )
|
||||
#endif
|
||||
|
||||
/* Given the column (c) of the output state variable, the following
|
||||
macros give the input state variables which are needed in its
|
||||
computation for each row (r) of the state. All the alternative
|
||||
macros give the same end values but expand into different ways
|
||||
of calculating these values. In particular the complex macro
|
||||
used for dynamically variable block sizes is designed to expand
|
||||
to a compile time constant whenever possible but will expand to
|
||||
conditional clauses on some branches (I am grateful to Frank
|
||||
Yellin for this construction)
|
||||
*/
|
||||
|
||||
#define inv_var(x,r,c)\
|
||||
( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
|
||||
: r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\
|
||||
: r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
|
||||
: ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0)))
|
||||
|
||||
#if defined(IT4_SET)
|
||||
#undef dec_imvars
|
||||
#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c))
|
||||
#elif defined(IT1_SET)
|
||||
#undef dec_imvars
|
||||
#define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c))
|
||||
#else
|
||||
#define inv_rnd(y,x,k,c) (s(y,c) = inv_mcol((k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)))
|
||||
#endif
|
||||
|
||||
#if defined(IL4_SET)
|
||||
#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c))
|
||||
#elif defined(IL1_SET)
|
||||
#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c))
|
||||
#else
|
||||
#define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))
|
||||
#endif
|
||||
|
||||
aes_rval aes_decrypt(const void *in_blk, void *out_blk, const aes_decrypt_ctx cx[1])
|
||||
{ aes_32t locals(b0, b1);
|
||||
#ifdef dec_imvars
|
||||
dec_imvars; /* declare variables for inv_mcol() if needed */
|
||||
#endif
|
||||
|
||||
aes_32t nr = (cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] ? cx->ks[52] : 14);
|
||||
const aes_32t *kp = cx->ks + nr * N_COLS;
|
||||
|
||||
#ifdef AES_ERR_CHK
|
||||
if( (nr != 10 || !(cx->ks[0] | cx->ks[3] | cx->ks[4]))
|
||||
&& (nr != 12 || !(cx->ks[0] | cx->ks[5] | cx->ks[6]))
|
||||
&& (nr != 14 || !(cx->ks[0] | cx->ks[7] | cx->ks[8])) )
|
||||
return aes_error;
|
||||
#endif
|
||||
|
||||
state_in(b0, in_blk, kp);
|
||||
|
||||
#if (DEC_UNROLL == FULL)
|
||||
|
||||
switch(nr)
|
||||
{
|
||||
case 14:
|
||||
round(inv_rnd, b1, b0, kp - 1 * N_COLS);
|
||||
round(inv_rnd, b0, b1, kp - 2 * N_COLS);
|
||||
kp -= 2 * N_COLS;
|
||||
case 12:
|
||||
round(inv_rnd, b1, b0, kp - 1 * N_COLS);
|
||||
round(inv_rnd, b0, b1, kp - 2 * N_COLS);
|
||||
kp -= 2 * N_COLS;
|
||||
case 10:
|
||||
round(inv_rnd, b1, b0, kp - 1 * N_COLS);
|
||||
round(inv_rnd, b0, b1, kp - 2 * N_COLS);
|
||||
round(inv_rnd, b1, b0, kp - 3 * N_COLS);
|
||||
round(inv_rnd, b0, b1, kp - 4 * N_COLS);
|
||||
round(inv_rnd, b1, b0, kp - 5 * N_COLS);
|
||||
round(inv_rnd, b0, b1, kp - 6 * N_COLS);
|
||||
round(inv_rnd, b1, b0, kp - 7 * N_COLS);
|
||||
round(inv_rnd, b0, b1, kp - 8 * N_COLS);
|
||||
round(inv_rnd, b1, b0, kp - 9 * N_COLS);
|
||||
round(inv_lrnd, b0, b1, kp - 10 * N_COLS);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if (DEC_UNROLL == PARTIAL)
|
||||
{ aes_32t rnd;
|
||||
for(rnd = 0; rnd < (nr >> 1) - 1; ++rnd)
|
||||
{
|
||||
kp -= N_COLS;
|
||||
round(inv_rnd, b1, b0, kp);
|
||||
kp -= N_COLS;
|
||||
round(inv_rnd, b0, b1, kp);
|
||||
}
|
||||
kp -= N_COLS;
|
||||
round(inv_rnd, b1, b0, kp);
|
||||
#else
|
||||
{ aes_32t rnd;
|
||||
for(rnd = 0; rnd < nr - 1; ++rnd)
|
||||
{
|
||||
kp -= N_COLS;
|
||||
round(inv_rnd, b1, b0, kp);
|
||||
l_copy(b0, b1);
|
||||
}
|
||||
#endif
|
||||
kp -= N_COLS;
|
||||
round(inv_lrnd, b0, b1, kp);
|
||||
}
|
||||
#endif
|
||||
|
||||
state_out(out_blk, b0);
|
||||
#ifdef AES_ERR_CHK
|
||||
return aes_good;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
463
aeskey.c
Normal file
463
aeskey.c
Normal file
@@ -0,0 +1,463 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 2003, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
|
||||
All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The free distribution and use of this software in both source and binary
|
||||
form is allowed (with or without changes) provided that:
|
||||
|
||||
1. distributions of this source code include the above copyright
|
||||
notice, this list of conditions and the following disclaimer;
|
||||
|
||||
2. distributions in binary form include the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other associated materials;
|
||||
|
||||
3. the copyright holder's name is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
ALTERNATIVELY, provided that this notice is retained in full, this product
|
||||
may be distributed under the terms of the GNU General Public License (GPL),
|
||||
in which case the provisions of the GPL apply INSTEAD OF those given above.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 26/08/2003
|
||||
|
||||
This file contains the code for implementing the key schedule for AES
|
||||
(Rijndael) for block and key sizes of 16, 24, and 32 bytes. See aesopt.h
|
||||
for further details including optimisation.
|
||||
*/
|
||||
|
||||
#include "aesopt.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* Initialise the key schedule from the user supplied key. The key
|
||||
length can be specified in bytes, with legal values of 16, 24
|
||||
and 32, or in bits, with legal values of 128, 192 and 256. These
|
||||
values correspond with Nk values of 4, 6 and 8 respectively.
|
||||
|
||||
The following macros implement a single cycle in the key
|
||||
schedule generation process. The number of cycles needed
|
||||
for each cx->n_col and nk value is:
|
||||
|
||||
nk = 4 5 6 7 8
|
||||
------------------------------
|
||||
cx->n_col = 4 10 9 8 7 7
|
||||
cx->n_col = 5 14 11 10 9 9
|
||||
cx->n_col = 6 19 15 12 11 11
|
||||
cx->n_col = 7 21 19 16 13 14
|
||||
cx->n_col = 8 29 23 19 17 14
|
||||
*/
|
||||
|
||||
#define ke4(k,i) \
|
||||
{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \
|
||||
k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \
|
||||
}
|
||||
#define kel4(k,i) \
|
||||
{ k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+5] = ss[1] ^= ss[0]; \
|
||||
k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2]; \
|
||||
}
|
||||
|
||||
#define ke6(k,i) \
|
||||
{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \
|
||||
k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \
|
||||
k[6*(i)+10] = ss[4] ^= ss[3]; k[6*(i)+11] = ss[5] ^= ss[4]; \
|
||||
}
|
||||
#define kel6(k,i) \
|
||||
{ k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 7] = ss[1] ^= ss[0]; \
|
||||
k[6*(i)+ 8] = ss[2] ^= ss[1]; k[6*(i)+ 9] = ss[3] ^= ss[2]; \
|
||||
}
|
||||
|
||||
#define ke8(k,i) \
|
||||
{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \
|
||||
k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \
|
||||
k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); k[8*(i)+13] = ss[5] ^= ss[4]; \
|
||||
k[8*(i)+14] = ss[6] ^= ss[5]; k[8*(i)+15] = ss[7] ^= ss[6]; \
|
||||
}
|
||||
#define kel8(k,i) \
|
||||
{ k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 9] = ss[1] ^= ss[0]; \
|
||||
k[8*(i)+10] = ss[2] ^= ss[1]; k[8*(i)+11] = ss[3] ^= ss[2]; \
|
||||
}
|
||||
|
||||
#if defined(ENCRYPTION_KEY_SCHEDULE)
|
||||
|
||||
#if defined(AES_128) || defined(AES_VAR)
|
||||
|
||||
aes_rval aes_encrypt_key128(const void *in_key, aes_encrypt_ctx cx[1])
|
||||
{ aes_32t ss[4];
|
||||
|
||||
cx->ks[0] = ss[0] = word_in(in_key, 0);
|
||||
cx->ks[1] = ss[1] = word_in(in_key, 1);
|
||||
cx->ks[2] = ss[2] = word_in(in_key, 2);
|
||||
cx->ks[3] = ss[3] = word_in(in_key, 3);
|
||||
|
||||
#if ENC_UNROLL == NONE
|
||||
{ aes_32t i;
|
||||
|
||||
for(i = 0; i < ((11 * N_COLS - 1) / 4); ++i)
|
||||
ke4(cx->ks, i);
|
||||
}
|
||||
#else
|
||||
ke4(cx->ks, 0); ke4(cx->ks, 1);
|
||||
ke4(cx->ks, 2); ke4(cx->ks, 3);
|
||||
ke4(cx->ks, 4); ke4(cx->ks, 5);
|
||||
ke4(cx->ks, 6); ke4(cx->ks, 7);
|
||||
ke4(cx->ks, 8); kel4(cx->ks, 9);
|
||||
#endif
|
||||
|
||||
/* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */
|
||||
/* key and must be non-zero for 128 and 192 bits keys */
|
||||
cx->ks[53] = cx->ks[45] = 0;
|
||||
cx->ks[52] = 10;
|
||||
#ifdef AES_ERR_CHK
|
||||
return aes_good;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(AES_192) || defined(AES_VAR)
|
||||
|
||||
aes_rval aes_encrypt_key192(const void *in_key, aes_encrypt_ctx cx[1])
|
||||
{ aes_32t ss[6];
|
||||
|
||||
cx->ks[0] = ss[0] = word_in(in_key, 0);
|
||||
cx->ks[1] = ss[1] = word_in(in_key, 1);
|
||||
cx->ks[2] = ss[2] = word_in(in_key, 2);
|
||||
cx->ks[3] = ss[3] = word_in(in_key, 3);
|
||||
cx->ks[4] = ss[4] = word_in(in_key, 4);
|
||||
cx->ks[5] = ss[5] = word_in(in_key, 5);
|
||||
|
||||
#if ENC_UNROLL == NONE
|
||||
{ aes_32t i;
|
||||
|
||||
for(i = 0; i < (13 * N_COLS - 1) / 6; ++i)
|
||||
ke6(cx->ks, i);
|
||||
}
|
||||
#else
|
||||
ke6(cx->ks, 0); ke6(cx->ks, 1);
|
||||
ke6(cx->ks, 2); ke6(cx->ks, 3);
|
||||
ke6(cx->ks, 4); ke6(cx->ks, 5);
|
||||
ke6(cx->ks, 6); kel6(cx->ks, 7);
|
||||
#endif
|
||||
|
||||
/* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */
|
||||
/* key and must be non-zero for 128 and 192 bits keys */
|
||||
cx->ks[53] = cx->ks[45];
|
||||
cx->ks[52] = 12;
|
||||
#ifdef AES_ERR_CHK
|
||||
return aes_good;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(AES_256) || defined(AES_VAR)
|
||||
|
||||
aes_rval aes_encrypt_key256(const void *in_key, aes_encrypt_ctx cx[1])
|
||||
{ aes_32t ss[8];
|
||||
|
||||
cx->ks[0] = ss[0] = word_in(in_key, 0);
|
||||
cx->ks[1] = ss[1] = word_in(in_key, 1);
|
||||
cx->ks[2] = ss[2] = word_in(in_key, 2);
|
||||
cx->ks[3] = ss[3] = word_in(in_key, 3);
|
||||
cx->ks[4] = ss[4] = word_in(in_key, 4);
|
||||
cx->ks[5] = ss[5] = word_in(in_key, 5);
|
||||
cx->ks[6] = ss[6] = word_in(in_key, 6);
|
||||
cx->ks[7] = ss[7] = word_in(in_key, 7);
|
||||
|
||||
#if ENC_UNROLL == NONE
|
||||
{ aes_32t i;
|
||||
|
||||
for(i = 0; i < (15 * N_COLS - 1) / 8; ++i)
|
||||
ke8(cx->ks, i);
|
||||
}
|
||||
#else
|
||||
ke8(cx->ks, 0); ke8(cx->ks, 1);
|
||||
ke8(cx->ks, 2); ke8(cx->ks, 3);
|
||||
ke8(cx->ks, 4); ke8(cx->ks, 5);
|
||||
kel8(cx->ks, 6);
|
||||
#endif
|
||||
#ifdef AES_ERR_CHK
|
||||
return aes_good;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(AES_VAR)
|
||||
|
||||
aes_rval aes_encrypt_key(const void *in_key, int key_len, aes_encrypt_ctx cx[1])
|
||||
{
|
||||
switch(key_len)
|
||||
{
|
||||
#ifdef AES_ERR_CHK
|
||||
case 16: case 128: return aes_encrypt_key128(in_key, cx);
|
||||
case 24: case 192: return aes_encrypt_key192(in_key, cx);
|
||||
case 32: case 256: return aes_encrypt_key256(in_key, cx);
|
||||
default: return aes_error;
|
||||
#else
|
||||
case 16: case 128: aes_encrypt_key128(in_key, cx); return;
|
||||
case 24: case 192: aes_encrypt_key192(in_key, cx); return;
|
||||
case 32: case 256: aes_encrypt_key256(in_key, cx); return;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(DECRYPTION_KEY_SCHEDULE)
|
||||
|
||||
#if DEC_ROUND == NO_TABLES
|
||||
#define ff(x) (x)
|
||||
#else
|
||||
#define ff(x) inv_mcol(x)
|
||||
#ifdef dec_imvars
|
||||
#define d_vars dec_imvars
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
#define kdf4(k,i) \
|
||||
{ ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; ss[1] = ss[1] ^ ss[3]; ss[2] = ss[2] ^ ss[3]; ss[3] = ss[3]; \
|
||||
ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \
|
||||
ss[4] ^= k[4*(i)]; k[4*(i)+4] = ff(ss[4]); ss[4] ^= k[4*(i)+1]; k[4*(i)+5] = ff(ss[4]); \
|
||||
ss[4] ^= k[4*(i)+2]; k[4*(i)+6] = ff(ss[4]); ss[4] ^= k[4*(i)+3]; k[4*(i)+7] = ff(ss[4]); \
|
||||
}
|
||||
#define kd4(k,i) \
|
||||
{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \
|
||||
k[4*(i)+4] = ss[4] ^= k[4*(i)]; k[4*(i)+5] = ss[4] ^= k[4*(i)+1]; \
|
||||
k[4*(i)+6] = ss[4] ^= k[4*(i)+2]; k[4*(i)+7] = ss[4] ^= k[4*(i)+3]; \
|
||||
}
|
||||
#define kdl4(k,i) \
|
||||
{ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \
|
||||
k[4*(i)+4] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; k[4*(i)+5] = ss[1] ^ ss[3]; \
|
||||
k[4*(i)+6] = ss[0]; k[4*(i)+7] = ss[1]; \
|
||||
}
|
||||
#else
|
||||
#define kdf4(k,i) \
|
||||
{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+ 4] = ff(ss[0]); ss[1] ^= ss[0]; k[4*(i)+ 5] = ff(ss[1]); \
|
||||
ss[2] ^= ss[1]; k[4*(i)+ 6] = ff(ss[2]); ss[3] ^= ss[2]; k[4*(i)+ 7] = ff(ss[3]); \
|
||||
}
|
||||
#define kd4(k,i) \
|
||||
{ ss[4] = ls_box(ss[3],3) ^ t_use(r,c)[i]; \
|
||||
ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[4*(i)+ 4] = ss[4] ^= k[4*(i)]; \
|
||||
ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[4] ^= k[4*(i)+ 1]; \
|
||||
ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[4] ^= k[4*(i)+ 2]; \
|
||||
ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[4] ^= k[4*(i)+ 3]; \
|
||||
}
|
||||
#define kdl4(k,i) \
|
||||
{ ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[4*(i)+ 4] = ss[0]; ss[1] ^= ss[0]; k[4*(i)+ 5] = ss[1]; \
|
||||
ss[2] ^= ss[1]; k[4*(i)+ 6] = ss[2]; ss[3] ^= ss[2]; k[4*(i)+ 7] = ss[3]; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define kdf6(k,i) \
|
||||
{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 6] = ff(ss[0]); ss[1] ^= ss[0]; k[6*(i)+ 7] = ff(ss[1]); \
|
||||
ss[2] ^= ss[1]; k[6*(i)+ 8] = ff(ss[2]); ss[3] ^= ss[2]; k[6*(i)+ 9] = ff(ss[3]); \
|
||||
ss[4] ^= ss[3]; k[6*(i)+10] = ff(ss[4]); ss[5] ^= ss[4]; k[6*(i)+11] = ff(ss[5]); \
|
||||
}
|
||||
#define kd6(k,i) \
|
||||
{ ss[6] = ls_box(ss[5],3) ^ t_use(r,c)[i]; \
|
||||
ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[6*(i)+ 6] = ss[6] ^= k[6*(i)]; \
|
||||
ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[6] ^= k[6*(i)+ 1]; \
|
||||
ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[6] ^= k[6*(i)+ 2]; \
|
||||
ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[6] ^= k[6*(i)+ 3]; \
|
||||
ss[4] ^= ss[3]; k[6*(i)+10] = ss[6] ^= k[6*(i)+ 4]; \
|
||||
ss[5] ^= ss[4]; k[6*(i)+11] = ss[6] ^= k[6*(i)+ 5]; \
|
||||
}
|
||||
#define kdl6(k,i) \
|
||||
{ ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[6*(i)+ 6] = ss[0]; ss[1] ^= ss[0]; k[6*(i)+ 7] = ss[1]; \
|
||||
ss[2] ^= ss[1]; k[6*(i)+ 8] = ss[2]; ss[3] ^= ss[2]; k[6*(i)+ 9] = ss[3]; \
|
||||
}
|
||||
|
||||
#define kdf8(k,i) \
|
||||
{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 8] = ff(ss[0]); ss[1] ^= ss[0]; k[8*(i)+ 9] = ff(ss[1]); \
|
||||
ss[2] ^= ss[1]; k[8*(i)+10] = ff(ss[2]); ss[3] ^= ss[2]; k[8*(i)+11] = ff(ss[3]); \
|
||||
ss[4] ^= ls_box(ss[3],0); k[8*(i)+12] = ff(ss[4]); ss[5] ^= ss[4]; k[8*(i)+13] = ff(ss[5]); \
|
||||
ss[6] ^= ss[5]; k[8*(i)+14] = ff(ss[6]); ss[7] ^= ss[6]; k[8*(i)+15] = ff(ss[7]); \
|
||||
}
|
||||
#define kd8(k,i) \
|
||||
{ aes_32t g = ls_box(ss[7],3) ^ t_use(r,c)[i]; \
|
||||
ss[0] ^= g; g = ff(g); k[8*(i)+ 8] = g ^= k[8*(i)]; \
|
||||
ss[1] ^= ss[0]; k[8*(i)+ 9] = g ^= k[8*(i)+ 1]; \
|
||||
ss[2] ^= ss[1]; k[8*(i)+10] = g ^= k[8*(i)+ 2]; \
|
||||
ss[3] ^= ss[2]; k[8*(i)+11] = g ^= k[8*(i)+ 3]; \
|
||||
g = ls_box(ss[3],0); \
|
||||
ss[4] ^= g; g = ff(g); k[8*(i)+12] = g ^= k[8*(i)+ 4]; \
|
||||
ss[5] ^= ss[4]; k[8*(i)+13] = g ^= k[8*(i)+ 5]; \
|
||||
ss[6] ^= ss[5]; k[8*(i)+14] = g ^= k[8*(i)+ 6]; \
|
||||
ss[7] ^= ss[6]; k[8*(i)+15] = g ^= k[8*(i)+ 7]; \
|
||||
}
|
||||
#define kdl8(k,i) \
|
||||
{ ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[8*(i)+ 8] = ss[0]; ss[1] ^= ss[0]; k[8*(i)+ 9] = ss[1]; \
|
||||
ss[2] ^= ss[1]; k[8*(i)+10] = ss[2]; ss[3] ^= ss[2]; k[8*(i)+11] = ss[3]; \
|
||||
}
|
||||
|
||||
#if defined(AES_128) || defined(AES_VAR)
|
||||
|
||||
aes_rval aes_decrypt_key128(const void *in_key, aes_decrypt_ctx cx[1])
|
||||
{ aes_32t ss[5];
|
||||
#ifdef d_vars
|
||||
d_vars;
|
||||
#endif
|
||||
cx->ks[0] = ss[0] = word_in(in_key, 0);
|
||||
cx->ks[1] = ss[1] = word_in(in_key, 1);
|
||||
cx->ks[2] = ss[2] = word_in(in_key, 2);
|
||||
cx->ks[3] = ss[3] = word_in(in_key, 3);
|
||||
|
||||
#if DEC_UNROLL == NONE
|
||||
{ aes_32t i;
|
||||
|
||||
for(i = 0; i < (11 * N_COLS - 1) / 4; ++i)
|
||||
ke4(cx->ks, i);
|
||||
#if !(DEC_ROUND == NO_TABLES)
|
||||
for(i = N_COLS; i < 10 * N_COLS; ++i)
|
||||
cx->ks[i] = inv_mcol(cx->ks[i]);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
kdf4(cx->ks, 0); kd4(cx->ks, 1);
|
||||
kd4(cx->ks, 2); kd4(cx->ks, 3);
|
||||
kd4(cx->ks, 4); kd4(cx->ks, 5);
|
||||
kd4(cx->ks, 6); kd4(cx->ks, 7);
|
||||
kd4(cx->ks, 8); kdl4(cx->ks, 9);
|
||||
#endif
|
||||
|
||||
/* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */
|
||||
/* key and must be non-zero for 128 and 192 bits keys */
|
||||
cx->ks[53] = cx->ks[45] = 0;
|
||||
cx->ks[52] = 10;
|
||||
#ifdef AES_ERR_CHK
|
||||
return aes_good;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(AES_192) || defined(AES_VAR)
|
||||
|
||||
aes_rval aes_decrypt_key192(const void *in_key, aes_decrypt_ctx cx[1])
|
||||
{ aes_32t ss[7];
|
||||
#ifdef d_vars
|
||||
d_vars;
|
||||
#endif
|
||||
cx->ks[0] = ss[0] = word_in(in_key, 0);
|
||||
cx->ks[1] = ss[1] = word_in(in_key, 1);
|
||||
cx->ks[2] = ss[2] = word_in(in_key, 2);
|
||||
cx->ks[3] = ss[3] = word_in(in_key, 3);
|
||||
|
||||
#if DEC_UNROLL == NONE
|
||||
cx->ks[4] = ss[4] = word_in(in_key, 4);
|
||||
cx->ks[5] = ss[5] = word_in(in_key, 5);
|
||||
{ aes_32t i;
|
||||
|
||||
for(i = 0; i < (13 * N_COLS - 1) / 6; ++i)
|
||||
ke6(cx->ks, i);
|
||||
#if !(DEC_ROUND == NO_TABLES)
|
||||
for(i = N_COLS; i < 12 * N_COLS; ++i)
|
||||
cx->ks[i] = inv_mcol(cx->ks[i]);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
cx->ks[4] = ff(ss[4] = word_in(in_key, 4));
|
||||
cx->ks[5] = ff(ss[5] = word_in(in_key, 5));
|
||||
kdf6(cx->ks, 0); kd6(cx->ks, 1);
|
||||
kd6(cx->ks, 2); kd6(cx->ks, 3);
|
||||
kd6(cx->ks, 4); kd6(cx->ks, 5);
|
||||
kd6(cx->ks, 6); kdl6(cx->ks, 7);
|
||||
#endif
|
||||
|
||||
/* cx->ks[45] ^ cx->ks[52] ^ cx->ks[53] is zero for a 256 bit */
|
||||
/* key and must be non-zero for 128 and 192 bits keys */
|
||||
cx->ks[53] = cx->ks[45];
|
||||
cx->ks[52] = 12;
|
||||
#ifdef AES_ERR_CHK
|
||||
return aes_good;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(AES_256) || defined(AES_VAR)
|
||||
|
||||
aes_rval aes_decrypt_key256(const void *in_key, aes_decrypt_ctx cx[1])
|
||||
{ aes_32t ss[8];
|
||||
#ifdef d_vars
|
||||
d_vars;
|
||||
#endif
|
||||
cx->ks[0] = ss[0] = word_in(in_key, 0);
|
||||
cx->ks[1] = ss[1] = word_in(in_key, 1);
|
||||
cx->ks[2] = ss[2] = word_in(in_key, 2);
|
||||
cx->ks[3] = ss[3] = word_in(in_key, 3);
|
||||
|
||||
#if DEC_UNROLL == NONE
|
||||
cx->ks[4] = ss[4] = word_in(in_key, 4);
|
||||
cx->ks[5] = ss[5] = word_in(in_key, 5);
|
||||
cx->ks[6] = ss[6] = word_in(in_key, 6);
|
||||
cx->ks[7] = ss[7] = word_in(in_key, 7);
|
||||
{ aes_32t i;
|
||||
|
||||
for(i = 0; i < (15 * N_COLS - 1) / 8; ++i)
|
||||
ke8(cx->ks, i);
|
||||
#if !(DEC_ROUND == NO_TABLES)
|
||||
for(i = N_COLS; i < 14 * N_COLS; ++i)
|
||||
cx->ks[i] = inv_mcol(cx->ks[i]);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
cx->ks[4] = ff(ss[4] = word_in(in_key, 4));
|
||||
cx->ks[5] = ff(ss[5] = word_in(in_key, 5));
|
||||
cx->ks[6] = ff(ss[6] = word_in(in_key, 6));
|
||||
cx->ks[7] = ff(ss[7] = word_in(in_key, 7));
|
||||
kdf8(cx->ks, 0); kd8(cx->ks, 1);
|
||||
kd8(cx->ks, 2); kd8(cx->ks, 3);
|
||||
kd8(cx->ks, 4); kd8(cx->ks, 5);
|
||||
kdl8(cx->ks, 6);
|
||||
#endif
|
||||
#ifdef AES_ERR_CHK
|
||||
return aes_good;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(AES_VAR)
|
||||
|
||||
aes_rval aes_decrypt_key(const void *in_key, int key_len, aes_decrypt_ctx cx[1])
|
||||
{
|
||||
switch(key_len)
|
||||
{
|
||||
#ifdef AES_ERR_CHK
|
||||
case 16: case 128: return aes_decrypt_key128(in_key, cx);
|
||||
case 24: case 192: return aes_decrypt_key192(in_key, cx);
|
||||
case 32: case 256: return aes_decrypt_key256(in_key, cx);
|
||||
default: return aes_error;
|
||||
#else
|
||||
case 16: case 128: aes_decrypt_key128(in_key, cx); return;
|
||||
case 24: case 192: aes_decrypt_key192(in_key, cx); return;
|
||||
case 32: case 256: aes_decrypt_key256(in_key, cx); return;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
232
aestab.c
Normal file
232
aestab.c
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 2003, Dr Brian Gladman <brg@gladman.me.uk>, Worcester, UK.
|
||||
All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The free distribution and use of this software in both source and binary
|
||||
form is allowed (with or without changes) provided that:
|
||||
|
||||
1. distributions of this source code include the above copyright
|
||||
notice, this list of conditions and the following disclaimer;
|
||||
|
||||
2. distributions in binary form include the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other associated materials;
|
||||
|
||||
3. the copyright holder's name is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
ALTERNATIVELY, provided that this notice is retained in full, this product
|
||||
may be distributed under the terms of the GNU General Public License (GPL),
|
||||
in which case the provisions of the GPL apply INSTEAD OF those given above.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 26/08/2003
|
||||
|
||||
*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define DO_TABLES
|
||||
|
||||
#include "aesopt.h"
|
||||
|
||||
#if defined(FIXED_TABLES)
|
||||
|
||||
/* implemented in case of wrong call for fixed tables */
|
||||
|
||||
void gen_tabs(void)
|
||||
{
|
||||
}
|
||||
|
||||
#else /* dynamic table generation */
|
||||
|
||||
#if !defined(FF_TABLES)
|
||||
|
||||
/* Generate the tables for the dynamic table option
|
||||
|
||||
It will generally be sensible to use tables to compute finite
|
||||
field multiplies and inverses but where memory is scarse this
|
||||
code might sometimes be better. But it only has effect during
|
||||
initialisation so its pretty unimportant in overall terms.
|
||||
*/
|
||||
|
||||
/* return 2 ^ (n - 1) where n is the bit number of the highest bit
|
||||
set in x with x in the range 1 < x < 0x00000200. This form is
|
||||
used so that locals within fi can be bytes rather than words
|
||||
*/
|
||||
|
||||
static aes_08t hibit(const aes_32t x)
|
||||
{ aes_08t r = (aes_08t)((x >> 1) | (x >> 2));
|
||||
|
||||
r |= (r >> 2);
|
||||
r |= (r >> 4);
|
||||
return (r + 1) >> 1;
|
||||
}
|
||||
|
||||
/* return the inverse of the finite field element x */
|
||||
|
||||
static aes_08t fi(const aes_08t x)
|
||||
{ aes_08t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
|
||||
|
||||
if(x < 2) return x;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(!n1) return v1;
|
||||
|
||||
while(n2 >= n1)
|
||||
{
|
||||
n2 /= n1; p2 ^= p1 * n2; v2 ^= v1 * n2; n2 = hibit(p2);
|
||||
}
|
||||
|
||||
if(!n2) return v2;
|
||||
|
||||
while(n1 >= n2)
|
||||
{
|
||||
n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* The forward and inverse affine transformations used in the S-box */
|
||||
|
||||
#define fwd_affine(x) \
|
||||
(w = (aes_32t)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(aes_08t)(w^(w>>8)))
|
||||
|
||||
#define inv_affine(x) \
|
||||
(w = (aes_32t)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(aes_08t)(w^(w>>8)))
|
||||
|
||||
static int init = 0;
|
||||
|
||||
void gen_tabs(void)
|
||||
{ aes_32t i, w;
|
||||
|
||||
#if defined(FF_TABLES)
|
||||
|
||||
aes_08t pow[512], log[256];
|
||||
|
||||
if(init) return;
|
||||
/* log and power tables for GF(2^8) finite field with
|
||||
WPOLY as modular polynomial - the simplest primitive
|
||||
root is 0x03, used here to generate the tables
|
||||
*/
|
||||
|
||||
i = 0; w = 1;
|
||||
do
|
||||
{
|
||||
pow[i] = (aes_08t)w;
|
||||
pow[i + 255] = (aes_08t)w;
|
||||
log[w] = (aes_08t)i++;
|
||||
w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0);
|
||||
}
|
||||
while (w != 1);
|
||||
|
||||
#else
|
||||
if(init) return;
|
||||
#endif
|
||||
|
||||
for(i = 0, w = 1; i < RC_LENGTH; ++i)
|
||||
{
|
||||
t_set(r,c)[i] = bytes2word(w, 0, 0, 0);
|
||||
w = f2(w);
|
||||
}
|
||||
|
||||
for(i = 0; i < 256; ++i)
|
||||
{ aes_08t b;
|
||||
|
||||
b = fwd_affine(fi((aes_08t)i));
|
||||
w = bytes2word(f2(b), b, b, f3(b));
|
||||
|
||||
#ifdef SBX_SET
|
||||
t_set(s,box)[i] = b;
|
||||
#endif
|
||||
|
||||
#ifdef FT1_SET /* tables for a normal encryption round */
|
||||
t_set(f,n)[i] = w;
|
||||
#endif
|
||||
#ifdef FT4_SET
|
||||
t_set(f,n)[0][i] = w;
|
||||
t_set(f,n)[1][i] = upr(w,1);
|
||||
t_set(f,n)[2][i] = upr(w,2);
|
||||
t_set(f,n)[3][i] = upr(w,3);
|
||||
#endif
|
||||
w = bytes2word(b, 0, 0, 0);
|
||||
|
||||
#ifdef FL1_SET /* tables for last encryption round (may also */
|
||||
t_set(f,l)[i] = w; /* be used in the key schedule) */
|
||||
#endif
|
||||
#ifdef FL4_SET
|
||||
t_set(f,l)[0][i] = w;
|
||||
t_set(f,l)[1][i] = upr(w,1);
|
||||
t_set(f,l)[2][i] = upr(w,2);
|
||||
t_set(f,l)[3][i] = upr(w,3);
|
||||
#endif
|
||||
|
||||
#ifdef LS1_SET /* table for key schedule if t_set(f,l) above is */
|
||||
t_set(l,s)[i] = w; /* not of the required form */
|
||||
#endif
|
||||
#ifdef LS4_SET
|
||||
t_set(l,s)[0][i] = w;
|
||||
t_set(l,s)[1][i] = upr(w,1);
|
||||
t_set(l,s)[2][i] = upr(w,2);
|
||||
t_set(l,s)[3][i] = upr(w,3);
|
||||
#endif
|
||||
|
||||
b = fi(inv_affine((aes_08t)i));
|
||||
w = bytes2word(fe(b), f9(b), fd(b), fb(b));
|
||||
|
||||
#ifdef IM1_SET /* tables for the inverse mix column operation */
|
||||
t_set(i,m)[b] = w;
|
||||
#endif
|
||||
#ifdef IM4_SET
|
||||
t_set(i,m)[0][b] = w;
|
||||
t_set(i,m)[1][b] = upr(w,1);
|
||||
t_set(i,m)[2][b] = upr(w,2);
|
||||
t_set(i,m)[3][b] = upr(w,3);
|
||||
#endif
|
||||
|
||||
#ifdef ISB_SET
|
||||
t_set(i,box)[i] = b;
|
||||
#endif
|
||||
#ifdef IT1_SET /* tables for a normal decryption round */
|
||||
t_set(i,n)[i] = w;
|
||||
#endif
|
||||
#ifdef IT4_SET
|
||||
t_set(i,n)[0][i] = w;
|
||||
t_set(i,n)[1][i] = upr(w,1);
|
||||
t_set(i,n)[2][i] = upr(w,2);
|
||||
t_set(i,n)[3][i] = upr(w,3);
|
||||
#endif
|
||||
w = bytes2word(b, 0, 0, 0);
|
||||
#ifdef IL1_SET /* tables for last decryption round */
|
||||
t_set(i,l)[i] = w;
|
||||
#endif
|
||||
#ifdef IL4_SET
|
||||
t_set(i,l)[0][i] = w;
|
||||
t_set(i,l)[1][i] = upr(w,1);
|
||||
t_set(i,l)[2][i] = upr(w,2);
|
||||
t_set(i,l)[3][i] = upr(w,3);
|
||||
#endif
|
||||
}
|
||||
init = 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
eagi-test
|
||||
eagi-sphinx-test
|
||||
0
agi/DialAnMp3.agi
Executable file → Normal file
0
agi/DialAnMp3.agi
Executable file → Normal file
22
agi/Makefile
Executable file → Normal file
22
agi/Makefile
Executable file → Normal file
@@ -15,19 +15,29 @@ AGIS=agi-test.agi eagi-test eagi-sphinx-test
|
||||
|
||||
CFLAGS+=
|
||||
|
||||
all: $(AGIS)
|
||||
all: depend $(AGIS)
|
||||
|
||||
install: all
|
||||
for x in $(AGIS); do $(INSTALL) -m 755 $$x $(AGI_DIR) ; done
|
||||
mkdir -p $(DESTDIR)$(AGI_DIR)
|
||||
for x in $(AGIS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(AGI_DIR) ; done
|
||||
|
||||
eagi-test: eagi-test.o
|
||||
$(CC) -o eagi-test eagi-test.o
|
||||
|
||||
$(CC) $(CFLAGS) -o eagi-test eagi-test.o
|
||||
|
||||
eagi-sphinx-test: eagi-sphinx-test.o
|
||||
$(CC) -o eagi-sphinx-test eagi-sphinx-test.o
|
||||
$(CC) $(CFLAGS) -o eagi-sphinx-test eagi-sphinx-test.o
|
||||
|
||||
clean:
|
||||
rm -f *.so *.o look
|
||||
rm -f *.so *.o look .depend eagi-test eagi-sphinx-test
|
||||
|
||||
%.so : %.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $<
|
||||
|
||||
ifneq ($(wildcard .depend),)
|
||||
include .depend
|
||||
endif
|
||||
|
||||
depend: .depend
|
||||
|
||||
.depend:
|
||||
../mkdep $(CFLAGS) `ls *.c`
|
||||
|
||||
36
agi/agi-test.agi
Executable file → Normal file
36
agi/agi-test.agi
Executable file → Normal file
@@ -1,5 +1,11 @@
|
||||
#!/usr/bin/perl
|
||||
use strict;
|
||||
|
||||
$|=1;
|
||||
|
||||
# Setup some variables
|
||||
my %AGI; my $tests = 0; my $fail = 0; my $pass = 0;
|
||||
|
||||
while(<STDIN>) {
|
||||
chomp;
|
||||
last unless length($_);
|
||||
@@ -9,7 +15,7 @@ while(<STDIN>) {
|
||||
}
|
||||
|
||||
print STDERR "AGI Environment Dump:\n";
|
||||
foreach $i (sort keys %AGI) {
|
||||
foreach my $i (sort keys %AGI) {
|
||||
print STDERR " -- $i = $AGI{$i}\n";
|
||||
}
|
||||
|
||||
@@ -35,38 +41,38 @@ sub checkresult {
|
||||
|
||||
print STDERR "1. Testing 'sendfile'...";
|
||||
print "STREAM FILE beep \"\"\n";
|
||||
$result = <STDIN>;
|
||||
checkresult($result);
|
||||
my $result = <STDIN>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "2. Testing 'sendtext'...";
|
||||
print "SEND TEXT \"hello world\"\n";
|
||||
$result = <STDIN>;
|
||||
checkresult($result);
|
||||
my $result = <STDIN>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "3. Testing 'sendimage'...";
|
||||
print "SEND IMAGE asterisk-image\n";
|
||||
$result = <STDIN>;
|
||||
checkresult($result);
|
||||
my $result = <STDIN>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "4. Testing 'saynumber'...";
|
||||
print "SAY NUMBER 192837465 \"\"\n";
|
||||
$result = <STDIN>;
|
||||
checkresult($result);
|
||||
my $result = <STDIN>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "5. Testing 'waitdtmf'...";
|
||||
print "WAIT FOR DIGIT 1000\n";
|
||||
$result = <STDIN>;
|
||||
checkresult($result);
|
||||
my $result = <STDIN>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "6. Testing 'record'...";
|
||||
print "RECORD FILE testagi gsm 1234 3000\n";
|
||||
$result = <STDIN>;
|
||||
checkresult($result);
|
||||
my $result = <STDIN>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "6a. Testing 'record' playback...";
|
||||
print "STREAM FILE testagi \"\"\n";
|
||||
$result = <STDIN>;
|
||||
checkresult($result);
|
||||
my $result = <STDIN>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "================== Complete ======================\n";
|
||||
print STDERR "$tests tests completed, $pass passed, $fail failed\n";
|
||||
|
||||
4
agi/eagi-sphinx-test.c
Executable file → Normal file
4
agi/eagi-sphinx-test.c
Executable file → Normal file
@@ -13,9 +13,9 @@
|
||||
#include <string.h>
|
||||
#include <sys/select.h>
|
||||
#include <fcntl.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#define AUDIO_FILENO (STDERR_FILENO + 1)
|
||||
@@ -44,7 +44,7 @@ static int connect_sphinx(void)
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(SPHINX_PORT);
|
||||
memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
|
||||
if (connect(sphinx_sock, &sin, sizeof(sin))) {
|
||||
if (connect(sphinx_sock, (struct sockaddr *)&sin, sizeof(sin))) {
|
||||
fprintf(stderr, "Unable to connect on socket: %s\n", strerror(errno));
|
||||
close(sphinx_sock);
|
||||
sphinx_sock = -1;
|
||||
|
||||
0
agi/eagi-test.c
Executable file → Normal file
0
agi/eagi-test.c
Executable file → Normal file
94
agi/fastagi-test
Normal file
94
agi/fastagi-test
Normal file
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/perl
|
||||
use strict;
|
||||
use Socket;
|
||||
use Carp;
|
||||
use IO::Handle;
|
||||
|
||||
my $port = 4573;
|
||||
|
||||
$|=1;
|
||||
|
||||
# Setup some variables
|
||||
my %AGI; my $tests = 0; my $fail = 0; my $pass = 0;
|
||||
|
||||
sub checkresult {
|
||||
my ($res) = @_;
|
||||
my $retval;
|
||||
$tests++;
|
||||
chomp $res;
|
||||
if ($res =~ /^200/) {
|
||||
$res =~ /result=(-?\d+)/;
|
||||
if (!length($1)) {
|
||||
print STDERR "FAIL ($res)\n";
|
||||
$fail++;
|
||||
} else {
|
||||
print STDERR "PASS ($1)\n";
|
||||
$pass++;
|
||||
}
|
||||
} else {
|
||||
print STDERR "FAIL (unexpected result '$res')\n";
|
||||
$fail++;
|
||||
}
|
||||
}
|
||||
|
||||
socket(SERVER, PF_INET, SOCK_STREAM, 0);
|
||||
setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, pack("l", 1));
|
||||
bind(SERVER, sockaddr_in($port, INADDR_ANY)) || die("can't bind\n");
|
||||
listen(SERVER, SOMAXCONN);
|
||||
|
||||
for(;;) {
|
||||
my $raddr = accept(CLIENT, SERVER);
|
||||
my ($s, $p) = sockaddr_in($raddr);
|
||||
CLIENT->autoflush(1);
|
||||
while(<CLIENT>) {
|
||||
chomp;
|
||||
last unless length($_);
|
||||
if (/^agi_(\w+)\:\s+(.*)$/) {
|
||||
$AGI{$1} = $2;
|
||||
}
|
||||
}
|
||||
print STDERR "AGI Environment Dump from $s:$p --\n";
|
||||
foreach my $i (sort keys %AGI) {
|
||||
print STDERR " -- $i = $AGI{$i}\n";
|
||||
}
|
||||
|
||||
print STDERR "1. Testing 'sendfile'...";
|
||||
print CLIENT "STREAM FILE beep \"\"\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "2. Testing 'sendtext'...";
|
||||
print CLIENT "SEND TEXT \"hello world\"\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "3. Testing 'sendimage'...";
|
||||
print CLIENT "SEND IMAGE asterisk-image\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "4. Testing 'saynumber'...";
|
||||
print CLIENT "SAY NUMBER 192837465 \"\"\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "5. Testing 'waitdtmf'...";
|
||||
print CLIENT "WAIT FOR DIGIT 1000\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "6. Testing 'record'...";
|
||||
print CLIENT "RECORD FILE testagi gsm 1234 3000\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
|
||||
print STDERR "6a. Testing 'record' playback...";
|
||||
print CLIENT "STREAM FILE testagi \"\"\n";
|
||||
my $result = <CLIENT>;
|
||||
&checkresult($result);
|
||||
close(CLIENT);
|
||||
print STDERR "================== Complete ======================\n";
|
||||
print STDERR "$tests tests completed, $pass passed, $fail failed\n";
|
||||
print STDERR "==================================================\n";
|
||||
}
|
||||
|
||||
0
agi/numeralize
Executable file → Normal file
0
agi/numeralize
Executable file → Normal file
810
app.c
Executable file → Normal file
810
app.c
Executable file → Normal file
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Channel Management
|
||||
* Convenient Application Routines
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999-2004, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
@@ -21,27 +20,35 @@
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <asterisk/dsp.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include "asterisk.h"
|
||||
#include "astconf.h"
|
||||
|
||||
#define MAX_OTHER_FORMATS 10
|
||||
|
||||
/* set timeout to 0 for "standard" timeouts. Set timeout to -1 for
|
||||
"ludicrous time" (essentially never times out) */
|
||||
int ast_app_getdata(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout)
|
||||
{
|
||||
int res,to,fto;
|
||||
/* XXX Merge with full version? XXX */
|
||||
if (maxlen)
|
||||
s[0] = '\0';
|
||||
if (prompt) {
|
||||
res = ast_streamfile(c, prompt, c->language);
|
||||
if (res < 0)
|
||||
return res;
|
||||
}
|
||||
fto = 6000;
|
||||
to = 2000;
|
||||
fto = c->pbx ? c->pbx->rtimeout * 1000 : 6000;
|
||||
to = c->pbx ? c->pbx->dtimeout * 1000 : 2000;
|
||||
|
||||
if (timeout > 0) fto = to = timeout;
|
||||
if (timeout < 0) fto = to = 1000000000;
|
||||
res = ast_readstring(c, s, maxlen, to, fto, "#");
|
||||
@@ -129,6 +136,13 @@ int ast_app_getvoice(struct ast_channel *c, char *dest, char *dstfmt, char *prom
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
res = ast_writestream(writer, f);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Failed to write to stream at %s!\n", dest);
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
@@ -148,23 +162,31 @@ int ast_app_has_voicemail(const char *mailbox)
|
||||
char fn[256];
|
||||
char tmp[256]="";
|
||||
char *mb, *cur;
|
||||
char *context;
|
||||
int ret;
|
||||
/* If no mailbox, return immediately */
|
||||
if (!strlen(mailbox))
|
||||
if (ast_strlen_zero(mailbox))
|
||||
return 0;
|
||||
if (strchr(mailbox, ',')) {
|
||||
strncpy(tmp, mailbox, sizeof(tmp));
|
||||
strncpy(tmp, mailbox, sizeof(tmp) - 1);
|
||||
mb = tmp;
|
||||
ret = 0;
|
||||
while((cur = strsep(&mb, ", "))) {
|
||||
if (strlen(cur)) {
|
||||
while((cur = strsep(&mb, ","))) {
|
||||
if (!ast_strlen_zero(cur)) {
|
||||
if (ast_app_has_voicemail(cur))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
snprintf(fn, sizeof(fn), "%s/vm/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, mailbox);
|
||||
strncpy(tmp, mailbox, sizeof(tmp) - 1);
|
||||
context = strchr(tmp, '@');
|
||||
if (context) {
|
||||
*context = '\0';
|
||||
context++;
|
||||
} else
|
||||
context = "default";
|
||||
snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, context, tmp);
|
||||
dir = opendir(fn);
|
||||
if (!dir)
|
||||
return 0;
|
||||
@@ -185,21 +207,22 @@ int ast_app_messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
|
||||
char fn[256];
|
||||
char tmp[256]="";
|
||||
char *mb, *cur;
|
||||
char *context;
|
||||
int ret;
|
||||
if (newmsgs)
|
||||
*newmsgs = 0;
|
||||
if (oldmsgs)
|
||||
*oldmsgs = 0;
|
||||
/* If no mailbox, return immediately */
|
||||
if (!strlen(mailbox))
|
||||
if (ast_strlen_zero(mailbox))
|
||||
return 0;
|
||||
if (strchr(mailbox, ',')) {
|
||||
int tmpnew, tmpold;
|
||||
strncpy(tmp, mailbox, sizeof(tmp));
|
||||
strncpy(tmp, mailbox, sizeof(tmp) - 1);
|
||||
mb = tmp;
|
||||
ret = 0;
|
||||
while((cur = strsep(&mb, ", "))) {
|
||||
if (strlen(cur)) {
|
||||
if (!ast_strlen_zero(cur)) {
|
||||
if (ast_app_messagecount(cur, newmsgs ? &tmpnew : NULL, oldmsgs ? &tmpold : NULL))
|
||||
return -1;
|
||||
else {
|
||||
@@ -212,8 +235,15 @@ int ast_app_messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
strncpy(tmp, mailbox, sizeof(tmp) - 1);
|
||||
context = strchr(tmp, '@');
|
||||
if (context) {
|
||||
*context = '\0';
|
||||
context++;
|
||||
} else
|
||||
context = "default";
|
||||
if (newmsgs) {
|
||||
snprintf(fn, sizeof(fn), "%s/vm/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, mailbox);
|
||||
snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, context, tmp);
|
||||
dir = opendir(fn);
|
||||
if (dir) {
|
||||
while ((de = readdir(dir))) {
|
||||
@@ -226,7 +256,7 @@ int ast_app_messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
|
||||
}
|
||||
}
|
||||
if (oldmsgs) {
|
||||
snprintf(fn, sizeof(fn), "%s/vm/%s/Old", (char *)ast_config_AST_SPOOL_DIR, mailbox);
|
||||
snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/Old", (char *)ast_config_AST_SPOOL_DIR, context, tmp);
|
||||
dir = opendir(fn);
|
||||
if (dir) {
|
||||
while ((de = readdir(dir))) {
|
||||
@@ -240,3 +270,751 @@ int ast_app_messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_dtmf_stream(struct ast_channel *chan,struct ast_channel *peer,char *digits,int between)
|
||||
{
|
||||
char *ptr=NULL;
|
||||
int res=0;
|
||||
struct ast_frame f;
|
||||
if (!between)
|
||||
between = 100;
|
||||
|
||||
if (peer)
|
||||
res = ast_autoservice_start(peer);
|
||||
|
||||
if (!res) {
|
||||
res = ast_waitfor(chan,100);
|
||||
if (res > -1) {
|
||||
for (ptr=digits; *ptr; ptr++) {
|
||||
if (*ptr == 'w') {
|
||||
res = ast_safe_sleep(chan, 500);
|
||||
if (res)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.frametype = AST_FRAME_DTMF;
|
||||
f.subclass = *ptr;
|
||||
f.src = "ast_dtmf_stream";
|
||||
if (strchr("0123456789*#abcdABCD",*ptr)==NULL) {
|
||||
ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n",*ptr);
|
||||
} else {
|
||||
res = ast_write(chan, &f);
|
||||
if (res)
|
||||
break;
|
||||
/* pause between digits */
|
||||
res = ast_safe_sleep(chan,between);
|
||||
if (res)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (peer)
|
||||
res = ast_autoservice_stop(peer);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
struct linear_state {
|
||||
int fd;
|
||||
int autoclose;
|
||||
int allowoverride;
|
||||
int origwfmt;
|
||||
};
|
||||
|
||||
static void linear_release(struct ast_channel *chan, void *params)
|
||||
{
|
||||
struct linear_state *ls = params;
|
||||
if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt)) {
|
||||
ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, ls->origwfmt);
|
||||
}
|
||||
if (ls->autoclose)
|
||||
close(ls->fd);
|
||||
free(params);
|
||||
}
|
||||
|
||||
static int linear_generator(struct ast_channel *chan, void *data, int len, int samples)
|
||||
{
|
||||
struct ast_frame f;
|
||||
short buf[2048 + AST_FRIENDLY_OFFSET / 2];
|
||||
struct linear_state *ls = data;
|
||||
int res;
|
||||
len = samples * 2;
|
||||
if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
|
||||
ast_log(LOG_WARNING, "Can't generate %d bytes of data!\n" ,len);
|
||||
len = sizeof(buf) - AST_FRIENDLY_OFFSET;
|
||||
}
|
||||
memset(&f, 0, sizeof(f));
|
||||
res = read(ls->fd, buf + AST_FRIENDLY_OFFSET/2, len);
|
||||
if (res > 0) {
|
||||
f.frametype = AST_FRAME_VOICE;
|
||||
f.subclass = AST_FORMAT_SLINEAR;
|
||||
f.data = buf + AST_FRIENDLY_OFFSET/2;
|
||||
f.datalen = res;
|
||||
f.samples = res / 2;
|
||||
f.offset = AST_FRIENDLY_OFFSET;
|
||||
ast_write(chan, &f);
|
||||
if (res == len)
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void *linear_alloc(struct ast_channel *chan, void *params)
|
||||
{
|
||||
struct linear_state *ls;
|
||||
/* In this case, params is already malloc'd */
|
||||
if (params) {
|
||||
ls = params;
|
||||
if (ls->allowoverride)
|
||||
chan->writeinterrupt = 1;
|
||||
else
|
||||
chan->writeinterrupt = 0;
|
||||
ls->origwfmt = chan->writeformat;
|
||||
if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
|
||||
ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", chan->name);
|
||||
free(ls);
|
||||
ls = params = NULL;
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
static struct ast_generator linearstream =
|
||||
{
|
||||
alloc: linear_alloc,
|
||||
release: linear_release,
|
||||
generate: linear_generator,
|
||||
};
|
||||
|
||||
int ast_linear_stream(struct ast_channel *chan, const char *filename, int fd, int allowoverride)
|
||||
{
|
||||
struct linear_state *lin;
|
||||
char tmpf[256] = "";
|
||||
int res = -1;
|
||||
int autoclose = 0;
|
||||
if (fd < 0) {
|
||||
if (!filename || ast_strlen_zero(filename))
|
||||
return -1;
|
||||
autoclose = 1;
|
||||
if (filename[0] == '/')
|
||||
strncpy(tmpf, filename, sizeof(tmpf) - 1);
|
||||
else
|
||||
snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", (char *)ast_config_AST_VAR_DIR, "sounds", filename);
|
||||
fd = open(tmpf, O_RDONLY);
|
||||
if (fd < 0){
|
||||
ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", tmpf, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
lin = malloc(sizeof(struct linear_state));
|
||||
if (lin) {
|
||||
memset(lin, 0, sizeof(lin));
|
||||
lin->fd = fd;
|
||||
lin->allowoverride = allowoverride;
|
||||
lin->autoclose = autoclose;
|
||||
res = ast_activate_generator(chan, &linearstream, lin);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int ast_control_streamfile(struct ast_channel *chan, char *file, char *fwd, char *rev, char *stop, char *pause, int skipms)
|
||||
{
|
||||
struct timeval started, ended;
|
||||
long elapsed = 0,last_elapsed =0;
|
||||
char *breaks=NULL;
|
||||
char *end=NULL;
|
||||
int blen=2;
|
||||
int res=0;
|
||||
|
||||
if (stop)
|
||||
blen += strlen(stop);
|
||||
if (pause)
|
||||
blen += strlen(pause);
|
||||
|
||||
if (blen > 2) {
|
||||
breaks = alloca(blen + 1);
|
||||
breaks[0] = '\0';
|
||||
strcat(breaks, stop);
|
||||
strcat(breaks, pause);
|
||||
}
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
res = ast_answer(chan);
|
||||
|
||||
if (chan)
|
||||
ast_stopstream(chan);
|
||||
|
||||
|
||||
if (file) {
|
||||
if ((end = strchr(file,':'))) {
|
||||
if (!strcasecmp(end, ":end")) {
|
||||
*end = '\0';
|
||||
end++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
gettimeofday(&started,NULL);
|
||||
|
||||
if (chan)
|
||||
ast_stopstream(chan);
|
||||
res = ast_streamfile(chan, file, chan->language);
|
||||
if (!res) {
|
||||
if (end) {
|
||||
ast_seekstream(chan->stream, 0, SEEK_END);
|
||||
end=NULL;
|
||||
}
|
||||
res = 1;
|
||||
if (elapsed) {
|
||||
ast_stream_fastforward(chan->stream, elapsed);
|
||||
last_elapsed = elapsed - 200;
|
||||
}
|
||||
if (res)
|
||||
res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (res < 1)
|
||||
break;
|
||||
|
||||
if (pause != NULL && strchr(pause, res)) {
|
||||
gettimeofday(&ended, NULL);
|
||||
elapsed = (((ended.tv_sec * 1000) + ended.tv_usec / 1000) - ((started.tv_sec * 1000) + started.tv_usec / 1000) + last_elapsed);
|
||||
for(;;) {
|
||||
if (chan)
|
||||
ast_stopstream(chan);
|
||||
res = ast_waitfordigit(chan, 1000);
|
||||
if (res == 0)
|
||||
continue;
|
||||
else if (res == -1 || strchr(pause, res) || (stop && strchr(stop, res)))
|
||||
break;
|
||||
}
|
||||
if (res == *pause) {
|
||||
res = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (res == -1)
|
||||
break;
|
||||
|
||||
/* if we get one of our stop chars, return it to the calling function */
|
||||
if (stop && strchr(stop, res)) {
|
||||
/* res = 0; */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (chan)
|
||||
ast_stopstream(chan);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int ast_play_and_wait(struct ast_channel *chan, char *fn)
|
||||
{
|
||||
int d;
|
||||
d = ast_streamfile(chan, fn, chan->language);
|
||||
if (d)
|
||||
return d;
|
||||
d = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
return d;
|
||||
}
|
||||
|
||||
static int global_silence_threshold = 128;
|
||||
static int global_maxsilence = 0;
|
||||
|
||||
int ast_play_and_record(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path)
|
||||
{
|
||||
int d;
|
||||
char *fmts;
|
||||
char comment[256];
|
||||
int x, fmtcnt=1, res=-1,outmsg=0;
|
||||
struct ast_frame *f;
|
||||
struct ast_filestream *others[MAX_OTHER_FORMATS];
|
||||
char *sfmt[MAX_OTHER_FORMATS];
|
||||
char *stringp=NULL;
|
||||
time_t start, end;
|
||||
struct ast_dsp *sildet=NULL; /* silence detector dsp */
|
||||
int totalsilence = 0;
|
||||
int dspsilence = 0;
|
||||
int gotsilence = 0; /* did we timeout for silence? */
|
||||
int rfmt=0;
|
||||
|
||||
if (silencethreshold < 0)
|
||||
silencethreshold = global_silence_threshold;
|
||||
|
||||
if (maxsilence < 0)
|
||||
maxsilence = global_maxsilence;
|
||||
|
||||
/* barf if no pointer passed to store duration in */
|
||||
if (duration == NULL) {
|
||||
ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_log(LOG_DEBUG,"play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
|
||||
snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);
|
||||
|
||||
if (playfile) {
|
||||
d = ast_play_and_wait(chan, playfile);
|
||||
if (d > -1)
|
||||
d = ast_streamfile(chan, "beep",chan->language);
|
||||
if (!d)
|
||||
d = ast_waitstream(chan,"");
|
||||
if (d < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
fmts = ast_strdupa(fmt);
|
||||
|
||||
stringp=fmts;
|
||||
strsep(&stringp, "|");
|
||||
ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);
|
||||
sfmt[0] = ast_strdupa(fmts);
|
||||
|
||||
while((fmt = strsep(&stringp, "|"))) {
|
||||
if (fmtcnt > MAX_OTHER_FORMATS - 1) {
|
||||
ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n");
|
||||
break;
|
||||
}
|
||||
sfmt[fmtcnt++] = ast_strdupa(fmt);
|
||||
}
|
||||
|
||||
time(&start);
|
||||
end=start; /* pre-initialize end to be same as start in case we never get into loop */
|
||||
for (x=0;x<fmtcnt;x++) {
|
||||
others[x] = ast_writefile(recordfile, sfmt[x], comment, O_TRUNC, 0, 0700);
|
||||
ast_verbose( VERBOSE_PREFIX_3 "x=%i, open writing: %s format: %s, %p\n", x, recordfile, sfmt[x], others[x]);
|
||||
|
||||
if (!others[x]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (path)
|
||||
ast_unlock_path(path);
|
||||
|
||||
|
||||
if (maxsilence > 0) {
|
||||
sildet = ast_dsp_new(); /* Create the silence detector */
|
||||
if (!sildet) {
|
||||
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
|
||||
return -1;
|
||||
}
|
||||
ast_dsp_set_threshold(sildet, silencethreshold);
|
||||
rfmt = chan->readformat;
|
||||
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
|
||||
ast_dsp_free(sildet);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (x == fmtcnt) {
|
||||
/* Loop forever, writing the packets we read to the writer(s), until
|
||||
we read a # or get a hangup */
|
||||
f = NULL;
|
||||
for(;;) {
|
||||
res = ast_waitfor(chan, 2000);
|
||||
if (!res) {
|
||||
ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
|
||||
/* Try one more time in case of masq */
|
||||
res = ast_waitfor(chan, 2000);
|
||||
if (!res) {
|
||||
ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (res < 0) {
|
||||
f = NULL;
|
||||
break;
|
||||
}
|
||||
f = ast_read(chan);
|
||||
if (!f)
|
||||
break;
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
/* write each format */
|
||||
for (x=0;x<fmtcnt;x++) {
|
||||
res = ast_writestream(others[x], f);
|
||||
}
|
||||
|
||||
/* Silence Detection */
|
||||
if (maxsilence > 0) {
|
||||
dspsilence = 0;
|
||||
ast_dsp_silence(sildet, f, &dspsilence);
|
||||
if (dspsilence)
|
||||
totalsilence = dspsilence;
|
||||
else
|
||||
totalsilence = 0;
|
||||
|
||||
if (totalsilence > maxsilence) {
|
||||
/* Ended happily with silence */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
|
||||
ast_frfree(f);
|
||||
gotsilence = 1;
|
||||
outmsg=2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Exit on any error */
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Error writing frame\n");
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
} else if (f->frametype == AST_FRAME_VIDEO) {
|
||||
/* Write only once */
|
||||
ast_writestream(others[0], f);
|
||||
} else if (f->frametype == AST_FRAME_DTMF) {
|
||||
if (f->subclass == '#') {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
|
||||
res = '#';
|
||||
outmsg = 2;
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (f->subclass == '0') {
|
||||
/* Check for a '0' during message recording also, in case caller wants operator */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User cancelled by pressing %c\n", f->subclass);
|
||||
res = '0';
|
||||
outmsg = 0;
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
if (maxtime) {
|
||||
time(&end);
|
||||
if (maxtime < (end - start)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
|
||||
outmsg = 2;
|
||||
res = 't';
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
if (end == start) time(&end);
|
||||
if (!f) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "User hung up\n");
|
||||
res = -1;
|
||||
outmsg=1;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]);
|
||||
}
|
||||
|
||||
*duration = end - start;
|
||||
|
||||
for (x=0;x<fmtcnt;x++) {
|
||||
if (!others[x])
|
||||
break;
|
||||
if (res > 0) {
|
||||
if (totalsilence)
|
||||
ast_stream_rewind(others[x], totalsilence-200);
|
||||
else
|
||||
ast_stream_rewind(others[x], 200);
|
||||
}
|
||||
ast_truncstream(others[x]);
|
||||
ast_closestream(others[x]);
|
||||
}
|
||||
if (rfmt) {
|
||||
if (ast_set_read_format(chan, rfmt)) {
|
||||
ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
|
||||
}
|
||||
}
|
||||
if (outmsg > 1) {
|
||||
/* Let them know recording is stopped */
|
||||
if(!ast_streamfile(chan, "auth-thankyou", chan->language))
|
||||
ast_waitstream(chan, "");
|
||||
}
|
||||
if (sildet)
|
||||
ast_dsp_free(sildet);
|
||||
return res;
|
||||
}
|
||||
|
||||
int ast_play_and_prepend(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence)
|
||||
{
|
||||
int d = 0;
|
||||
char *fmts;
|
||||
char comment[256];
|
||||
int x, fmtcnt=1, res=-1,outmsg=0;
|
||||
struct ast_frame *f;
|
||||
struct ast_filestream *others[MAX_OTHER_FORMATS];
|
||||
struct ast_filestream *realfiles[MAX_OTHER_FORMATS];
|
||||
char *sfmt[MAX_OTHER_FORMATS];
|
||||
char *stringp=NULL;
|
||||
time_t start, end;
|
||||
struct ast_dsp *sildet; /* silence detector dsp */
|
||||
int totalsilence = 0;
|
||||
int dspsilence = 0;
|
||||
int gotsilence = 0; /* did we timeout for silence? */
|
||||
int rfmt=0;
|
||||
char prependfile[80];
|
||||
|
||||
if (silencethreshold < 0)
|
||||
silencethreshold = global_silence_threshold;
|
||||
|
||||
if (maxsilence < 0)
|
||||
maxsilence = global_maxsilence;
|
||||
|
||||
/* barf if no pointer passed to store duration in */
|
||||
if (duration == NULL) {
|
||||
ast_log(LOG_WARNING, "Error play_and_prepend called without duration pointer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_log(LOG_DEBUG,"play_and_prepend: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
|
||||
snprintf(comment,sizeof(comment),"Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);
|
||||
|
||||
if (playfile || beep) {
|
||||
if (!beep)
|
||||
d = ast_play_and_wait(chan, playfile);
|
||||
if (d > -1)
|
||||
d = ast_streamfile(chan, "beep",chan->language);
|
||||
if (!d)
|
||||
d = ast_waitstream(chan,"");
|
||||
if (d < 0)
|
||||
return -1;
|
||||
}
|
||||
strncpy(prependfile, recordfile, sizeof(prependfile) -1);
|
||||
strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1);
|
||||
|
||||
fmts = ast_strdupa(fmt);
|
||||
|
||||
stringp=fmts;
|
||||
strsep(&stringp, "|");
|
||||
ast_log(LOG_DEBUG,"Recording Formats: sfmts=%s\n", fmts);
|
||||
sfmt[0] = ast_strdupa(fmts);
|
||||
|
||||
while((fmt = strsep(&stringp, "|"))) {
|
||||
if (fmtcnt > MAX_OTHER_FORMATS - 1) {
|
||||
ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app_voicemail.c\n");
|
||||
break;
|
||||
}
|
||||
sfmt[fmtcnt++] = ast_strdupa(fmt);
|
||||
}
|
||||
|
||||
time(&start);
|
||||
end=start; /* pre-initialize end to be same as start in case we never get into loop */
|
||||
for (x=0;x<fmtcnt;x++) {
|
||||
others[x] = ast_writefile(prependfile, sfmt[x], comment, O_TRUNC, 0, 0700);
|
||||
ast_verbose( VERBOSE_PREFIX_3 "x=%i, open writing: %s format: %s, %p\n", x, prependfile, sfmt[x], others[x]);
|
||||
if (!others[x]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sildet = ast_dsp_new(); /* Create the silence detector */
|
||||
if (!sildet) {
|
||||
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
|
||||
return -1;
|
||||
}
|
||||
ast_dsp_set_threshold(sildet, silencethreshold);
|
||||
|
||||
if (maxsilence > 0) {
|
||||
rfmt = chan->readformat;
|
||||
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (x == fmtcnt) {
|
||||
/* Loop forever, writing the packets we read to the writer(s), until
|
||||
we read a # or get a hangup */
|
||||
f = NULL;
|
||||
for(;;) {
|
||||
res = ast_waitfor(chan, 2000);
|
||||
if (!res) {
|
||||
ast_log(LOG_DEBUG, "One waitfor failed, trying another\n");
|
||||
/* Try one more time in case of masq */
|
||||
res = ast_waitfor(chan, 2000);
|
||||
if (!res) {
|
||||
ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (res < 0) {
|
||||
f = NULL;
|
||||
break;
|
||||
}
|
||||
f = ast_read(chan);
|
||||
if (!f)
|
||||
break;
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
/* write each format */
|
||||
for (x=0;x<fmtcnt;x++) {
|
||||
if (!others[x])
|
||||
break;
|
||||
res = ast_writestream(others[x], f);
|
||||
}
|
||||
|
||||
/* Silence Detection */
|
||||
if (maxsilence > 0) {
|
||||
dspsilence = 0;
|
||||
ast_dsp_silence(sildet, f, &dspsilence);
|
||||
if (dspsilence)
|
||||
totalsilence = dspsilence;
|
||||
else
|
||||
totalsilence = 0;
|
||||
|
||||
if (totalsilence > maxsilence) {
|
||||
/* Ended happily with silence */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
|
||||
ast_frfree(f);
|
||||
gotsilence = 1;
|
||||
outmsg=2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Exit on any error */
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Error writing frame\n");
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
} else if (f->frametype == AST_FRAME_VIDEO) {
|
||||
/* Write only once */
|
||||
ast_writestream(others[0], f);
|
||||
} else if (f->frametype == AST_FRAME_DTMF) {
|
||||
/* stop recording with any digit */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "User ended message by pressing %c\n", f->subclass);
|
||||
res = 't';
|
||||
outmsg = 2;
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
if (maxtime) {
|
||||
time(&end);
|
||||
if (maxtime < (end - start)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Took too long, cutting it short...\n");
|
||||
res = 't';
|
||||
outmsg=2;
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
if (end == start) time(&end);
|
||||
if (!f) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "User hung up\n");
|
||||
res = -1;
|
||||
outmsg=1;
|
||||
#if 0
|
||||
/* delete all the prepend files */
|
||||
for (x=0;x<fmtcnt;x++) {
|
||||
if (!others[x])
|
||||
break;
|
||||
ast_closestream(others[x]);
|
||||
ast_filedelete(prependfile, sfmt[x]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", prependfile, sfmt[x]);
|
||||
}
|
||||
*duration = end - start;
|
||||
#if 0
|
||||
if (outmsg > 1) {
|
||||
#else
|
||||
if (outmsg) {
|
||||
#endif
|
||||
struct ast_frame *fr;
|
||||
for (x=0;x<fmtcnt;x++) {
|
||||
snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]);
|
||||
realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0);
|
||||
if (!others[x] || !realfiles[x])
|
||||
break;
|
||||
if (totalsilence)
|
||||
ast_stream_rewind(others[x], totalsilence-200);
|
||||
else
|
||||
ast_stream_rewind(others[x], 200);
|
||||
ast_truncstream(others[x]);
|
||||
/* add the original file too */
|
||||
while ((fr = ast_readframe(realfiles[x]))) {
|
||||
ast_writestream(others[x],fr);
|
||||
}
|
||||
ast_closestream(others[x]);
|
||||
ast_closestream(realfiles[x]);
|
||||
ast_filerename(prependfile, recordfile, sfmt[x]);
|
||||
#if 0
|
||||
ast_verbose("Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x],prependfile,recordfile);
|
||||
#endif
|
||||
ast_filedelete(prependfile, sfmt[x]);
|
||||
}
|
||||
}
|
||||
if (rfmt) {
|
||||
if (ast_set_read_format(chan, rfmt)) {
|
||||
ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
|
||||
}
|
||||
}
|
||||
if (outmsg) {
|
||||
if (outmsg > 1) {
|
||||
/* Let them know it worked */
|
||||
ast_streamfile(chan, "auth-thankyou", chan->language);
|
||||
ast_waitstream(chan, "");
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int ast_lock_path(const char *path)
|
||||
{
|
||||
char *s;
|
||||
char *fs;
|
||||
int res;
|
||||
int fd;
|
||||
time_t start;
|
||||
s = alloca(strlen(path) + 10);
|
||||
fs = alloca(strlen(path) + 20);
|
||||
if (!fs || !s) {
|
||||
ast_log(LOG_WARNING, "Out of memory!\n");
|
||||
return -1;
|
||||
}
|
||||
snprintf(fs, strlen(path) + 19, "%s/%s-%08x", path, ".lock", rand());
|
||||
fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Unable to create lock file: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
|
||||
time(&start);
|
||||
while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5))
|
||||
usleep(1);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno));
|
||||
}
|
||||
unlink(fs);
|
||||
ast_log(LOG_DEBUG, "Locked path '%s'\n", path);
|
||||
return res;
|
||||
}
|
||||
|
||||
int ast_unlock_path(const char *path)
|
||||
{
|
||||
char *s;
|
||||
s = alloca(strlen(path) + 10);
|
||||
if (!s)
|
||||
return -1;
|
||||
snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
|
||||
ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path);
|
||||
return unlink(s);
|
||||
}
|
||||
|
||||
|
||||
82
apps/Makefile
Executable file → Normal file
82
apps/Makefile
Executable file → Normal file
@@ -11,52 +11,94 @@
|
||||
# the GNU General Public License
|
||||
#
|
||||
|
||||
USE_MYSQL_VM_INTERFACE=0
|
||||
USE_POSTGRES_VM_INTERFACE=0
|
||||
|
||||
#APPS=app_dial.so app_playback.so app_directory.so app_intercom.so app_mp3.so
|
||||
APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_intercom.so app_mp3.so \
|
||||
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_agi.so app_qcall.so app_adsiprog.so app_getcpeid.so app_milliwatt.so \
|
||||
app_zapateller.so app_datetime.so app_setcallerid.so app_festival.so \
|
||||
app_qcall.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_striplsd.so \
|
||||
app_setcidname.so app_lookupcidname.so app_substring.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_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_sms.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
|
||||
|
||||
ifneq (${OSARCH},Darwin)
|
||||
APPS+=app_intercom.so
|
||||
endif
|
||||
|
||||
#APPS+=app_sql_postgres.so
|
||||
#APPS+=app_sql_odbc.so
|
||||
#APPS+=app_rpt.so
|
||||
|
||||
APPS+=$(shell if [ -f /usr/include/linux/zaptel.h ]; then echo "app_zapras.so app_meetme.so app_flash.so app_zapbarge.so" ; fi)
|
||||
#APPS+=$(shell if [ -f /usr/include/zap.h ]; then echo "app_rpt.so" ; fi)
|
||||
APPS+=$(shell if [ -f /usr/include/linux/zaptel.h ]; then echo "app_zapras.so app_meetme.so app_flash.so app_zapbarge.so app_zapscan.so" ; fi)
|
||||
APPS+=$(shell if [ -f /usr/local/include/zaptel.h ]; then echo "app_zapras.so app_meetme.so app_flash.so app_zapbarge.so app_zapscan.so" ; fi)
|
||||
APPS+=$(shell if [ -f /usr/include/osp/osp.h ]; then echo "app_osplookup.so" ; fi)
|
||||
|
||||
CFLAGS+=
|
||||
CFLAGS+=-fPIC
|
||||
|
||||
ifeq ($(USE_POSTGRES_VM_INTERFACE),1)
|
||||
CFLAGS+=-DUSEPOSTGRESVM
|
||||
endif
|
||||
|
||||
ifeq ($(USE_MYSQL_VM_INTERFACE),1)
|
||||
CFLAGS+=-DUSEMYSQLVM
|
||||
endif
|
||||
|
||||
all: $(APPS)
|
||||
|
||||
clean:
|
||||
rm -f *.so *.o look
|
||||
rm -f *.so *.o look .depend
|
||||
|
||||
%.so : %.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $<
|
||||
$(CC) $(SOLINK) -o $@ $<
|
||||
|
||||
app_rpt.so : app_rpt.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $< -ltonezone
|
||||
$(CC) $(SOLINK) -o $@ $< -ltonezone
|
||||
|
||||
install: all
|
||||
for x in $(APPS); do $(INSTALL) -m 755 $$x $(MODULES_DIR) ; done
|
||||
for x in $(APPS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/app_datetime.so
|
||||
|
||||
app_todd.o: app_todd.c
|
||||
gcc -pipe -O6 -g -Iinclude -I../include -D_REENTRANT -march=i586 -DDO_CRASH -c -o app_todd.o app_todd.c
|
||||
|
||||
app_todd.so: app_todd.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $< -L/usr/local/ssl/lib -lssl -lcrypto
|
||||
app_voicemail.so : app_voicemail.o
|
||||
ifeq ($(USE_MYSQL_VM_INTERFACE),1)
|
||||
$(CC) $(SOLINK) -o $@ $(MLFLAGS) $< -L/usr/lib/mysql -lmysqlclient -lz
|
||||
else
|
||||
ifeq ($(USE_POSTGRES_VM_INTERFACE),1)
|
||||
$(CC) $(SOLINK) -o $@ $(MLFLAGS) $< -lpq
|
||||
else
|
||||
$(CC) $(SOLINK) -o $@ $(MLFLAGS) $<
|
||||
endif
|
||||
endif
|
||||
|
||||
app_sql_postgres.o: app_sql_postgres.c
|
||||
$(CC) -pipe -I/usr/local/pgsql/include -Wall -Wmissing-prototypes -Wmissing-declarations -O6 -g -Iinclude -I../include -D_REENTRANT -D_GNU_SOURCE -march=i686 -DASTERISK_VERSION=\"CVS-07/21/02-14:49:14\" -DDO_CRASH -DDEBUG_THREADS -c -o app_sql_postgres.o app_sql_postgres.c
|
||||
$(CC) -pipe -I/usr/local/pgsql/include $(CFLAGS) -c -o app_sql_postgres.o app_sql_postgres.c
|
||||
|
||||
app_sql_postgres.so: app_sql_postgres.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $< -L/usr/local/pgsql/lib -lpq
|
||||
$(CC) $(SOLINK) -o $@ $< -L/usr/local/pgsql/lib -lpq
|
||||
|
||||
app_sql_odbc.so: app_sql_odbc.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $< -lodbc
|
||||
$(CC) $(SOLINK) -o $@ $< -lodbc
|
||||
|
||||
look: look.c
|
||||
gcc -pipe -O6 -g look.c -o look -lncurses
|
||||
$(CC) -pipe -O6 -g look.c -o look -lncurses
|
||||
|
||||
ifneq ($(wildcard .depend),)
|
||||
include .depend
|
||||
endif
|
||||
|
||||
depend: .depend
|
||||
|
||||
.depend:
|
||||
../mkdep $(CFLAGS) `ls *.c`
|
||||
|
||||
env:
|
||||
env
|
||||
|
||||
48
apps/app_adsiprog.c
Executable file → Normal file
48
apps/app_adsiprog.c
Executable file → Normal file
@@ -11,6 +11,7 @@
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
@@ -18,6 +19,8 @@
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/adsi.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@@ -27,8 +30,6 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "../asterisk.h"
|
||||
#include "../astconf.h"
|
||||
|
||||
@@ -177,7 +178,7 @@ static int process_token(void *out, char *src, int maxlen, int argtype)
|
||||
maxlen = strlen(src) - 1;
|
||||
memcpy(out, src, maxlen);
|
||||
((char *)out)[maxlen] = '\0';
|
||||
} else if (strlen(src) && (src[0] == '\\')) {
|
||||
} else if (!ast_strlen_zero(src) && (src[0] == '\\')) {
|
||||
if (!(argtype & ARG_NUMBER))
|
||||
return -1;
|
||||
/* Octal value */
|
||||
@@ -197,7 +198,7 @@ static int process_token(void *out, char *src, int maxlen, int argtype)
|
||||
/* Convert */
|
||||
*((unsigned int *)out) = htonl(*((unsigned int *)out));
|
||||
}
|
||||
} else if ((strlen(src) && isdigit(src[0]))) {
|
||||
} else if ((!ast_strlen_zero(src) && isdigit(src[0]))) {
|
||||
if (!(argtype & ARG_NUMBER))
|
||||
return -1;
|
||||
/* Hex value */
|
||||
@@ -665,7 +666,7 @@ static int showdisplay(char *buf, char *name, int id, char *args, struct adsi_sc
|
||||
}
|
||||
|
||||
buf[0] = id;
|
||||
buf[1] = (cmd << 6) | (disp->id & 0x2f);
|
||||
buf[1] = (cmd << 6) | (disp->id & 0x3f);
|
||||
buf[2] = ((line & 0x1f) << 3) | (flag & 0x7);
|
||||
return 3;
|
||||
}
|
||||
@@ -694,6 +695,18 @@ static int digitdirect(char *buf, char *name, int id, char *args, struct adsi_sc
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int clearcbone(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
|
||||
{
|
||||
char *tok;
|
||||
tok = get_token(&args, script, lineno);
|
||||
if (tok)
|
||||
ast_log(LOG_WARNING, "CLEARCB1 requires no arguments ('%s') at line %d of %s\n", tok, lineno, script);
|
||||
|
||||
buf[0] = id;
|
||||
buf[1] = 0;
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int digitcollect(char *buf, char *name, int id, char *args, struct adsi_script *istate, char *script, int lineno)
|
||||
{
|
||||
char *tok;
|
||||
@@ -830,6 +843,7 @@ static struct adsi_key_cmd kcmds[] = {
|
||||
{ "VOICEMODE", 0x93 },
|
||||
/* Display call buffer 'n' */
|
||||
/* Clear call buffer 'n' */
|
||||
{ "CLEARCB1", 0x95, clearcbone },
|
||||
{ "DIGITCOLLECT", 0x96, digitcollect },
|
||||
{ "DIGITDIRECT", 0x96, digitdirect },
|
||||
{ "CLEAR", 0x97 },
|
||||
@@ -987,7 +1001,7 @@ static int adsi_process(struct adsi_script *state, char *buf, char *script, int
|
||||
break;
|
||||
}
|
||||
if (process_token(vname, args, sizeof(vname) - 1, ARG_STRING)) {
|
||||
ast_log(LOG_WARNING "'%s' is not a valid token for a KEY name at line %d of %s\n", args, lineno, script);
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid token for a KEY name at line %d of %s\n", args, lineno, script);
|
||||
break;
|
||||
}
|
||||
state->key = getkeybyname(state, vname, script, lineno);
|
||||
@@ -1010,7 +1024,7 @@ static int adsi_process(struct adsi_script *state, char *buf, char *script, int
|
||||
break;
|
||||
}
|
||||
if (process_token(tmp, args, sizeof(tmp) - 1, ARG_STRING)) {
|
||||
ast_log(LOG_WARNING "'%s' is not a valid token for a KEY short name at line %d of %s\n", args, lineno, script);
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid token for a KEY short name at line %d of %s\n", args, lineno, script);
|
||||
break;
|
||||
}
|
||||
args = get_token(&buf, script, lineno);
|
||||
@@ -1025,7 +1039,7 @@ static int adsi_process(struct adsi_script *state, char *buf, char *script, int
|
||||
break;
|
||||
}
|
||||
if (process_token(tmp2, args, sizeof(tmp2) - 1, ARG_STRING)) {
|
||||
ast_log(LOG_WARNING "'%s' is not a valid token for a KEY long name at line %d of %s\n", args, lineno, script);
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid token for a KEY long name at line %d of %s\n", args, lineno, script);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -1065,7 +1079,7 @@ static int adsi_process(struct adsi_script *state, char *buf, char *script, int
|
||||
break;
|
||||
}
|
||||
if (process_token(vname, args, sizeof(vname) - 1, ARG_STRING)) {
|
||||
ast_log(LOG_WARNING "'%s' is not a valid token for a KEY name at line %d of %s\n", args, lineno, script);
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid token for a KEY name at line %d of %s\n", args, lineno, script);
|
||||
break;
|
||||
}
|
||||
state->sub = getsubbyname(state, vname, script, lineno);
|
||||
@@ -1103,7 +1117,7 @@ static int adsi_process(struct adsi_script *state, char *buf, char *script, int
|
||||
break;
|
||||
}
|
||||
if (process_token(vname, args, sizeof(vname) - 1, ARG_STRING)) {
|
||||
ast_log(LOG_WARNING "'%s' is not a valid token for a STATE name at line %d of %s\n", args, lineno, script);
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid token for a STATE name at line %d of %s\n", args, lineno, script);
|
||||
break;
|
||||
}
|
||||
if (getstatebyname(state, vname, script, lineno, 0)) {
|
||||
@@ -1118,7 +1132,7 @@ static int adsi_process(struct adsi_script *state, char *buf, char *script, int
|
||||
break;
|
||||
}
|
||||
if (process_token(vname, args, sizeof(vname) - 1, ARG_STRING)) {
|
||||
ast_log(LOG_WARNING "'%s' is not a valid token for a FLAG name at line %d of %s\n", args, lineno, script);
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid token for a FLAG name at line %d of %s\n", args, lineno, script);
|
||||
break;
|
||||
}
|
||||
if (getflagbyname(state, vname, script, lineno, 0)) {
|
||||
@@ -1135,7 +1149,7 @@ static int adsi_process(struct adsi_script *state, char *buf, char *script, int
|
||||
break;
|
||||
}
|
||||
if (process_token(vname, args, sizeof(vname) - 1, ARG_STRING)) {
|
||||
ast_log(LOG_WARNING "'%s' is not a valid token for a KEY name at line %d of %s\n", args, lineno, script);
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid token for a KEY name at line %d of %s\n", args, lineno, script);
|
||||
break;
|
||||
}
|
||||
if (getdisplaybyname(state, vname, script, lineno, 0)) {
|
||||
@@ -1349,7 +1363,7 @@ static struct adsi_script *compile_script(char *script)
|
||||
/* Strip comments */
|
||||
if (c)
|
||||
*c = '\0';
|
||||
if (strlen(buf))
|
||||
if (!ast_strlen_zero(buf))
|
||||
adsi_process(scr, buf, script, lineno);
|
||||
}
|
||||
}
|
||||
@@ -1434,7 +1448,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
bytes = 0;
|
||||
/* Start with key definitions */
|
||||
for (x=0;x<scr->numkeys;x++) {
|
||||
if (bytes + scr->keys[x].retstrlen > 254) {
|
||||
if (bytes + scr->keys[x].retstrlen > 253) {
|
||||
/* Send what we've collected so far */
|
||||
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
|
||||
@@ -1458,7 +1472,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
bytes = 0;
|
||||
/* Continue with the display messages */
|
||||
for (x=0;x<scr->numdisplays;x++) {
|
||||
if (bytes + scr->displays[x].datalen > 254) {
|
||||
if (bytes + scr->displays[x].datalen > 253) {
|
||||
/* Send what we've collected so far */
|
||||
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
|
||||
@@ -1482,7 +1496,7 @@ static int adsi_prog(struct ast_channel *chan, char *script)
|
||||
bytes = 0;
|
||||
/* Send subroutines */
|
||||
for (x=0;x<scr->numsubs;x++) {
|
||||
if (bytes + scr->subs[x].datalen > 254) {
|
||||
if (bytes + scr->subs[x].datalen > 253) {
|
||||
/* Send what we've collected so far */
|
||||
if (adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD)) {
|
||||
ast_log(LOG_WARNING, "Unable to send chunk ending at %d\n", x);
|
||||
@@ -1526,7 +1540,7 @@ static int adsi_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
if (!data || !strlen(data))
|
||||
if (!data || ast_strlen_zero(data))
|
||||
data = "asterisk.adsi";
|
||||
LOCAL_USER_ADD(u);
|
||||
if (!adsi_available(chan)) {
|
||||
|
||||
858
apps/app_alarmreceiver.c
Normal file
858
apps/app_alarmreceiver.c
Normal file
@@ -0,0 +1,858 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Central Station Alarm receiver for Ademco Contact ID
|
||||
*
|
||||
* Copyright (C) 2004 Steve Rodgers
|
||||
*
|
||||
* Steve Rodgers <hwstar@rodgers.sdcoxmail.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*
|
||||
* *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***
|
||||
*
|
||||
* Use at your own risk. Please consult the GNU GPL license document included with Asterisk details. *
|
||||
*
|
||||
* *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING *** WARNING ***
|
||||
*
|
||||
*/
|
||||
|
||||
#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/ulaw.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <asterisk/dsp.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/localtime.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <asterisk/astdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define ALMRCV_CONFIG "alarmreceiver.conf"
|
||||
#define ADEMCO_CONTACT_ID "ADEMCO_CONTACT_ID"
|
||||
|
||||
struct event_node{
|
||||
char data[17];
|
||||
struct event_node *next;
|
||||
};
|
||||
|
||||
typedef struct event_node event_node_t;
|
||||
|
||||
static char *tdesc = "Alarm Receiver for Asterisk";
|
||||
|
||||
static char *app = "AlarmReceiver";
|
||||
|
||||
static char *synopsis = "Provide support for receving alarm reports from a burglar or fire alarm panel";
|
||||
static char *descrip =
|
||||
"Alarm receiver application for Asterisk. Only 1 signalling format is supported at this time:\n"
|
||||
"Ademco Contact ID. This application should be called whenever there is an alarm panel calling in\n"
|
||||
"to dump its events. The application will handshake with the alarm panel, and receive events,\n"
|
||||
"validate them, handshake them, and store them until the panel hangs up. Once the panel hangs up,\n"
|
||||
"the application will run the command line specified by the eventcmd setting in alarmreceiver.conf\n"
|
||||
"and pipe the events to the standard input of the application. Alarmreceiver.conf also contains settings\n"
|
||||
"for DTMF timing, and for the loudness of the acknowledgement tones.\n";
|
||||
|
||||
/* Config Variables */
|
||||
|
||||
static int fdtimeout = 2000;
|
||||
static int sdtimeout = 200;
|
||||
static int toneloudness = 4096;
|
||||
static int log_individual_events = 0;
|
||||
static char event_spool_dir[128] = {'\0'};
|
||||
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
|
||||
* The alarmreceiver app will write statistics to a few variables
|
||||
* in this family if it is defined. If the new key doesn't exist in the
|
||||
* family, then create it and set its value to 1.
|
||||
*/
|
||||
|
||||
static void database_increment( char *key )
|
||||
{
|
||||
int res = 0;
|
||||
unsigned v;
|
||||
char value[16];
|
||||
|
||||
|
||||
if(!strlen(db_family))
|
||||
return; /* If not defined, don't do anything */
|
||||
|
||||
res = ast_db_get(db_family, key, value, sizeof(value) - 1);
|
||||
|
||||
if(res){
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Creating database entry %s and setting to 1\n", key);
|
||||
/* Guess we have to create it */
|
||||
res = ast_db_put(db_family, key, "1");
|
||||
return;
|
||||
}
|
||||
|
||||
sscanf(value, "%u", &v);
|
||||
v++;
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: New value for %s: %u\n", key, v);
|
||||
|
||||
snprintf(value, sizeof(value), "%u", v);
|
||||
|
||||
res = ast_db_put(db_family, key, value);
|
||||
|
||||
if((res)&&(option_verbose >= 4))
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: database_increment write error");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Build a MuLaw data block for a single frequency tone
|
||||
*/
|
||||
|
||||
static void make_tone_burst(unsigned char *data, float freq, float loudness, int len, int *x)
|
||||
{
|
||||
int i;
|
||||
float val;
|
||||
|
||||
for(i = 0; i < len; i++){
|
||||
val = loudness * sin((freq * 2.0 * M_PI * (*x)++)/8000.0);
|
||||
data[i] = AST_LIN2MU((int)val);
|
||||
}
|
||||
|
||||
/* wrap back around from 8000 */
|
||||
|
||||
if (*x >= 8000) *x = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a single tone burst for a specifed duration and frequency.
|
||||
* Returns 0 if successful
|
||||
*/
|
||||
|
||||
static int send_tone_burst(struct ast_channel *chan, float freq, int duration, int tldn)
|
||||
{
|
||||
int res = 0;
|
||||
int i = 0;
|
||||
int x = 0;
|
||||
struct ast_frame *f, wf;
|
||||
|
||||
struct {
|
||||
unsigned char offset[AST_FRIENDLY_OFFSET];
|
||||
unsigned char buf[640];
|
||||
} tone_block;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
|
||||
if (ast_waitfor(chan, -1) < 0){
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
f = ast_read(chan);
|
||||
if (!f){
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
wf.frametype = AST_FRAME_VOICE;
|
||||
wf.subclass = AST_FORMAT_ULAW;
|
||||
wf.offset = AST_FRIENDLY_OFFSET;
|
||||
wf.mallocd = 0;
|
||||
wf.data = tone_block.buf;
|
||||
wf.datalen = f->datalen;
|
||||
wf.samples = wf.datalen;
|
||||
|
||||
make_tone_burst(tone_block.buf, freq, (float) tldn, wf.datalen, &x);
|
||||
|
||||
i += wf.datalen / 8;
|
||||
if (i > duration) {
|
||||
break;
|
||||
}
|
||||
if (ast_write(chan, &wf)){
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Failed to write frame on %s\n", chan->name);
|
||||
ast_log(LOG_WARNING, "AlarmReceiver Failed to write frame on %s\n",chan->name);
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ast_frfree(f);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the difference in milliseconds between two timeval structs
|
||||
*/
|
||||
|
||||
static int ms_diff(struct timeval *tv1, struct timeval *tv2){
|
||||
|
||||
int ms;
|
||||
|
||||
ms = (tv1->tv_sec - tv2->tv_sec) * 1000;
|
||||
ms += (tv1->tv_usec - tv2->tv_usec) / 1000;
|
||||
|
||||
return(ms);
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive a string of DTMF digits where the length of the digit string is known in advance. Do not give preferential
|
||||
* treatment to any digit value, and allow separate time out values to be specified for the first digit and all subsequent
|
||||
* digits.
|
||||
*
|
||||
* Returns 0 if all digits successfully received.
|
||||
* Returns 1 if a digit time out occurred
|
||||
* Returns -1 if the caller hung up or there was a channel error.
|
||||
*
|
||||
*/
|
||||
|
||||
static int receive_dtmf_digits(struct ast_channel *chan, char *digit_string, int length, int fdto, int sdto)
|
||||
{
|
||||
int res = 0;
|
||||
int i = 0;
|
||||
int r;
|
||||
struct ast_frame *f;
|
||||
struct timeval now, lastdigittime;
|
||||
|
||||
gettimeofday(&lastdigittime,NULL);
|
||||
for(;;){
|
||||
gettimeofday(&now,NULL);
|
||||
|
||||
/* if outa time, leave */
|
||||
if (ms_diff(&now,&lastdigittime) >
|
||||
((i > 0) ? sdto : fdto)){
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: DTMF Digit Timeout on %s\n", chan->name);
|
||||
|
||||
ast_log(LOG_DEBUG,"AlarmReceiver: DTMF timeout on chan %s\n",chan->name);
|
||||
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((r = ast_waitfor(chan, -1) < 0)) {
|
||||
ast_log(LOG_DEBUG, "Waitfor returned %d\n", r);
|
||||
continue;
|
||||
}
|
||||
|
||||
f = ast_read(chan);
|
||||
|
||||
if (f == NULL){
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* If they hung up, leave */
|
||||
if ((f->frametype == AST_FRAME_CONTROL) &&
|
||||
(f->subclass == AST_CONTROL_HANGUP)){
|
||||
ast_frfree(f);
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* if not DTMF, just do it again */
|
||||
if (f->frametype != AST_FRAME_DTMF){
|
||||
ast_frfree(f);
|
||||
continue;
|
||||
}
|
||||
|
||||
digit_string[i++] = f->subclass; /* save digit */
|
||||
|
||||
ast_frfree(f);
|
||||
|
||||
/* If we have all the digits we expect, leave */
|
||||
if(i >= length)
|
||||
break;
|
||||
|
||||
gettimeofday(&lastdigittime,NULL);
|
||||
}
|
||||
|
||||
digit_string[i] = '\0'; /* Nul terminate the end of the digit string */
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the metadata to the log file
|
||||
*/
|
||||
|
||||
static int write_metadata( FILE *logfile, char *signalling_type, struct ast_channel *chan)
|
||||
{
|
||||
int res = 0;
|
||||
time_t t;
|
||||
struct tm now;
|
||||
char *cl,*cn;
|
||||
char workstring[80];
|
||||
char timestamp[80];
|
||||
|
||||
/* Extract the caller ID location */
|
||||
|
||||
strncpy(workstring, chan->callerid, sizeof(workstring) - 1);
|
||||
workstring[sizeof(workstring) - 1] = '\0';
|
||||
|
||||
ast_callerid_parse(workstring, &cn, &cl);
|
||||
if (cl)
|
||||
ast_shrink_phone_number(cl);
|
||||
|
||||
|
||||
/* Get the current time */
|
||||
|
||||
time(&t);
|
||||
ast_localtime(&t, &now, NULL);
|
||||
|
||||
/* Format the time */
|
||||
|
||||
strftime(timestamp, sizeof(timestamp), time_stamp_format, &now);
|
||||
|
||||
|
||||
res = fprintf(logfile, "\n\n[metadata]\n\n");
|
||||
|
||||
if(res >= 0)
|
||||
res = fprintf(logfile, "PROTOCOL=%s\n", signalling_type);
|
||||
|
||||
if(res >= 0)
|
||||
res = fprintf(logfile, "CALLINGFROM=%s\n", (!cl) ? "<unknown>" : cl);
|
||||
|
||||
if(res >- 0)
|
||||
res = fprintf(logfile, "CALLERNAME=%s\n", (!cn) ? "<unknown>" : cn);
|
||||
|
||||
if(res >= 0)
|
||||
res = fprintf(logfile, "TIMESTAMP=%s\n\n", timestamp);
|
||||
|
||||
if(res >= 0)
|
||||
res = fprintf(logfile, "[events]\n\n");
|
||||
|
||||
if(res < 0){
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: can't write metadata\n");
|
||||
|
||||
ast_log(LOG_DEBUG,"AlarmReceiver: can't write metadata\n");
|
||||
}
|
||||
else
|
||||
res = 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a single event to the log file
|
||||
*/
|
||||
|
||||
static int write_event( FILE *logfile, event_node_t *event)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
if( fprintf(logfile, "%s\n", event->data) < 0)
|
||||
res = -1;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If we are configured to log events, do so here.
|
||||
*
|
||||
*/
|
||||
|
||||
static int log_events(struct ast_channel *chan, char *signalling_type, event_node_t *event)
|
||||
{
|
||||
|
||||
int res = 0;
|
||||
char workstring[sizeof(event_spool_dir)+sizeof(event_file)] = "";
|
||||
int fd;
|
||||
FILE *logfile;
|
||||
event_node_t *elp = event;
|
||||
|
||||
if(strlen(event_spool_dir)){
|
||||
|
||||
/* Make a template */
|
||||
|
||||
strncpy(workstring, event_spool_dir, sizeof(workstring) - 1);
|
||||
strncat(workstring, event_file, sizeof(workstring) - strlen(workstring) - 1);
|
||||
|
||||
/* Make the temporary file */
|
||||
|
||||
fd = mkstemp(workstring);
|
||||
|
||||
if(fd == -1){
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: can't make temporary file\n");
|
||||
ast_log(LOG_DEBUG,"AlarmReceiver: can't make temporary file\n");
|
||||
res = -1;
|
||||
}
|
||||
|
||||
if(!res){
|
||||
logfile = fdopen(fd, "w");
|
||||
if(logfile){
|
||||
/* Write the file */
|
||||
res = write_metadata(logfile, signalling_type, chan);
|
||||
if(!res)
|
||||
while((!res) && (elp != NULL)){
|
||||
res = write_event(logfile, elp);
|
||||
elp = elp->next;
|
||||
}
|
||||
if(!res){
|
||||
if(fflush(logfile) == EOF)
|
||||
res = -1;
|
||||
if(!res){
|
||||
if(fclose(logfile) == EOF)
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function implements the logic to receive the Ademco contact ID format.
|
||||
*
|
||||
* The function will return 0 when the caller hangs up, else a -1 if there was a problem.
|
||||
*/
|
||||
|
||||
static int receive_ademco_contact_id( struct ast_channel *chan, void *data, int fdto, int sdto, int tldn, event_node_t **ehead)
|
||||
{
|
||||
int i,j;
|
||||
int res = 0;
|
||||
int checksum;
|
||||
char event[17];
|
||||
event_node_t *enew, *elp;
|
||||
int got_some_digits = 0;
|
||||
int events_received = 0;
|
||||
int ack_retries = 0;
|
||||
|
||||
static char digit_map[15] = "0123456789*#ABC";
|
||||
static unsigned char digit_weights[15] = {10,1,2,3,4,5,6,7,8,9,11,12,13,14,15};
|
||||
|
||||
database_increment("calls-received");
|
||||
|
||||
/* Wait for first event */
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Waiting for first event from panel\n");
|
||||
|
||||
while(res >= 0){
|
||||
|
||||
if(got_some_digits == 0){
|
||||
|
||||
/* Send ACK tone sequence */
|
||||
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Sending 1400Hz 100ms burst (ACK)\n");
|
||||
|
||||
|
||||
res = send_tone_burst(chan, 1400.0, 100, tldn);
|
||||
|
||||
if(!res)
|
||||
res = ast_safe_sleep(chan, 100);
|
||||
|
||||
if(!res){
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Sending 2300Hz 100ms burst (ACK)\n");
|
||||
|
||||
res = send_tone_burst(chan, 2300.0, 100, tldn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( res >= 0)
|
||||
res = receive_dtmf_digits(chan, event, sizeof(event) - 1, fdto, sdto);
|
||||
|
||||
if (res < 0){
|
||||
|
||||
if(events_received == 0)
|
||||
/* Hangup with no events received should be logged in the DB */
|
||||
database_increment("no-events-received");
|
||||
else{
|
||||
if(ack_retries){
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: ACK retries during this call: %d\n", ack_retries);
|
||||
|
||||
database_increment("ack-retries");
|
||||
}
|
||||
}
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: App exiting...\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(res != 0){
|
||||
/* Didn't get all of the digits */
|
||||
if(option_verbose >= 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Incomplete string: %s, trying again...\n", event);
|
||||
|
||||
if(!got_some_digits){
|
||||
got_some_digits = (strlen(event)) ? 1 : 0;
|
||||
ack_retries++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
got_some_digits = 1;
|
||||
|
||||
if(option_verbose >= 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Received Event %s\n", event);
|
||||
ast_log(LOG_DEBUG, "AlarmReceiver: Received event: %s\n", event);
|
||||
|
||||
/* Calculate checksum */
|
||||
|
||||
for(j = 0, checksum = 0; j < 16; j++){
|
||||
for(i = 0 ; i < sizeof(digit_map) ; i++){
|
||||
if(digit_map[i] == event[j])
|
||||
break;
|
||||
}
|
||||
|
||||
if(i == 16)
|
||||
break;
|
||||
|
||||
checksum += digit_weights[i];
|
||||
}
|
||||
|
||||
if(i == 16){
|
||||
if(option_verbose >= 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Bad DTMF character %c, trying again\n", event[j]);
|
||||
continue; /* Bad character */
|
||||
}
|
||||
|
||||
/* Checksum is mod(15) of the total */
|
||||
|
||||
checksum = checksum % 15;
|
||||
|
||||
if(checksum){
|
||||
database_increment("checksum-errors");
|
||||
if(option_verbose >= 2){
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Nonzero checksum\n");
|
||||
ast_log(LOG_DEBUG, "AlarmReceiver: Nonzero checksum\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the message type for correctness */
|
||||
|
||||
if(strncmp(event + 4, "18", 2)){
|
||||
if(strncmp(event + 4, "98", 2)){
|
||||
database_increment("format-errors");
|
||||
if(option_verbose >= 2)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "AlarmReceiver: Wrong message type\n");
|
||||
ast_log(LOG_DEBUG, "AlarmReceiver: Wrong message type\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
events_received++;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
memset(enew, 0, sizeof(event_node_t));
|
||||
|
||||
enew->next = NULL;
|
||||
strncpy(enew->data, event, sizeof(enew->data) - 1);
|
||||
|
||||
/*
|
||||
* Insert event onto end of list
|
||||
*/
|
||||
|
||||
if(*ehead == NULL){
|
||||
*ehead = enew;
|
||||
}
|
||||
else{
|
||||
for(elp = *ehead; elp->next != NULL; elp = elp->next)
|
||||
;
|
||||
|
||||
elp->next = enew;
|
||||
}
|
||||
|
||||
if(res > 0)
|
||||
res = 0;
|
||||
|
||||
/* Let the user have the option of logging the single event before sending the kissoff tone */
|
||||
|
||||
if((res == 0) && (log_individual_events))
|
||||
res = log_events(chan, ADEMCO_CONTACT_ID, enew);
|
||||
|
||||
/* Wait 200 msec before sending kissoff */
|
||||
|
||||
if(res == 0)
|
||||
res = ast_safe_sleep(chan, 200);
|
||||
|
||||
/* Send the kissoff tone */
|
||||
|
||||
if(res == 0)
|
||||
res = send_tone_burst(chan, 1400.0, 900, tldn);
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This is the main function called by Asterisk Core whenever the App is invoked in the extension logic.
|
||||
* This function will always return 0.
|
||||
*/
|
||||
|
||||
static int alarmreceiver_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
event_node_t *elp, *efree;
|
||||
char signalling_type[64] = "";
|
||||
|
||||
event_node_t *event_head = NULL;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Set write and read formats to ULAW */
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Setting read and write formats to ULAW\n");
|
||||
|
||||
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);
|
||||
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);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set default values for this invokation of the application */
|
||||
|
||||
strncpy(signalling_type, ADEMCO_CONTACT_ID, sizeof(signalling_type) - 1);
|
||||
|
||||
|
||||
/* Answer the channel if it is not already */
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Answering channel\n");
|
||||
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
|
||||
res = ast_answer(chan);
|
||||
|
||||
if (res) {
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for the connection to settle post-answer */
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Waiting for connection to stabilize\n");
|
||||
|
||||
res = ast_safe_sleep(chan, 1250);
|
||||
|
||||
/* Attempt to receive the events */
|
||||
|
||||
if(!res){
|
||||
|
||||
/* Determine the protocol to receive in advance */
|
||||
/* Note: Ademco contact is the only one supported at this time */
|
||||
/* Others may be added later */
|
||||
|
||||
if(!strcmp(signalling_type, ADEMCO_CONTACT_ID))
|
||||
receive_ademco_contact_id(chan, data, fdtimeout, sdtimeout, toneloudness, &event_head);
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Events queued by receiver, write them all out here if so configured */
|
||||
|
||||
if((!res) && (log_individual_events == 0)){
|
||||
res = log_events(chan, signalling_type, event_head);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Do we exec a command line at the end?
|
||||
*/
|
||||
|
||||
if((!res) && (strlen(event_app)) && (event_head)){
|
||||
ast_log(LOG_DEBUG,"Alarmreceiver: executing: %s\n", event_app);
|
||||
ast_safe_system(event_app);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free up the data allocated in our linked list
|
||||
*/
|
||||
|
||||
for(elp = event_head; (elp != NULL);){
|
||||
efree = elp;
|
||||
elp = elp->next;
|
||||
free(efree);
|
||||
}
|
||||
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Load the configuration from the configuration file
|
||||
*/
|
||||
|
||||
static int load_config(void)
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
char *p;
|
||||
|
||||
/* Read in the config file */
|
||||
|
||||
cfg = ast_load(ALMRCV_CONFIG);
|
||||
|
||||
if(!cfg){
|
||||
|
||||
if(option_verbose >= 4)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: No config file\n");
|
||||
}
|
||||
else{
|
||||
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "eventcmd");
|
||||
|
||||
if(p){
|
||||
strncpy(event_app, p, sizeof(event_app) - 1);
|
||||
event_app[sizeof(event_app) - 1] = '\0';
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "loudness");
|
||||
if(p){
|
||||
toneloudness = atoi(p);
|
||||
if(toneloudness < 100)
|
||||
toneloudness = 100;
|
||||
if(toneloudness > 8192)
|
||||
toneloudness = 8192;
|
||||
}
|
||||
p = ast_variable_retrieve(cfg, "general", "fdtimeout");
|
||||
if(p){
|
||||
fdtimeout = atoi(p);
|
||||
if(fdtimeout < 1000)
|
||||
fdtimeout = 1000;
|
||||
if(fdtimeout > 10000)
|
||||
fdtimeout = 10000;
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "sdtimeout");
|
||||
if(p){
|
||||
sdtimeout = atoi(p);
|
||||
if(sdtimeout < 110)
|
||||
sdtimeout = 110;
|
||||
if(sdtimeout > 4000)
|
||||
sdtimeout = 4000;
|
||||
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "logindividualevents");
|
||||
if(p){
|
||||
log_individual_events = ast_true(p);
|
||||
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "eventspooldir");
|
||||
|
||||
if(p){
|
||||
strncpy(event_spool_dir, p, sizeof(event_spool_dir) - 1);
|
||||
event_spool_dir[sizeof(event_spool_dir) - 1] = '\0';
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "timestampformat");
|
||||
|
||||
if(p){
|
||||
strncpy(time_stamp_format, p, sizeof(time_stamp_format) - 1);
|
||||
time_stamp_format[sizeof(time_stamp_format) - 1] = '\0';
|
||||
}
|
||||
|
||||
p = ast_variable_retrieve(cfg, "general", "db-family");
|
||||
|
||||
if(p){
|
||||
strncpy(db_family, p, sizeof(db_family) - 1);
|
||||
db_family[sizeof(db_family) - 1] = '\0';
|
||||
}
|
||||
ast_destroy(cfg);
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* These functions are required to implement an Asterisk App.
|
||||
*/
|
||||
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
load_config();
|
||||
return ast_register_application(app, alarmreceiver_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
54
apps/app_authenticate.c
Executable file → Normal file
54
apps/app_authenticate.c
Executable file → Normal file
@@ -18,14 +18,14 @@
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <asterisk/astdb.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Authentication Application";
|
||||
|
||||
@@ -41,7 +41,11 @@ static char *descrip =
|
||||
"an optional set of opions may be provided by concatenating any\n"
|
||||
"of the following letters:\n"
|
||||
" a - Set account code to the password that is entered\n"
|
||||
" d - Interpret path as database key, not literal file\n"
|
||||
" r - Remove database key upon successful entry (valid with 'd' only)\n"
|
||||
"\n"
|
||||
"When using a database key, the value associated with the key can be\n"
|
||||
"anything.\n"
|
||||
"Returns 0 if the user enters a valid password within three\n"
|
||||
"tries, or -1 otherwise (or on hangup).\n";
|
||||
|
||||
@@ -58,7 +62,7 @@ static int auth_exec(struct ast_channel *chan, void *data)
|
||||
char passwd[256];
|
||||
char *opts;
|
||||
char *prompt;
|
||||
if (!data || !strlen(data)) {
|
||||
if (!data || ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "Authenticate requires an argument(password)\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -85,24 +89,36 @@ static int auth_exec(struct ast_channel *chan, void *data)
|
||||
break;
|
||||
res = 0;
|
||||
if (password[0] == '/') {
|
||||
/* Compare against a file */
|
||||
FILE *f;
|
||||
f = fopen(password, "r");
|
||||
if (f) {
|
||||
char buf[256] = "";
|
||||
while(!feof(f)) {
|
||||
fgets(buf, sizeof(buf), f);
|
||||
if (!feof(f) && strlen(buf)) {
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
if (strlen(buf) && !strcmp(passwd, buf))
|
||||
break;
|
||||
if (strchr(opts, 'd')) {
|
||||
char tmp[256];
|
||||
/* Compare against a database key */
|
||||
if (!ast_db_get(password + 1, passwd, tmp, sizeof(tmp))) {
|
||||
/* It's a good password */
|
||||
if (strchr(opts, 'r')) {
|
||||
ast_db_del(password + 1, passwd);
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
if (strlen(buf) && !strcmp(passwd, buf))
|
||||
break;
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", password, strerror(errno));
|
||||
}
|
||||
} else {
|
||||
/* Compare against a file */
|
||||
FILE *f;
|
||||
f = fopen(password, "r");
|
||||
if (f) {
|
||||
char buf[256] = "";
|
||||
while(!feof(f)) {
|
||||
fgets(buf, sizeof(buf), f);
|
||||
if (!feof(f) && !ast_strlen_zero(buf)) {
|
||||
buf[strlen(buf) - 1] = '\0';
|
||||
if (!ast_strlen_zero(buf) && !strcmp(passwd, buf))
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
if (!ast_strlen_zero(buf) && !strcmp(passwd, buf))
|
||||
break;
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", password, strerror(errno));
|
||||
}
|
||||
} else {
|
||||
/* Compare against a fixed password */
|
||||
if (!strcmp(passwd, password))
|
||||
|
||||
66
apps/app_cdr.c
Normal file
66
apps/app_cdr.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Applictions connected with CDR engine
|
||||
*
|
||||
* Copyright (C) 2003, Digium
|
||||
*
|
||||
* Martin Pycko <martinp@digium.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static char *tdesc = "Make sure asterisk doesn't save CDR for a certain call";
|
||||
|
||||
static char *nocdr_descrip = "NoCDR(): makes sure there won't be any CDR written for a certain call";
|
||||
static char *nocdr_app = "NoCDR";
|
||||
static char *nocdr_synopsis = "Make sure asterisk doesn't save CDR for a certain call";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int nocdr_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
if (chan->cdr) {
|
||||
ast_cdr_free(chan->cdr);
|
||||
chan->cdr = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(nocdr_app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(nocdr_app, nocdr_exec, nocdr_synopsis, nocdr_descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
28
apps/app_chanisavail.c
Executable file → Normal file
28
apps/app_chanisavail.c
Executable file → Normal file
@@ -27,8 +27,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Check if channel is available";
|
||||
|
||||
static char *app = "ChanIsAvail";
|
||||
@@ -38,12 +36,14 @@ static char *synopsis = "Check if channel is available";
|
||||
static char *descrip =
|
||||
" ChanIsAvail(Technology/resource[&Technology2/resource2...]): \n"
|
||||
"Checks is any of the requested channels are available. If none\n"
|
||||
"of the requested channels are available the new priority will\n"
|
||||
"be n+101 (unless such a priority does not exist, in which case\n"
|
||||
"ChanIsAvail will return -1. If any of the requested channels\n"
|
||||
"are available, the next priority will be n+1, the channel variable\n"
|
||||
"${AVAILCHAN} will be set to the name of the available channel and\n"
|
||||
"the ChanIsAvail app will return 0.\n";
|
||||
"of the requested channels are available the new priority will be\n"
|
||||
"n+101 (unless such a priority does not exist or on error, in which\n"
|
||||
"case ChanIsAvail will return -1).\n"
|
||||
"If any of the requested channels are available, the next priority will be n+1,\n"
|
||||
"the channel variable ${AVAILCHAN} will be set to the name of the available channel\n"
|
||||
"and the ChanIsAvail app will return 0.\n"
|
||||
"${AVAILORIGCHAN} is the canonical channel name that was used to create the channel.\n"
|
||||
"${AVAILSTATUS} is the status code for the channel.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -53,7 +53,7 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=-1;
|
||||
struct localuser *u;
|
||||
char info[256], *peers, *tech, *number, *rest, *cur;
|
||||
char info[512], tmp[512], *peers, *tech, *number, *rest, *cur;
|
||||
struct ast_channel *tempchan;
|
||||
|
||||
if (!data) {
|
||||
@@ -62,7 +62,7 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1);
|
||||
strncpy(info, (char *)data, sizeof(info)-1);
|
||||
peers = info;
|
||||
if (peers) {
|
||||
cur = peers;
|
||||
@@ -76,13 +76,16 @@ static int chanavail_exec(struct ast_channel *chan, void *data)
|
||||
tech = cur;
|
||||
number = strchr(tech, '/');
|
||||
if (!number) {
|
||||
ast_log(LOG_WARNING, "ChanIsAvail argument takes format (Zap/[device])\n");
|
||||
continue;
|
||||
ast_log(LOG_WARNING, "ChanIsAvail argument takes format ([technology]/[device])\n");
|
||||
return -1;
|
||||
}
|
||||
*number = '\0';
|
||||
number++;
|
||||
if ((tempchan = ast_request(tech, chan->nativeformats, number))) {
|
||||
pbx_builtin_setvar_helper(chan, "AVAILCHAN", tempchan->name);
|
||||
/* Store the originally used channel too */
|
||||
snprintf(tmp, sizeof(tmp), "%s/%s", tech, number);
|
||||
pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", tmp);
|
||||
ast_hangup(tempchan);
|
||||
tempchan = NULL;
|
||||
res = 1;
|
||||
@@ -94,6 +97,7 @@ 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 (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority+=100;
|
||||
else
|
||||
|
||||
138
apps/app_controlplayback.c
Normal file
138
apps/app_controlplayback.c
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Trivial application to control playback a sound file
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static char *tdesc = "Control Playback Application";
|
||||
|
||||
static char *app = "ControlPlayback";
|
||||
|
||||
static char *synopsis = "Play a file with fast forward and rewind";
|
||||
|
||||
static char *descrip =
|
||||
"ControlPlayback(filename[|skipms[|ffchar[|rewchar[|stopchar[|pausechr]]]]]):\n"
|
||||
" Plays back a given filename (do not put extension). Options may also\n"
|
||||
" be included following a pipe symbol. You can use * and # to rewind and\n"
|
||||
" fast forward the playback specified. If 'stopchar' is added the file will\n"
|
||||
" terminate playback when 'stopchar' is pressed. Returns -1 if the channel\n"
|
||||
" was hung up, or if the file does not exist. Returns 0 otherwise.\n\n"
|
||||
" Example: exten => 1234,1,ControlPlayback(file|4000|*|#|1|0)\n\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int is_on_phonepad(char key)
|
||||
{
|
||||
return (key == 35 || key == 42 || (key >= 48 && key <= 57)) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int controlplayback_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
int skipms = 0;
|
||||
struct localuser *u;
|
||||
char tmp[256];
|
||||
char *skip = NULL, *fwd = NULL, *rev = NULL, *stop = NULL, *pause = NULL, *file = NULL;
|
||||
|
||||
if (!data || ast_strlen_zero((char *)data)) {
|
||||
ast_log(LOG_WARNING, "ControlPlayback requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(tmp, (char *)data, sizeof(tmp)-1);
|
||||
file = tmp;
|
||||
|
||||
if ((skip=strchr(tmp,'|'))) {
|
||||
*skip++ = '\0';
|
||||
fwd=strchr(skip,'|');
|
||||
if (fwd) {
|
||||
*fwd++ = '\0';
|
||||
rev = strchr(fwd,'|');
|
||||
if (rev) {
|
||||
*rev++ = '\0';
|
||||
stop = strchr(rev,'|');
|
||||
if (stop) {
|
||||
*stop++ = '\0';
|
||||
pause = strchr(stop,'|');
|
||||
if (pause) {
|
||||
*pause++ = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
skipms = skip ? atoi(skip) : 3000;
|
||||
if (!skipms)
|
||||
skipms = 3000;
|
||||
|
||||
if (!fwd || !is_on_phonepad(*fwd))
|
||||
fwd = "#";
|
||||
if (!rev || !is_on_phonepad(*rev))
|
||||
rev = "*";
|
||||
if (stop && !is_on_phonepad(*stop))
|
||||
stop = NULL;
|
||||
if (pause && !is_on_phonepad(*pause))
|
||||
pause = NULL;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
res = ast_control_streamfile(chan, file, fwd, rev, stop, pause, skipms);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
/* If we stopped on one of our stop keys, return 0 */
|
||||
if(stop && strchr(stop, res))
|
||||
res = 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, controlplayback_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
198
apps/app_cut.c
Normal file
198
apps/app_cut.c
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Cut application
|
||||
*
|
||||
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <app_cut__v003@the-tilghman.com>
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This code is released by the author with no restrictions on usage.
|
||||
*
|
||||
*/
|
||||
|
||||
#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>
|
||||
|
||||
/* Maximum length of any variable */
|
||||
#define MAXRESULT 1024
|
||||
|
||||
static char *tdesc = "Cuts up variables";
|
||||
|
||||
static char *app_cut = "Cut";
|
||||
|
||||
static char *cut_synopsis = "Splits a variable's content using the specified delimiter";
|
||||
|
||||
static char *cut_descrip =
|
||||
"Usage: Cut(newvar=varname,delimiter,fieldspec)\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"
|
||||
" Returns 0 or -1 on hangup or error.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int cut_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *s, *newvar=NULL, *varname=NULL, *delimiter=NULL, *field=NULL;
|
||||
int args_okay = 0;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Check and parse arguments */
|
||||
if (data) {
|
||||
s = ast_strdupa((char *)data);
|
||||
if (s) {
|
||||
newvar = strsep(&s, "=");
|
||||
if (newvar && (newvar[0] != '\0')) {
|
||||
varname = strsep(&s, "|");
|
||||
if (varname && (varname[0] != '\0')) {
|
||||
delimiter = strsep(&s, "|");
|
||||
if (delimiter) {
|
||||
field = strsep(&s, "|");
|
||||
if (field) {
|
||||
args_okay = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (args_okay) {
|
||||
char d, ds[2];
|
||||
char *tmp = alloca(strlen(varname) + 4);
|
||||
char varvalue[MAXRESULT], *tmp2=varvalue;
|
||||
char retstring[MAXRESULT];
|
||||
|
||||
memset(retstring, 0, MAXRESULT);
|
||||
|
||||
if (tmp) {
|
||||
snprintf(tmp, strlen(varname) + 4, "${%s}", varname);
|
||||
memset(varvalue, 0, sizeof(varvalue));
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (delimiter[0])
|
||||
d = delimiter[0];
|
||||
else
|
||||
d = '-';
|
||||
|
||||
/* String form of the delimiter, for use with strsep(3) */
|
||||
snprintf(ds, sizeof(ds), "%c", d);
|
||||
|
||||
pbx_substitute_variables_helper(chan, tmp, tmp2, MAXRESULT - 1);
|
||||
|
||||
if (tmp2) {
|
||||
int curfieldnum = 1;
|
||||
while ((tmp2 != NULL) && (field != NULL)) {
|
||||
char *nextgroup = strsep(&field, "&");
|
||||
int num1 = 0, num2 = MAXRESULT;
|
||||
char trashchar;
|
||||
|
||||
if (sscanf(nextgroup, "%d-%d", &num1, &num2) == 2) {
|
||||
/* range with both start and end */
|
||||
} else if (sscanf(nextgroup, "-%d", &num2) == 1) {
|
||||
/* range with end */
|
||||
num1 = 0;
|
||||
} else if ((sscanf(nextgroup, "%d%c", &num1, &trashchar) == 2) && (trashchar == '-')) {
|
||||
/* range with start */
|
||||
num2 = MAXRESULT;
|
||||
} else if (sscanf(nextgroup, "%d", &num1) == 1) {
|
||||
/* single number */
|
||||
num2 = num1;
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Cut(): Illegal range '%s'\n", nextgroup);
|
||||
ast_log(LOG_ERROR, "Usage: %s\n", cut_synopsis);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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, "Cut(): 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(retstring);
|
||||
|
||||
if (strlen(retstring)) {
|
||||
snprintf(retstring + curlen, MAXRESULT - curlen, "%c%s", d, tmp3);
|
||||
} else {
|
||||
snprintf(retstring, MAXRESULT, "%s", tmp3);
|
||||
}
|
||||
|
||||
curfieldnum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pbx_builtin_setvar_helper(chan, newvar, retstring);
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app_cut);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app_cut, cut_exec, cut_synopsis, cut_descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
3
apps/app_datetime.c
Executable file → Normal file
3
apps/app_datetime.c
Executable file → Normal file
@@ -23,9 +23,6 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Date and Time";
|
||||
|
||||
static char *app = "DateTime";
|
||||
|
||||
410
apps/app_db.c
Executable file → Normal file
410
apps/app_db.c
Executable file → Normal file
@@ -13,39 +13,38 @@
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/astdb.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Database access functions for Asterisk extension logic";
|
||||
|
||||
static char *g_descrip =
|
||||
" DBget(varname=family/key): Retrieves a value from the Asterisk\n"
|
||||
"database and stores it in the given variable. Always returns 0. If the\n"
|
||||
"requested key is not found, jumps to priority n+101 if available.\n";
|
||||
" DBget(varname=family/key): Retrieves a value from the Asterisk\n"
|
||||
"database and stores it in the given variable. Always returns 0. If the\n"
|
||||
"requested key is not found, jumps to priority n+101 if available.\n";
|
||||
|
||||
static char *p_descrip =
|
||||
" DBput(family/key=value): Stores the given value in the Asterisk\n"
|
||||
"database. Always returns 0.\n";
|
||||
" DBput(family/key=value): Stores the given value in the Asterisk\n"
|
||||
"database. Always returns 0.\n";
|
||||
|
||||
static char *d_descrip =
|
||||
" DBdel(family/key): Deletes a key from the Asterisk database. Always\n"
|
||||
"returns 0.\n";
|
||||
" DBdel(family/key): Deletes a key from the Asterisk database. Always\n"
|
||||
"returns 0.\n";
|
||||
|
||||
static char *dt_descrip =
|
||||
" DBdeltree(family[/keytree]): Deletes a family or keytree from the Asterisk\n"
|
||||
"database. Always returns 0.\n";
|
||||
" DBdeltree(family[/keytree]): Deletes a family or keytree from the Asterisk\n"
|
||||
"database. Always returns 0.\n";
|
||||
|
||||
static char *g_app = "DBget";
|
||||
static char *p_app = "DBput";
|
||||
@@ -61,255 +60,196 @@ STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
|
||||
static int
|
||||
deltree_exec (struct ast_channel *chan, void *data)
|
||||
static int deltree_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
int arglen;
|
||||
char *argv, *family, *keytree;
|
||||
int arglen;
|
||||
char *argv, *family, *keytree;
|
||||
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) /* Why would this fail? */
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
if (strchr (argv, '/')) {
|
||||
{
|
||||
family = strsep (&argv, "/");
|
||||
keytree = strsep (&argv, "\0");
|
||||
if (!family || !keytree)
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) { /* Why would this fail? */
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
if (!strlen (keytree))
|
||||
keytree = 0;
|
||||
}
|
||||
} else
|
||||
{
|
||||
family = argv;
|
||||
keytree = 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
if (option_verbose > 2)
|
||||
{
|
||||
if (keytree)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: family=%s, keytree=%s\n",
|
||||
family, keytree);
|
||||
else
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: family=%s\n", family);
|
||||
}
|
||||
|
||||
if (ast_db_deltree (family, keytree))
|
||||
{
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBdeltree: Error deleting key from database.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
del_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
int arglen;
|
||||
char *argv, *family, *key;
|
||||
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) /* Why would this fail? */
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
if (strchr (argv, '/'))
|
||||
{
|
||||
family = strsep (&argv, "/");
|
||||
key = strsep (&argv, "\0");
|
||||
if (!family || !key)
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
}
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBdel: family=%s, key=%s\n", family, key);
|
||||
if (ast_db_del (family, key))
|
||||
{
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBdel: Error deleting key from database.\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
put_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
int arglen;
|
||||
char *argv, *value, *family, *key;
|
||||
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) /* Why would this fail? */
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
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");
|
||||
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");
|
||||
if (strchr (argv, '/')) {
|
||||
family = strsep (&argv, "/");
|
||||
keytree = strsep (&argv, "\0");
|
||||
if (!family || !keytree) {
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
}
|
||||
if (!strlen (keytree))
|
||||
keytree = 0;
|
||||
} else {
|
||||
family = argv;
|
||||
keytree = 0;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
get_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
int arglen;
|
||||
char *argv, *varname, *family, *key;
|
||||
char dbresult[256];
|
||||
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) /* Why would this fail? */
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
if (strchr (argv, '=') && strchr (argv, '/'))
|
||||
{
|
||||
varname = strsep (&argv, "=");
|
||||
family = strsep (&argv, "/");
|
||||
key = strsep (&argv, "\0");
|
||||
if (!varname || !family || !key)
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
}
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3
|
||||
"DBget: Value not found in database.\n");
|
||||
/* Send the call to n+101 priority, where n is the current priority */
|
||||
if (ast_exists_extension
|
||||
(chan, chan->context, chan->exten, chan->priority + 101,
|
||||
chan->callerid))
|
||||
chan->priority += 100;
|
||||
if (option_verbose > 2) {
|
||||
if (keytree)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: family=%s, keytree=%s\n", family, keytree);
|
||||
else
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: family=%s\n", family);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
}
|
||||
if (ast_db_deltree (family, keytree)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBdeltree: Error deleting key from database.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
unload_module (void)
|
||||
static int del_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
int retval;
|
||||
int arglen;
|
||||
char *argv, *family, *key;
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
retval = ast_unregister_application (dt_app);
|
||||
retval |= ast_unregister_application (d_app);
|
||||
retval |= ast_unregister_application (p_app);
|
||||
retval |= ast_unregister_application (g_app);
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) { /* Why would this fail? */
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
return retval;
|
||||
if (strchr (argv, '/')) {
|
||||
family = strsep (&argv, "/");
|
||||
key = strsep (&argv, "\0");
|
||||
if (!family || !key) {
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
}
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBdel: family=%s, key=%s\n", family, key);
|
||||
if (ast_db_del (family, key)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBdel: Error deleting key from database.\n");
|
||||
}
|
||||
} else {
|
||||
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
load_module (void)
|
||||
static int put_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
int retval;
|
||||
int arglen;
|
||||
char *argv, *value, *family, *key;
|
||||
|
||||
retval = ast_register_application (g_app, get_exec, g_synopsis, g_descrip);
|
||||
if (!retval)
|
||||
retval =
|
||||
ast_register_application (p_app, put_exec, p_synopsis, p_descrip);
|
||||
if (!retval)
|
||||
retval =
|
||||
ast_register_application (d_app, del_exec, d_synopsis, d_descrip);
|
||||
if (!retval)
|
||||
retval =
|
||||
ast_register_application (dt_app, deltree_exec, dt_synopsis,
|
||||
dt_descrip);
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) { /* Why would this fail? */
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
return retval;
|
||||
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");
|
||||
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");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
description (void)
|
||||
static int get_exec (struct ast_channel *chan, void *data)
|
||||
{
|
||||
return tdesc;
|
||||
int arglen;
|
||||
char *argv, *varname, *family, *key;
|
||||
char dbresult[256];
|
||||
|
||||
arglen = strlen (data);
|
||||
argv = alloca (arglen + 1);
|
||||
if (!argv) { /* Why would this fail? */
|
||||
ast_log (LOG_DEBUG, "Memory allocation failed\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy (argv, data, arglen + 1);
|
||||
|
||||
if (strchr (argv, '=') && strchr (argv, '/')) {
|
||||
varname = strsep (&argv, "=");
|
||||
family = strsep (&argv, "/");
|
||||
key = strsep (&argv, "\0");
|
||||
if (!varname || !family || !key) {
|
||||
ast_log (LOG_DEBUG, "Ignoring; Syntax error in argument\n");
|
||||
return 0;
|
||||
}
|
||||
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);
|
||||
} else {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose (VERBOSE_PREFIX_3 "DBget: Value not found in database.\n");
|
||||
/* Send the call to n+101 priority, where n is the current priority */
|
||||
if (ast_exists_extension (chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
}
|
||||
|
||||
} else {
|
||||
ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
usecount (void)
|
||||
int unload_module (void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT (res);
|
||||
return res;
|
||||
int retval;
|
||||
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
retval = ast_unregister_application (dt_app);
|
||||
retval |= ast_unregister_application (d_app);
|
||||
retval |= ast_unregister_application (p_app);
|
||||
retval |= ast_unregister_application (g_app);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
char *
|
||||
key ()
|
||||
int load_module (void)
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
int retval;
|
||||
|
||||
retval = ast_register_application (g_app, get_exec, g_synopsis, g_descrip);
|
||||
if (!retval)
|
||||
retval = ast_register_application (p_app, put_exec, p_synopsis, p_descrip);
|
||||
if (!retval)
|
||||
retval = ast_register_application (d_app, del_exec, d_synopsis, d_descrip);
|
||||
if (!retval)
|
||||
retval = ast_register_application (dt_app, deltree_exec, dt_synopsis, dt_descrip);
|
||||
return retval;
|
||||
}
|
||||
|
||||
char *description (void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount (void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT (res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key ()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
761
apps/app_dial.c
Executable file → Normal file
761
apps/app_dial.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
223
apps/app_directory.c
Executable file → Normal file
223
apps/app_directory.c
Executable file → Normal file
@@ -19,10 +19,10 @@
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/say.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include "../asterisk.h"
|
||||
#include "../astconf.h"
|
||||
@@ -32,12 +32,15 @@ static char *app = "Directory";
|
||||
|
||||
static char *synopsis = "Provide directory of voicemail extensions";
|
||||
static char *descrip =
|
||||
" Directory(context): Presents the user with a directory of extensions from\n"
|
||||
"which they may select by name. The list of names and extensions is\n"
|
||||
"discovered from voicemail.conf. The context argument is required, and\n"
|
||||
"specifies the context in which to interpret the extensions\n. Returns 0\n"
|
||||
"unless the user hangs up. It also sets up the channel on exit to enter the\n"
|
||||
"extension the user selected.\n";
|
||||
" Directory(vm-context[|dial-context[|options]]): Presents the user with a directory\n"
|
||||
"of extensions from which they may select by name. The list of names \n"
|
||||
"and extensions is discovered from voicemail.conf. The vm-context argument\n"
|
||||
"is required, and specifies the context of voicemail.conf to use. The\n"
|
||||
"dial-context is the context to use for dialing the users, and defaults to\n"
|
||||
"the vm-context if unspecified. The 'f' option causes the directory to match\n"
|
||||
"based on the first name in voicemail.conf instead of the last name.\n"
|
||||
"Returns 0 unless the user hangs up. It also sets up the channel on exit\n"
|
||||
"to enter the extension the user selected.\n";
|
||||
|
||||
/* For simplicity, I'm keeping the format compatible with the voicemail config,
|
||||
but i'm open to suggestions for isolating it */
|
||||
@@ -112,7 +115,6 @@ static char *convert(char *lastname)
|
||||
case 'Z':
|
||||
tmp[lcount++] = '9';
|
||||
break;
|
||||
default:
|
||||
}
|
||||
lastname++;
|
||||
}
|
||||
@@ -121,17 +123,108 @@ static char *convert(char *lastname)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *context, char digit)
|
||||
/* play name of mailbox owner.
|
||||
* returns: -1 for bad or missing extension
|
||||
* '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 res = 0;
|
||||
int loop = 3;
|
||||
char fn[256];
|
||||
char fn2[256];
|
||||
|
||||
/* Check for the VoiceMail2 greeting first */
|
||||
snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet",
|
||||
(char *)ast_config_AST_SPOOL_DIR, context, ext);
|
||||
|
||||
/* Otherwise, check for an old-style Voicemail greeting */
|
||||
snprintf(fn2, sizeof(fn2), "%s/vm/%s/greet",
|
||||
(char *)ast_config_AST_SPOOL_DIR, ext);
|
||||
|
||||
if (ast_fileexists(fn, NULL, chan->language) > 0) {
|
||||
res = ast_streamfile(chan, fn, chan->language);
|
||||
if (!res) {
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
}
|
||||
ast_stopstream(chan);
|
||||
} 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, !ast_strlen_zero(name) ? name : ext,
|
||||
AST_DIGIT_ANY, chan->language);
|
||||
}
|
||||
|
||||
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 > -1) {
|
||||
switch (res) {
|
||||
case '1':
|
||||
/* Name selected */
|
||||
loop = 0;
|
||||
if (ast_exists_extension(chan,dialcontext,ext,1,chan->callerid)) {
|
||||
strncpy(chan->exten, ext, sizeof(chan->exten)-1);
|
||||
chan->priority = 0;
|
||||
strncpy(chan->context, dialcontext, sizeof(chan->context)-1);
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
} /* end while */
|
||||
|
||||
return(res);
|
||||
}
|
||||
|
||||
static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *context, char *dialcontext, char digit, int last)
|
||||
{
|
||||
/* Read in the first three digits.. "digit" is the first digit, already read */
|
||||
char ext[NUMDIGITS + 1];
|
||||
char name[80] = "";
|
||||
struct ast_variable *v;
|
||||
int res;
|
||||
int found=0;
|
||||
int lastuserchoice = 0;
|
||||
char *start, *pos, *conv,*stringp=NULL;
|
||||
char fn[256];
|
||||
if (!context || !strlen(context)) {
|
||||
ast_log(LOG_WARNING, "Directory must be called with an argument (context in which to interpret extensions)\n");
|
||||
|
||||
if (!context || ast_strlen_zero(context)) {
|
||||
ast_log(LOG_WARNING,
|
||||
"Directory must be called with an argument "
|
||||
"(context in which to interpret extensions)\n");
|
||||
return -1;
|
||||
}
|
||||
memset(ext, 0, sizeof(ext));
|
||||
@@ -151,8 +244,9 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
|
||||
strsep(&stringp, ",");
|
||||
pos = strsep(&stringp, ",");
|
||||
if (pos) {
|
||||
strncpy(name, pos, sizeof(name) - 1);
|
||||
/* Grab the last name */
|
||||
if (strrchr(pos, ' '))
|
||||
if (last && strrchr(pos,' '))
|
||||
pos = strrchr(pos, ' ') + 1;
|
||||
conv = convert(pos);
|
||||
if (conv) {
|
||||
@@ -170,51 +264,46 @@ static int do_directory(struct ast_channel *chan, struct ast_config *cfg, char *
|
||||
}
|
||||
v = v->next;
|
||||
}
|
||||
|
||||
if (v) {
|
||||
/* We have a match -- play a greeting if they have it */
|
||||
snprintf(fn, sizeof(fn), "%s/vm/%s/greet", (char *)ast_config_AST_SPOOL_DIR, v->name);
|
||||
if (ast_fileexists(fn, NULL, chan->language) > 0) {
|
||||
res = ast_streamfile(chan, fn, chan->language);
|
||||
if (!res)
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
} else {
|
||||
res = ast_say_digit_str(chan, v->name, AST_DIGIT_ANY, chan->language);
|
||||
}
|
||||
ahem:
|
||||
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 > -1) {
|
||||
if (res == '1') {
|
||||
strncpy(chan->exten, v->name, sizeof(chan->exten)-1);
|
||||
res = play_mailbox_owner(chan, context, dialcontext, v->name, name);
|
||||
switch (res) {
|
||||
case -1:
|
||||
/* user pressed '1' but extension does not exist, or
|
||||
* user hungup
|
||||
*/
|
||||
lastuserchoice = 0;
|
||||
break;
|
||||
case '1':
|
||||
/* user pressed '1' and extensions exists */
|
||||
lastuserchoice = res;
|
||||
strncpy(chan->context, dialcontext, sizeof(chan->context) - 1);
|
||||
strncpy(chan->exten, v->name, sizeof(chan->exten) - 1);
|
||||
chan->priority = 0;
|
||||
strncpy(chan->context, context, sizeof(chan->context)-1);
|
||||
break;
|
||||
case '*':
|
||||
/* user pressed '*' to skip something found */
|
||||
lastuserchoice = res;
|
||||
res = 0;
|
||||
break;
|
||||
} else if (res == '*') {
|
||||
res = 0;
|
||||
v = v->next;
|
||||
} else {
|
||||
res = 0;
|
||||
goto ahem;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
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;
|
||||
v = v->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (lastuserchoice != '1') {
|
||||
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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -224,8 +313,11 @@ static int directory_exec(struct ast_channel *chan, void *data)
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
struct ast_config *cfg;
|
||||
int last = 1;
|
||||
char *context, *dialcontext, *dirintro, *options;
|
||||
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "directory requires an argument (context)\n");
|
||||
ast_log(LOG_WARNING, "directory requires an argument (context[,dialcontext])\n");
|
||||
return -1;
|
||||
}
|
||||
cfg = ast_load(DIRECTORY_CONFIG);
|
||||
@@ -235,15 +327,40 @@ static int directory_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
top:
|
||||
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;
|
||||
}
|
||||
} else
|
||||
dialcontext = context;
|
||||
dirintro = ast_variable_retrieve(cfg, context, "directoryintro");
|
||||
if (!dirintro || ast_strlen_zero(dirintro))
|
||||
dirintro = ast_variable_retrieve(cfg, "general", "directoryintro");
|
||||
if (!dirintro || ast_strlen_zero(dirintro)) {
|
||||
if (last)
|
||||
dirintro = "dir-intro";
|
||||
else
|
||||
dirintro = "dir-intro-fn";
|
||||
}
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
res = ast_answer(chan);
|
||||
if (!res)
|
||||
res = ast_streamfile(chan, "dir-intro", chan->language);
|
||||
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, (char *)data, res);
|
||||
res = do_directory(chan, cfg, context, dialcontext, res, last);
|
||||
if (res > 0) {
|
||||
res = ast_waitstream(chan, AST_DIGIT_ANY);
|
||||
ast_stopstream(chan);
|
||||
|
||||
208
apps/app_disa.c
Executable file → Normal file
208
apps/app_disa.c
Executable file → Normal file
@@ -7,6 +7,8 @@
|
||||
*
|
||||
* Jim Dixon <jim@lambdatel.com>
|
||||
*
|
||||
* Made only slightly more sane by Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
@@ -15,20 +17,18 @@
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/indications.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/ulaw.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
/*
|
||||
#define TONE_BLOCK_SIZE 320
|
||||
*/
|
||||
|
||||
static char *tdesc = "DISA (Direct Inward System Access) Application";
|
||||
|
||||
@@ -81,26 +81,8 @@ STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static float loudness=4096.0;
|
||||
|
||||
int firstdigittimeout = 20000; /* 20 seconds first digit timeout */
|
||||
int digittimeout = 10000; /* 10 seconds subsequent digit timeout */
|
||||
|
||||
static void make_tone_block(unsigned char *data, float f1, float f2, int len, int *x)
|
||||
{
|
||||
int i;
|
||||
float val;
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
val = loudness * sin((f1 * 2.0 * M_PI * (*x))/8000.0);
|
||||
val += loudness * sin((f2 * 2.0 * M_PI * (*x)++)/8000.0);
|
||||
data[i] = AST_LIN2MU((int)val);
|
||||
}
|
||||
/* wrap back around from 8000 */
|
||||
if (*x >= 8000) *x = 0;
|
||||
return;
|
||||
}
|
||||
static int firstdigittimeout = 20000; /* 20 seconds first digit timeout */
|
||||
static int digittimeout = 10000; /* 10 seconds subsequent digit timeout */
|
||||
|
||||
static int ms_diff(struct timeval *tv1, struct timeval *tv2)
|
||||
{
|
||||
@@ -111,16 +93,26 @@ int ms;
|
||||
return(ms);
|
||||
}
|
||||
|
||||
static void play_dialtone(struct ast_channel *chan)
|
||||
{
|
||||
const struct tone_zone_sound *ts = NULL;
|
||||
ts = ast_get_indication_tone(chan->zone, "dial");
|
||||
if (ts)
|
||||
ast_playtones_start(chan, 0, ts->data, 0);
|
||||
else
|
||||
ast_tonepair_start(chan, 350, 440, 0, 0);
|
||||
}
|
||||
|
||||
static int disa_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int i,j,k,x;
|
||||
int i,j,k,x,did_ignore;
|
||||
struct localuser *u;
|
||||
char tmp[256],arg2[256],exten[AST_MAX_EXTENSION],acctcode[20];
|
||||
unsigned char tone_block[640];
|
||||
char tmp[256],arg2[256]="",exten[AST_MAX_EXTENSION],acctcode[20]="";
|
||||
char *ourcontext,*ourcallerid;
|
||||
struct ast_frame *f,wf;
|
||||
struct ast_frame *f;
|
||||
struct timeval lastout, now, lastdigittime;
|
||||
int res;
|
||||
time_t rstart;
|
||||
FILE *fp;
|
||||
char *stringp=NULL;
|
||||
|
||||
@@ -145,7 +137,7 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
ourcontext = strsep(&stringp, "|");
|
||||
/* if context specified, save 2nd arg and parse third */
|
||||
if (ourcontext) {
|
||||
strcpy(arg2,ourcontext);
|
||||
strncpy(arg2,ourcontext, sizeof(arg2) - 1);
|
||||
ourcallerid = strsep(&stringp,"|");
|
||||
}
|
||||
/* if context not specified, use "disa" */
|
||||
@@ -161,25 +153,32 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
ast_answer(chan);
|
||||
}
|
||||
i = k = x = 0; /* k is 0 for pswd entry, 1 for ext entry */
|
||||
did_ignore = 0;
|
||||
exten[0] = 0;
|
||||
acctcode[0] = 0;
|
||||
/* can we access DISA without password? */
|
||||
|
||||
ast_log(LOG_DEBUG, "Context: %s\n",ourcontext);
|
||||
|
||||
if (!strcasecmp(tmp, "no-password"))
|
||||
{
|
||||
k = 1;
|
||||
{;
|
||||
k |= 1; /* We have the password */
|
||||
ast_log(LOG_DEBUG, "DISA no-password login success\n");
|
||||
}
|
||||
gettimeofday(&lastdigittime,NULL);
|
||||
|
||||
play_dialtone(chan);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
gettimeofday(&now,NULL);
|
||||
/* if outa time, give em reorder */
|
||||
if (ms_diff(&now,&lastdigittime) >
|
||||
((k) ? digittimeout : firstdigittimeout))
|
||||
((k&2) ? digittimeout : firstdigittimeout))
|
||||
{
|
||||
ast_log(LOG_DEBUG,"DISA %s entry timeout on chan %s\n",
|
||||
((k) ? "extension" : "password"),chan->name);
|
||||
goto reorder;
|
||||
((k&1) ? "extension" : "password"),chan->name);
|
||||
break;
|
||||
}
|
||||
if ((res = ast_waitfor(chan, -1) < 0)) {
|
||||
ast_log(LOG_DEBUG, "Waitfor returned %d\n", res);
|
||||
@@ -200,24 +199,7 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
return -1;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
if (!i || (ast_ignore_pattern(ourcontext, exten) && k)) {
|
||||
wf.frametype = AST_FRAME_VOICE;
|
||||
wf.subclass = AST_FORMAT_ULAW;
|
||||
wf.offset = AST_FRIENDLY_OFFSET;
|
||||
wf.mallocd = 0;
|
||||
wf.data = tone_block;
|
||||
wf.datalen = f->datalen;
|
||||
make_tone_block(tone_block, 350, 440, f->datalen, &x);
|
||||
wf.samples = wf.datalen;
|
||||
ast_frfree(f);
|
||||
if (ast_write(chan, &wf))
|
||||
{
|
||||
ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
ast_frfree(f);
|
||||
ast_frfree(f);
|
||||
continue;
|
||||
}
|
||||
/* if not DTMF, just do it again */
|
||||
@@ -229,12 +211,16 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
j = f->subclass; /* save digit */
|
||||
ast_frfree(f);
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
k|=2; /* We have the first digit */
|
||||
ast_playtones_stop(chan);
|
||||
}
|
||||
gettimeofday(&lastdigittime,NULL);
|
||||
/* got a DTMF tone */
|
||||
if (i < AST_MAX_EXTENSION) /* if still valid number of digits */
|
||||
{
|
||||
if (!k) /* if in password state */
|
||||
if (!(k&1)) /* if in password state */
|
||||
{
|
||||
if (j == '#') /* end of password */
|
||||
{
|
||||
@@ -282,80 +268,76 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
}
|
||||
/* password good, set to dial state */
|
||||
ast_log(LOG_WARNING,"DISA on chan %s password is good\n",chan->name);
|
||||
k = 1;
|
||||
ast_log(LOG_DEBUG,"DISA on chan %s password is good\n",chan->name);
|
||||
play_dialtone(chan);
|
||||
|
||||
k|=1; /* In number mode */
|
||||
i = 0; /* re-set buffer pointer */
|
||||
exten[sizeof(acctcode)] = 0;
|
||||
strcpy(acctcode,exten);
|
||||
strncpy(acctcode,exten, sizeof(acctcode) - 1);
|
||||
exten[0] = 0;
|
||||
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) continue; /* if getting password, continue doing it */
|
||||
if (!(k&1)) continue; /* if getting password, continue doing it */
|
||||
/* if this exists */
|
||||
if (ast_exists_extension(chan,ourcontext,exten,1, chan->callerid))
|
||||
{
|
||||
if (ourcallerid && *ourcallerid)
|
||||
{
|
||||
if (chan->callerid) free(chan->callerid);
|
||||
chan->callerid = strdup(ourcallerid);
|
||||
|
||||
if (ast_ignore_pattern(ourcontext, exten)) {
|
||||
play_dialtone(chan);
|
||||
did_ignore = 1;
|
||||
} else
|
||||
if (did_ignore) {
|
||||
ast_playtones_stop(chan);
|
||||
did_ignore = 0;
|
||||
}
|
||||
strcpy(chan->exten,exten);
|
||||
strcpy(chan->context,ourcontext);
|
||||
strcpy(chan->accountcode,acctcode);
|
||||
chan->priority = 0;
|
||||
ast_cdr_init(chan->cdr,chan);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if can do some more, do it */
|
||||
if (ast_canmatch_extension(chan,ourcontext,exten,1, chan->callerid)) continue;
|
||||
}
|
||||
reorder:
|
||||
|
||||
/* something is invalid, give em reorder forever */
|
||||
x = 0;
|
||||
k = 0; /* k = 0 means busy tone, k = 1 means silence) */
|
||||
i = 0; /* Number of samples we've done */
|
||||
for(;;)
|
||||
{
|
||||
if (ast_waitfor(chan, -1) < 0)
|
||||
if (!ast_matchmore_extension(chan,ourcontext,exten,1, chan->callerid)) {
|
||||
break;
|
||||
f = ast_read(chan);
|
||||
if (!f)
|
||||
break;
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
wf.frametype = AST_FRAME_VOICE;
|
||||
wf.subclass = AST_FORMAT_ULAW;
|
||||
wf.offset = AST_FRIENDLY_OFFSET;
|
||||
wf.mallocd = 0;
|
||||
wf.data = tone_block;
|
||||
wf.datalen = f->datalen;
|
||||
wf.samples = wf.datalen;
|
||||
if (k)
|
||||
memset(tone_block, 0x7f, wf.datalen);
|
||||
else
|
||||
make_tone_block(tone_block,480.0, 620.0,wf.datalen, &x);
|
||||
i += wf.datalen / 8;
|
||||
if (i > 250) {
|
||||
i = 0;
|
||||
k = !k;
|
||||
}
|
||||
if (ast_write(chan, &wf))
|
||||
{
|
||||
ast_log(LOG_WARNING, "DISA Failed to write frame on %s\n",chan->name);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((k==3) && (ast_exists_extension(chan,ourcontext,exten,1, chan->callerid)))
|
||||
{
|
||||
ast_playtones_stop(chan);
|
||||
/* We're authenticated and have a valid extension */
|
||||
if (ourcallerid && *ourcallerid)
|
||||
{
|
||||
if (chan->callerid) free(chan->callerid);
|
||||
chan->callerid = strdup(ourcallerid);
|
||||
}
|
||||
strncpy(chan->exten, exten, sizeof(chan->exten) - 1);
|
||||
strncpy(chan->context, ourcontext, sizeof(chan->context) - 1);
|
||||
if (!ast_strlen_zero(acctcode))
|
||||
strncpy(chan->accountcode, acctcode, sizeof(chan->accountcode) - 1);
|
||||
chan->priority = 0;
|
||||
ast_cdr_init(chan->cdr,chan);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
reorder:
|
||||
|
||||
ast_indicate(chan,AST_CONTROL_CONGESTION);
|
||||
/* something is invalid, give em reorder for several seconds */
|
||||
time(&rstart);
|
||||
while(time(NULL) < rstart + 10)
|
||||
{
|
||||
if (ast_waitfor(chan, -1) < 0)
|
||||
break;
|
||||
f = ast_read(chan);
|
||||
if (!f)
|
||||
break;
|
||||
ast_frfree(f);
|
||||
}
|
||||
ast_playtones_stop(chan);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
@@ -381,7 +363,7 @@ int usecount(void)
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
char *key(void)
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
8
apps/app_echo.c
Executable file → Normal file
8
apps/app_echo.c
Executable file → Normal file
@@ -22,9 +22,6 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Simple Echo Application";
|
||||
|
||||
static char *app = "Echo";
|
||||
@@ -52,9 +49,14 @@ static int echo_exec(struct ast_channel *chan, void *data)
|
||||
f = ast_read(chan);
|
||||
if (!f)
|
||||
break;
|
||||
f->delivery.tv_sec = 0;
|
||||
f->delivery.tv_usec = 0;
|
||||
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;
|
||||
|
||||
203
apps/app_enumlookup.c
Normal file
203
apps/app_enumlookup.c
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Time of day - Report the time of day
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#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 <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static char *tdesc = "ENUM Lookup";
|
||||
|
||||
static char *app = "EnumLookup";
|
||||
|
||||
static char *synopsis = "Lookup number in ENUM";
|
||||
|
||||
static char *descrip =
|
||||
" EnumLookup(exten): 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"
|
||||
"Returns -1 on hangup, or 0 on completion regardless of whether the \n"
|
||||
"lookup was successful. \n"
|
||||
"Currently, the enumservices SIP, H323, IAX, IAX2 and TEL are recognized. \n"
|
||||
"A good SIP, H323, IAX or IAX2 entry will result in normal priority handling, \n"
|
||||
"whereas a good TEL entry will increase the priority by 51 (if existing).\n"
|
||||
"If the lookup was *not* successful and there exists a priority n + 101,\n"
|
||||
"then that priority will be taken next.\n" ;
|
||||
|
||||
#define ENUM_CONFIG "enum.conf"
|
||||
|
||||
static char h323driver[80] = "";
|
||||
#define H323DRIVERDEFAULT "H323"
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int enumlookup_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
char tech[80];
|
||||
char dest[80];
|
||||
char tmp[256];
|
||||
char *c,*t;
|
||||
struct localuser *u;
|
||||
if (!data || ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "EnumLookup requires an argument (extension)\n");
|
||||
res = 1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
if (!res) {
|
||||
res = ast_get_enum(chan, data, dest, sizeof(dest), tech, sizeof(tech));
|
||||
printf("ENUM got '%d'\n", res);
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
/* 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 (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 51, chan->callerid))
|
||||
chan->priority += 50;
|
||||
else
|
||||
res = 0;
|
||||
}
|
||||
} else if (!ast_strlen_zero(tech)) {
|
||||
ast_log(LOG_NOTICE, "Don't know how to handle technology '%s'\n", tech);
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
if (!res) {
|
||||
/* Look for a "busy" place */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
} else if (res > 0)
|
||||
res = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_config(void)
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
char *s;
|
||||
|
||||
cfg = ast_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_destroy(cfg);
|
||||
return 0;
|
||||
}
|
||||
ast_log(LOG_NOTICE, "No ENUM Config file, using defaults\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
res = ast_register_application(app, enumlookup_exec, synopsis, descrip);
|
||||
if (res)
|
||||
return(res);
|
||||
if ((res=load_config())) {
|
||||
return(res);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int reload(void)
|
||||
{
|
||||
return(load_config());
|
||||
}
|
||||
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
101
apps/app_eval.c
Normal file
101
apps/app_eval.c
Normal file
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Eval application
|
||||
*
|
||||
* Copyright (c) 2004 Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <app_eval__v001@the-tilghman.com>
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This code is released by the author with no restrictions on usage.
|
||||
*
|
||||
*/
|
||||
|
||||
#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>
|
||||
|
||||
/* 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];
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app_eval);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
113
apps/app_exec.c
Normal file
113
apps/app_exec.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Exec application
|
||||
*
|
||||
* Copyright (c) 2004 Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <app_exec__v001@the-tilghman.com>
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* This code is released by the author with no restrictions on usage.
|
||||
*
|
||||
*/
|
||||
|
||||
#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>
|
||||
|
||||
/* Maximum length of any variable */
|
||||
#define MAXRESULT 1024
|
||||
|
||||
static char *tdesc = "Executes applications";
|
||||
|
||||
static char *app_exec = "Exec";
|
||||
|
||||
static char *exec_synopsis = "Exec(Appname(arguments))";
|
||||
|
||||
static char *exec_descrip =
|
||||
"Exec(appname(arguments))\n"
|
||||
" Allows an arbitrary application to be invoked even when not\n"
|
||||
"hardcoded into the dialplan. Returns whatever value the\n"
|
||||
"app returns or -2 when the app cannot be found.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int exec_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *s, *appname, *endargs, args[MAXRESULT];
|
||||
struct ast_app *app;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
memset(args, 0, MAXRESULT);
|
||||
|
||||
/* Check and parse arguments */
|
||||
if (data) {
|
||||
s = ast_strdupa((char *)data);
|
||||
if (s) {
|
||||
appname = strsep(&s, "(");
|
||||
if (s) {
|
||||
endargs = strrchr(s, ')');
|
||||
if (endargs)
|
||||
*endargs = '\0';
|
||||
pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
|
||||
}
|
||||
if (appname) {
|
||||
app = pbx_findapp(appname);
|
||||
if (app) {
|
||||
res = pbx_exec(chan, app, args, 1);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
|
||||
res = -2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app_exec);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
190
apps/app_festival.c
Executable file → Normal file
190
apps/app_festival.c
Executable file → Normal file
@@ -5,12 +5,13 @@
|
||||
*
|
||||
* Copyright (C) 2002, Christos Ricudis
|
||||
*
|
||||
* Christos Ricudis <ricudis@paiko.gr>
|
||||
* Christos Ricudis <ricudis@itc.auth.gr>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
@@ -18,6 +19,8 @@
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/md5.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
@@ -33,7 +36,6 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
#define FESTIVAL_CONFIG "festival.conf"
|
||||
@@ -45,8 +47,9 @@ static char *app = "Festival";
|
||||
static char *synopsis = "Say text to the user";
|
||||
|
||||
static char *descrip =
|
||||
" Festival(): Connect to Festival, send the argument, get back the waveform,"
|
||||
"play it to the user.\n";
|
||||
" Festival(text[|intkeys]): Connect to Festival, send the argument, get back the waveform,"
|
||||
"play it to the user, allowing any given interrupt keys to immediately terminate and return\n"
|
||||
"the value, or 'any' to allow any number back (useful in dialplan)\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -104,6 +107,10 @@ static int send_waveform_to_fd(char *waveform, int length, int fd) {
|
||||
|
||||
int res;
|
||||
int x;
|
||||
#ifdef __PPC__
|
||||
char c;
|
||||
#endif
|
||||
|
||||
res = fork();
|
||||
if (res < 0)
|
||||
ast_log(LOG_WARNING, "Fork failed\n");
|
||||
@@ -113,39 +120,44 @@ static int send_waveform_to_fd(char *waveform, int length, int fd) {
|
||||
if (x != fd)
|
||||
close(x);
|
||||
}
|
||||
//IAS
|
||||
#ifdef __PPC__
|
||||
for( x=0; x<length; x+=2)
|
||||
{
|
||||
c = *(waveform+x+1);
|
||||
*(waveform+x+1)=*(waveform+x);
|
||||
*(waveform+x)=c;
|
||||
}
|
||||
#endif
|
||||
|
||||
write(fd,waveform,length);
|
||||
write(fd,"a",1);
|
||||
close(fd);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, int length) {
|
||||
static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, int length, char *intkeys) {
|
||||
int res=0;
|
||||
int fds[2];
|
||||
int rfds[1 + AST_MAX_FDS];
|
||||
int ms = -1;
|
||||
int pid = -1;
|
||||
int us;
|
||||
int exception;
|
||||
int needed = 0;
|
||||
int owriteformat;
|
||||
struct timeval tv;
|
||||
struct timeval last;
|
||||
struct ast_frame *f;
|
||||
int x;
|
||||
struct myframe {
|
||||
struct ast_frame f;
|
||||
char offset[AST_FRIENDLY_OFFSET];
|
||||
char frdata[160];
|
||||
char frdata[2048];
|
||||
} myf;
|
||||
last.tv_usec = 0;
|
||||
last.tv_sec = 0;
|
||||
|
||||
if (pipe(fds)) {
|
||||
ast_log(LOG_WARNING, "Unable to create pipe\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Answer if it's not already going */
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
ast_answer(chan);
|
||||
ast_stopstream(chan);
|
||||
|
||||
owriteformat = chan->writeformat;
|
||||
@@ -160,53 +172,36 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
|
||||
pid = res;
|
||||
/* Order is important -- there's almost always going to be mp3... we want to prioritize the
|
||||
user */
|
||||
rfds[AST_MAX_FDS] = fds[0];
|
||||
for (;;) {
|
||||
CHECK_BLOCKING(chan);
|
||||
for (x=0;x<AST_MAX_FDS;x++)
|
||||
rfds[x] = chan->fds[x];
|
||||
res = ast_waitfor_n_fd(rfds, AST_MAX_FDS+1, &ms, &exception);
|
||||
chan->blocking = 0;
|
||||
ms = 1000;
|
||||
res = ast_waitfor(chan, ms);
|
||||
if (res < 1) {
|
||||
ast_log(LOG_DEBUG, "Hangup detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
for(x=0;x<AST_MAX_FDS;x++)
|
||||
if (res == chan->fds[x])
|
||||
break;
|
||||
|
||||
if (x < AST_MAX_FDS) {
|
||||
if (exception)
|
||||
chan->exception = 1;
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_DTMF) {
|
||||
ast_log(LOG_DEBUG, "User pressed a key\n");
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
ast_log(LOG_WARNING, "Null frame == hangup() detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_DTMF) {
|
||||
ast_log(LOG_DEBUG, "User pressed a key\n");
|
||||
if (intkeys && strchr(intkeys, f->subclass)) {
|
||||
res = f->subclass;
|
||||
ast_frfree(f);
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
} else if (res == fds[0]) {
|
||||
gettimeofday(&tv, NULL);
|
||||
if (last.tv_sec || last.tv_usec) {
|
||||
/* We should wait at least a frame length */
|
||||
us = sizeof(myf.frdata) / 16 * 1000;
|
||||
/* Subtract 1,000,000 us for each second late we've passed */
|
||||
us -= (tv.tv_sec - last.tv_sec) * 1000000;
|
||||
/* And one for each us late we've passed */
|
||||
us -= (tv.tv_usec - last.tv_usec);
|
||||
/* Sleep that long if needed */
|
||||
if (us > 0)
|
||||
usleep(us);
|
||||
}
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
/* Treat as a generator */
|
||||
needed = f->samples * 2;
|
||||
if (needed > sizeof(myf.frdata)) {
|
||||
ast_log(LOG_WARNING, "Only able to deliver %d of %d requested samples\n",
|
||||
(int)sizeof(myf.frdata) / 2, needed/2);
|
||||
needed = sizeof(myf.frdata);
|
||||
}
|
||||
last = tv;
|
||||
res = read(fds[0], myf.frdata, sizeof(myf.frdata));
|
||||
res = read(fds[0], myf.frdata, needed);
|
||||
if (res > 0) {
|
||||
myf.f.frametype = AST_FRAME_VOICE;
|
||||
myf.f.subclass = AST_FORMAT_SLINEAR;
|
||||
@@ -220,20 +215,17 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (res < sizeof(myf.frdata)) { // last frame
|
||||
ast_log(LOG_WARNING, "Last frame\n");
|
||||
if (res < needed) { // last frame
|
||||
ast_log(LOG_DEBUG, "Last frame\n");
|
||||
res=0;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "No more waveform\n");
|
||||
ast_log(LOG_DEBUG, "No more waveform\n");
|
||||
res = 0;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_DEBUG, "HuhHHH?\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
close(fds[0]);
|
||||
@@ -251,13 +243,14 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
|
||||
|
||||
|
||||
|
||||
static int festival_exec(struct ast_channel *chan, void *data)
|
||||
static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
{
|
||||
int usecache;
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
struct sockaddr_in serv_addr;
|
||||
struct hostent *serverhost;
|
||||
struct ast_hostent ahp;
|
||||
int fd;
|
||||
FILE *fs;
|
||||
char *host;
|
||||
@@ -274,15 +267,17 @@ static int festival_exec(struct ast_channel *chan, void *data)
|
||||
int i;
|
||||
struct MD5Context md5ctx;
|
||||
unsigned char MD5Res[16];
|
||||
char MD5Hex[32];
|
||||
char koko[4];
|
||||
char cachefile[MAXFESTLEN];
|
||||
char MD5Hex[33] = "";
|
||||
char koko[4] = "";
|
||||
char cachefile[MAXFESTLEN]="";
|
||||
int readcache=0;
|
||||
int writecache=0;
|
||||
int strln;
|
||||
int fdesc;
|
||||
int fdesc = -1;
|
||||
char buffer[16384];
|
||||
int seekpos;
|
||||
int seekpos = 0;
|
||||
char data[256] = "";
|
||||
char *intstr;
|
||||
|
||||
struct ast_config *cfg;
|
||||
cfg = ast_load(FESTIVAL_CONFIG);
|
||||
@@ -301,9 +296,7 @@ static int festival_exec(struct ast_channel *chan, void *data)
|
||||
if (!(temp = ast_variable_retrieve(cfg, "general", "usecache"))) {
|
||||
usecache=0;
|
||||
} else {
|
||||
if (strcasecmp(temp,"yes")==0) {
|
||||
usecache=1;
|
||||
}
|
||||
usecache = ast_true(temp);
|
||||
}
|
||||
if (!(cachedir = ast_variable_retrieve(cfg, "general", "cachedir"))) {
|
||||
cachedir = "/tmp/";
|
||||
@@ -311,29 +304,36 @@ static int festival_exec(struct ast_channel *chan, void *data)
|
||||
if (!(festivalcommand = ast_variable_retrieve(cfg, "general", "festivalcommand"))) {
|
||||
festivalcommand = "(tts_textasterisk \"%s\" 'file)(quit)\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!data) {
|
||||
if (!vdata || ast_strlen_zero(vdata)) {
|
||||
ast_log(LOG_WARNING, "festival requires an argument (text)\n");
|
||||
ast_destroy(cfg);
|
||||
return -1;
|
||||
}
|
||||
strncpy(data, vdata, sizeof(data) - 1);
|
||||
if ((intstr = strchr(data, '|'))) {
|
||||
*intstr = '\0';
|
||||
intstr++;
|
||||
if (!strcasecmp(intstr, "any"))
|
||||
intstr = AST_DIGIT_ANY;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
ast_log(LOG_WARNING, "Text passed to festival server : %s\n",(char *)data);
|
||||
ast_log(LOG_DEBUG, "Text passed to festival server : %s\n",(char *)data);
|
||||
/* Connect to local festival server */
|
||||
|
||||
fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
|
||||
if (fd < 0) {
|
||||
ast_log(LOG_WARNING,"festival_client: can't get socket\n");
|
||||
ast_destroy(cfg);
|
||||
return -1;
|
||||
}
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
if ((serv_addr.sin_addr.s_addr = inet_addr(host)) == -1) {
|
||||
/* its a name rather than an ipnum */
|
||||
serverhost = gethostbyname(host);
|
||||
serverhost = ast_gethostbyname(host, &ahp);
|
||||
if (serverhost == (struct hostent *)0) {
|
||||
ast_log(LOG_WARNING,"festival_client: gethostbyname failed\n");
|
||||
ast_destroy(cfg);
|
||||
return -1;
|
||||
}
|
||||
memmove(&serv_addr.sin_addr,serverhost->h_addr, serverhost->h_length);
|
||||
@@ -343,6 +343,7 @@ static int festival_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
|
||||
ast_log(LOG_WARNING,"festival_client: connect to server failed\n");
|
||||
ast_destroy(cfg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -350,37 +351,38 @@ static int festival_exec(struct ast_channel *chan, void *data)
|
||||
MD5Init(&md5ctx);
|
||||
MD5Update(&md5ctx,(unsigned char const *)data,strlen(data));
|
||||
MD5Final(MD5Res,&md5ctx);
|
||||
strcpy(MD5Hex,"");
|
||||
MD5Hex[0] = '\0';
|
||||
|
||||
/* Convert to HEX and look if there is any matching file in the cache
|
||||
directory */
|
||||
for (i=0;i<16;i++) {
|
||||
sprintf(koko,"%X",MD5Res[i]);
|
||||
strcat(MD5Hex,koko);
|
||||
snprintf(koko, sizeof(koko), "%X",MD5Res[i]);
|
||||
strncat(MD5Hex, koko, sizeof(MD5Hex) - strlen(MD5Hex) - 1);
|
||||
}
|
||||
readcache=0;
|
||||
writecache=0;
|
||||
if (strlen(cachedir)+strlen(MD5Hex)+1<=MAXFESTLEN && (usecache==1)) {
|
||||
sprintf(cachefile,"%s/%s",cachedir,MD5Hex);
|
||||
if (strlen(cachedir)+strlen(MD5Hex)+1<=MAXFESTLEN && (usecache==-1)) {
|
||||
snprintf(cachefile, sizeof(cachefile), "%s/%s", cachedir, MD5Hex);
|
||||
fdesc=open(cachefile,O_RDWR);
|
||||
if (fdesc==-1) {
|
||||
fdesc=open(cachefile,O_CREAT|O_RDWR,0);
|
||||
fdesc=open(cachefile,O_CREAT|O_RDWR,0777);
|
||||
if (fdesc!=-1) {
|
||||
writecache=1;
|
||||
strln=strlen((char *)data);
|
||||
ast_log(LOG_WARNING,"line length : %d\n",strln);
|
||||
ast_log(LOG_DEBUG,"line length : %d\n",strln);
|
||||
write(fdesc,&strln,sizeof(int));
|
||||
write(fdesc,data,strln);
|
||||
seekpos=lseek(fdesc,0,SEEK_CUR);
|
||||
ast_log(LOG_WARNING,"Seek position : %d\n",seekpos);
|
||||
ast_log(LOG_DEBUG,"Seek position : %d\n",seekpos);
|
||||
}
|
||||
} else {
|
||||
read(fdesc,&strln,sizeof(int));
|
||||
ast_log(LOG_WARNING,"Cache file exists, strln=%d, strlen=%d\n",strln,strlen((char *)data));
|
||||
ast_log(LOG_DEBUG,"Cache file exists, strln=%d, strlen=%d\n",strln,(int)strlen((char *)data));
|
||||
if (strlen((char *)data)==strln) {
|
||||
ast_log(LOG_WARNING,"Size OK\n");
|
||||
ast_log(LOG_DEBUG,"Size OK\n");
|
||||
read(fdesc,&bigstring,strln);
|
||||
if (strcmp(bigstring,data)==0) {
|
||||
bigstring[strln] = 0;
|
||||
if (strcmp(bigstring,data)==0) {
|
||||
readcache=1;
|
||||
} else {
|
||||
ast_log(LOG_WARNING,"Strings do not match\n");
|
||||
@@ -394,9 +396,9 @@ static int festival_exec(struct ast_channel *chan, void *data)
|
||||
if (readcache==1) {
|
||||
close(fd);
|
||||
fd=fdesc;
|
||||
ast_log(LOG_WARNING,"Reading from cache...\n");
|
||||
ast_log(LOG_DEBUG,"Reading from cache...\n");
|
||||
} else {
|
||||
ast_log(LOG_WARNING,"Passing text to festival...\n");
|
||||
ast_log(LOG_DEBUG,"Passing text to festival...\n");
|
||||
fs=fdopen(dup(fd),"wb");
|
||||
fprintf(fs,festivalcommand,(char *)data);
|
||||
fflush(fs);
|
||||
@@ -405,7 +407,7 @@ static int festival_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
/* Write to cache and then pass it down */
|
||||
if (writecache==1) {
|
||||
ast_log(LOG_WARNING,"Writing result to cache...\n");
|
||||
ast_log(LOG_DEBUG,"Writing result to cache...\n");
|
||||
while ((strln=read(fd,buffer,16384))!=0) {
|
||||
write(fdesc,buffer,strln);
|
||||
}
|
||||
@@ -415,7 +417,7 @@ static int festival_exec(struct ast_channel *chan, void *data)
|
||||
lseek(fd,seekpos,SEEK_SET);
|
||||
}
|
||||
|
||||
ast_log(LOG_WARNING,"Passing data to channel...\n");
|
||||
ast_log(LOG_DEBUG,"Passing data to channel...\n");
|
||||
|
||||
/* Read back info from server */
|
||||
/* This assumes only one waveform will come back, also LP is unlikely */
|
||||
@@ -425,15 +427,14 @@ static int festival_exec(struct ast_channel *chan, void *data)
|
||||
n += read(fd,ack+n,3-n);
|
||||
ack[3] = '\0';
|
||||
if (strcmp(ack,"WV\n") == 0) { /* receive a waveform */
|
||||
ast_log(LOG_WARNING,"Festival WV command");
|
||||
ast_log(LOG_DEBUG,"Festival WV command\n");
|
||||
waveform = socket_receive_file_to_buff(fd,&filesize);
|
||||
send_waveform_to_channel(chan,waveform,filesize);
|
||||
res = send_waveform_to_channel(chan,waveform,filesize, intstr);
|
||||
free(waveform);
|
||||
res=0;
|
||||
break;
|
||||
}
|
||||
else if (strcmp(ack,"LP\n") == 0) { /* receive an s-expr */
|
||||
ast_log(LOG_WARNING,"Festival LP command");
|
||||
ast_log(LOG_DEBUG,"Festival LP command\n");
|
||||
waveform = socket_receive_file_to_buff(fd,&filesize);
|
||||
waveform[filesize]='\0';
|
||||
ast_log(LOG_WARNING,"Festival returned LP : %s\n",waveform);
|
||||
@@ -445,6 +446,7 @@ static int festival_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
} while (strcmp(ack,"OK\n") != 0);
|
||||
close(fd);
|
||||
ast_destroy(cfg);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
|
||||
|
||||
5
apps/app_flash.c
Executable file → Normal file
5
apps/app_flash.c
Executable file → Normal file
@@ -21,11 +21,14 @@
|
||||
#include <asterisk/image.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <sys/ioctl.h>
|
||||
#ifdef __linux__
|
||||
#include <linux/zaptel.h>
|
||||
#else
|
||||
#include <zaptel.h>
|
||||
#endif /* __linux__ */
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Flash zap trunk application";
|
||||
|
||||
|
||||
90
apps/app_forkcdr.c
Normal file
90
apps/app_forkcdr.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Fork CDR application
|
||||
* Copyright Anthony Minessale anthmct@yahoo.com
|
||||
* Development of this app Sponsered/Funded by TAAN Softworks Corp
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/cdr.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <pthread.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(): Causes the Call Data Record to fork an additional\n"
|
||||
"cdr record starting from the time of the fork call\n";
|
||||
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
|
||||
static void ast_cdr_clone(struct ast_cdr *cdr) {
|
||||
struct ast_cdr *newcdr = ast_cdr_alloc();
|
||||
memcpy(newcdr,cdr,sizeof(struct ast_cdr));
|
||||
ast_cdr_append(cdr,newcdr);
|
||||
gettimeofday(&newcdr->start, NULL);
|
||||
memset(&newcdr->answer, 0, sizeof(newcdr->answer));
|
||||
ast_cdr_add_flag(cdr,AST_CDR_FLAG_CHILD|AST_CDR_FLAG_LOCKED);
|
||||
}
|
||||
|
||||
static void ast_cdr_fork(struct ast_channel *chan) {
|
||||
if(chan && chan->cdr) {
|
||||
ast_cdr_clone(chan->cdr);
|
||||
}
|
||||
}
|
||||
|
||||
static int forkcdr_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
ast_cdr_fork(chan);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, forkcdr_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
33
apps/app_getcpeid.c
Executable file → Normal file
33
apps/app_getcpeid.c
Executable file → Normal file
@@ -3,9 +3,9 @@
|
||||
*
|
||||
* Execute arbitrary system commands
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999-2005, Digium
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
@@ -24,9 +24,6 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Get ADSI CPE ID";
|
||||
|
||||
static char *app = "GetCPEID";
|
||||
@@ -34,9 +31,9 @@ static char *app = "GetCPEID";
|
||||
static char *synopsis = "Get ADSI CPE ID";
|
||||
|
||||
static char *descrip =
|
||||
" GetCPEID: Obtains and displays CPE ID and other information in order to\n"
|
||||
"properly setup zapata.conf for on-hook operations. Returns -1 on hanup\n"
|
||||
"only.";
|
||||
" GetCPEID: Obtains and displays ADSI CPE ID and other information in order\n"
|
||||
"to properly setup zapata.conf for on-hook operations.\n"
|
||||
"Returns -1 on hangup only.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -70,9 +67,9 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
|
||||
stuff[2] = data[2];
|
||||
stuff[3] = data[3];
|
||||
memset(data, 0, sizeof(data));
|
||||
strcpy(stuff[0], "** CPE Info **");
|
||||
strcpy(stuff[1], "Identifying CPE...");
|
||||
strcpy(stuff[2], "Please wait...");
|
||||
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, stuff, 0);
|
||||
@@ -83,8 +80,8 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
|
||||
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(stuff[1], "Measuring CPE...");
|
||||
strcpy(stuff[2], "Please wait...");
|
||||
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) {
|
||||
@@ -95,14 +92,14 @@ static int cpeid_exec(struct ast_channel *chan, void *idata)
|
||||
}
|
||||
if (res > -1) {
|
||||
if (gotcpeid)
|
||||
sprintf(stuff[1], "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(stuff[1], "CPEID Unknown");
|
||||
strncpy(stuff[1], "CPEID Unknown", sizeof(data[1]) - 1);
|
||||
if (gotgeometry)
|
||||
sprintf(stuff[2], "Geom: %dx%d, %d buttons", width, height, buttons);
|
||||
snprintf(stuff[2], sizeof(data[2]), "Geom: %dx%d, %d buttons", width, height, buttons);
|
||||
else
|
||||
strcpy(stuff[2], "Geometry unknown");
|
||||
strcpy(stuff[3], "Press # to exit");
|
||||
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);
|
||||
|
||||
224
apps/app_groupcount.c
Normal file
224
apps/app_groupcount.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Group Manipulation Applications
|
||||
*
|
||||
* Copyright (c) 2004 Digium
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#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/utils.h>
|
||||
|
||||
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 *group_count_synopsis = "GetGroupCount([groupname][@category])";
|
||||
static char *group_set_synopsis = "SetGroup(groupname[@category])";
|
||||
static char *group_check_synopsis = "CheckGroup(max[@category])";
|
||||
|
||||
static char *group_count_descrip =
|
||||
"GetGroupCount([group][@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. Always returns 0.\n";
|
||||
|
||||
static char *group_set_descrip =
|
||||
"SetGroup(group)\n"
|
||||
" Sets the channel group to the specified value. Equivalent to\n"
|
||||
"SetVar(GROUP=group). Always returns 0.\n";
|
||||
|
||||
static char *group_check_descrip =
|
||||
"CheckGroup(max)\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. If the\n"
|
||||
"number does in fact exceed max, if priority n+101 exists, then\n"
|
||||
"execution continues at that step, otherwise -1 is returned.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
#define DEFAULT_CATEGORY "GROUP"
|
||||
|
||||
static int group_get_count(char *group, char *category)
|
||||
{
|
||||
struct ast_channel *chan;
|
||||
int count = 0;
|
||||
char *test;
|
||||
if (group && !ast_strlen_zero(group)) {
|
||||
chan = ast_channel_walk_locked(NULL);
|
||||
while(chan) {
|
||||
test = pbx_builtin_getvar_helper(chan, category);
|
||||
if (test && !strcasecmp(test, group))
|
||||
count++;
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
chan = ast_channel_walk_locked(chan);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int group_count_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
int count;
|
||||
struct localuser *u;
|
||||
char *group=NULL;
|
||||
char *cat = NULL;
|
||||
char ret[80]="";
|
||||
char tmp[256]="";
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Check and parse arguments */
|
||||
if (data && !ast_strlen_zero(data)) {
|
||||
strncpy(tmp, data, sizeof(tmp) - 1);
|
||||
group = tmp;
|
||||
cat = strchr(tmp, '@');
|
||||
if (cat) {
|
||||
*cat = '\0';
|
||||
cat++;
|
||||
}
|
||||
}
|
||||
if (cat)
|
||||
snprintf(ret, sizeof(ret), "GROUP_%s", cat);
|
||||
else
|
||||
strncpy(ret, DEFAULT_CATEGORY, sizeof(ret) - 1);
|
||||
|
||||
if (!group || ast_strlen_zero(group)) {
|
||||
group = pbx_builtin_getvar_helper(chan, ret);
|
||||
}
|
||||
count = group_get_count(group, ret);
|
||||
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;
|
||||
char ret[80] = "";
|
||||
char tmp[256] = "";
|
||||
char *cat=NULL, *group=NULL;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Check and parse arguments */
|
||||
if (data && !ast_strlen_zero(data)) {
|
||||
strncpy(tmp, data, sizeof(tmp) - 1);
|
||||
group = tmp;
|
||||
cat = strchr(tmp, '@');
|
||||
if (cat) {
|
||||
*cat = '\0';
|
||||
cat++;
|
||||
}
|
||||
}
|
||||
if (cat)
|
||||
snprintf(ret, sizeof(ret), "GROUP_%s", cat);
|
||||
else
|
||||
strncpy(ret, DEFAULT_CATEGORY, sizeof(ret) - 1);
|
||||
|
||||
if (group && !ast_strlen_zero(group)) {
|
||||
pbx_builtin_setvar_helper(chan, ret, group);
|
||||
} else
|
||||
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 ret[80] = "";
|
||||
char tmp[256] = "";
|
||||
char *cat, *group;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (data && !ast_strlen_zero(data)) {
|
||||
strncpy(tmp, data, sizeof(tmp) - 1);
|
||||
group = tmp;
|
||||
cat = strchr(tmp, '@');
|
||||
if (cat) {
|
||||
*cat = '\0';
|
||||
cat++;
|
||||
}
|
||||
if ((sscanf((char *)tmp, "%i", &max) == 1) && (max > -1)) {
|
||||
if (cat)
|
||||
snprintf(ret, sizeof(ret), "GROUP_%s", cat);
|
||||
else
|
||||
strncpy(ret, DEFAULT_CATEGORY, sizeof(ret) - 1);
|
||||
|
||||
count = group_get_count(pbx_builtin_getvar_helper(chan, ret), ret);
|
||||
if (count > max) {
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
} else
|
||||
ast_log(LOG_WARNING, "CheckGroup requires a positive integer argument (max)\n");
|
||||
} else
|
||||
ast_log(LOG_WARNING, "CheckGroup requires an argument(max)\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
res = ast_unregister_application(app_group_count);
|
||||
res |= ast_unregister_application(app_group_set);
|
||||
res |= ast_unregister_application(app_group_check);
|
||||
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);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
169
apps/app_hasnewvoicemail.c
Normal file
169
apps/app_hasnewvoicemail.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* HasVoicemail application
|
||||
* Changes Copyright (c) 2004 Todd Freeman <freeman@andrews.edu>
|
||||
*
|
||||
* 95% based on HasNewVoicemail by:
|
||||
*
|
||||
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <asterisk-hasnewvoicemail-app@the-tilghman.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/types.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/utils.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "../astconf.h"
|
||||
|
||||
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";
|
||||
static char *hasvoicemail_descrip =
|
||||
"HasVoicemail(vmbox[@context][:folder][|varname])\n"
|
||||
" Branches to priority + 101, if there is voicemail in folder indicated."
|
||||
" Optionally sets <varname> to the number of messages in that folder."
|
||||
" Assumes folder of INBOX if not specified.\n";
|
||||
|
||||
static char *app_hasnewvoicemail = "HasNewVoicemail";
|
||||
static char *hasnewvoicemail_synopsis = "Conditionally branches to priority + 101";
|
||||
static char *hasnewvoicemail_descrip =
|
||||
"HasNewVoicemail(vmbox[@context][|varname])\n"
|
||||
" Branches to priority + 101, if there is voicemail in folder INBOX."
|
||||
" Optionally sets <varname> to the number of messages in that folder.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int hasvoicemail_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char vmpath[256], *temps, *input, *varname = NULL, *vmbox, *vmfolder = "INBOX", *context = "default";
|
||||
DIR *vmdir;
|
||||
struct dirent *vment;
|
||||
int vmcount = 0;
|
||||
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "HasVoicemail requires an argument (vm-box[@context][:folder]|varname)\n");
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
input = ast_strdupa((char *)data);
|
||||
if (input) {
|
||||
temps = input;
|
||||
if ((temps = strsep(&input, "|"))) {
|
||||
if (input && !ast_strlen_zero(input))
|
||||
varname = input;
|
||||
input = temps;
|
||||
}
|
||||
if ((temps = strsep(&input, ":"))) {
|
||||
if (input && !ast_strlen_zero(input))
|
||||
vmfolder = input;
|
||||
input = temps;
|
||||
}
|
||||
if ((vmbox = strsep(&input, "@")))
|
||||
if (input && !ast_strlen_zero(input))
|
||||
context = input;
|
||||
if (!vmbox)
|
||||
vmbox = input;
|
||||
|
||||
snprintf(vmpath,sizeof(vmpath), "%s/voicemail/%s/%s/%s", (char *)ast_config_AST_SPOOL_DIR, context, vmbox, vmfolder);
|
||||
if (!(vmdir = opendir(vmpath))) {
|
||||
ast_log(LOG_NOTICE, "Voice mailbox %s at %s does not exist\n", vmbox, vmpath);
|
||||
} else {
|
||||
|
||||
/* No matter what the format of VM, there will always be a .txt file for each message. */
|
||||
while ((vment = readdir(vmdir)))
|
||||
if (!strncmp(vment->d_name + 7,".txt",4))
|
||||
vmcount++;
|
||||
closedir(vmdir);
|
||||
}
|
||||
/* Set the count in the channel variable */
|
||||
if (varname) {
|
||||
char tmp[12];
|
||||
snprintf(tmp, sizeof(tmp), "%d", vmcount);
|
||||
pbx_builtin_setvar_helper(chan, varname, tmp);
|
||||
}
|
||||
|
||||
if (vmcount > 0) {
|
||||
/* Branch to the next extension */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid)) {
|
||||
chan->priority += 100;
|
||||
} else
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Out of memory error\n");
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
res = ast_unregister_application(app_hasvoicemail);
|
||||
res |= ast_unregister_application(app_hasnewvoicemail);
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
res = ast_register_application(app_hasvoicemail, hasvoicemail_exec, hasvoicemail_synopsis, hasvoicemail_descrip);
|
||||
res |= ast_register_application(app_hasnewvoicemail, hasvoicemail_exec, hasnewvoicemail_synopsis, hasnewvoicemail_descrip);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
196
apps/app_ices.c
Normal file
196
apps/app_ices.c
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Stream to an icecast server via ICES (see contrib/asterisk-ices.xml)
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/frame.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
#include <errno.h>
|
||||
#include "../astconf.h"
|
||||
|
||||
#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'";
|
||||
|
||||
static char *descrip =
|
||||
" ICES(config.xml) Streams to an icecast server using ices\n"
|
||||
"(available separately). A configuration file must be supplied\n"
|
||||
"for ices (see examples/asterisk-ices.conf). Returns -1 on\n"
|
||||
"hangup or 0 otherwise.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int icesencode(char *filename, int fd)
|
||||
{
|
||||
int res;
|
||||
int x;
|
||||
res = fork();
|
||||
if (res < 0)
|
||||
ast_log(LOG_WARNING, "Fork failed\n");
|
||||
if (res)
|
||||
return res;
|
||||
dup2(fd, STDIN_FILENO);
|
||||
for (x=STDERR_FILENO + 1;x<256;x++) {
|
||||
if ((x != STDIN_FILENO) && (x != STDOUT_FILENO))
|
||||
close(x);
|
||||
}
|
||||
/* Most commonly installed in /usr/local/bin */
|
||||
execl(ICES, "ices", filename, (char *)NULL);
|
||||
/* But many places has it in /usr/bin */
|
||||
execl(LOCAL_ICES, "ices", filename, (char *)NULL);
|
||||
/* As a last-ditch effort, try to use PATH */
|
||||
execlp("ices", "ices", filename, (char *)NULL);
|
||||
ast_log(LOG_WARNING, "Execute of ices failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ices_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
int fds[2];
|
||||
int ms = -1;
|
||||
int pid = -1;
|
||||
int flags;
|
||||
int oreadformat;
|
||||
struct timeval last;
|
||||
struct ast_frame *f;
|
||||
char filename[256]="";
|
||||
char *c;
|
||||
last.tv_usec = 0;
|
||||
last.tv_sec = 0;
|
||||
if (!data || !strlen(data)) {
|
||||
ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n");
|
||||
return -1;
|
||||
}
|
||||
if (pipe(fds)) {
|
||||
ast_log(LOG_WARNING, "Unable to create pipe\n");
|
||||
return -1;
|
||||
}
|
||||
flags = fcntl(fds[1], F_GETFL);
|
||||
fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
ast_stopstream(chan);
|
||||
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
res = ast_answer(chan);
|
||||
|
||||
if (res) {
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
ast_log(LOG_WARNING, "Answer failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
oreadformat = chan->readformat;
|
||||
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
|
||||
return -1;
|
||||
}
|
||||
if (((char *)data)[0] == '/')
|
||||
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 */
|
||||
c = strchr(filename, '|');
|
||||
if (c)
|
||||
*c = '\0';
|
||||
res = icesencode(filename, fds[0]);
|
||||
close(fds[0]);
|
||||
if (res >= 0) {
|
||||
pid = res;
|
||||
for (;;) {
|
||||
/* Wait for audio, and stream */
|
||||
ms = ast_waitfor(chan, -1);
|
||||
if (ms < 0) {
|
||||
ast_log(LOG_DEBUG, "Hangup detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
res = write(fds[1], f->data, f->datalen);
|
||||
if (res < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
close(fds[1]);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
if (pid > -1)
|
||||
kill(pid, SIGKILL);
|
||||
if (!res && oreadformat)
|
||||
ast_set_read_format(chan, oreadformat);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, ices_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
1
apps/app_image.c
Executable file → Normal file
1
apps/app_image.c
Executable file → Normal file
@@ -21,7 +21,6 @@
|
||||
#include <asterisk/image.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Image Transmission Application";
|
||||
|
||||
|
||||
24
apps/app_intercom.c
Executable file → Normal file
24
apps/app_intercom.c
Executable file → Normal file
@@ -24,12 +24,22 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#include <linux/soundcard.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <linux/soundcard.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <sys/soundcard.h>
|
||||
#else
|
||||
#include <soundcard.h>
|
||||
#endif
|
||||
|
||||
#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
|
||||
@@ -48,26 +58,26 @@ STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static pthread_mutex_t sound_lock = AST_MUTEX_INITIALIZER;
|
||||
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_pthread_mutex_lock(&sound_lock);
|
||||
ast_mutex_lock(&sound_lock);
|
||||
if (sound < 0) {
|
||||
ast_log(LOG_WARNING, "Sound device closed?\n");
|
||||
ast_pthread_mutex_unlock(&sound_lock);
|
||||
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_pthread_mutex_unlock(&sound_lock);
|
||||
ast_mutex_unlock(&sound_lock);
|
||||
return -1;
|
||||
}
|
||||
res = write(sound, data, len);
|
||||
ast_pthread_mutex_unlock(&sound_lock);
|
||||
ast_mutex_unlock(&sound_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
1
apps/app_lookupblacklist.c
Executable file → Normal file
1
apps/app_lookupblacklist.c
Executable file → Normal file
@@ -24,7 +24,6 @@
|
||||
#include <asterisk/astdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Look up Caller*ID name/number from blacklist database";
|
||||
|
||||
|
||||
1
apps/app_lookupcidname.c
Executable file → Normal file
1
apps/app_lookupcidname.c
Executable file → Normal file
@@ -24,7 +24,6 @@
|
||||
#include <asterisk/astdb.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Look up CallerID Name from local database";
|
||||
|
||||
|
||||
37
apps/app_macro.c
Executable file → Normal file
37
apps/app_macro.c
Executable file → Normal file
@@ -11,19 +11,20 @@
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#define MAX_ARGS 80
|
||||
|
||||
static char *tdesc = "Extension Macros";
|
||||
@@ -58,7 +59,7 @@ static int macro_exec(struct ast_channel *chan, void *data)
|
||||
char varname[80];
|
||||
char *oldargs[MAX_ARGS + 1] = { NULL, };
|
||||
int argc, x;
|
||||
int res;
|
||||
int res=0;
|
||||
char oldexten[256]="";
|
||||
int oldpriority;
|
||||
char pc[80];
|
||||
@@ -72,14 +73,14 @@ static int macro_exec(struct ast_channel *chan, void *data)
|
||||
char *save_macro_priority;
|
||||
char *save_macro_offset;
|
||||
|
||||
if (!data || !strlen(data)) {
|
||||
if (!data || ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "Invalid Macro incantation\n");
|
||||
return 0;
|
||||
}
|
||||
strncpy(tmp, data, sizeof(tmp) - 1);
|
||||
rest = tmp;
|
||||
macro = strsep(&rest, "|");
|
||||
if (!macro || !strlen(macro)) {
|
||||
if (!macro || ast_strlen_zero(macro)) {
|
||||
ast_log(LOG_WARNING, "Invalid macro name specified\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -95,8 +96,10 @@ static int macro_exec(struct ast_channel *chan, void *data)
|
||||
oldpriority = chan->priority;
|
||||
strncpy(oldexten, chan->exten, sizeof(oldexten) - 1);
|
||||
strncpy(oldcontext, chan->context, sizeof(oldcontext) - 1);
|
||||
if (!strlen(chan->macrocontext)) {
|
||||
if (ast_strlen_zero(chan->macrocontext)) {
|
||||
strncpy(chan->macrocontext, chan->context, sizeof(chan->macrocontext) - 1);
|
||||
strncpy(chan->macroexten, chan->exten, sizeof(chan->macroexten) - 1);
|
||||
chan->macropriority = chan->priority;
|
||||
setmacrocontext=1;
|
||||
}
|
||||
argc = 1;
|
||||
@@ -119,24 +122,26 @@ static int macro_exec(struct ast_channel *chan, void *data)
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL);
|
||||
|
||||
/* Setup environment for new run */
|
||||
strcpy(chan->exten, "s");
|
||||
strncpy(chan->context, fullmacro, sizeof(chan->context));
|
||||
chan->exten[0] = 's';
|
||||
chan->exten[1] = '\0';
|
||||
strncpy(chan->context, fullmacro, sizeof(chan->context) - 1);
|
||||
chan->priority = 1;
|
||||
|
||||
while((cur = strsep(&rest, "|")) && (argc < MAX_ARGS)) {
|
||||
/* Save copy of old arguments if we're overwriting some, otherwise
|
||||
let them pass through to the other macro */
|
||||
snprintf(varname, sizeof(varname), "ARG%d", argc);
|
||||
oldargs[argc] = pbx_builtin_getvar_helper(chan, varname);
|
||||
if (oldargs[argc])
|
||||
oldargs[argc] = strdup(oldargs[argc]);
|
||||
snprintf(varname, sizeof(varname), "ARG%d", argc);
|
||||
pbx_builtin_setvar_helper(chan, varname, cur);
|
||||
argc++;
|
||||
}
|
||||
while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->callerid)) {
|
||||
if ((res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->callerid))) {
|
||||
/* Something bad happened, or a hangup has been requested. */
|
||||
if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F'))) {
|
||||
if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) ||
|
||||
(res == '*') || (res == '#')) {
|
||||
/* Just return result as to the previous application as if it had been dialed */
|
||||
ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res);
|
||||
break;
|
||||
@@ -162,7 +167,8 @@ static int macro_exec(struct ast_channel *chan, void *data)
|
||||
ast_verbose(VERBOSE_PREFIX_2 "Channel '%s' jumping out of macro '%s'\n", chan->name, macro);
|
||||
break;
|
||||
}
|
||||
if (chan->_softhangup) {
|
||||
/* don't stop executing extensions when we're in "h" */
|
||||
if (chan->_softhangup && strcasecmp(oldexten,"h")) {
|
||||
ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n",
|
||||
chan->exten, chan->priority);
|
||||
goto out;
|
||||
@@ -188,14 +194,17 @@ out:
|
||||
if (save_macro_context) free(save_macro_context);
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
|
||||
if (save_macro_priority) free(save_macro_priority);
|
||||
if (setmacrocontext)
|
||||
strcpy(chan->macrocontext, "");
|
||||
if (setmacrocontext) {
|
||||
chan->macrocontext[0] = '\0';
|
||||
chan->macroexten[0] = '\0';
|
||||
chan->macropriority = 0;
|
||||
}
|
||||
|
||||
if (!strcasecmp(chan->context, fullmacro)) {
|
||||
/* If we're leaving the macro normally, restore original information */
|
||||
chan->priority = oldpriority;
|
||||
strncpy(chan->context, oldcontext, sizeof(chan->context) - 1);
|
||||
if (!chan->_softhangup) {
|
||||
if (!(chan->_softhangup & AST_SOFTHANGUP_ASYNCGOTO)) {
|
||||
/* Copy the extension, so long as we're not in softhangup, where we could be given an asyncgoto */
|
||||
strncpy(chan->exten, oldexten, sizeof(chan->exten) - 1);
|
||||
if ((offsets = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"))) {
|
||||
|
||||
1448
apps/app_meetme.c
Executable file → Normal file
1448
apps/app_meetme.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
8
apps/app_milliwatt.c
Executable file → Normal file
8
apps/app_milliwatt.c
Executable file → Normal file
@@ -23,8 +23,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Digital Milliwatt (mu-law) Test Application";
|
||||
|
||||
static char *app = "Milliwatt";
|
||||
@@ -55,7 +53,7 @@ static void milliwatt_release(struct ast_channel *chan, void *data)
|
||||
return;
|
||||
}
|
||||
|
||||
static int milliwatt_generate(struct ast_channel *chan, void *data, int len)
|
||||
static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int samples)
|
||||
{
|
||||
struct ast_frame wf;
|
||||
unsigned char waste[AST_FRIENDLY_OFFSET];
|
||||
@@ -64,7 +62,7 @@ static int milliwatt_generate(struct ast_channel *chan, void *data, int len)
|
||||
|
||||
if (len > sizeof(buf))
|
||||
{
|
||||
ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",sizeof(buf),len);
|
||||
ast_log(LOG_WARNING,"Only doing %d bytes (%d bytes requested)\n",(int)sizeof(buf),len);
|
||||
len = sizeof(buf);
|
||||
}
|
||||
waste[0] = 0; /* make compiler happy */
|
||||
@@ -76,6 +74,8 @@ static int milliwatt_generate(struct ast_channel *chan, void *data, int len)
|
||||
wf.datalen = len;
|
||||
wf.samples = wf.datalen;
|
||||
wf.src = "app_milliwatt";
|
||||
wf.delivery.tv_sec = 0;
|
||||
wf.delivery.tv_usec = 0;
|
||||
/* create a buffer containing the digital milliwatt pattern */
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
|
||||
123
apps/app_mp3.c
Executable file → Normal file
123
apps/app_mp3.c
Executable file → Normal file
@@ -3,9 +3,9 @@
|
||||
*
|
||||
* Silly application to play an MP3 file -- uses mpg123
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999-2004, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
@@ -25,9 +25,9 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define LOCAL_MPG_123 "/usr/local/bin/mpg123"
|
||||
#define MPG_123 "/usr/bin/mpg123"
|
||||
|
||||
static char *tdesc = "Silly MP3 Application";
|
||||
@@ -60,14 +60,41 @@ static int mp3play(char *filename, int fd)
|
||||
close(x);
|
||||
}
|
||||
/* Execute mpg123, but buffer if it's a net connection */
|
||||
if (strncmp(filename, "http://", 7))
|
||||
execl(MPG_123, MPG_123, "-q", "-s", "-b", "1024", "--mono", "-r", "8000", filename, NULL);
|
||||
else
|
||||
execl(MPG_123, MPG_123, "-q", "-s", "--mono", "-r", "8000", filename, NULL);
|
||||
if (!strncasecmp(filename, "http://", 7)) {
|
||||
/* Most commonly installed in /usr/local/bin */
|
||||
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
/* But many places has it in /usr/bin */
|
||||
execl(MPG_123, "mpg123", "-q", "-s", "-b", "1024","-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
/* As a last-ditch effort, try to use PATH */
|
||||
execlp("mpg123", "mpg123", "-q", "-s", "-b", "1024", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
}
|
||||
else {
|
||||
/* Most commonly installed in /usr/local/bin */
|
||||
execl(MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
/* But many places has it in /usr/bin */
|
||||
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
/* As a last-ditch effort, try to use PATH */
|
||||
execlp("mpg123", "mpg123", "-q", "-s", "-f", "8192", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
}
|
||||
ast_log(LOG_WARNING, "Execute of mpg123 failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int timed_read(int fd, void *data, int datalen, int timeout)
|
||||
{
|
||||
int res;
|
||||
struct pollfd fds[1];
|
||||
fds[0].fd = fd;
|
||||
fds[0].events = POLLIN;
|
||||
res = poll(fds, 1, timeout);
|
||||
if (res < 1) {
|
||||
ast_log(LOG_NOTICE, "Poll timed out/errored out with %d\n", res);
|
||||
return -1;
|
||||
}
|
||||
return read(fd, data, datalen);
|
||||
|
||||
}
|
||||
|
||||
static int mp3_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
@@ -76,15 +103,14 @@ static int mp3_exec(struct ast_channel *chan, void *data)
|
||||
int ms = -1;
|
||||
int pid = -1;
|
||||
int owriteformat;
|
||||
struct timeval last;
|
||||
int timeout = 2000;
|
||||
struct timeval now, next;
|
||||
struct ast_frame *f;
|
||||
struct myframe {
|
||||
struct ast_frame f;
|
||||
char offset[AST_FRIENDLY_OFFSET];
|
||||
short frdata[160];
|
||||
} myf;
|
||||
last.tv_usec = 0;
|
||||
last.tv_sec = 0;
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n");
|
||||
return -1;
|
||||
@@ -103,36 +129,36 @@ static int mp3_exec(struct ast_channel *chan, void *data)
|
||||
return -1;
|
||||
}
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
res = mp3play((char *)data, fds[1]);
|
||||
if (!strncasecmp((char *)data, "http://", 7)) {
|
||||
timeout = 10000;
|
||||
}
|
||||
/* Wait 1000 ms first */
|
||||
ms = 1000;
|
||||
next = now;
|
||||
next.tv_sec += 1;
|
||||
if (res >= 0) {
|
||||
pid = res;
|
||||
/* Order is important -- there's almost always going to be mp3... we want to prioritize the
|
||||
user */
|
||||
for (;;) {
|
||||
ms = ast_waitfor(chan, ms);
|
||||
if (ms < 0) {
|
||||
ast_log(LOG_DEBUG, "Hangup detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (ms) {
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
gettimeofday(&now, NULL);
|
||||
ms = (next.tv_sec - now.tv_sec) * 1000;
|
||||
ms += (next.tv_usec - now.tv_usec) / 1000;
|
||||
#if 0
|
||||
printf("ms: %d\n", ms);
|
||||
#endif
|
||||
if (ms <= 0) {
|
||||
#if 0
|
||||
{
|
||||
static struct timeval last;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
printf("Since last: %ld\n", (tv.tv_sec - last.tv_sec) * 1000 + (tv.tv_usec - last.tv_usec) / 1000);
|
||||
last = tv;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_DTMF) {
|
||||
ast_log(LOG_DEBUG, "User pressed a key\n");
|
||||
ast_frfree(f);
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
} else {
|
||||
res = read(fds[0], myf.frdata, sizeof(myf.frdata));
|
||||
#endif
|
||||
res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout);
|
||||
if (res > 0) {
|
||||
myf.f.frametype = AST_FRAME_VOICE;
|
||||
myf.f.subclass = AST_FORMAT_SLINEAR;
|
||||
@@ -141,6 +167,8 @@ static int mp3_exec(struct ast_channel *chan, void *data)
|
||||
myf.f.mallocd = 0;
|
||||
myf.f.offset = AST_FRIENDLY_OFFSET;
|
||||
myf.f.src = __PRETTY_FUNCTION__;
|
||||
myf.f.delivery.tv_sec = 0;
|
||||
myf.f.delivery.tv_usec = 0;
|
||||
myf.f.data = myf.frdata;
|
||||
if (ast_write(chan, &myf.f) < 0) {
|
||||
res = -1;
|
||||
@@ -151,7 +179,36 @@ static int mp3_exec(struct ast_channel *chan, void *data)
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
ms = res / 16;
|
||||
next.tv_usec += res / 2 * 125;
|
||||
if (next.tv_usec >= 1000000) {
|
||||
next.tv_usec -= 1000000;
|
||||
next.tv_sec++;
|
||||
}
|
||||
#if 0
|
||||
printf("Next: %d\n", ms);
|
||||
#endif
|
||||
} else {
|
||||
ms = ast_waitfor(chan, ms);
|
||||
if (ms < 0) {
|
||||
ast_log(LOG_DEBUG, "Hangup detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (ms) {
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_DTMF) {
|
||||
ast_log(LOG_DEBUG, "User pressed a key\n");
|
||||
ast_frfree(f);
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
229
apps/app_nbscat.c
Normal file
229
apps/app_nbscat.c
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Silly application to play an NBScat file -- uses nbscat8k
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/frame.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#define LOCAL_NBSCAT "/usr/local/bin/nbscat8k"
|
||||
#define NBSCAT "/usr/bin/nbscat8k"
|
||||
|
||||
static char *tdesc = "Silly NBS Stream Application";
|
||||
|
||||
static char *app = "NBScat";
|
||||
|
||||
static char *synopsis = "Play an NBS local stream";
|
||||
|
||||
static char *descrip =
|
||||
" NBScat: Executes nbscat to listen to the local NBS stream.\n"
|
||||
"Returns -1 on\n hangup or 0 otherwise. User can exit by \n"
|
||||
"pressing any key\n.";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int NBScatplay(int fd)
|
||||
{
|
||||
int res;
|
||||
int x;
|
||||
res = fork();
|
||||
if (res < 0)
|
||||
ast_log(LOG_WARNING, "Fork failed\n");
|
||||
if (res)
|
||||
return res;
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
for (x=0;x<256;x++) {
|
||||
if (x != STDOUT_FILENO)
|
||||
close(x);
|
||||
}
|
||||
/* Most commonly installed in /usr/local/bin */
|
||||
execl(NBSCAT, "nbscat8k", "-d", (char *)NULL);
|
||||
execl(LOCAL_NBSCAT, "nbscat8k", "-d", (char *)NULL);
|
||||
ast_log(LOG_WARNING, "Execute of nbscat8k failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int timed_read(int fd, void *data, int datalen)
|
||||
{
|
||||
int res;
|
||||
struct pollfd fds[1];
|
||||
fds[0].fd = fd;
|
||||
fds[0].events = POLLIN;
|
||||
res = poll(fds, 1, 2000);
|
||||
if (res < 1) {
|
||||
ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res);
|
||||
return -1;
|
||||
}
|
||||
return read(fd, data, datalen);
|
||||
|
||||
}
|
||||
|
||||
static int NBScat_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
int fds[2];
|
||||
int ms = -1;
|
||||
int pid = -1;
|
||||
int owriteformat;
|
||||
struct timeval now, next;
|
||||
struct ast_frame *f;
|
||||
struct myframe {
|
||||
struct ast_frame f;
|
||||
char offset[AST_FRIENDLY_OFFSET];
|
||||
short frdata[160];
|
||||
} myf;
|
||||
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fds)) {
|
||||
ast_log(LOG_WARNING, "Unable to create socketpair\n");
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
ast_stopstream(chan);
|
||||
|
||||
owriteformat = chan->writeformat;
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = NBScatplay(fds[1]);
|
||||
/* Wait 1000 ms first */
|
||||
next = now;
|
||||
next.tv_sec += 1;
|
||||
if (res >= 0) {
|
||||
pid = res;
|
||||
/* Order is important -- there's almost always going to be mp3... we want to prioritize the
|
||||
user */
|
||||
for (;;) {
|
||||
gettimeofday(&now, NULL);
|
||||
ms = (next.tv_sec - now.tv_sec) * 1000;
|
||||
ms += (next.tv_usec - now.tv_usec) / 1000;
|
||||
#if 0
|
||||
printf("ms: %d\n", ms);
|
||||
#endif
|
||||
if (ms <= 0) {
|
||||
#if 0
|
||||
{
|
||||
static struct timeval last;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
printf("Since last: %ld\n", (tv.tv_sec - last.tv_sec) * 1000 + (tv.tv_usec - last.tv_usec) / 1000);
|
||||
last = tv;
|
||||
}
|
||||
#endif
|
||||
res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata));
|
||||
if (res > 0) {
|
||||
myf.f.frametype = AST_FRAME_VOICE;
|
||||
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.delivery.tv_sec = 0;
|
||||
myf.f.delivery.tv_usec = 0;
|
||||
myf.f.data = myf.frdata;
|
||||
if (ast_write(chan, &myf.f) < 0) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_DEBUG, "No more mp3\n");
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
next.tv_usec += res / 2 * 125;
|
||||
if (next.tv_usec >= 1000000) {
|
||||
next.tv_usec -= 1000000;
|
||||
next.tv_sec++;
|
||||
}
|
||||
#if 0
|
||||
printf("Next: %d\n", ms);
|
||||
#endif
|
||||
} else {
|
||||
ms = ast_waitfor(chan, ms);
|
||||
if (ms < 0) {
|
||||
ast_log(LOG_DEBUG, "Hangup detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (ms) {
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if (f->frametype == AST_FRAME_DTMF) {
|
||||
ast_log(LOG_DEBUG, "User pressed a key\n");
|
||||
ast_frfree(f);
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
close(fds[0]);
|
||||
close(fds[1]);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
if (pid > -1)
|
||||
kill(pid, SIGKILL);
|
||||
if (!res && owriteformat)
|
||||
ast_set_write_format(chan, owriteformat);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, NBScat_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
277
apps/app_osplookup.c
Normal file
277
apps/app_osplookup.c
Normal file
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Time of day - Report the time of day
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#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/utils.h>
|
||||
#include <asterisk/causes.h>
|
||||
#include <asterisk/astosp.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static char *tdesc = "OSP Lookup";
|
||||
|
||||
static char *app = "OSPLookup";
|
||||
static char *app2 = "OSPNext";
|
||||
static char *app3 = "OSPFinish";
|
||||
|
||||
static char *synopsis = "Lookup number in OSP";
|
||||
static char *synopsis2 = "Lookup next OSP entry";
|
||||
static char *synopsis3 = "Record OSP entry";
|
||||
|
||||
static char *descrip =
|
||||
" OSPLookup(exten[|provider[|options]]): Looks up an extension via OSP and sets\n"
|
||||
"the variables, where 'n' is the number of the result beginning with 1:\n"
|
||||
" ${OSPTECH}: The technology to use for the call\n"
|
||||
" ${OSPDEST}: The destination to use for the call\n"
|
||||
" ${OSPTOKEN}: The actual OSP token as a string\n"
|
||||
" ${OSPHANDLE}: The OSP Handle for anything remaining\n"
|
||||
" ${OSPRESULTS}: The number of OSP results total remaining\n"
|
||||
"\n"
|
||||
"If the lookup was *not* successful and there exists a priority n + 101,\n"
|
||||
"then that priority will be taken next.\n" ;
|
||||
|
||||
static char *descrip2 =
|
||||
" OSPNext: Looks up the next OSP Destination for ${OSPHANDLE}\n"
|
||||
"See OSPLookup for more information\n"
|
||||
"\n"
|
||||
"If the lookup was *not* successful and there exists a priority n + 101,\n"
|
||||
"then that priority will be taken next.\n" ;
|
||||
|
||||
static char *descrip3 =
|
||||
" OSPFinish(status): Records call state for ${OSPHANDLE}, according to\n"
|
||||
"status, which should be one of BUSY, CONGESTION, ANSWER, NOANSWER, or NOCHANAVAIL\n"
|
||||
"or coincidentally, just what the Dial application stores in its ${DIALSTATUS}\n"
|
||||
"\n"
|
||||
"If the finishing was *not* successful and there exists a priority n + 101,\n"
|
||||
"then that priority will be taken next.\n" ;
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int str2cause(char *cause)
|
||||
{
|
||||
if (!strcasecmp(cause, "BUSY"))
|
||||
return AST_CAUSE_BUSY;
|
||||
if (!strcasecmp(cause, "CONGESTION"))
|
||||
return AST_CAUSE_CONGESTION;
|
||||
if (!strcasecmp(cause, "ANSWER"))
|
||||
return AST_CAUSE_NORMAL;
|
||||
if (!strcasecmp(cause, "CANCEL"))
|
||||
return AST_CAUSE_NORMAL;
|
||||
if (!strcasecmp(cause, "NOANSWER"))
|
||||
return AST_CAUSE_NOANSWER;
|
||||
if (!strcasecmp(cause, "NOCHANAVAIL"))
|
||||
return AST_CAUSE_CONGESTION;
|
||||
ast_log(LOG_WARNING, "Unknown cause '%s', using NORMAL\n", cause);
|
||||
return AST_CAUSE_NORMAL;
|
||||
}
|
||||
|
||||
static int osplookup_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *temp;
|
||||
char *provider, *opts=NULL;
|
||||
struct ast_osp_result result;
|
||||
if (!data || ast_strlen_zero(data) || !(temp = ast_strdupa(data))) {
|
||||
ast_log(LOG_WARNING, "OSPLookup requires an argument (extension)\n");
|
||||
return -1;
|
||||
}
|
||||
provider = strchr(temp, '|');
|
||||
if (provider) {
|
||||
*provider = '\0';
|
||||
provider++;
|
||||
opts = strchr(provider, '|');
|
||||
if (opts) {
|
||||
*opts = '\0';
|
||||
opts++;
|
||||
}
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
ast_log(LOG_DEBUG, "Whoo hoo, looking up OSP on '%s' via '%s'\n", temp, provider ? provider : "<default>");
|
||||
if ((res = ast_osp_lookup(chan, provider, temp, chan->callerid, &result)) > 0) {
|
||||
char tmp[80];
|
||||
snprintf(tmp, sizeof(tmp), "%d", result.handle);
|
||||
pbx_builtin_setvar_helper(chan, "OSPHANDLE", tmp);
|
||||
pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
|
||||
pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
|
||||
pbx_builtin_setvar_helper(chan, "OSPTOKEN", result.token);
|
||||
snprintf(tmp, sizeof(tmp), "%d", result.numresults);
|
||||
pbx_builtin_setvar_helper(chan, "OSPRESULTS", tmp);
|
||||
} else {
|
||||
if (!res)
|
||||
ast_log(LOG_NOTICE, "OSP Lookup failed for '%s' (provider '%s')\n", temp, provider ? provider : "<default>");
|
||||
else
|
||||
ast_log(LOG_DEBUG, "Got hangup on '%s' while doing OSP Lookup for '%s' (provider '%s')!\n", chan->name, temp, provider ? provider : "<default>" );
|
||||
}
|
||||
if (!res) {
|
||||
/* Look for a "busy" place */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
} else if (res > 0)
|
||||
res = 0;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int ospnext_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *temp;
|
||||
int cause;
|
||||
struct ast_osp_result result;
|
||||
if (!data || ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "OSPNext should have an argument (cause)\n");
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
cause = str2cause((char *)data);
|
||||
temp = pbx_builtin_getvar_helper(chan, "OSPHANDLE");
|
||||
result.handle = -1;
|
||||
if (temp && strlen(temp) && (sscanf(temp, "%i", &result.handle) == 1) && (result.handle > -1)) {
|
||||
if ((res = ast_osp_next(&result, cause)) > 0) {
|
||||
char tmp[80];
|
||||
snprintf(tmp, sizeof(tmp), "%d", result.handle);
|
||||
pbx_builtin_setvar_helper(chan, "OSPHANDLE", tmp);
|
||||
pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
|
||||
pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
|
||||
pbx_builtin_setvar_helper(chan, "OSPTOKEN", result.token);
|
||||
snprintf(tmp, sizeof(tmp), "%d", result.numresults);
|
||||
pbx_builtin_setvar_helper(chan, "OSPRESULTS", tmp);
|
||||
}
|
||||
} else {
|
||||
if (!res) {
|
||||
if (result.handle < 0)
|
||||
ast_log(LOG_NOTICE, "OSP Lookup Next failed for handle '%d'\n", result.handle);
|
||||
else
|
||||
ast_log(LOG_DEBUG, "No OSP handle specified\n");
|
||||
} else
|
||||
ast_log(LOG_DEBUG, "Got hangup on '%s' while doing OSP Next!\n", chan->name);
|
||||
}
|
||||
if (!res) {
|
||||
/* Look for a "busy" place */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
} else if (res > 0)
|
||||
res = 0;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int ospfinished_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *temp;
|
||||
int cause;
|
||||
time_t start=0, duration=0;
|
||||
struct ast_osp_result result;
|
||||
if (!data || ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "OSPFinish should have an argument (cause)\n");
|
||||
}
|
||||
if (chan->cdr) {
|
||||
start = chan->cdr->answer.tv_sec;
|
||||
if (start)
|
||||
duration = time(NULL) - start;
|
||||
else
|
||||
duration = 0;
|
||||
} else
|
||||
ast_log(LOG_WARNING, "OSPFinish called on channel '%s' with no CDR!\n", chan->name);
|
||||
LOCAL_USER_ADD(u);
|
||||
cause = str2cause((char *)data);
|
||||
temp = pbx_builtin_getvar_helper(chan, "OSPHANDLE");
|
||||
result.handle = -1;
|
||||
if (temp && strlen(temp) && (sscanf(temp, "%i", &result.handle) == 1) && (result.handle > -1)) {
|
||||
if (!ast_osp_terminate(result.handle, cause, start, duration)) {
|
||||
pbx_builtin_setvar_helper(chan, "OSPHANDLE", "");
|
||||
res = 1;
|
||||
}
|
||||
} else {
|
||||
if (!res) {
|
||||
if (result.handle > -1)
|
||||
ast_log(LOG_NOTICE, "OSP Finish failed for handle '%d'\n", result.handle);
|
||||
else
|
||||
ast_log(LOG_DEBUG, "No OSP handle specified\n");
|
||||
} else
|
||||
ast_log(LOG_DEBUG, "Got hangup on '%s' while doing OSP Terminate!\n", chan->name);
|
||||
}
|
||||
if (!res) {
|
||||
/* Look for a "busy" place */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
} else if (res > 0)
|
||||
res = 0;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
res = ast_unregister_application(app3);
|
||||
res |= ast_unregister_application(app2);
|
||||
res |= ast_unregister_application(app);
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
res = ast_register_application(app, osplookup_exec, synopsis, descrip);
|
||||
if (res)
|
||||
return(res);
|
||||
res = ast_register_application(app2, ospnext_exec, synopsis2, descrip2);
|
||||
if (res)
|
||||
return(res);
|
||||
res = ast_register_application(app3, ospfinished_exec, synopsis3, descrip3);
|
||||
if (res)
|
||||
return(res);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int reload(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
289
apps/app_parkandannounce.c
Executable file → Normal file
289
apps/app_parkandannounce.c
Executable file → Normal file
@@ -14,24 +14,24 @@
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/channel_pvt.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/parking.h>
|
||||
#include <asterisk/features.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/say.h>
|
||||
#include <asterisk/lock.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Call Parking and Announce Application";
|
||||
|
||||
static char *app = "ParkAndAnnounce";
|
||||
@@ -41,7 +41,7 @@ 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 over the console.\n"
|
||||
"announce template: colon seperated list of files to announce, the word PARKED\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"
|
||||
@@ -54,170 +54,171 @@ LOCAL_USER_DECL;
|
||||
|
||||
static int parkandannounce_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
char *return_context;
|
||||
int l, lot, timeout, dres;
|
||||
char *working, *context, *exten, *priority, *dial, *dialtech, *dialstr;
|
||||
char *template, *tpl_working, *tpl_current;
|
||||
char *tmp[100];
|
||||
int looptemp=0,i=0;
|
||||
char *s,*orig_s;
|
||||
int res=0;
|
||||
char *return_context;
|
||||
int l, lot, timeout = 0, dres;
|
||||
char *working, *context, *exten, *priority, *dial, *dialtech, *dialstr;
|
||||
char *template, *tpl_working, *tpl_current;
|
||||
char *tmp[100];
|
||||
int looptemp=0,i=0;
|
||||
char *s,*orig_s;
|
||||
|
||||
struct ast_channel *dchan;
|
||||
int outstate;
|
||||
struct ast_channel *dchan;
|
||||
int outstate;
|
||||
|
||||
struct localuser *u;
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "Park requires an argument (parkinglot)\n");
|
||||
return -1;
|
||||
}
|
||||
struct localuser *u;
|
||||
if(!data || (data && !strlen(data))) {
|
||||
ast_log(LOG_WARNING, "ParkAndAnnounce requires arguments: (announce:template|timeout|dial|[return_context])\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
l=strlen(data)+2;
|
||||
orig_s=malloc(l);
|
||||
s=orig_s;
|
||||
strncpy(s,data,l);
|
||||
l=strlen(data)+2;
|
||||
orig_s=malloc(l);
|
||||
if(!orig_s) {
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
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");
|
||||
free(orig_s);
|
||||
return -1;
|
||||
}
|
||||
template=strsep(&s,"|");
|
||||
if(! template) {
|
||||
ast_log(LOG_WARNING, "PARK: An announce template must be defined\n");
|
||||
free(orig_s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
timeout = atoi(strsep(&s, "|"));
|
||||
timeout *= 1000;
|
||||
if(s) {
|
||||
timeout = atoi(strsep(&s, "|"));
|
||||
timeout *= 1000;
|
||||
}
|
||||
dial=strsep(&s, "|");
|
||||
if(!dial) {
|
||||
ast_log(LOG_WARNING, "PARK: A dial resource must be specified i.e: Console/dsp or Zap/g1/5551212\n");
|
||||
free(orig_s);
|
||||
return -1;
|
||||
} else {
|
||||
dialtech=strsep(&dial, "/");
|
||||
dialstr=dial;
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Dial Tech,String: (%s,%s)\n", dialtech,dialstr);
|
||||
}
|
||||
|
||||
dial=strsep(&s, "|");
|
||||
if (! dial) {
|
||||
ast_log(LOG_WARNING, "PARK: A dial resouce must be specified i.e: Console/dsp or Zap/g1/5551212\n");
|
||||
free(orig_s);
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
dialtech=strsep(&dial, "/");
|
||||
dialstr=dial;
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Dial Tech,String: (%s,%s)\n", dialtech,dialstr);
|
||||
}
|
||||
|
||||
return_context = s;
|
||||
return_context = s;
|
||||
|
||||
if (return_context != NULL) {
|
||||
/* set the return context. Code borrowed from the Goto builtin */
|
||||
if(return_context != NULL) {
|
||||
/* set the return context. Code borrowed from the Goto builtin */
|
||||
|
||||
working = return_context;
|
||||
context = strsep(&working, "|");
|
||||
exten = strsep(&working, "|");
|
||||
if (!exten) {
|
||||
/* Only a priority in this one */
|
||||
priority = context;
|
||||
exten = NULL;
|
||||
context = NULL;
|
||||
} else {
|
||||
priority = strsep(&working, "|");
|
||||
if (!priority) {
|
||||
/* Only an extension and priority in this one */
|
||||
priority = exten;
|
||||
exten = context;
|
||||
context = NULL;
|
||||
}
|
||||
}
|
||||
if (atoi(priority) < 0) {
|
||||
ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
|
||||
free(orig_s);
|
||||
return -1;
|
||||
}
|
||||
/* At this point we have a priority and maybe an extension and a context */
|
||||
chan->priority = atoi(priority);
|
||||
if (exten && strcasecmp(exten, "BYEXTENSION"))
|
||||
strncpy(chan->exten, exten, sizeof(chan->exten)-1);
|
||||
if (context)
|
||||
strncpy(chan->context, context, sizeof(chan->context)-1);
|
||||
}
|
||||
else { /* increment the priority by default*/
|
||||
chan->priority++;
|
||||
}
|
||||
working = return_context;
|
||||
context = strsep(&working, "|");
|
||||
exten = strsep(&working, "|");
|
||||
if(!exten) {
|
||||
/* Only a priority in this one */
|
||||
priority = context;
|
||||
exten = NULL;
|
||||
context = NULL;
|
||||
} else {
|
||||
priority = strsep(&working, "|");
|
||||
if(!priority) {
|
||||
/* Only an extension and priority in this one */
|
||||
priority = exten;
|
||||
exten = context;
|
||||
context = NULL;
|
||||
}
|
||||
}
|
||||
if(atoi(priority) < 0) {
|
||||
ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", priority);
|
||||
free(orig_s);
|
||||
return -1;
|
||||
}
|
||||
/* At this point we have a priority and maybe an extension and a context */
|
||||
chan->priority = atoi(priority);
|
||||
if(exten && strcasecmp(exten, "BYEXTENSION"))
|
||||
strncpy(chan->exten, exten, sizeof(chan->exten)-1);
|
||||
if(context)
|
||||
strncpy(chan->context, context, sizeof(chan->context)-1);
|
||||
} else { /* increment the priority by default*/
|
||||
chan->priority++;
|
||||
}
|
||||
|
||||
|
||||
if (option_verbose > 2) {
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->callerid);
|
||||
if (!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->callerid)) {
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
|
||||
}
|
||||
}
|
||||
if(option_verbose > 2) {
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Return Context: (%s,%s,%d) ID: %s\n", chan->context,chan->exten, chan->priority, chan->callerid);
|
||||
if(!ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->callerid)) {
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Warning: Return Context Invalid, call will return to default|s\n");
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
|
||||
before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
|
||||
/* we are using masq_park here to protect * from touching the channel once we park it. If the channel comes out of timeout
|
||||
before we are done announcing and the channel is messed with, Kablooeee. So we use Masq to prevent this. */
|
||||
|
||||
ast_masq_park_call(chan, NULL, timeout, &lot);
|
||||
ast_masq_park_call(chan, NULL, timeout, &lot);
|
||||
|
||||
res=-1;
|
||||
res=-1;
|
||||
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Call Parking Called, lot: %d, timeout: %d, context: %s\n", lot, timeout, return_context);
|
||||
|
||||
/* Now place the call to the extention */
|
||||
/* Now place the call to the extention */
|
||||
|
||||
dchan = ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->callerid);
|
||||
dchan = ast_request_and_dial(dialtech, AST_FORMAT_SLINEAR, dialstr,30000, &outstate, chan->callerid);
|
||||
|
||||
if (dchan) {
|
||||
if (dchan->_state == AST_STATE_UP) {
|
||||
if (option_verbose > 3)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", dchan->name);
|
||||
} else {
|
||||
if (option_verbose > 3)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", dchan->name);
|
||||
ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name);
|
||||
ast_hangup(dchan);
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
if(dchan) {
|
||||
if(dchan->_state == AST_STATE_UP) {
|
||||
if(option_verbose > 3)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was answered.\n", dchan->name);
|
||||
} else {
|
||||
if(option_verbose > 3)
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", dchan->name);
|
||||
ast_log(LOG_WARNING, "PARK: Channel %s was never answered for the announce.\n", dchan->name);
|
||||
ast_hangup(dchan);
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "PARK: Unable to allocate announce channel.\n");
|
||||
free(orig_s);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_stopstream(dchan);
|
||||
ast_stopstream(dchan);
|
||||
|
||||
/* now we have the call placed and are ready to play stuff to it */
|
||||
/* now we have the call placed and are ready to play stuff to it */
|
||||
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Announce Template:%s\n", template);
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Announce Template:%s\n", template);
|
||||
|
||||
tpl_working = template;
|
||||
tpl_current=strsep(&tpl_working, ":");
|
||||
tpl_working = template;
|
||||
tpl_current=strsep(&tpl_working, ":");
|
||||
|
||||
while ( tpl_current && looptemp < sizeof(tmp)) {
|
||||
tmp[looptemp]=tpl_current;
|
||||
looptemp++;
|
||||
tpl_current=strsep(&tpl_working,":");
|
||||
}
|
||||
while(tpl_current && looptemp < sizeof(tmp)) {
|
||||
tmp[looptemp]=tpl_current;
|
||||
looptemp++;
|
||||
tpl_current=strsep(&tpl_working,":");
|
||||
}
|
||||
|
||||
for(i=0; i<looptemp; i++) {
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Announce:%s\n", tmp[i]);
|
||||
if (!strcmp(tmp[i], "PARKED")) {
|
||||
ast_say_digits(dchan, lot, "", dchan->language);
|
||||
}
|
||||
else {
|
||||
dres = ast_streamfile(dchan, tmp[i], dchan->language);
|
||||
if (!dres)
|
||||
dres = ast_waitstream(dchan, "");
|
||||
else {
|
||||
ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], dchan->name);
|
||||
dres = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(i=0; i<looptemp; i++) {
|
||||
ast_verbose(VERBOSE_PREFIX_4 "Announce:%s\n", tmp[i]);
|
||||
if(!strcmp(tmp[i], "PARKED")) {
|
||||
ast_say_digits(dchan, lot, "", dchan->language);
|
||||
} else {
|
||||
dres = ast_streamfile(dchan, tmp[i], dchan->language);
|
||||
if(!dres) {
|
||||
dres = ast_waitstream(dchan, "");
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], dchan->name);
|
||||
dres = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ast_stopstream(dchan);
|
||||
ast_hangup(dchan);
|
||||
ast_stopstream(dchan);
|
||||
ast_hangup(dchan);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
free(orig_s);
|
||||
return res;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
free(orig_s);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -230,8 +231,8 @@ int unload_module(void)
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
/* return ast_register_application(app, park_exec); */
|
||||
return ast_register_application(app, parkandannounce_exec, synopsis, descrip);
|
||||
/* return ast_register_application(app, park_exec); */
|
||||
return ast_register_application(app, parkandannounce_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
|
||||
20
apps/app_playback.c
Executable file → Normal file
20
apps/app_playback.c
Executable file → Normal file
@@ -18,9 +18,9 @@
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Trivial Playback Application";
|
||||
|
||||
@@ -30,14 +30,14 @@ static char *synopsis = "Play a file";
|
||||
|
||||
static char *descrip =
|
||||
" Playback(filename[|option]): Plays back a given filename (do not put\n"
|
||||
"extension). Options may also be included following a pipe symbol. The only\n"
|
||||
"defined option at this time is 'skip', which causes the playback of the\n"
|
||||
"message to be skipped if the channel is not in the 'up' state (i.e. it\n"
|
||||
"hasn't been answered yet. If 'skip' is specified, the application will\n"
|
||||
"return immediately should the channel not be off hook. Otherwise, unless\n"
|
||||
"'noanswer' is specified, the channel channel will be answered before the sound\n"
|
||||
"is played. Not all channels support playing messages while on hook. Returns -1\n"
|
||||
"if the channel was hung up, or if the file does not exist. Returns 0 otherwise.\n";
|
||||
"extension). Options may also be included following a pipe symbol. The 'skip'\n"
|
||||
"option causes the playback of the message to be skipped if the channel\n"
|
||||
"is not in the 'up' state (i.e. it hasn't been answered yet. If 'skip' is \n"
|
||||
"specified, the application will return immediately should the channel not be\n"
|
||||
"off hook. Otherwise, unless 'noanswer' is specified, the channel channel will\n"
|
||||
"be answered before the sound is played. Not all channels support playing\n"
|
||||
"messages while still hook. Returns -1 if the channel was hung up, or if the\n"
|
||||
"file does not exist. Returns 0 otherwise.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -52,7 +52,7 @@ static int playback_exec(struct ast_channel *chan, void *data)
|
||||
int option_skip=0;
|
||||
int option_noanswer = 0;
|
||||
char *stringp;
|
||||
if (!data || !strlen((char *)data)) {
|
||||
if (!data || ast_strlen_zero((char *)data)) {
|
||||
ast_log(LOG_WARNING, "Playback requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
3
apps/app_privacy.c
Executable file → Normal file
3
apps/app_privacy.c
Executable file → Normal file
@@ -25,7 +25,6 @@
|
||||
#include <asterisk/config.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define PRIV_CONFIG "privacy.conf"
|
||||
|
||||
@@ -38,7 +37,7 @@ static char *synopsis = "Require phone number to be entered, if no CallerID sent
|
||||
static char *descrip =
|
||||
" PrivacyManager: If no Caller*ID is sent, PrivacyManager answers the\n"
|
||||
"channel and asks the caller to enter their 10 digit phone number.\n"
|
||||
"The caller is given 3 attempts. If after 3 attempts, they do no enter\n"
|
||||
"The caller is given 3 attempts. If after 3 attempts, they do not enter\n"
|
||||
"their 10 digit phone number, and if there exists a priority n + 101,\n"
|
||||
"where 'n' is the priority of the current instance, then the\n"
|
||||
"channel will be setup to continue at that priority level.\n"
|
||||
|
||||
52
apps/app_qcall.c
Executable file → Normal file
52
apps/app_qcall.c
Executable file → Normal file
@@ -51,6 +51,7 @@
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
@@ -62,7 +63,6 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
@@ -73,7 +73,7 @@
|
||||
#include <sys/file.h>
|
||||
#include "../astconf.h"
|
||||
|
||||
char qdir[255];
|
||||
static char qdir[255];
|
||||
static char *tdesc = "Call from Queue";
|
||||
static pthread_t qcall_thread;
|
||||
static int debug = 0;
|
||||
@@ -123,7 +123,7 @@ pthread_attr_t attr;
|
||||
while((dp = readdir(dirp)) != NULL)
|
||||
{
|
||||
if (dp->d_name[0] == '.') continue;
|
||||
sprintf(fname,"%s/%s",qdir,dp->d_name);
|
||||
snprintf(fname, sizeof(fname), "%s/%s", qdir, dp->d_name);
|
||||
if (stat(fname,&mystat) == -1)
|
||||
{
|
||||
perror("app_qcall:stat");
|
||||
@@ -157,7 +157,7 @@ pthread_attr_t attr;
|
||||
arg = (void *) strdup(fname);
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
if (pthread_create(&dialer_thread,&attr,qcall_do,arg) == -1)
|
||||
if (ast_pthread_create(&dialer_thread,&attr,qcall_do,arg) == -1)
|
||||
{
|
||||
perror("qcall: Cannot create thread");
|
||||
continue;
|
||||
@@ -172,15 +172,20 @@ pthread_attr_t attr;
|
||||
/* single thread with one file (request) to dial */
|
||||
static void *qcall_do(void *arg)
|
||||
{
|
||||
char fname[300],dialstr[300],extstr[300],ident[300],reqinp[300],buf[300];
|
||||
char clid[300],*tele,*context;
|
||||
FILE *fp;
|
||||
int ms = MAXWAITFORANSWER,maxsecs;
|
||||
struct ast_channel *channel;
|
||||
time_t t;
|
||||
char fname[300] = "";
|
||||
char dialstr[300];
|
||||
char extstr[300];
|
||||
char ident[300] = "";
|
||||
char reqinp[300] = "";
|
||||
char buf[300];
|
||||
char clid[300],*tele,*context;
|
||||
FILE *fp;
|
||||
int ms = MAXWAITFORANSWER,maxsecs;
|
||||
struct ast_channel *channel;
|
||||
time_t t;
|
||||
|
||||
/* get the filename from the arg */
|
||||
strcpy(fname,(char *)arg);
|
||||
strncpy(fname,(char *)arg, sizeof(fname) - 1);
|
||||
free(arg);
|
||||
time(&t);
|
||||
fp = fopen(fname,"r");
|
||||
@@ -198,8 +203,11 @@ time_t t;
|
||||
fprintf(stderr,"%s\n",fname);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
strcpy(reqinp,"1"); /* default required input for acknowledgement */
|
||||
strcpy(ident, ""); /* default no ident */
|
||||
/* default required input for acknowledgement */
|
||||
reqinp[0] = '1';
|
||||
reqinp[1] = '\0';
|
||||
/* default no ident */
|
||||
ident[0] = '\0'; /* default no ident */
|
||||
if (fscanf(fp,"%s %s %s %d %s %s",dialstr,clid,
|
||||
extstr,&maxsecs,ident,reqinp) < 4)
|
||||
{
|
||||
@@ -308,8 +316,8 @@ time_t t;
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Qcall got accept, now putting through to %s@%s on %s\n",
|
||||
extstr,context,channel->name);
|
||||
if (strlen(ident)) {
|
||||
strcat(ident,"-ok");
|
||||
/* if file existant, play it */
|
||||
strncat(ident,"-ok", sizeof(ident) - strlen(ident) - 1);
|
||||
/* if file existent, play it */
|
||||
if (!ast_streamfile(channel,ident,0))
|
||||
{
|
||||
ast_waitstream(channel,"");
|
||||
@@ -326,7 +334,7 @@ time_t t;
|
||||
channel->amaflags = AMAFLAGS;
|
||||
#endif
|
||||
#ifdef ACCTCODE
|
||||
strcpy(channel->accountcode,ACCTCODE);
|
||||
strncpy(channel->accountcode, ACCTCODE, sizeof(chan->accountcode) - 1);
|
||||
#else
|
||||
channel->accountcode[0] = 0;
|
||||
#endif
|
||||
@@ -335,10 +343,10 @@ time_t t;
|
||||
time(&channel->whentohangup);
|
||||
channel->whentohangup += maxsecs;
|
||||
}
|
||||
strcpy(channel->exten,extstr);
|
||||
strcpy(channel->context,context);
|
||||
strncpy(channel->exten, extstr, sizeof(channel->exten) - 1);
|
||||
strncpy(channel->context, context, sizeof(channel->context) - 1);
|
||||
channel->priority = 1;
|
||||
printf("Caller ID is %s\n", channel->callerid);
|
||||
if(debug) printf("Caller ID is %s\n", channel->callerid);
|
||||
ast_pbx_run(channel);
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
@@ -362,9 +370,9 @@ int unload_module(void)
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
snprintf((char *)qdir,sizeof(qdir)-1,"%s/%s",(char *)ast_config_AST_SPOOL_DIR,"qcall");
|
||||
mkdir(qdir,0660);
|
||||
pthread_create(&qcall_thread,NULL,qcall,NULL);
|
||||
snprintf(qdir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "qcall");
|
||||
mkdir(qdir,0760);
|
||||
ast_pthread_create(&qcall_thread,NULL,qcall,NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
2064
apps/app_queue.c
Executable file → Normal file
2064
apps/app_queue.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
127
apps/app_random.c
Normal file
127
apps/app_random.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Random application
|
||||
*
|
||||
* Copyright (c) 2003-2004 Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <asterisk__app_random__20040111@the-tilghman.com>
|
||||
*
|
||||
* This code is released by the author with no restrictions on usage or distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static char *tdesc = "Random goto";
|
||||
|
||||
static char *app_random = "Random";
|
||||
|
||||
static char *random_synopsis = "Conditionally branches, based upon a probability";
|
||||
|
||||
static char *random_descrip =
|
||||
"Random([probability]:[[context|]extension|]priority)\n"
|
||||
" probability := INTEGER in the range 1 to 100\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int random_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
|
||||
char *s;
|
||||
char *exten, *pri, *context;
|
||||
char *prob;
|
||||
int probint, priorityint;
|
||||
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "Random requires an argument ([probability]:[[context|]extension|]priority)\n");
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
s = ast_strdupa((void *) data);
|
||||
|
||||
prob = strsep(&s,":");
|
||||
if ((!prob) || (sscanf(prob, "%d", &probint) != 1))
|
||||
probint = 0;
|
||||
|
||||
if ((random() % 100) + probint > 100) {
|
||||
context = strsep(&s, "|");
|
||||
exten = strsep(&s, "|");
|
||||
if (!exten) {
|
||||
/* Only a priority */
|
||||
pri = context;
|
||||
exten = NULL;
|
||||
context = NULL;
|
||||
} else {
|
||||
pri = strsep(&s, "|");
|
||||
if (!pri) {
|
||||
pri = exten;
|
||||
exten = context;
|
||||
context = NULL;
|
||||
}
|
||||
}
|
||||
if (!pri) {
|
||||
ast_log(LOG_WARNING, "No label specified\n");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
} else if (sscanf(pri, "%d", &priorityint) != 1) {
|
||||
ast_log(LOG_WARNING, "Priority '%s' must be a number > 0\n", pri);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
/* At this point we have a priority and */
|
||||
/* maybe an extension and a context */
|
||||
chan->priority = priorityint - 1;
|
||||
if (exten && strcasecmp(exten, "BYEXTENSION"))
|
||||
strncpy(chan->exten, exten, sizeof(chan->exten)-1);
|
||||
if (context)
|
||||
strncpy(chan->context, context, sizeof(chan->context)-1);
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Random branches to (%s,%s,%d)\n",
|
||||
chan->context,chan->exten, chan->priority+1);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app_random);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app_random, random_exec, random_synopsis, random_descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
144
apps/app_read.c
Normal file
144
apps/app_read.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Trivial application to read a variable
|
||||
*
|
||||
* Copyright (C) 2003, Digium
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static char *tdesc = "Read Variable Application";
|
||||
|
||||
static char *app = "Read";
|
||||
|
||||
static char *synopsis = "Read a variable";
|
||||
|
||||
static char *descrip =
|
||||
" Read(variable[|filename][|maxdigits][|option])\n\n"
|
||||
"Reads a #-terminated string of digits from the user in to the given variable,\n"
|
||||
"optionally playing a given filename first.\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 -- 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\n"
|
||||
"Returns -1 on hangup or error and 0 otherwise.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int read_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
char tmp[256];
|
||||
char argdata[256] = "";
|
||||
char *varname;
|
||||
char *filename;
|
||||
char *stringp;
|
||||
char *maxdigitstr;
|
||||
char *options;
|
||||
int option_skip = 0;
|
||||
int option_noanswer = 0;
|
||||
int maxdigits=255;
|
||||
if (!data || ast_strlen_zero((char *)data)) {
|
||||
ast_log(LOG_WARNING, "Read requires an argument (variable)\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(argdata, (char *)data, sizeof(argdata)-1);
|
||||
stringp=argdata;
|
||||
varname = strsep(&stringp, "|");
|
||||
filename = strsep(&stringp, "|");
|
||||
maxdigitstr = strsep(&stringp,"|");
|
||||
options = strsep(&stringp, "|");
|
||||
if (options && !strcasecmp(options, "skip"))
|
||||
option_skip = 1;
|
||||
if (options && !strcasecmp(options, "noanswer"))
|
||||
option_noanswer = 1;
|
||||
if (!(filename) || ast_strlen_zero(filename))
|
||||
filename = NULL;
|
||||
if (maxdigitstr) {
|
||||
maxdigits = atoi(maxdigitstr);
|
||||
if ((maxdigits<1) || (maxdigits>255)) {
|
||||
maxdigits = 255;
|
||||
} else
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Accepting a maximum of %i digits.\n", maxdigits);
|
||||
}
|
||||
if (!(varname) || ast_strlen_zero(varname)) {
|
||||
ast_log(LOG_WARNING, "Read requires an variable name\n");
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
if (option_skip) {
|
||||
/* At the user's option, skip if the line is not up */
|
||||
pbx_builtin_setvar_helper(chan, varname, "\0");
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
} else if (!option_noanswer) {
|
||||
/* Otherwise answer unless we're supposed to read while on-hook */
|
||||
res = ast_answer(chan);
|
||||
}
|
||||
}
|
||||
if (!res) {
|
||||
ast_stopstream(chan);
|
||||
res = ast_app_getdata(chan, filename, tmp, maxdigits, 0);
|
||||
if (res > -1) {
|
||||
pbx_builtin_setvar_helper(chan, varname, tmp);
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User entered '%s'\n", tmp);
|
||||
res = 0;
|
||||
} else {
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User disconnected\n");
|
||||
}
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, read_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
213
apps/app_record.c
Executable file → Normal file
213
apps/app_record.c
Executable file → Normal file
@@ -18,9 +18,9 @@
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/dsp.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Trivial Record Application";
|
||||
|
||||
@@ -29,9 +29,19 @@ static char *app = "Record";
|
||||
static char *synopsis = "Record to a file";
|
||||
|
||||
static char *descrip =
|
||||
" Record(filename:extension): Records from the channel into a given\n"
|
||||
"filename. If the file exists it will be overwritten. The 'extension'\n"
|
||||
"is the extension of the file type to be recorded (wav, gsm, etc).\n"
|
||||
" Record(filename:format|silence[|maxduration][|option])\n\n"
|
||||
"Records from the channel into a given filename. If the file exists it will\n"
|
||||
"be overwritten.\n"
|
||||
"- 'format' is the format of the file type to be recorded (wav, gsm, etc).\n"
|
||||
"- 'silence' is the number of seconds of silence to allow before returning.\n"
|
||||
"- 'maxduration' is the maximum recording duration in seconds. If missing\n"
|
||||
"or 0 there is no maximum.\n"
|
||||
"- 'option' may be 'skip' to return immediately if the line is not up,\n"
|
||||
"or 'noanswer' to attempt to record even if the line is not up.\n\n"
|
||||
"If filename contains '%d', these characters will be replaced with a number\n"
|
||||
"incremented by one each time the file is recorded. \n\n"
|
||||
"Formats: g723, g729, gsm, h263, ulaw, alaw, vox, wav, WAV\n\n"
|
||||
"User can press '#' to terminate the recording and continue to the next priority.\n\n"
|
||||
"Returns -1 when the user hangs up.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
@@ -46,58 +56,142 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
char fil[256];
|
||||
char tmp[256];
|
||||
char ext[10];
|
||||
char * vdata; /* Used so I don't have to typecast every use of *data */
|
||||
char *vdata;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
|
||||
struct ast_filestream *s = '\0';
|
||||
struct localuser *u;
|
||||
struct ast_frame *f = NULL;
|
||||
|
||||
vdata = data; /* explained above */
|
||||
|
||||
struct ast_dsp *sildet = NULL; /* silence detector dsp */
|
||||
int totalsilence = 0;
|
||||
int dspsilence = 0;
|
||||
int silence = 0; /* amount of silence to allow */
|
||||
int gotsilence = 0; /* did we timeout for silence? */
|
||||
char silencestr[5];
|
||||
char durationstr[8];
|
||||
int maxduration = 0; /* max duration of recording */
|
||||
int gottimeout = 0; /* did we timeout for maxduration exceeded? */
|
||||
time_t timeout = 0;
|
||||
char option[16];
|
||||
int option_skip = 0;
|
||||
int option_noanswer = 0;
|
||||
int rfmt = 0;
|
||||
int flags;
|
||||
char *end=NULL;
|
||||
char *p=NULL;
|
||||
|
||||
|
||||
|
||||
/* The next few lines of code parse out the filename and header from the input string */
|
||||
if (!vdata) { /* no data implies no filename or anything is present */
|
||||
if (!data) { /* no data implies no filename or anything is present */
|
||||
ast_log(LOG_WARNING, "Record requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
vdata = ast_strdupa(data);
|
||||
|
||||
p = vdata;
|
||||
while(p && (p=strchr(p,':'))) {
|
||||
end=p;
|
||||
if(!strcasecmp(end,":end")) {
|
||||
*end='\0';
|
||||
end++;
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
end=NULL;
|
||||
}
|
||||
|
||||
|
||||
for (; vdata[i] && (vdata[i] != ':') && (vdata[i] != '|'); i++ ) {
|
||||
if ((vdata[i] == '%') && (vdata[i+1] == 'd')) {
|
||||
percentflag = 1; /* the wildcard is used */
|
||||
}
|
||||
|
||||
if (i == strlen(vdata) ) {
|
||||
ast_log(LOG_WARNING, "No extension found\n");
|
||||
return -1;
|
||||
}
|
||||
fil[i] = vdata[i];
|
||||
if (j < sizeof(fil) - 1)
|
||||
fil[j++] = vdata[i];
|
||||
}
|
||||
fil[i++] = '\0';
|
||||
fil[j] = '\0';
|
||||
|
||||
for (; j < 10 && i < strlen(data); i++, j++)
|
||||
ext[j] = vdata[i];
|
||||
if (vdata[i] != ':') {
|
||||
ast_log(LOG_WARNING, "No extension found\n");
|
||||
return -1;
|
||||
}
|
||||
i++;
|
||||
|
||||
j = 0;
|
||||
for (; vdata[i] && (vdata[i] != '|'); i++)
|
||||
if (j < sizeof(ext) - 1)
|
||||
ext[j++] = vdata[i];
|
||||
ext[j] = '\0';
|
||||
|
||||
if (vdata[i] == '|')
|
||||
i++;
|
||||
|
||||
j = 0;
|
||||
for (; vdata[i] && (vdata[i] != '|'); i++)
|
||||
if (j < sizeof(silencestr) - 1)
|
||||
silencestr[j++] = vdata[i];
|
||||
silencestr[j] = '\0';
|
||||
|
||||
if (j > 0) {
|
||||
silence = atoi(silencestr);
|
||||
if (silence > 0)
|
||||
silence *= 1000;
|
||||
}
|
||||
|
||||
if (vdata[i] == '|')
|
||||
i++;
|
||||
|
||||
j = 0;
|
||||
for (; vdata[i] && (vdata[i] != '|'); i++)
|
||||
if (j < sizeof(durationstr) - 1)
|
||||
durationstr[j++] = vdata[i];
|
||||
durationstr[j] = '\0';
|
||||
|
||||
if (j > 0)
|
||||
maxduration = atoi(durationstr);
|
||||
|
||||
if (vdata[i] == '|')
|
||||
i++;
|
||||
|
||||
j = 0;
|
||||
for (; vdata[i] && (vdata[i] != '|'); i++)
|
||||
if (j < sizeof(option) - 1)
|
||||
option[j++] = vdata[i];
|
||||
option[j] = '\0';
|
||||
|
||||
if (!strcasecmp(option, "skip"))
|
||||
option_skip = 1;
|
||||
if (!strcasecmp(option, "noanswer"))
|
||||
option_noanswer = 1;
|
||||
|
||||
/* done parsing */
|
||||
|
||||
|
||||
|
||||
/* these are to allow the use of the %d in the config file for a wild card of sort to
|
||||
create a new file with the inputed name scheme */
|
||||
if (percentflag) {
|
||||
do {
|
||||
snprintf(tmp, 256, fil, count);
|
||||
snprintf(tmp, sizeof(tmp), fil, count);
|
||||
count++;
|
||||
} while ( ast_fileexists(tmp, ext, chan->language) != -1 );
|
||||
pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp);
|
||||
} else
|
||||
strncpy(tmp, fil, 256-1);
|
||||
strncpy(tmp, fil, sizeof(tmp)-1);
|
||||
/* end of routine mentioned */
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
res = ast_answer(chan); /* Shouldn't need this, but checking to see if channel is already answered
|
||||
* Theoretically asterisk should already have answered before running the app */
|
||||
if (option_skip) {
|
||||
/* At the user's option, skip if the line is not up */
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
} else if (!option_noanswer) {
|
||||
/* Otherwise answer unless we're supposed to record while on-hook */
|
||||
res = ast_answer(chan);
|
||||
}
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
@@ -109,11 +203,40 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", chan->name);
|
||||
}
|
||||
ast_stopstream(chan);
|
||||
|
||||
/* The end of beep code. Now the recording starts */
|
||||
s = ast_writefile( tmp, ext, NULL, O_CREAT|O_TRUNC|O_WRONLY , 0, 0644);
|
||||
|
||||
|
||||
|
||||
if (silence > 0) {
|
||||
rfmt = chan->readformat;
|
||||
res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
|
||||
return -1;
|
||||
}
|
||||
sildet = ast_dsp_new();
|
||||
if (!sildet) {
|
||||
ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
|
||||
return -1;
|
||||
}
|
||||
ast_dsp_set_threshold(sildet, 256);
|
||||
}
|
||||
|
||||
|
||||
flags = end ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY;
|
||||
s = ast_writefile( tmp, ext, NULL, flags , 0, 0644);
|
||||
|
||||
|
||||
if (s) {
|
||||
if (maxduration > 0)
|
||||
timeout = time(NULL) + (time_t)maxduration;
|
||||
|
||||
while (ast_waitfor(chan, -1) > -1) {
|
||||
if (maxduration > 0 && time(NULL) > timeout) {
|
||||
gottimeout = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
res = -1;
|
||||
@@ -126,6 +249,30 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
ast_log(LOG_WARNING, "Problem writing frame\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (silence > 0) {
|
||||
dspsilence = 0;
|
||||
ast_dsp_silence(sildet, f, &dspsilence);
|
||||
if (dspsilence) {
|
||||
totalsilence = dspsilence;
|
||||
} else {
|
||||
totalsilence = 0;
|
||||
}
|
||||
if (totalsilence > silence) {
|
||||
/* Ended happily with silence */
|
||||
ast_frfree(f);
|
||||
gotsilence = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (f->frametype == AST_FRAME_VIDEO) {
|
||||
res = ast_writestream(s, f);
|
||||
|
||||
if (res) {
|
||||
ast_log(LOG_WARNING, "Problem writing frame\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((f->frametype == AST_FRAME_DTMF) &&
|
||||
(f->subclass == '#')) {
|
||||
@@ -138,6 +285,15 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
ast_log(LOG_DEBUG, "Got hangup\n");
|
||||
res = -1;
|
||||
}
|
||||
|
||||
if (gotsilence) {
|
||||
ast_stream_rewind(s, silence-1000);
|
||||
ast_truncstream(s);
|
||||
} else if (!gottimeout) {
|
||||
/* Strip off the last 1/4 second of it */
|
||||
ast_stream_rewind(s, 250);
|
||||
ast_truncstream(s);
|
||||
}
|
||||
ast_closestream(s);
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Could not create file %s\n", fil);
|
||||
@@ -145,6 +301,13 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
if ((silence > 0) && rfmt) {
|
||||
res = ast_set_read_format(chan, rfmt);
|
||||
if (res)
|
||||
ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
|
||||
if (sildet)
|
||||
ast_dsp_free(sildet);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
3857
apps/app_rpt.c
Executable file → Normal file
3857
apps/app_rpt.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
141
apps/app_sayunixtime.c
Normal file
141
apps/app_sayunixtime.c
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* SayUnixTime application
|
||||
*
|
||||
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <app_sayunixtime__200309@the-tilghman.com>
|
||||
*
|
||||
* This code is released by the author with no restrictions on usage.
|
||||
*
|
||||
*/
|
||||
|
||||
#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/say.h>
|
||||
|
||||
|
||||
static char *tdesc = "Say time";
|
||||
|
||||
static char *app_sayunixtime = "SayUnixTime";
|
||||
static char *app_datetime = "DateTime";
|
||||
|
||||
static char *sayunixtime_synopsis = "Says a specified time in a custom format";
|
||||
|
||||
static char *sayunixtime_descrip =
|
||||
"SayUnixTime([unixtime][|[timezone][|format]])\n"
|
||||
" unixtime: time, in seconds since Jan 1, 1970. May be negative.\n"
|
||||
" defaults to now.\n"
|
||||
" timezone: timezone, see /usr/share/zoneinfo for a list.\n"
|
||||
" defaults to machine default.\n"
|
||||
" format: a format the time is to be said in. See voicemail.conf.\n"
|
||||
" defaults to \"ABdY 'digits/at' IMp\"\n"
|
||||
" Returns 0 or -1 on hangup.\n";
|
||||
static char *datetime_descrip =
|
||||
"DateTime([unixtime][|[timezone][|format]])\n"
|
||||
" unixtime: time, in seconds since Jan 1, 1970. May be negative.\n"
|
||||
" defaults to now.\n"
|
||||
" timezone: timezone, see /usr/share/zoneinfo for a list.\n"
|
||||
" defaults to machine default.\n"
|
||||
" format: a format the time is to be said in. See voicemail.conf.\n"
|
||||
" defaults to \"ABdY 'digits/at' IMp\"\n"
|
||||
" Returns 0 or -1 on hangup.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int sayunixtime_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char *s,*zone=NULL,*timec;
|
||||
time_t unixtime;
|
||||
char *format = "ABdY 'digits/at' IMp";
|
||||
struct timeval tv;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
gettimeofday(&tv,NULL);
|
||||
unixtime = (time_t)tv.tv_sec;
|
||||
|
||||
if (data) {
|
||||
s = data;
|
||||
s = ast_strdupa(s);
|
||||
if (s) {
|
||||
timec = strsep(&s,"|");
|
||||
if ((timec) && (*timec != '\0')) {
|
||||
long timein;
|
||||
if (sscanf(timec,"%ld",&timein) == 1) {
|
||||
unixtime = (time_t)timein;
|
||||
}
|
||||
}
|
||||
if (s) {
|
||||
zone = strsep(&s,"|");
|
||||
if (zone && (*zone == '\0'))
|
||||
zone = NULL;
|
||||
if (s) {
|
||||
format = s;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Out of memory error\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
res = ast_answer(chan);
|
||||
}
|
||||
if (!res)
|
||||
res = ast_say_date_with_format(chan, unixtime, AST_DIGIT_ANY, chan->language, format, zone);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
res = ast_unregister_application(app_sayunixtime);
|
||||
if (! res)
|
||||
return ast_unregister_application(app_datetime);
|
||||
else
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
res = ast_register_application(app_sayunixtime, sayunixtime_exec, sayunixtime_synopsis, sayunixtime_descrip);
|
||||
if (! res)
|
||||
return ast_register_application(app_datetime, sayunixtime_exec, sayunixtime_synopsis, datetime_descrip);
|
||||
else
|
||||
return res;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
33
apps/app_senddtmf.c
Executable file → Normal file
33
apps/app_senddtmf.c
Executable file → Normal file
@@ -19,9 +19,10 @@
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Send DTMF digits Application";
|
||||
|
||||
@@ -30,8 +31,9 @@ static char *app = "SendDTMF";
|
||||
static char *synopsis = "Sends arbitrary DTMF digits";
|
||||
|
||||
static char *descrip =
|
||||
" SendDTMF(digits): Sends DTMF digits on a channel. Returns 0 on success"
|
||||
"or -1 on a hangup.\n";
|
||||
" SendDTMF(digits): Sends DTMF digits on a channel. \n"
|
||||
" Accepted digits: 0-9, *#abcd\n"
|
||||
" Returns 0 on success or -1 on a hangup.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -42,30 +44,13 @@ static int senddtmf_exec(struct ast_channel *chan, void *data)
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
char *digits = data;
|
||||
struct ast_frame f;
|
||||
int x;
|
||||
if (!digits || !strlen(digits)) {
|
||||
ast_log(LOG_WARNING, "SendDTMF requires an argument (digits)\n");
|
||||
|
||||
if (!digits || ast_strlen_zero(digits)) {
|
||||
ast_log(LOG_WARNING, "SendDTMF requires an argument (digits or *#aAbBcCdD)\n");
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
for (x=0;x<strlen(digits);x++) {
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.frametype = AST_FRAME_DTMF;
|
||||
f.subclass = digits[x];
|
||||
f.src = "app_senddtmf";
|
||||
res = ast_write(chan, &f);
|
||||
if (res)
|
||||
break;
|
||||
/* Wait 250ms */
|
||||
res = ast_safe_sleep(chan, 250);
|
||||
if (res)
|
||||
break;
|
||||
}
|
||||
if (!res)
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Sent digit string '%s' on %s\n", digits, chan->name);
|
||||
|
||||
res = ast_dtmf_stream(chan,NULL,digits,250);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
94
apps/app_sendtext.c
Normal file
94
apps/app_sendtext.c
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* App to transmit a text message
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/channel_pvt.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static char *tdesc = "Send Text Applications";
|
||||
|
||||
static char *app = "SendText";
|
||||
|
||||
static char *synopsis = "Send a Text Message";
|
||||
|
||||
static char *descrip =
|
||||
" SendText(text): Sends text to client. If the client\n"
|
||||
"does not support text transport, and there exists a step with\n"
|
||||
"priority n + 101, then execution will continue at that step.\n"
|
||||
"Otherwise, execution will continue at the next priority level.\n"
|
||||
"SendText only returns 0 if the text was sent correctly or if\n"
|
||||
"the channel does not support text transport, and -1 otherwise.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int sendtext_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
if (!data || !strlen((char *)data)) {
|
||||
ast_log(LOG_WARNING, "SendText requires an argument (text)\n");
|
||||
return -1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
ast_mutex_lock(&chan->lock);
|
||||
if (!chan->pvt->send_text) {
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
/* Does not support transport */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
ast_mutex_unlock(&chan->lock);
|
||||
res = ast_sendtext(chan, (char *)data);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, sendtext_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
81
apps/app_setcallerid.c
Executable file → Normal file
81
apps/app_setcallerid.c
Executable file → Normal file
@@ -19,9 +19,82 @@
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *app2 = "SetCallerPres";
|
||||
|
||||
static char *synopsis2 = "Set CallerID Presentation";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static struct {
|
||||
int val;
|
||||
char *name;
|
||||
} preses[] = {
|
||||
{ AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED, "allowed_not_screened" },
|
||||
{ AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, "allowed_passed_screen" },
|
||||
{ AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN, "allowed_failed_screen" },
|
||||
{ AST_PRES_ALLOWED_NETWORK_NUMBER, "allowed" },
|
||||
{ AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED , "prohib_not_screened" },
|
||||
{ AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "prohib_passed_screen" },
|
||||
{ AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "prohib_failed_screen" },
|
||||
{ AST_PRES_PROHIB_NETWORK_NUMBER, "prohib" },
|
||||
{ AST_PRES_NUMBER_NOT_AVAILABLE, "unavailable" },
|
||||
};
|
||||
|
||||
static char *descrip2 =
|
||||
" SetCallerPres(presentation): Set Caller*ID presentation on\n"
|
||||
"a call to a new value. Sets ANI as well if a flag is used.\n"
|
||||
"Always returns 0. Valid presentations are:\n"
|
||||
"\n"
|
||||
" allowed_not_screened : Presentation Allowed, Not Screened\n"
|
||||
" allowed_passed_screen : Presentation Allowed, Passed Screen\n"
|
||||
" allowed_failed_screen : Presentation Allowed, Failed Screen\n"
|
||||
" allowed : Presentation Allowed, Network Number\n"
|
||||
" prohib_not_screened : Presentation Prohibited, Not Screened\n"
|
||||
" prohib_passed_screen : Presentation Prohibited, Passed Screen\n"
|
||||
" prohib_failed_screen : Presentation Prohibited, Failed Screen\n"
|
||||
" prohib : Presentation Prohibited, Network Number\n"
|
||||
" unavailable : Number Unavailable\n"
|
||||
"\n"
|
||||
;
|
||||
|
||||
static int setcallerid_pres_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
char tmp[256] = "";
|
||||
struct localuser *u;
|
||||
int x;
|
||||
char *opts;
|
||||
int pres = -1;
|
||||
if (data)
|
||||
strncpy(tmp, (char *)data, sizeof(tmp) - 1);
|
||||
opts = strchr(tmp, '|');
|
||||
if (opts) {
|
||||
*opts = '\0';
|
||||
opts++;
|
||||
}
|
||||
for (x=0;x<sizeof(preses) / sizeof(preses[0]);x++) {
|
||||
if (!strcasecmp(preses[x].name, tmp)) {
|
||||
pres = preses[x].val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pres < 0) {
|
||||
ast_log(LOG_WARNING, "'%s' is not a valid presentation (see 'show application SetCallerPres')\n", tmp);
|
||||
return 0;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
chan->callingpres = pres;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static char *tdesc = "Set CallerID Application";
|
||||
|
||||
@@ -33,10 +106,6 @@ static char *descrip =
|
||||
" SetCallerID(clid[|a]): Set Caller*ID on a call to a new\n"
|
||||
"value. Sets ANI as well if a flag is used. Always returns 0\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
@@ -62,11 +131,13 @@ static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
ast_unregister_application(app2);
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
ast_register_application(app2, setcallerid_pres_exec, synopsis2, descrip2);
|
||||
return ast_register_application(app, setcallerid_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
|
||||
165
apps/app_setcdruserfield.c
Normal file
165
apps/app_setcdruserfield.c
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Applictions connected with CDR engine
|
||||
*
|
||||
* Copyright (C) 2003, Digium
|
||||
*
|
||||
* Justin Huff <jjhuff@mspin.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/cdr.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/manager.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static char *tdesc = "CDR user field apps";
|
||||
|
||||
static char *setcdruserfield_descrip =
|
||||
"[Synopsis]\n"
|
||||
"SetCDRUserField(value)\n\n"
|
||||
"[Description]\n"
|
||||
"SetCDRUserField(value): Set the CDR 'user field' to value\n"
|
||||
" The Call Data Record (CDR) user field is an extra field you\n"
|
||||
" 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"
|
||||
" Always returns 0\n";
|
||||
|
||||
|
||||
static char *setcdruserfield_app = "SetCDRUserField";
|
||||
static char *setcdruserfield_synopsis = "Set the CDR user field";
|
||||
|
||||
static char *appendcdruserfield_descrip =
|
||||
"[Synopsis]\n"
|
||||
"AppendCDRUserField(value)\n\n"
|
||||
"[Description]\n"
|
||||
"AppendCDRUserField(value): Append value to the CDR user field\n"
|
||||
" The Call Data Record (CDR) user field is an extra field you\n"
|
||||
" 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"
|
||||
" Always returns 0\n";
|
||||
|
||||
static char *appendcdruserfield_app = "AppendCDRUserField";
|
||||
static char *appendcdruserfield_synopsis = "Append to the CDR user field";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int action_setcdruserfield(struct mansession *s, struct message *m)
|
||||
{
|
||||
struct ast_channel *c = NULL;
|
||||
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");
|
||||
return 0;
|
||||
}
|
||||
if (ast_strlen_zero(userfield)) {
|
||||
astman_send_error(s, m, "No UserField specified");
|
||||
return 0;
|
||||
}
|
||||
c = ast_channel_walk_locked(NULL);
|
||||
while (c) {
|
||||
if (!strcasecmp(c->name, channel))
|
||||
break;
|
||||
ast_mutex_unlock(&c->lock);
|
||||
c = ast_channel_walk_locked(c);
|
||||
}
|
||||
if (!c) {
|
||||
astman_send_error(s, m, "No such channel");
|
||||
return 0;
|
||||
}
|
||||
if (ast_true(append))
|
||||
ast_cdr_appenduserfield(c, userfield);
|
||||
else
|
||||
ast_cdr_setuserfield(c, userfield);
|
||||
ast_mutex_unlock(&c->lock);
|
||||
astman_send_ack(s, m, "CDR Userfield Set");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setcdruserfield_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
int res = 0;
|
||||
|
||||
LOCAL_USER_ADD(u)
|
||||
if (chan->cdr && data)
|
||||
{
|
||||
ast_cdr_setuserfield(chan, (char*)data);
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int appendcdruserfield_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
int res = 0;
|
||||
|
||||
LOCAL_USER_ADD(u)
|
||||
if (chan->cdr && data)
|
||||
{
|
||||
ast_cdr_appenduserfield(chan, (char*)data);
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
res = ast_unregister_application(setcdruserfield_app);
|
||||
res |= ast_unregister_application(appendcdruserfield_app);
|
||||
ast_manager_unregister("SetCDRUserField");
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
res = ast_register_application(setcdruserfield_app, setcdruserfield_exec, setcdruserfield_synopsis, setcdruserfield_descrip);
|
||||
res |= ast_register_application(appendcdruserfield_app, appendcdruserfield_exec, appendcdruserfield_synopsis, appendcdruserfield_descrip);
|
||||
ast_manager_register("SetCDRUserField", EVENT_FLAG_CALL, action_setcdruserfield, "Set the CDR UserField");
|
||||
return res;
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
12
apps/app_setcidname.c
Executable file → Normal file
12
apps/app_setcidname.c
Executable file → Normal file
@@ -20,9 +20,9 @@
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/image.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Set CallerID Name";
|
||||
|
||||
@@ -63,17 +63,17 @@ static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
strncpy(oldcid, chan->callerid, sizeof(oldcid) - 1);
|
||||
ast_callerid_parse(oldcid, &n, &l);
|
||||
n = tmp;
|
||||
if (strlen(n)) {
|
||||
if (l && strlen(l))
|
||||
if (!ast_strlen_zero(n)) {
|
||||
if (l && !ast_strlen_zero(l))
|
||||
snprintf(newcid, sizeof(newcid), "\"%s\" <%s>", n, l);
|
||||
else
|
||||
strncpy(newcid, tmp, sizeof(newcid) - 1);
|
||||
} else if (l && strlen(l)) {
|
||||
} else if (l && !ast_strlen_zero(l)) {
|
||||
strncpy(newcid, l, sizeof(newcid) - 1);
|
||||
}
|
||||
} else
|
||||
strncpy(newcid, tmp, sizeof(newcid));
|
||||
ast_set_callerid(chan, strlen(newcid) ? newcid : NULL, anitoo);
|
||||
strncpy(newcid, tmp, sizeof(newcid) - 1);
|
||||
ast_set_callerid(chan, !ast_strlen_zero(newcid) ? newcid : NULL, anitoo);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
108
apps/app_setcidnum.c
Normal file
108
apps/app_setcidnum.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* App to set callerid
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Oliver Daudey <traveler@xs4all.nl>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#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>
|
||||
#include <string.h>
|
||||
#include <stdlib.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. Always returns 0\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
char tmp[256] = "";
|
||||
char oldcid[256] = "", *l, *n;
|
||||
char newcid[256] = "";
|
||||
struct localuser *u;
|
||||
char *opt;
|
||||
int anitoo = 0;
|
||||
if (data)
|
||||
strncpy(tmp, (char *)data, sizeof(tmp) - 1);
|
||||
opt = strchr(tmp, '|');
|
||||
if (opt) {
|
||||
*opt = '\0';
|
||||
opt++;
|
||||
if (*opt == 'a')
|
||||
anitoo = 1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
if (chan->callerid) {
|
||||
strncpy(oldcid, chan->callerid, sizeof(oldcid) - 1);
|
||||
ast_callerid_parse(oldcid, &n, &l);
|
||||
l = tmp;
|
||||
if (!ast_strlen_zero(l)) {
|
||||
if (n && !ast_strlen_zero(n))
|
||||
snprintf(newcid, sizeof(newcid), "\"%s\" <%s>", n, l);
|
||||
else
|
||||
strncpy(newcid, tmp, sizeof(newcid) - 1);
|
||||
} else if (n && !ast_strlen_zero(n)) {
|
||||
strncpy(newcid, n, sizeof(newcid) - 1);
|
||||
}
|
||||
} else
|
||||
strncpy(newcid, tmp, sizeof(newcid) - 1);
|
||||
ast_set_callerid(chan, !ast_strlen_zero(newcid) ? newcid : NULL, anitoo);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
11
apps/app_skel.c
Executable file → Normal file
11
apps/app_skel.c
Executable file → Normal file
@@ -16,17 +16,16 @@
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Trivial skeleton Application";
|
||||
|
||||
static char *app = "skel";
|
||||
static char *synopsis =
|
||||
" This is a skeleton application that shows you the basic structure to create your\n"
|
||||
"own asterisk applications.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -54,7 +53,7 @@ int unload_module(void)
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, skel_exec);
|
||||
return ast_register_application(app, skel_exec, synopsis, tdesc);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
|
||||
1236
apps/app_sms.c
Normal file
1236
apps/app_sms.c
Normal file
File diff suppressed because it is too large
Load Diff
11
apps/app_softhangup.c
Executable file → Normal file
11
apps/app_softhangup.c
Executable file → Normal file
@@ -11,19 +11,18 @@
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <sys/types.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 <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *synopsis = "Soft Hangup Application";
|
||||
|
||||
static char *tdesc = "Hangs up the requested channel";
|
||||
@@ -46,13 +45,15 @@ static int softhangup_exec(struct ast_channel *chan, void *data)
|
||||
return 0;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
c = ast_channel_walk(NULL);
|
||||
c = ast_channel_walk_locked(NULL);
|
||||
while (c) {
|
||||
if (!strcasecmp(c->name, data)) {
|
||||
ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
|
||||
ast_mutex_unlock(&c->lock);
|
||||
break;
|
||||
}
|
||||
c = ast_channel_walk(c);
|
||||
ast_mutex_unlock(&c->lock);
|
||||
c = ast_channel_walk_locked(c);
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
|
||||
128
apps/app_sql_postgres.c
Executable file → Normal file
128
apps/app_sql_postgres.c
Executable file → Normal file
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* Copyright (C) 2002, Christos Ricudis
|
||||
*
|
||||
* Christos Ricudis <ricudis@paiko.gr>
|
||||
* Christos Ricudis <ricudis@itc.auth.gr>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
@@ -26,10 +26,9 @@
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include "libpq-fe.h"
|
||||
|
||||
|
||||
#define EXTRA_LOG 0
|
||||
|
||||
|
||||
static char *tdesc = "Simple PostgreSQL Interface";
|
||||
@@ -39,57 +38,67 @@ static char *app = "PGSQL";
|
||||
static char *synopsis = "Do several SQLy things";
|
||||
|
||||
static char *descrip =
|
||||
" PGSQL(): Do several SQLy things\n";
|
||||
"PGSQL(): Do several SQLy things\n"
|
||||
"Syntax:\n"
|
||||
" PGSQL(Connect var option-string)\n"
|
||||
" Connects to a database. Option string contains standard PostgreSQL\n"
|
||||
" parameters like host=, dbname=, user=. Connection identifer returned\n"
|
||||
" in ${var}\n"
|
||||
" PGSQL(Query var ${connection_identifier} query-string)\n"
|
||||
" Executes standard SQL query contained in query-string using established\n"
|
||||
" connection identified by ${connection_identifier}. Reseult of query is\n"
|
||||
" is stored in ${var}.\n"
|
||||
" PGSQL(Fetch statusvar ${result_identifier} var1 var2 ... varn)\n"
|
||||
" Fetches a single row from a result set contained in ${result_identifier}.\n"
|
||||
" Assigns returned fields to ${var1} ... ${varn}. ${statusvar} is set TRUE\n"
|
||||
" if additional rows exist in reseult set.\n"
|
||||
" PGSQL(Clear ${result_identifier})\n"
|
||||
" Frees memory and datastructures associated with result set.\n"
|
||||
" PGSQL(Disconnect ${connection_identifier})\n"
|
||||
" Disconnects from named connection to PostgreSQL.\n" ;
|
||||
|
||||
/*
|
||||
|
||||
Syntax of SQL commands :
|
||||
|
||||
Connect #var option-string
|
||||
Connect var option-string
|
||||
|
||||
Connects to a database using the option-string and stores the
|
||||
connection identifier in $var
|
||||
connection identifier in ${var}
|
||||
|
||||
|
||||
Query var connection-identifier query-string
|
||||
Query var ${connection_identifier} query-string
|
||||
|
||||
Submits query-string to database backend and stores the result
|
||||
identifier in ${var}
|
||||
|
||||
|
||||
Fetch statusvar result-identifier var1 var2 var3 ... varn
|
||||
Fetch statusvar ${result_identifier} var1 var2 var3 ... varn
|
||||
|
||||
Fetches a row from the query and stores end-of-table status in
|
||||
${statusvar} and columns in ${var1}..${varn}
|
||||
|
||||
|
||||
Clear result-identifier
|
||||
Clear ${result_identifier}
|
||||
|
||||
Clears data structures associated with result-identifier
|
||||
Clears data structures associated with ${result_identifier}
|
||||
|
||||
|
||||
Disconnect connection-identifier
|
||||
Disconnect ${connection_identifier}
|
||||
|
||||
Disconnects from named connection
|
||||
|
||||
|
||||
EXAMPLES OF USE :
|
||||
|
||||
(
|
||||
$2 = Connection Identifier
|
||||
$3 = Result Identifier
|
||||
$4 = Fetch Status Identifier (0 = no more rows)
|
||||
$5, $6 = Data variables
|
||||
)
|
||||
|
||||
exten => s,2,PGSQL,"Connect connid host=localhost user=asterisk dbname=credit";
|
||||
exten => s,3,PGSQL,"Query resultid ${connid} SELECT username,credit FROM credit WHERE callerid=${callerid}";
|
||||
exten => s,4,PGSQL,"Fetch fetchid ${resultid} datavar1 datavar2";
|
||||
exten => s,5,GotoIf,"${fetchid}=1?s|6:s|8";
|
||||
exten => s,6,blablabla ${datavar1} ${datavar2} (does blablabla, datavar1 = username, datavar2 = credit);
|
||||
exten => s,7,Goto,s|4
|
||||
exten => s,8,PGSQL,"Clear ${resultid}";
|
||||
exten => s,9,PGSQL,"Disconnect ${connid}";
|
||||
exten => s,2,PGSQL(Connect connid host=localhost user=asterisk dbname=credit)
|
||||
exten => s,3,PGSQL(Query resultid ${connid} SELECT username,credit FROM credit WHERE callerid=${CALLERIDNUM})
|
||||
exten => s,4,PGSQL(Fetch fetchid ${resultid} datavar1 datavar2)
|
||||
exten => s,5,GotoIf(${fetchid}?6:8)
|
||||
exten => s,6,Festival("User ${datavar1} currently has credit balance of ${datavar2} dollars.")
|
||||
exten => s,7,Goto(s,4)
|
||||
exten => s,8,PGSQL(Clear ${resultid})
|
||||
exten => s,9,PGSQL(Disconnect ${connid})
|
||||
|
||||
*/
|
||||
|
||||
@@ -97,8 +106,6 @@ STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
extern void pbx_builtin_setvar_helper(struct ast_channel *chan, char *name, char *value);
|
||||
|
||||
#define AST_PGSQL_ID_DUMMY 0
|
||||
#define AST_PGSQL_ID_CONNID 1
|
||||
#define AST_PGSQL_ID_RESID 2
|
||||
@@ -201,8 +208,8 @@ static int del_identifier(int identifier,int identifier_type) {
|
||||
|
||||
static int aPGSQL_connect(struct ast_channel *chan, void *data) {
|
||||
|
||||
char *s1,*s4;
|
||||
char s[100];
|
||||
char *s1;
|
||||
char s[100] = "";
|
||||
char *optionstring;
|
||||
char *var;
|
||||
int l;
|
||||
@@ -215,7 +222,7 @@ static int aPGSQL_connect(struct ast_channel *chan, void *data) {
|
||||
res=0;
|
||||
l=strlen(data)+2;
|
||||
s1=malloc(l);
|
||||
strncpy(s1,data,l);
|
||||
strncpy(s1, data, l -1);
|
||||
stringp=s1;
|
||||
strsep(&stringp," "); // eat the first token, we already know it :P
|
||||
var=strsep(&stringp," ");
|
||||
@@ -229,8 +236,7 @@ static int aPGSQL_connect(struct ast_channel *chan, void *data) {
|
||||
} else {
|
||||
ast_log(LOG_WARNING,"adding identifier\n");
|
||||
id=add_identifier(AST_PGSQL_ID_CONNID,karoto);
|
||||
s4=&s[0];
|
||||
sprintf(s4,"%d",id);
|
||||
snprintf(s, sizeof(s), "%d", id);
|
||||
pbx_builtin_setvar_helper(chan,var,s);
|
||||
}
|
||||
|
||||
@@ -240,8 +246,9 @@ static int aPGSQL_connect(struct ast_channel *chan, void *data) {
|
||||
|
||||
static int aPGSQL_query(struct ast_channel *chan, void *data) {
|
||||
|
||||
char *s1,*s2,*s3,*s4,*s5;
|
||||
char s[100];
|
||||
|
||||
char *s1,*s2,*s3,*s4;
|
||||
char s[100] = "";
|
||||
char *querystring;
|
||||
char *var;
|
||||
int l;
|
||||
@@ -256,7 +263,7 @@ static int aPGSQL_query(struct ast_channel *chan, void *data) {
|
||||
l=strlen(data)+2;
|
||||
s1=malloc(l);
|
||||
s2=malloc(l);
|
||||
strcpy(s1,data);
|
||||
strncpy(s1, data, l - 1);
|
||||
stringp=s1;
|
||||
strsep(&stringp," "); // eat the first token, we already know it :P
|
||||
s3=strsep(&stringp," ");
|
||||
@@ -285,21 +292,21 @@ static int aPGSQL_query(struct ast_channel *chan, void *data) {
|
||||
}
|
||||
nres=PQnfields(PGSQLres);
|
||||
id1=add_identifier(AST_PGSQL_ID_RESID,PGSQLres);
|
||||
s5=&s[0];
|
||||
sprintf(s5,"%d",id1);
|
||||
snprintf(s, sizeof(s), "%d", id1);
|
||||
pbx_builtin_setvar_helper(chan,var,s);
|
||||
break;
|
||||
}
|
||||
|
||||
free(s1);
|
||||
free(s2);
|
||||
|
||||
return(res);
|
||||
}
|
||||
|
||||
|
||||
static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
|
||||
|
||||
char *s1,*s2,*s3,*s4,*s5,*s6,*s7;
|
||||
char *s1,*s2,*fetchid_var,*s4,*s5,*s6,*s7;
|
||||
char s[100];
|
||||
char *var;
|
||||
int l;
|
||||
@@ -319,16 +326,16 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
|
||||
s7=NULL;
|
||||
s1=malloc(l);
|
||||
s2=malloc(l);
|
||||
strcpy(s1,data);
|
||||
strncpy(s1, data, l - 1);
|
||||
stringp=s1;
|
||||
strsep(&stringp," "); // eat the first token, we already know it :P
|
||||
s3=strsep(&stringp," ");
|
||||
fetchid_var=strsep(&stringp," ");
|
||||
while (1) { // ugly trick to make branches with break;
|
||||
var=s3; // fetchid
|
||||
var=fetchid_var; // fetchid
|
||||
fnd=0;
|
||||
|
||||
AST_LIST_TRAVERSE(headp,variables,entries) {
|
||||
if (strncasecmp(ast_var_name(variables),s3,strlen(s3))==0) {
|
||||
if (strncasecmp(ast_var_name(variables),fetchid_var,strlen(fetchid_var))==0) {
|
||||
s7=ast_var_value(variables);
|
||||
fnd=1;
|
||||
break;
|
||||
@@ -337,7 +344,7 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
|
||||
|
||||
if (fnd==0) {
|
||||
s7="0";
|
||||
pbx_builtin_setvar_helper(chan,s3,s7);
|
||||
pbx_builtin_setvar_helper(chan,fetchid_var,s7);
|
||||
}
|
||||
|
||||
s4=strsep(&stringp," ");
|
||||
@@ -349,12 +356,14 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
|
||||
}
|
||||
id=atoi(s7); //fetchid
|
||||
if ((lalares=find_identifier(id,AST_PGSQL_ID_FETCHID))==NULL) {
|
||||
i=0;
|
||||
i=0; // fetching the very first row
|
||||
} else {
|
||||
i=*lalares;
|
||||
free(lalares);
|
||||
del_identifier(id,AST_PGSQL_ID_FETCHID);
|
||||
del_identifier(id,AST_PGSQL_ID_FETCHID); // will re-add it a bit later
|
||||
}
|
||||
|
||||
if (i<PQntuples(PGSQLres)) {
|
||||
nres=PQnfields(PGSQLres);
|
||||
ast_log(LOG_WARNING,"ast_PGSQL_fetch : nres = %d i = %d ;\n",nres,i);
|
||||
for (j=0;j<nres;j++) {
|
||||
@@ -363,7 +372,6 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
|
||||
ast_log(LOG_WARNING,"ast_PGSQL_fetch : More tuples (%d) than variables (%d)\n",nres,j);
|
||||
break;
|
||||
}
|
||||
|
||||
s6=PQgetvalue(PGSQLres,i,j);
|
||||
if (s6==NULL) {
|
||||
ast_log(LOG_WARNING,"PWgetvalue(res,%d,%d) returned NULL in ast_PGSQL_fetch\n",i,j);
|
||||
@@ -372,18 +380,16 @@ static int aPGSQL_fetch(struct ast_channel *chan, void *data) {
|
||||
ast_log(LOG_WARNING,"===setting variable '%s' to '%s'\n",s5,s6);
|
||||
pbx_builtin_setvar_helper(chan,s5,s6);
|
||||
}
|
||||
i++;
|
||||
if (i<PQntuples(PGSQLres)) {
|
||||
lalares=malloc(sizeof(int));
|
||||
*lalares=i;
|
||||
id1=add_identifier(AST_PGSQL_ID_FETCHID,lalares);
|
||||
*lalares = ++i; // advance to the next row
|
||||
id1 = add_identifier(AST_PGSQL_ID_FETCHID,lalares);
|
||||
} else {
|
||||
id1=0;
|
||||
ast_log(LOG_WARNING,"ast_PGSQL_fetch : EOF\n");
|
||||
id1 = 0; // no more rows
|
||||
}
|
||||
s5=&s[0];
|
||||
sprintf(s5,"%d",id1);
|
||||
ast_log(LOG_WARNING,"Setting var '%s' to value '%s'\n",s3,s);
|
||||
pbx_builtin_setvar_helper(chan,s3,s);
|
||||
snprintf(s, sizeof(s), "%d", id1);
|
||||
ast_log(LOG_WARNING,"Setting var '%s' to value '%s'\n",fetchid_var,s);
|
||||
pbx_builtin_setvar_helper(chan,fetchid_var,s);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -403,7 +409,7 @@ static int aPGSQL_reset(struct ast_channel *chan, void *data) {
|
||||
|
||||
l=strlen(data)+2;
|
||||
s1=malloc(l);
|
||||
strcpy(s1,data);
|
||||
strncpy(s1, data, l - 1);
|
||||
stringp=s1;
|
||||
strsep(&stringp," "); // eat the first token, we already know it :P
|
||||
s3=strsep(&stringp," ");
|
||||
@@ -429,7 +435,7 @@ static int aPGSQL_clear(struct ast_channel *chan, void *data) {
|
||||
|
||||
l=strlen(data)+2;
|
||||
s1=malloc(l);
|
||||
strcpy(s1,data);
|
||||
strncpy(s1, data, l - 1);
|
||||
stringp=s1;
|
||||
strsep(&stringp," "); // eat the first token, we already know it :P
|
||||
s3=strsep(&stringp," ");
|
||||
@@ -459,7 +465,7 @@ static int aPGSQL_disconnect(struct ast_channel *chan, void *data) {
|
||||
|
||||
l=strlen(data)+2;
|
||||
s1=malloc(l);
|
||||
strcpy(s1,data);
|
||||
strncpy(s1, data, l - 1);
|
||||
stringp=s1;
|
||||
strsep(&stringp," "); // eat the first token, we already know it :P
|
||||
s3=strsep(&stringp," ");
|
||||
@@ -487,6 +493,10 @@ static int PGSQL_exec(struct ast_channel *chan, void *data)
|
||||
struct localuser *u;
|
||||
int result;
|
||||
|
||||
#if EXTRA_LOG
|
||||
printf("PRSQL_exec: data=%s\n",(char*)data);
|
||||
#endif
|
||||
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "APP_PGSQL requires an argument (see manual)\n");
|
||||
return -1;
|
||||
|
||||
36
apps/app_striplsd.c
Executable file → Normal file
36
apps/app_striplsd.c
Executable file → Normal file
@@ -11,19 +11,18 @@
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <sys/types.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 <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Strip trailing digits";
|
||||
|
||||
static char *descrip =
|
||||
@@ -46,16 +45,27 @@ LOCAL_USER_DECL;
|
||||
|
||||
static int striplsd_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
char newexten[AST_MAX_EXTENSION] = "";
|
||||
if (!data || !atoi(data)) {
|
||||
ast_log(LOG_DEBUG, "Ignoring, since number of digits to strip is 0\n");
|
||||
return 0;
|
||||
}
|
||||
if (strlen(chan->exten) > atoi(data)) {
|
||||
strncpy(newexten, chan->exten, strlen(chan->exten)-atoi(data));
|
||||
}
|
||||
strncpy(chan->exten, newexten, sizeof(chan->exten)-1);
|
||||
return 0;
|
||||
char newexten[AST_MAX_EXTENSION] = "";
|
||||
int maxbytes = 0;
|
||||
int stripcount = 0;
|
||||
int extlen = strlen(chan->exten);
|
||||
|
||||
maxbytes = sizeof(newexten) - 1;
|
||||
if (data) {
|
||||
stripcount = atoi(data);
|
||||
}
|
||||
if (!stripcount) {
|
||||
ast_log(LOG_DEBUG, "Ignoring, since number of digits to strip is 0\n");
|
||||
return 0;
|
||||
}
|
||||
if (extlen > stripcount) {
|
||||
if (extlen - stripcount <= maxbytes) {
|
||||
maxbytes = extlen - stripcount;
|
||||
}
|
||||
strncpy(newexten, chan->exten, maxbytes);
|
||||
}
|
||||
strncpy(chan->exten, newexten, sizeof(chan->exten)-1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
|
||||
28
apps/app_substring.c
Executable file → Normal file
28
apps/app_substring.c
Executable file → Normal file
@@ -11,40 +11,44 @@
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Save substring digits in a given variable";
|
||||
static char *tdesc = "(Deprecated) Save substring digits in a given variable";
|
||||
|
||||
static char *descrip =
|
||||
" StripLSD(variable=string_of_digits|count1|count2): Assigns the substring\n"
|
||||
" (Deprecated, use ${variable:a:b} instead)\n"
|
||||
"\n"
|
||||
" SubString(variable=string_of_digits|count1|count2): Assigns the substring\n"
|
||||
"of string_of_digits to a given variable. Parameter count1 may be positive\n"
|
||||
"or negative. If it's positive then we skip the first count1 digits from the\n"
|
||||
"left. If it's negative, we move count1 digits counting from the end of\n"
|
||||
"the string to the left. Parameter count2 may be only positive and implies\n"
|
||||
"how many digits we're taking from the point that count1 placed us.\n"
|
||||
"the string to the left. Parameter count2 implies how many digits we are\n"
|
||||
"taking from the point that count1 placed us. If count2 is negative, then\n"
|
||||
"that many digits are omitted from the end.\n"
|
||||
"For example:\n"
|
||||
"exten => _NXXXXXX,1,SubString,test=2564286161|0|3\n"
|
||||
"assigns the area code (3 first digits) to variable test.\n"
|
||||
"exten => _NXXXXXX,1,SubString,test=2564286161|-7|7\n"
|
||||
"assigns the last 7 digits to variable test.\n"
|
||||
"exten => _NXXXXXX,1,SubString,test=2564286161|0|-4\n"
|
||||
"assigns all but the last 4 digits to variable test.\n"
|
||||
"If there are no parameters it'll return with -1.\n"
|
||||
"If there wrong parameters it go on and return with 0\n";
|
||||
|
||||
static char *app = "SubString";
|
||||
|
||||
static char *synopsis = "Save substring digits in a given variable";
|
||||
static char *synopsis = "(Deprecated) Save substring digits in a given variable";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
@@ -55,9 +59,10 @@ static int substring_exec(struct ast_channel *chan, void *data)
|
||||
char newexten[AST_MAX_EXTENSION] = "";
|
||||
char *count1, *count2;
|
||||
char *first, *second, *stringp;
|
||||
|
||||
stringp=alloca(strlen(data)+1);
|
||||
ast_log(LOG_WARNING, "The use of Substring application is deprecated. Please use ${variable:a:b} instead\n");
|
||||
strncpy(stringp,data,strlen(data)+1);
|
||||
strncpy(stringp,data,strlen(data));
|
||||
if (strchr(stringp,'|')&&strchr(stringp,'=')) {
|
||||
int icount1,icount2;
|
||||
first=strsep(&stringp,"=");
|
||||
@@ -70,9 +75,8 @@ static int substring_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
icount1=atoi(count1);
|
||||
icount2=atoi(count2);
|
||||
if (icount2<=0) {
|
||||
ast_log(LOG_DEBUG, "Exiting, wrong parameter count2\n");
|
||||
return -1;
|
||||
if (icount2<0) {
|
||||
icount2 = icount2 + strlen(second);
|
||||
}
|
||||
if (abs(icount1)>strlen(second)) {
|
||||
ast_log(LOG_WARNING, "Limiting count1 parameter because it exceeds the length of the string\n");
|
||||
|
||||
48
apps/app_system.c
Executable file → Normal file
48
apps/app_system.c
Executable file → Normal file
@@ -3,9 +3,9 @@
|
||||
*
|
||||
* Execute arbitrary system commands
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
* Copyright (C) 1999-2004, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
@@ -17,20 +17,23 @@
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
static char *tdesc = "Generic System() application";
|
||||
|
||||
static char *app = "System";
|
||||
|
||||
static char *app2 = "TrySystem";
|
||||
|
||||
static char *synopsis = "Execute a system command";
|
||||
|
||||
static char *synopsis2 = "Try executing a system command";
|
||||
|
||||
static char *descrip =
|
||||
" System(command): Executes a command by using system(). Returns -1 on\n"
|
||||
"failure to execute the specified command. If the command itself executes\n"
|
||||
@@ -38,28 +41,37 @@ static char *descrip =
|
||||
"priority of the current instance, then the channel will be setup to\n"
|
||||
"continue at that priority level. Otherwise, System returns 0.\n";
|
||||
|
||||
static char *descrip2 =
|
||||
" TrySystem(command): Executes a command by using system(). Returns 0\n"
|
||||
"on any situation. If the command itself executes but is in error, and if\n"
|
||||
"there exists a priority n + 101, where 'n' is the priority of the current\n"
|
||||
"instance, then the channel will be setup to continue at that\n"
|
||||
"priority level. Otherwise, System returns 0.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int skel_exec(struct ast_channel *chan, void *data)
|
||||
static int system_exec_helper(struct ast_channel *chan, void *data, int failmode)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "System requires an argument(command)\n");
|
||||
return -1;
|
||||
return failmode;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
/* Do our thing here */
|
||||
res = system((char *)data);
|
||||
if (res < 0) {
|
||||
res = ast_safe_system((char *)data);
|
||||
if ((res < 0) && (errno != ECHILD)) {
|
||||
ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
|
||||
res = -1;
|
||||
res = failmode;
|
||||
} else if (res == 127) {
|
||||
ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
|
||||
res = -1;
|
||||
res = failmode;
|
||||
} else {
|
||||
if (res < 0)
|
||||
res = 0;
|
||||
if (res && ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority+=100;
|
||||
res = 0;
|
||||
@@ -68,15 +80,27 @@ static int skel_exec(struct ast_channel *chan, void *data)
|
||||
return res;
|
||||
}
|
||||
|
||||
static int system_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
return system_exec_helper(chan, data, -1);
|
||||
}
|
||||
|
||||
static int trysystem_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
return system_exec_helper(chan, data, 0);
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
ast_unregister_application(app2);
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, skel_exec, synopsis, descrip);
|
||||
ast_register_application(app2, trysystem_exec, synopsis2, descrip2);
|
||||
return ast_register_application(app, system_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
|
||||
218
apps/app_talkdetect.c
Normal file
218
apps/app_talkdetect.c
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Playback a file with audio detect
|
||||
*
|
||||
* Copyright (C) 2004, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/dsp.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static char *tdesc = "Playback with Talk Detection";
|
||||
|
||||
static char *app = "BackgroundDetect";
|
||||
|
||||
static char *synopsis = "Background a file with talk detect";
|
||||
|
||||
static char *descrip =
|
||||
" BackgroundDetect(filename[|sil[|min|[max]]]): Plays back a given\n"
|
||||
"filename, waiting for interruption from a given digit (the digit must\n"
|
||||
"start the beginning of a valid extension, or it will be ignored).\n"
|
||||
"During the playback of the file, audio is monitored in the receive\n"
|
||||
"direction, and if a period of non-silence which is greater than 'min' ms\n"
|
||||
"yet less than 'max' ms is followed by silence for at least 'sil' ms then\n"
|
||||
"the audio playback is aborted and processing jumps to the 'talk' extension\n"
|
||||
"if available. If unspecified, sil, min, and max default to 1000, 100, and\n"
|
||||
"infinity respectively. Returns -1 on hangup, and 0 on successful playback\n"
|
||||
"completion with no exit conditions.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int background_detect_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
char tmp[256];
|
||||
char *options;
|
||||
char *stringp;
|
||||
struct ast_frame *fr;
|
||||
int notsilent=0;
|
||||
struct timeval start = { 0, 0}, end = {0, 0};
|
||||
int sil = 1000;
|
||||
int min = 100;
|
||||
int max = -1;
|
||||
int x;
|
||||
int origrformat=0;
|
||||
struct ast_dsp *dsp;
|
||||
if (!data || ast_strlen_zero((char *)data)) {
|
||||
ast_log(LOG_WARNING, "BackgroundDetect requires an argument (filename)\n");
|
||||
return -1;
|
||||
}
|
||||
strncpy(tmp, (char *)data, sizeof(tmp)-1);
|
||||
stringp=tmp;
|
||||
strsep(&stringp, "|");
|
||||
options = strsep(&stringp, "|");
|
||||
if (options) {
|
||||
if ((sscanf(options, "%d", &x) == 1) && (x > 0))
|
||||
sil = x;
|
||||
options = strsep(&stringp, "|");
|
||||
if (options) {
|
||||
if ((sscanf(options, "%d", &x) == 1) && (x > 0))
|
||||
min = x;
|
||||
options = strsep(&stringp, "|");
|
||||
if (options) {
|
||||
if ((sscanf(options, "%d", &x) == 1) && (x > 0))
|
||||
max = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_log(LOG_DEBUG, "Preparing detect of '%s', sil=%d,min=%d,max=%d\n",
|
||||
tmp, sil, min, max);
|
||||
LOCAL_USER_ADD(u);
|
||||
if (chan->_state != AST_STATE_UP) {
|
||||
/* Otherwise answer unless we're supposed to send this while on-hook */
|
||||
res = ast_answer(chan);
|
||||
}
|
||||
if (!res) {
|
||||
origrformat = chan->readformat;
|
||||
if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)))
|
||||
ast_log(LOG_WARNING, "Unable to set read format to linear!\n");
|
||||
}
|
||||
if (!(dsp = ast_dsp_new())) {
|
||||
ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
|
||||
res = -1;
|
||||
}
|
||||
if (!res) {
|
||||
ast_stopstream(chan);
|
||||
res = ast_streamfile(chan, tmp, chan->language);
|
||||
if (!res) {
|
||||
while(chan->stream) {
|
||||
res = ast_sched_wait(chan->sched);
|
||||
if ((res < 0) && !chan->timingfunc) {
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
if (res < 0)
|
||||
res = 1000;
|
||||
res = ast_waitfor(chan, res);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Waitfor failed on %s\n", chan->name);
|
||||
break;
|
||||
} else if (res > 0) {
|
||||
fr = ast_read(chan);
|
||||
if (!fr) {
|
||||
res = -1;
|
||||
break;
|
||||
} else if (fr->frametype == AST_FRAME_DTMF) {
|
||||
char t[2];
|
||||
t[0] = fr->subclass;
|
||||
t[1] = '\0';
|
||||
if (ast_canmatch_extension(chan, chan->context, t, 1, chan->callerid)) {
|
||||
/* They entered a valid extension, or might be anyhow */
|
||||
res = fr->subclass;
|
||||
ast_frfree(fr);
|
||||
break;
|
||||
}
|
||||
} else if ((fr->frametype == AST_FRAME_VOICE) && (fr->subclass == AST_FORMAT_SLINEAR)) {
|
||||
int totalsilence;
|
||||
int ms;
|
||||
res = ast_dsp_silence(dsp, fr, &totalsilence);
|
||||
if (res && (totalsilence > sil)) {
|
||||
/* We've been quiet a little while */
|
||||
if (notsilent) {
|
||||
/* We had heard some talking */
|
||||
gettimeofday(&end, NULL);
|
||||
ms = (end.tv_sec - start.tv_sec) * 1000;
|
||||
ms += (end.tv_usec - start.tv_usec) / 1000;
|
||||
ms -= sil;
|
||||
if (ms < 0)
|
||||
ms = 0;
|
||||
if ((ms > min) && ((max < 0) || (ms < max))) {
|
||||
ast_log(LOG_DEBUG, "Found qualified token of %d ms\n", ms);
|
||||
if (ast_exists_extension(chan, chan->context, "talk", 1, chan->callerid)) {
|
||||
strncpy(chan->exten, "talk", sizeof(chan->exten) -1 );
|
||||
chan->priority = 0;
|
||||
}
|
||||
res = 0;
|
||||
ast_frfree(fr);
|
||||
break;
|
||||
} else
|
||||
ast_log(LOG_DEBUG, "Found unqualified token of %d ms\n", ms);
|
||||
notsilent = 0;
|
||||
}
|
||||
} else {
|
||||
if (!notsilent) {
|
||||
/* Heard some audio, mark the begining of the token */
|
||||
gettimeofday(&start, NULL);
|
||||
ast_log(LOG_DEBUG, "Start of voice token!\n");
|
||||
notsilent = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
ast_frfree(fr);
|
||||
}
|
||||
ast_sched_runq(chan->sched);
|
||||
}
|
||||
ast_stopstream(chan);
|
||||
} else {
|
||||
ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char *)data);
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
if (res > -1) {
|
||||
if (origrformat && ast_set_read_format(chan, origrformat)) {
|
||||
ast_log(LOG_WARNING, "Failed to restore read format for %s to %s\n",
|
||||
chan->name, ast_getformatname(origrformat));
|
||||
}
|
||||
}
|
||||
if (dsp)
|
||||
ast_dsp_free(dsp);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, background_detect_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
473
apps/app_test.c
Normal file
473
apps/app_test.c
Normal file
@@ -0,0 +1,473 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Applications to test connection and produce report in text file
|
||||
*
|
||||
* Copyright (C) 2004, Digium, Inc.
|
||||
*
|
||||
* Mark Spencer <markster@digium.com>
|
||||
* Russell Bryant <russelb@clemson.edu>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include "../astconf.h"
|
||||
|
||||
|
||||
static char *tdesc = "Interface Test Application";
|
||||
|
||||
static char *tests_descrip =
|
||||
"TestServer(): Perform test server function and write call report.\n"
|
||||
"Results stored in /var/log/asterisk/testreports/<testid>-server.txt";
|
||||
static char *tests_app = "TestServer";
|
||||
static char *tests_synopsis = "Execute Interface Test Server";
|
||||
|
||||
static char *testc_descrip =
|
||||
"TestClient(testid): Executes test client with given testid.\n"
|
||||
"Results stored in /var/log/asterisk/testreports/<testid>-client.txt";
|
||||
|
||||
static char *testc_app = "TestClient";
|
||||
static char *testc_synopsis = "Execute Interface Test Client";
|
||||
|
||||
static int measurenoise(struct ast_channel *chan, int ms, char *who)
|
||||
{
|
||||
int res=0;
|
||||
int mssofar;
|
||||
int noise=0;
|
||||
int samples=0;
|
||||
int x;
|
||||
short *foo;
|
||||
struct timeval start, tv;
|
||||
struct ast_frame *f;
|
||||
int rformat;
|
||||
rformat = chan->readformat;
|
||||
if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
|
||||
ast_log(LOG_NOTICE, "Unable to set to linear mode!\n");
|
||||
return -1;
|
||||
}
|
||||
gettimeofday(&start, NULL);
|
||||
for(;;) {
|
||||
gettimeofday(&tv, NULL);
|
||||
mssofar = (tv.tv_sec - start.tv_sec) * 1000;
|
||||
mssofar += (tv.tv_usec - start.tv_usec) / 1000;
|
||||
if (mssofar > ms)
|
||||
break;
|
||||
res = ast_waitfor(chan, ms - mssofar);
|
||||
if (res < 1)
|
||||
break;
|
||||
f = ast_read(chan);
|
||||
if (!f) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
if ((f->frametype == AST_FRAME_VOICE) && (f->subclass == AST_FORMAT_SLINEAR)) {
|
||||
foo = (short *)f->data;
|
||||
for (x=0;x<f->samples;x++) {
|
||||
noise += abs(foo[x]);
|
||||
samples++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rformat) {
|
||||
if (ast_set_read_format(chan, rformat)) {
|
||||
ast_log(LOG_NOTICE, "Unable to restore original format!\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (res < 0)
|
||||
return res;
|
||||
if (!samples) {
|
||||
ast_log(LOG_NOTICE, "No samples were received from the other side!\n");
|
||||
return -1;
|
||||
}
|
||||
ast_log(LOG_DEBUG, "%s: Noise: %d, samples: %d, avg: %d\n", who, noise, samples, noise / samples);
|
||||
return (noise / samples);
|
||||
}
|
||||
|
||||
static int sendnoise(struct ast_channel *chan, int ms)
|
||||
{
|
||||
int res;
|
||||
res = ast_tonepair_start(chan, 1537, 2195, ms, 8192);
|
||||
if (!res) {
|
||||
res = ast_waitfordigit(chan, ms);
|
||||
ast_tonepair_stop(chan);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int testclient_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
int res = 0;
|
||||
char *testid=data;
|
||||
char fn[80];
|
||||
char serverver[80];
|
||||
FILE *f;
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
/* Check for test id */
|
||||
if (!testid || ast_strlen_zero(testid)) {
|
||||
ast_log(LOG_WARNING, "TestClient requires an argument - the test id\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
res = ast_answer(chan);
|
||||
|
||||
/* Wait a few just to be sure things get started */
|
||||
res = ast_safe_sleep(chan, 3000);
|
||||
/* Transmit client version */
|
||||
if (!res)
|
||||
res = ast_dtmf_stream(chan, NULL, "8378*1#", 0);
|
||||
ast_log(LOG_DEBUG, "Transmit client version\n");
|
||||
|
||||
/* Read server version */
|
||||
ast_log(LOG_DEBUG, "Read server version\n");
|
||||
if (!res)
|
||||
res = ast_app_getdata(chan, NULL, serverver, sizeof(serverver) - 1, 0);
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
ast_log(LOG_DEBUG, "server version: %s\n", serverver);
|
||||
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
|
||||
if (!res)
|
||||
res = ast_safe_sleep(chan, 1000);
|
||||
/* Send test id */
|
||||
if (!res)
|
||||
res = ast_dtmf_stream(chan, NULL, testid, 0);
|
||||
if (!res)
|
||||
res = ast_dtmf_stream(chan, NULL, "#", 0);
|
||||
ast_log(LOG_DEBUG, "send test identifier: %s\n", testid);
|
||||
|
||||
if ((res >=0) && (!ast_strlen_zero(testid))) {
|
||||
/* Make the directory to hold the test results in case it's not there */
|
||||
snprintf(fn, sizeof(fn), "%s/testresults", ast_config_AST_LOG_DIR);
|
||||
mkdir(fn, 0777);
|
||||
snprintf(fn, sizeof(fn), "%s/testresults/%s-client.txt", ast_config_AST_LOG_DIR, testid);
|
||||
if ((f = fopen(fn, "w+"))) {
|
||||
setlinebuf(f);
|
||||
fprintf(f, "CLIENTCHAN: %s\n", chan->name);
|
||||
fprintf(f, "CLIENTTEST ID: %s\n", testid);
|
||||
fprintf(f, "ANSWER: PASS\n");
|
||||
res = 0;
|
||||
|
||||
if (!res) {
|
||||
/* Step 1: Wait for "1" */
|
||||
ast_log(LOG_DEBUG, "TestClient: 2. Wait DTMF 1\n");
|
||||
res = ast_waitfordigit(chan, 3000);
|
||||
fprintf(f, "WAIT DTMF 1: %s\n", (res != '1') ? "FAIL" : "PASS");
|
||||
if (res == '1')
|
||||
res = 0;
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
if (!res)
|
||||
res = ast_safe_sleep(chan, 1000);
|
||||
if (!res) {
|
||||
/* Step 2: Send "2" */
|
||||
ast_log(LOG_DEBUG, "TestClient: 2. Send DTMF 2\n");
|
||||
res = ast_dtmf_stream(chan, NULL, "2", 0);
|
||||
fprintf(f, "SEND DTMF 2: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 3: Wait one second */
|
||||
ast_log(LOG_DEBUG, "TestClient: 3. Wait one second\n");
|
||||
res = ast_safe_sleep(chan, 1000);
|
||||
fprintf(f, "WAIT 1 SEC: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 4: Measure noise */
|
||||
ast_log(LOG_DEBUG, "TestClient: 4. Measure noise\n");
|
||||
res = measurenoise(chan, 5000, "TestClient");
|
||||
fprintf(f, "MEASURENOISE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 5: Wait for "4" */
|
||||
ast_log(LOG_DEBUG, "TestClient: 5. Wait DTMF 4\n");
|
||||
res = ast_waitfordigit(chan, 3000);
|
||||
fprintf(f, "WAIT DTMF 4: %s\n", (res != '4') ? "FAIL" : "PASS");
|
||||
if (res == '4')
|
||||
res = 0;
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 6: Transmit tone noise */
|
||||
ast_log(LOG_DEBUG, "TestClient: 6. Transmit tone\n");
|
||||
res = sendnoise(chan, 6000);
|
||||
fprintf(f, "SENDTONE: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
}
|
||||
if (!res || (res == '5')) {
|
||||
/* Step 7: Wait for "5" */
|
||||
ast_log(LOG_DEBUG, "TestClient: 7. Wait DTMF 5\n");
|
||||
if (!res)
|
||||
res = ast_waitfordigit(chan, 3000);
|
||||
fprintf(f, "WAIT DTMF 5: %s\n", (res != '5') ? "FAIL" : "PASS");
|
||||
if (res == '5')
|
||||
res = 0;
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 8: Wait one second */
|
||||
ast_log(LOG_DEBUG, "TestClient: 8. Wait one second\n");
|
||||
res = ast_safe_sleep(chan, 1000);
|
||||
fprintf(f, "WAIT 1 SEC: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 9: Measure noise */
|
||||
ast_log(LOG_DEBUG, "TestClient: 6. Measure tone\n");
|
||||
res = measurenoise(chan, 4000, "TestClient");
|
||||
fprintf(f, "MEASURETONE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 10: Send "7" */
|
||||
ast_log(LOG_DEBUG, "TestClient: 7. Send DTMF 7\n");
|
||||
res = ast_dtmf_stream(chan, NULL, "7", 0);
|
||||
fprintf(f, "SEND DTMF 7: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res =0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 11: Wait for "8" */
|
||||
ast_log(LOG_DEBUG, "TestClient: 11. Wait DTMF 8\n");
|
||||
res = ast_waitfordigit(chan, 3000);
|
||||
fprintf(f, "WAIT DTMF 8: %s\n", (res != '8') ? "FAIL" : "PASS");
|
||||
if (res == '8')
|
||||
res = 0;
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 12: Hangup! */
|
||||
ast_log(LOG_DEBUG, "TestClient: 12. Hangup\n");
|
||||
}
|
||||
|
||||
ast_log(LOG_DEBUG, "-- TEST COMPLETE--\n");
|
||||
fprintf(f, "-- END TEST--\n");
|
||||
fclose(f);
|
||||
res = -1;
|
||||
} else
|
||||
res = -1;
|
||||
} else {
|
||||
ast_log(LOG_NOTICE, "Did not read a test ID on '%s'\n", chan->name);
|
||||
res = -1;
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int testserver_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
int res = 0;
|
||||
char testid[80]="";
|
||||
char fn[80];
|
||||
FILE *f;
|
||||
LOCAL_USER_ADD(u);
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
res = ast_answer(chan);
|
||||
/* Read version */
|
||||
ast_log(LOG_DEBUG, "Read client version\n");
|
||||
if (!res)
|
||||
res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
ast_log(LOG_DEBUG, "client version: %s\n", testid);
|
||||
ast_log(LOG_DEBUG, "Transmit server version\n");
|
||||
res = ast_safe_sleep(chan, 1000);
|
||||
if (!res)
|
||||
res = ast_dtmf_stream(chan, NULL, "8378*1#", 0);
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
|
||||
if (!res)
|
||||
res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
|
||||
ast_log(LOG_DEBUG, "read test identifier: %s\n", testid);
|
||||
/* Check for sneakyness */
|
||||
if (strchr(testid, '/'))
|
||||
res = -1;
|
||||
if ((res >=0) && (!ast_strlen_zero(testid))) {
|
||||
/* Got a Test ID! Whoo hoo! */
|
||||
/* Make the directory to hold the test results in case it's not there */
|
||||
snprintf(fn, sizeof(fn), "%s/testresults", ast_config_AST_LOG_DIR);
|
||||
mkdir(fn, 0777);
|
||||
snprintf(fn, sizeof(fn), "%s/testresults/%s-server.txt", ast_config_AST_LOG_DIR, testid);
|
||||
if ((f = fopen(fn, "w+"))) {
|
||||
setlinebuf(f);
|
||||
fprintf(f, "SERVERCHAN: %s\n", chan->name);
|
||||
fprintf(f, "SERVERTEST ID: %s\n", testid);
|
||||
fprintf(f, "ANSWER: PASS\n");
|
||||
ast_log(LOG_DEBUG, "Processing Test ID '%s'\n", testid);
|
||||
res = ast_safe_sleep(chan, 1000);
|
||||
if (!res) {
|
||||
/* Step 1: Send "1" */
|
||||
ast_log(LOG_DEBUG, "TestServer: 1. Send DTMF 1\n");
|
||||
res = ast_dtmf_stream(chan, NULL, "1", 0);
|
||||
fprintf(f, "SEND DTMF 1: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 2: Wait for "2" */
|
||||
ast_log(LOG_DEBUG, "TestServer: 2. Wait DTMF 2\n");
|
||||
res = ast_waitfordigit(chan, 3000);
|
||||
fprintf(f, "WAIT DTMF 2: %s\n", (res != '2') ? "FAIL" : "PASS");
|
||||
if (res == '2')
|
||||
res = 0;
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 3: Measure noise */
|
||||
ast_log(LOG_DEBUG, "TestServer: 3. Measure noise\n");
|
||||
res = measurenoise(chan, 6000, "TestServer");
|
||||
fprintf(f, "MEASURENOISE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 4: Send "4" */
|
||||
ast_log(LOG_DEBUG, "TestServer: 4. Send DTMF 4\n");
|
||||
res = ast_dtmf_stream(chan, NULL, "4", 0);
|
||||
fprintf(f, "SEND DTMF 4: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
/* Step 5: Wait one second */
|
||||
ast_log(LOG_DEBUG, "TestServer: 5. Wait one second\n");
|
||||
res = ast_safe_sleep(chan, 1000);
|
||||
fprintf(f, "WAIT 1 SEC: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
/* Step 6: Measure noise */
|
||||
ast_log(LOG_DEBUG, "TestServer: 6. Measure tone\n");
|
||||
res = measurenoise(chan, 4000, "TestServer");
|
||||
fprintf(f, "MEASURETONE: %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
/* Step 7: Send "5" */
|
||||
ast_log(LOG_DEBUG, "TestServer: 7. Send DTMF 5\n");
|
||||
res = ast_dtmf_stream(chan, NULL, "5", 0);
|
||||
fprintf(f, "SEND DTMF 5: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
/* Step 8: Transmit tone noise */
|
||||
ast_log(LOG_DEBUG, "TestServer: 8. Transmit tone\n");
|
||||
res = sendnoise(chan, 6000);
|
||||
fprintf(f, "SENDTONE: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
}
|
||||
|
||||
if (!res || (res == '7')) {
|
||||
/* Step 9: Wait for "7" */
|
||||
ast_log(LOG_DEBUG, "TestServer: 9. Wait DTMF 7\n");
|
||||
if (!res)
|
||||
res = ast_waitfordigit(chan, 3000);
|
||||
fprintf(f, "WAIT DTMF 7: %s\n", (res != '7') ? "FAIL" : "PASS");
|
||||
if (res == '7')
|
||||
res = 0;
|
||||
else
|
||||
res = -1;
|
||||
}
|
||||
if (!res)
|
||||
res = ast_safe_sleep(chan, 1000);
|
||||
if (!res) {
|
||||
/* Step 10: Send "8" */
|
||||
ast_log(LOG_DEBUG, "TestServer: 10. Send DTMF 8\n");
|
||||
res = ast_dtmf_stream(chan, NULL, "8", 0);
|
||||
fprintf(f, "SEND DTMF 8: %s\n", (res < 0) ? "FAIL" : "PASS");
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
}
|
||||
if (!res) {
|
||||
/* Step 11: Wait for hangup to arrive! */
|
||||
ast_log(LOG_DEBUG, "TestServer: 11. Waiting for hangup\n");
|
||||
res = ast_safe_sleep(chan, 10000);
|
||||
fprintf(f, "WAIT HANGUP: %s\n", (res < 0) ? "PASS" : "FAIL");
|
||||
}
|
||||
|
||||
ast_log(LOG_DEBUG, "-- TEST COMPLETE--\n");
|
||||
fprintf(f, "-- END TEST--\n");
|
||||
fclose(f);
|
||||
res = -1;
|
||||
} else
|
||||
res = -1;
|
||||
} else {
|
||||
ast_log(LOG_NOTICE, "Did not read a test ID on '%s'\n", chan->name);
|
||||
res = -1;
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
ast_unregister_application(testc_app);
|
||||
return ast_unregister_application(tests_app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
ast_register_application(testc_app, testclient_exec, testc_synopsis, testc_descrip);
|
||||
return ast_register_application(tests_app, testserver_exec, tests_synopsis, tests_descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key(void)
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
91
apps/app_transfer.c
Normal file
91
apps/app_transfer.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Transfer a caller
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#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 <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static char *tdesc = "Transfer";
|
||||
|
||||
static char *app = "Transfer";
|
||||
|
||||
static char *synopsis = "Transfer caller to remote extension";
|
||||
|
||||
static char *descrip =
|
||||
" Transfer(exten): Requests the remote caller be transferred to\n"
|
||||
"a given extension. Returns -1 on hangup, or 0 on completion\n"
|
||||
"regardless of whether the transfer was successful. If the transfer\n"
|
||||
"was *not* supported or successful and there exists a priority n + 101,\n"
|
||||
"then that priority will be taken next.\n" ;
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int transfer_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
if (!data || !strlen(data)) {
|
||||
ast_log(LOG_WARNING, "Transfer requires an argument (destination)\n");
|
||||
res = 1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
if (!res) {
|
||||
res = ast_transfer(chan, data);
|
||||
}
|
||||
if (!res) {
|
||||
/* Look for a "busy" place */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
}
|
||||
if (res > 0)
|
||||
res = 0;
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, transfer_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
145
apps/app_txtcidname.c
Normal file
145
apps/app_txtcidname.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Caller*id name lookup - Look up the caller's name via DNS
|
||||
*
|
||||
* Copyright (C) 1999-2004, Digium
|
||||
*
|
||||
* Mark Spencer <markster@linux-support.net>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#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 <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static char *tdesc = "TXTCIDName";
|
||||
|
||||
static char *app = "TXTCIDName";
|
||||
|
||||
static char *synopsis = "Lookup caller name from TXT record";
|
||||
|
||||
static char *descrip =
|
||||
" TXTLookup(CallerID): Looks up a Caller Name via DNS and sets\n"
|
||||
"the variable 'TXTCIDNAME'. TXTCIDName will either be blank\n"
|
||||
"or return the value found in the TXT record in DNS.\n" ;
|
||||
|
||||
#define ENUM_CONFIG "enum.conf"
|
||||
|
||||
static char h323driver[80] = "";
|
||||
#define H323DRIVERDEFAULT "H323"
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int txtcidname_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
char tech[80];
|
||||
char txt[256] = "";
|
||||
char dest[80];
|
||||
|
||||
struct localuser *u;
|
||||
if (!data || !strlen(data)) {
|
||||
ast_log(LOG_WARNING, "TXTCIDName requires an argument (extension)\n");
|
||||
res = 1;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
if (!res) {
|
||||
res = ast_get_txt(chan, data, dest, sizeof(dest), tech, sizeof(tech), txt, sizeof(txt));
|
||||
}
|
||||
LOCAL_USER_REMOVE(u);
|
||||
/* Parse it out */
|
||||
if (res > 0) {
|
||||
if (!ast_strlen_zero(txt)) {
|
||||
pbx_builtin_setvar_helper(chan, "TXTCIDNAME", txt);
|
||||
#if 0
|
||||
ast_log(LOG_DEBUG, "TXTCIDNAME got '%s'\n", txt);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (!res) {
|
||||
/* Look for a "busy" place */
|
||||
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->callerid))
|
||||
chan->priority += 100;
|
||||
} else if (res > 0)
|
||||
res = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_config(void)
|
||||
{
|
||||
struct ast_config *cfg;
|
||||
char *s;
|
||||
|
||||
cfg = ast_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_destroy(cfg);
|
||||
return 0;
|
||||
}
|
||||
ast_log(LOG_NOTICE, "No ENUM Config file, using defaults\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
int res;
|
||||
res = ast_register_application(app, txtcidname_exec, synopsis, descrip);
|
||||
if (res)
|
||||
return(res);
|
||||
if ((res=load_config())) {
|
||||
return(res);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int reload(void)
|
||||
{
|
||||
return(load_config());
|
||||
}
|
||||
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
|
||||
1
apps/app_url.c
Executable file → Normal file
1
apps/app_url.c
Executable file → Normal file
@@ -21,7 +21,6 @@
|
||||
#include <asterisk/image.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Send URL Applications";
|
||||
|
||||
|
||||
106
apps/app_userevent.c
Normal file
106
apps/app_userevent.c
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* UserEvent application -- send manager event
|
||||
*
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#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/manager.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static char *tdesc = "Custom User Event Application";
|
||||
|
||||
static char *app = "UserEvent";
|
||||
|
||||
static char *synopsis = "Send an arbitrary event to the manager interface";
|
||||
|
||||
static char *descrip =
|
||||
" UserEvent(eventname[|body]): Sends an arbitrary event to the\n"
|
||||
"manager interface, with an optional body representing additional\n"
|
||||
"arguments. The format of the event will be:\n"
|
||||
" Event: UserEvent<specified event name>\n"
|
||||
" Channel: <channel name>\n"
|
||||
" Uniqueid: <call uniqueid>\n"
|
||||
" [body]\n"
|
||||
"If the body is not specified, only Event, Channel, and Uniqueid fields\n"
|
||||
"will be present. Returns 0.";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int userevent_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
struct localuser *u;
|
||||
char info[512];
|
||||
char eventname[512];
|
||||
char *eventbody;
|
||||
|
||||
if (!data || !strlen(data)) {
|
||||
ast_log(LOG_WARNING, "UserEvent requires an argument (eventname|optional event body)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1);
|
||||
snprintf(eventname, sizeof(eventname), "UserEvent%s", info);
|
||||
eventbody = strchr(eventname, '|');
|
||||
if (eventbody) {
|
||||
*eventbody = '\0';
|
||||
eventbody++;
|
||||
}
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if(eventbody) {
|
||||
ast_log(LOG_DEBUG, "Sending user event: %s, %s\n", eventname, eventbody);
|
||||
manager_event(EVENT_FLAG_USER, eventname,
|
||||
"Channel: %s\r\nUniqueid: %s\r\n%s\r\n",
|
||||
chan->name, chan->uniqueid, eventbody);
|
||||
} else {
|
||||
ast_log(LOG_DEBUG, "Sending user event: %s\n", eventname);
|
||||
manager_event(EVENT_FLAG_USER, eventname,
|
||||
"Channel: %s\r\nUniqueid: %s\r\n", chan->name, chan->uniqueid);
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app, userevent_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
110
apps/app_verbose.c
Normal file
110
apps/app_verbose.c
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Verbose application
|
||||
*
|
||||
* Copyright (c) 2004 Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <app_verbose_v001@the-tilghman.com>
|
||||
*
|
||||
* This code is released by the author with no restrictions on usage.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
|
||||
|
||||
static char *tdesc = "Send verbose output";
|
||||
|
||||
static char *app_verbose = "Verbose";
|
||||
|
||||
static char *verbose_synopsis = "Send arbitrary text to verbose output";
|
||||
|
||||
static char *verbose_descrip =
|
||||
"Verbose([<level>|]<message>)\n"
|
||||
" level must be an integer value. If not specified, defaults to 0."
|
||||
" Always returns 0.\n";
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static int verbose_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
char *vtext;
|
||||
int vsize;
|
||||
|
||||
if (data) {
|
||||
vtext = ast_strdupa((char *)data);
|
||||
if (vtext) {
|
||||
char *tmp = strsep(&vtext, "|,");
|
||||
if (vtext) {
|
||||
if (sscanf(tmp, "%d", &vsize) != 1) {
|
||||
vsize = 0;
|
||||
ast_log(LOG_WARNING, "'%s' is not a verboser number\n", vtext);
|
||||
}
|
||||
} else {
|
||||
vtext = tmp;
|
||||
vsize = 0;
|
||||
}
|
||||
if (option_verbose >= vsize) {
|
||||
switch (vsize) {
|
||||
case 0:
|
||||
ast_verbose("%s\n", vtext);
|
||||
break;
|
||||
case 1:
|
||||
ast_verbose(VERBOSE_PREFIX_1 "%s\n", vtext);
|
||||
break;
|
||||
case 2:
|
||||
ast_verbose(VERBOSE_PREFIX_2 "%s\n", vtext);
|
||||
break;
|
||||
case 3:
|
||||
ast_verbose(VERBOSE_PREFIX_3 "%s\n", vtext);
|
||||
break;
|
||||
default:
|
||||
ast_verbose(VERBOSE_PREFIX_4 "%s\n", vtext);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Out of memory\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app_verbose);
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app_verbose, verbose_exec, verbose_synopsis, verbose_descrip);
|
||||
}
|
||||
|
||||
char *description(void)
|
||||
{
|
||||
return tdesc;
|
||||
}
|
||||
|
||||
int usecount(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_USECOUNT(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *key()
|
||||
{
|
||||
return ASTERISK_GPL_KEY;
|
||||
}
|
||||
4943
apps/app_voicemail.c
Executable file → Normal file
4943
apps/app_voicemail.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
7
apps/app_waitforring.c
Executable file → Normal file
7
apps/app_waitforring.c
Executable file → Normal file
@@ -11,20 +11,19 @@
|
||||
* the GNU General Public License
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <asterisk/file.h>
|
||||
#include <asterisk/logger.h>
|
||||
#include <asterisk/channel.h>
|
||||
#include <asterisk/pbx.h>
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/lock.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *synopsis = "Wait for Ring Application";
|
||||
|
||||
static char *tdesc = "Waits until first ring after time";
|
||||
@@ -47,7 +46,7 @@ static int waitforring_exec(struct ast_channel *chan, void *data)
|
||||
int res = 0;
|
||||
int ms;
|
||||
if (!data || (sscanf(data, "%d", &ms) != 1)) {
|
||||
ast_log(LOG_WARNING, "SoftHangup requires an argument (minimum seconds)\n");
|
||||
ast_log(LOG_WARNING, "WaitForRing requires an argument (minimum seconds)\n");
|
||||
return 0;
|
||||
}
|
||||
ms *= 1000;
|
||||
|
||||
1
apps/app_zapateller.c
Executable file → Normal file
1
apps/app_zapateller.c
Executable file → Normal file
@@ -20,7 +20,6 @@
|
||||
#include <asterisk/translate.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Block Telemarketers with Special Information Tone";
|
||||
|
||||
|
||||
13
apps/app_zapbarge.c
Executable file → Normal file
13
apps/app_zapbarge.c
Executable file → Normal file
@@ -25,6 +25,7 @@
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/cli.h>
|
||||
#include <asterisk/say.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
@@ -32,8 +33,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#ifdef __linux__
|
||||
#include <linux/zaptel.h>
|
||||
#else
|
||||
#include <zaptel.h>
|
||||
#endif /* __linux__ */
|
||||
|
||||
static char *tdesc = "Barge in on Zap channel application";
|
||||
|
||||
static char *app = "ZapBarge";
|
||||
@@ -244,9 +249,9 @@ static int conf_exec(struct ast_channel *chan, void *data)
|
||||
int retrycnt = 0;
|
||||
int confflags = 0;
|
||||
int confno = 0;
|
||||
char confstr[80];
|
||||
char confstr[80] = "";
|
||||
|
||||
if (data && strlen(data)) {
|
||||
if (data && !ast_strlen_zero(data)) {
|
||||
if ((sscanf(data, "Zap/%d", &confno) != 1) &&
|
||||
(sscanf(data, "%d", &confno) != 1)) {
|
||||
ast_log(LOG_WARNING, "ZapBarge Argument (if specified) must be a channel number, not '%s'\n", (char *)data);
|
||||
@@ -259,7 +264,7 @@ static int conf_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
while(!confno && (++retrycnt < 4)) {
|
||||
/* Prompt user for conference number */
|
||||
strcpy(confstr, "");
|
||||
confstr[0] = '\0';
|
||||
res = ast_app_getdata(chan, "conf-getchannel",confstr, sizeof(confstr) - 1, 0);
|
||||
if (res <0) goto out;
|
||||
if (sscanf(confstr, "%d", &confno) != 1)
|
||||
|
||||
39
apps/app_zapras.c
Executable file → Normal file
39
apps/app_zapras.c
Executable file → Normal file
@@ -20,7 +20,11 @@
|
||||
#include <asterisk/options.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/wait.h>
|
||||
#ifdef __linux__
|
||||
#include <sys/signal.h>
|
||||
#else
|
||||
#include <signal.h>
|
||||
#endif /* __linux__ */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@@ -30,10 +34,12 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/* Need some zaptel help here */
|
||||
#ifdef __linux__
|
||||
#include <linux/zaptel.h>
|
||||
#else
|
||||
#include <zaptel.h>
|
||||
#endif /* __linux__ */
|
||||
|
||||
static char *tdesc = "Zap RAS Application";
|
||||
|
||||
@@ -44,7 +50,7 @@ static char *synopsis = "Executes Zaptel ISDN RAS application";
|
||||
static char *descrip =
|
||||
" ZapRAS(args): Executes a RAS server using pppd on the given channel.\n"
|
||||
"The channel must be a clear channel (i.e. PRI source) and a Zaptel\n"
|
||||
"channel to be able to use this function (No modem emulcation is included).\n"
|
||||
"channel to be able to use this function (No modem emulation is included).\n"
|
||||
"Your pppd must be patched to be zaptel aware. Arguments should be\n"
|
||||
"separated by | characters. Always returns -1.\n";
|
||||
|
||||
@@ -119,8 +125,14 @@ static void run_ras(struct ast_channel *chan, char *args)
|
||||
int status;
|
||||
int res;
|
||||
int signalled = 0;
|
||||
struct zt_bufferinfo bi;
|
||||
struct zt_bufferinfo savebi;
|
||||
int x;
|
||||
|
||||
res = ioctl(chan->fds[0], ZT_GET_BUFINFO, &savebi);
|
||||
if(res) {
|
||||
ast_log(LOG_WARNING, "Unable to check buffer policy on channel %s\n", chan->name);
|
||||
return;
|
||||
}
|
||||
|
||||
pid = spawn_ras(chan, args);
|
||||
if (pid < 0) {
|
||||
@@ -156,20 +168,11 @@ static void run_ras(struct ast_channel *chan, char *args)
|
||||
x = 1;
|
||||
ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
|
||||
|
||||
/* Double check buffering too */
|
||||
res = ioctl(chan->fds[0], ZT_GET_BUFINFO, &bi);
|
||||
if (!res) {
|
||||
/* XXX This is ZAP_BLOCKSIZE XXX */
|
||||
bi.bufsize = 204;
|
||||
bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
|
||||
bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
|
||||
bi.numbufs = 4;
|
||||
res = ioctl(chan->fds[0], ZT_SET_BUFINFO, &bi);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set buffer policy on channel %s\n", chan->name);
|
||||
}
|
||||
} else
|
||||
ast_log(LOG_WARNING, "Unable to check buffer policy on channel %s\n", chan->name);
|
||||
/* Restore saved values */
|
||||
res = ioctl(chan->fds[0], ZT_SET_BUFINFO, &savebi);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Unable to set buffer policy on channel %s\n", chan->name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user