mirror of
https://github.com/asterisk/asterisk.git
synced 2026-03-14 17:57:27 +00:00
Compare commits
2083 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5c262931d | ||
|
|
63046de1cb | ||
|
|
e132aba5c9 | ||
|
|
4196243583 | ||
|
|
9ce061aa3f | ||
|
|
168ed954eb | ||
|
|
0d1660a369 | ||
|
|
ebb8253d2f | ||
|
|
11f81ad761 | ||
|
|
ad8786f355 | ||
|
|
17fd431b31 | ||
|
|
45c9175c77 | ||
|
|
8355d829bb | ||
|
|
b14b81d8b4 | ||
|
|
e875a17b48 | ||
|
|
7f9f2f6543 | ||
|
|
b2cfc35315 | ||
|
|
31c57904fd | ||
|
|
0ead801f25 | ||
|
|
009b812d76 | ||
|
|
a0d4959fc5 | ||
|
|
11c11d27bc | ||
|
|
6b36952664 | ||
|
|
afdd1c5512 | ||
|
|
ac303de4aa | ||
|
|
508b3ba688 | ||
|
|
75b0c4445a | ||
|
|
2f5ced421e | ||
|
|
d09714e12b | ||
|
|
52171d4c26 | ||
|
|
8bd93a96ac | ||
|
|
5a80b57ccf | ||
|
|
b2fb3d501c | ||
|
|
6cf8ee01a6 | ||
|
|
153119a7bc | ||
|
|
9b8ba163f2 | ||
|
|
bfac0241be | ||
|
|
09f5f15a72 | ||
|
|
84957104b2 | ||
|
|
312008513e | ||
|
|
08630905fa | ||
|
|
83ef83a5f8 | ||
|
|
2595998b8f | ||
|
|
7fe4d52579 | ||
|
|
39d4e1253b | ||
|
|
f7eada3cff | ||
|
|
405ff91e92 | ||
|
|
ce07ed72c0 | ||
|
|
150fc177cd | ||
|
|
c73ad9e6f9 | ||
|
|
cf638de6ad | ||
|
|
40ea953811 | ||
|
|
8061ba32c3 | ||
|
|
120e4bc237 | ||
|
|
4fc7030156 | ||
|
|
34d2254f70 | ||
|
|
b47ed67c84 | ||
|
|
e6f049f9bf | ||
|
|
7491dba549 | ||
|
|
3e7d040f3f | ||
|
|
c78761cc7c | ||
|
|
6b6eb7977b | ||
|
|
a795d02a30 | ||
|
|
2faf30d730 | ||
|
|
c2a39b5c64 | ||
|
|
ffc2c34f15 | ||
|
|
57cb8c168c | ||
|
|
f1274662f4 | ||
|
|
9f6e57f90a | ||
|
|
8ff6d5cabf | ||
|
|
298718ebaa | ||
|
|
171872003b | ||
|
|
5fe5bf08b2 | ||
|
|
cf238fa10d | ||
|
|
7e3d58e030 | ||
|
|
508b530e39 | ||
|
|
5e168ffd67 | ||
|
|
9e05fb4f39 | ||
|
|
a2c28355e0 | ||
|
|
0e4c9f9765 | ||
|
|
4d504015d4 | ||
|
|
3e2bd82411 | ||
|
|
2877470389 | ||
|
|
4a15544b22 | ||
|
|
9400e87db0 | ||
|
|
200ca9631d | ||
|
|
4f1e96c0b6 | ||
|
|
eac2ef9374 | ||
|
|
dd70231e97 | ||
|
|
02bb0b5e22 | ||
|
|
f14775e845 | ||
|
|
ee90d54c2e | ||
|
|
f4c2a167ed | ||
|
|
0ad6773b76 | ||
|
|
320be7fff9 | ||
|
|
0c2abdf74e | ||
|
|
0b3cfb26b4 | ||
|
|
cbc30c9163 | ||
|
|
71a395e3e3 | ||
|
|
b2073cb75f | ||
|
|
df905cf5a2 | ||
|
|
cf45c660cc | ||
|
|
2995096956 | ||
|
|
a6e8158ddc | ||
|
|
68206d0890 | ||
|
|
6dbcb94c01 | ||
|
|
91f9740856 | ||
|
|
083cf7af1d | ||
|
|
984142aebe | ||
|
|
29f7161c9b | ||
|
|
6618cec0d7 | ||
|
|
ebe377fc5c | ||
|
|
268eedc2f3 | ||
|
|
eadb02a84f | ||
|
|
c98832d092 | ||
|
|
888c329e65 | ||
|
|
548ce34d97 | ||
|
|
2e4b4764fb | ||
|
|
bf1069b3ae | ||
|
|
f717cd2719 | ||
|
|
cda604fabe | ||
|
|
6125965ff5 | ||
|
|
a6cea6892b | ||
|
|
1031a3c36d | ||
|
|
89d62574ef | ||
|
|
262e9c3003 | ||
|
|
43e32456ca | ||
|
|
fcb8ab5da6 | ||
|
|
0f5dbaf7ec | ||
|
|
8e267ac60a | ||
|
|
794d0b2c68 | ||
|
|
8c97879e99 | ||
|
|
47f2779b9d | ||
|
|
c77e7ed452 | ||
|
|
a9fd6fca9e | ||
|
|
57b353cebf | ||
|
|
07c87b82ff | ||
|
|
f1c3d761aa | ||
|
|
34f9e85a11 | ||
|
|
56cf655835 | ||
|
|
4d1e5adfdc | ||
|
|
3d263c243a | ||
|
|
334e508e66 | ||
|
|
28eedd8e44 | ||
|
|
e0aaf08b3b | ||
|
|
e16718bb2e | ||
|
|
1e70fa09cd | ||
|
|
a2f752ec6c | ||
|
|
3ad71d439c | ||
|
|
d667d39367 | ||
|
|
c96d5eabad | ||
|
|
941ba1c5be | ||
|
|
17045b502f | ||
|
|
916f6b627a | ||
|
|
e56c7ba459 | ||
|
|
34bc1ac241 | ||
|
|
4920426fbd | ||
|
|
e5f2fef425 | ||
|
|
4faec1b262 | ||
|
|
efc4fdf079 | ||
|
|
8b6aa2741c | ||
|
|
90fea452ac | ||
|
|
8451fd7f7d | ||
|
|
ed8a15efce | ||
|
|
6bee09440d | ||
|
|
d54b330a2e | ||
|
|
621b5be6cd | ||
|
|
687846975e | ||
|
|
315e0c3054 | ||
|
|
4f4009663c | ||
|
|
48f1386fff | ||
|
|
8f0e43be23 | ||
|
|
4b165caef4 | ||
|
|
4a14b7c071 | ||
|
|
e12e134ef9 | ||
|
|
7b319eb03a | ||
|
|
98d05f22ac | ||
|
|
7ba20c5024 | ||
|
|
2e6d346313 | ||
|
|
8aaa9e194e | ||
|
|
60a9627192 | ||
|
|
28a319be01 | ||
|
|
f066af663f | ||
|
|
1e2baaf12e | ||
|
|
f56ba6a441 | ||
|
|
2ea44416b2 | ||
|
|
78f6f43d19 | ||
|
|
42b84afa40 | ||
|
|
be446083ab | ||
|
|
61538bec92 | ||
|
|
4402a86f93 | ||
|
|
4ead78e851 | ||
|
|
d056623e60 | ||
|
|
a281bef2b3 | ||
|
|
4b30e9ee37 | ||
|
|
2b1a8d34d9 | ||
|
|
bc70235479 | ||
|
|
857bf5486b | ||
|
|
4d6e2801d1 | ||
|
|
f4a80f1609 | ||
|
|
26d298f693 | ||
|
|
926270782f | ||
|
|
fd7f18421d | ||
|
|
ee53dc7286 | ||
|
|
d565dc3225 | ||
|
|
fe07794bba | ||
|
|
4aa9d15438 | ||
|
|
83e1402d8a | ||
|
|
f1c93a8ff3 | ||
|
|
a004c5ca9e | ||
|
|
d6efd17100 | ||
|
|
3aeb519068 | ||
|
|
eb767e674f | ||
|
|
b4af00a20f | ||
|
|
39e574a8bd | ||
|
|
04c06471e6 | ||
|
|
687b01f298 | ||
|
|
8e59e3e38c | ||
|
|
1dec1dfb9c | ||
|
|
292059c9cb | ||
|
|
63b6e2a2a1 | ||
|
|
9420fee71d | ||
|
|
ece9341019 | ||
|
|
e608ffdaa9 | ||
|
|
684ffcce61 | ||
|
|
a346745899 | ||
|
|
5ef097f5d7 | ||
|
|
d35a82a5b6 | ||
|
|
b2ab9ffaec | ||
|
|
2e88a61fa3 | ||
|
|
9e1d3683fa | ||
|
|
528d2dcff5 | ||
|
|
40969e6b29 | ||
|
|
59814ed3e5 | ||
|
|
8f2106c5e3 | ||
|
|
37a80ea3bc | ||
|
|
a46350e315 | ||
|
|
e1a6d33ed0 | ||
|
|
4979d7fbb1 | ||
|
|
bdcbd76e13 | ||
|
|
081e28667e | ||
|
|
1ef98ac6de | ||
|
|
b90f6b40d9 | ||
|
|
2bb388ebc8 | ||
|
|
1714f299c9 | ||
|
|
5571294b91 | ||
|
|
3696407c67 | ||
|
|
76b18e2d6e | ||
|
|
d9d599a84d | ||
|
|
36d08dc8f0 | ||
|
|
3035547927 | ||
|
|
517413928f | ||
|
|
b3ee85ee4a | ||
|
|
540a2571ca | ||
|
|
53840ccffc | ||
|
|
61d87e19f1 | ||
|
|
63a98a2bed | ||
|
|
4542f92842 | ||
|
|
fa023ceccf | ||
|
|
6c5bf0d542 | ||
|
|
a3b4b4459c | ||
|
|
58b1b7f825 | ||
|
|
4f5f53706d | ||
|
|
a87fb09763 | ||
|
|
fb3de07e39 | ||
|
|
02bb7498b0 | ||
|
|
8c9f25ece1 | ||
|
|
6356638b6a | ||
|
|
659eb8bd36 | ||
|
|
2ef418765c | ||
|
|
33cffbd344 | ||
|
|
5d877f53ed | ||
|
|
334bd9f57d | ||
|
|
a6fb9eef88 | ||
|
|
d9d070e30b | ||
|
|
73f50db89e | ||
|
|
d1b6552ef7 | ||
|
|
8b079c4bf2 | ||
|
|
22db312ca1 | ||
|
|
fbc3e2e3ce | ||
|
|
d2d967d775 | ||
|
|
c69bb18184 | ||
|
|
dc5042762f | ||
|
|
efcc597742 | ||
|
|
b0a516034f | ||
|
|
2880956743 | ||
|
|
56dd7681f8 | ||
|
|
a6d0cc6c02 | ||
|
|
9c92ca2d27 | ||
|
|
f8526ef3ba | ||
|
|
96624911f0 | ||
|
|
5967d8f2bc | ||
|
|
dcd5da730a | ||
|
|
3c54495507 | ||
|
|
f9eedef7ee | ||
|
|
de117b689e | ||
|
|
5799a6a60c | ||
|
|
a97e1f873f | ||
|
|
74239cb26c | ||
|
|
fa7a75c886 | ||
|
|
4a187156b2 | ||
|
|
f45b8fcc70 | ||
|
|
1db571cb37 | ||
|
|
8289500dd5 | ||
|
|
ec9f642dc3 | ||
|
|
f2a2787b42 | ||
|
|
da0fb57df3 | ||
|
|
10378ed083 | ||
|
|
b0b9c0928b | ||
|
|
9386b25b51 | ||
|
|
9a81d7270e | ||
|
|
29062def81 | ||
|
|
ad851c87b5 | ||
|
|
b67759975d | ||
|
|
f4adada2e8 | ||
|
|
a4671a3d88 | ||
|
|
379d3a133c | ||
|
|
dd8d225b4e | ||
|
|
78693d31e9 | ||
|
|
49d18cef95 | ||
|
|
cc8996361c | ||
|
|
8060744e05 | ||
|
|
799ff464f2 | ||
|
|
b107f9c1c9 | ||
|
|
0e39f602ea | ||
|
|
a391baf1be | ||
|
|
3384173257 | ||
|
|
51ea5a2797 | ||
|
|
1298f6585d | ||
|
|
2ebc21f175 | ||
|
|
6c6ec855a7 | ||
|
|
10bbbf2c14 | ||
|
|
fcf810801f | ||
|
|
665cf4fb64 | ||
|
|
6f60468d3d | ||
|
|
00f2912aaa | ||
|
|
b32ffb8190 | ||
|
|
4ceafc96b1 | ||
|
|
bed2bda4f4 | ||
|
|
a97bf16d2d | ||
|
|
8a987daf3b | ||
|
|
8d135aa5ae | ||
|
|
0a4530cead | ||
|
|
ad1ee839cc | ||
|
|
1b53088a4b | ||
|
|
a5b4c8881e | ||
|
|
2583e00e03 | ||
|
|
7e3f8ee419 | ||
|
|
b035299213 | ||
|
|
4020387145 | ||
|
|
3e7c0ce67f | ||
|
|
0caa4033c9 | ||
|
|
cd65e922b2 | ||
|
|
90f22a990d | ||
|
|
0b74a19625 | ||
|
|
429432f5ff | ||
|
|
46f97f76a5 | ||
|
|
ec3b5c9b5b | ||
|
|
a160a8c9d5 | ||
|
|
65d6be272d | ||
|
|
1e75116e74 | ||
|
|
187942d00a | ||
|
|
418ff58e61 | ||
|
|
bb6333e01f | ||
|
|
df6c1f8b39 | ||
|
|
2b9417e2e5 | ||
|
|
f53fe9761c | ||
|
|
902661dd8e | ||
|
|
646dc459fa | ||
|
|
3d48bc2f61 | ||
|
|
28109dedf5 | ||
|
|
10781d30d2 | ||
|
|
c0c9a1a5f0 | ||
|
|
13e54102fd | ||
|
|
f4470352ff | ||
|
|
77ad568144 | ||
|
|
1b05a4639d | ||
|
|
e73c4e4a44 | ||
|
|
60c2988f53 | ||
|
|
35dd204d76 | ||
|
|
8eb984caec | ||
|
|
9801c6c63f | ||
|
|
1b754ff59d | ||
|
|
713ddd2172 | ||
|
|
d3cb67a4cd | ||
|
|
1f02d433b3 | ||
|
|
dbf6ad2ecd | ||
|
|
c6938534bd | ||
|
|
ac659af3ea | ||
|
|
bdabdcbf1e | ||
|
|
457d6f2822 | ||
|
|
0d23dbb490 | ||
|
|
3cd77bab28 | ||
|
|
a39d05855e | ||
|
|
66d0e5756f | ||
|
|
591eb8fac1 | ||
|
|
0ae97da489 | ||
|
|
014a0a178b | ||
|
|
5e8f6247fb | ||
|
|
de1c7219ea | ||
|
|
7352e07e12 | ||
|
|
bfe333ed67 | ||
|
|
ec25eab17f | ||
|
|
e212b875fc | ||
|
|
92f1ec6be4 | ||
|
|
4443cc2107 | ||
|
|
d612a5ce42 | ||
|
|
808ecc893a | ||
|
|
1e9087357b | ||
|
|
124c88fba3 | ||
|
|
ef3f4d29c9 | ||
|
|
67478da442 | ||
|
|
67c451783b | ||
|
|
517e58c5df | ||
|
|
b86dbdb22c | ||
|
|
807bbf3461 | ||
|
|
8b1cdad2f5 | ||
|
|
ce25d82aa7 | ||
|
|
d354512eca | ||
|
|
f0131ed0f2 | ||
|
|
a4111e1f93 | ||
|
|
f7098a28be | ||
|
|
fdffdc9364 | ||
|
|
d91f0dadc9 | ||
|
|
291309df4a | ||
|
|
eb08e2600f | ||
|
|
0faa51794d | ||
|
|
5f5017defd | ||
|
|
737023e9d4 | ||
|
|
e98d85bf09 | ||
|
|
6adefd13c1 | ||
|
|
5c37031b1c | ||
|
|
141a82674e | ||
|
|
2423b41fd9 | ||
|
|
f85277c7b3 | ||
|
|
d60b955324 | ||
|
|
663636b515 | ||
|
|
8bccbf9afb | ||
|
|
1d10b782b4 | ||
|
|
3cd48f9a41 | ||
|
|
d50ef1d333 | ||
|
|
fbcd14b30b | ||
|
|
09ca3690b5 | ||
|
|
6db145dd07 | ||
|
|
0ff4ffd27f | ||
|
|
ba5a68e731 | ||
|
|
df358f42e0 | ||
|
|
0e518edee4 | ||
|
|
dea58d2e88 | ||
|
|
97efb246b3 | ||
|
|
17a3454b92 | ||
|
|
3680bb43cd | ||
|
|
b0180d6665 | ||
|
|
f9be91101f | ||
|
|
e16c9c9ecd | ||
|
|
57c86cec8e | ||
|
|
d600998f7e | ||
|
|
a75365ea8e | ||
|
|
8b34f224e7 | ||
|
|
97d664a128 | ||
|
|
04bcd2ff23 | ||
|
|
3f9482f7bc | ||
|
|
ebf15d6151 | ||
|
|
38f5196684 | ||
|
|
31457d7be1 | ||
|
|
a196c598b6 | ||
|
|
ca88a7476f | ||
|
|
eda8998156 | ||
|
|
b1b4db95c2 | ||
|
|
01e406626e | ||
|
|
89da44223d | ||
|
|
ddf2648326 | ||
|
|
4c2148bea5 | ||
|
|
66bf105bbc | ||
|
|
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 |
@@ -1,5 +0,0 @@
|
||||
asterisk
|
||||
build.h
|
||||
ast_expr.c
|
||||
.version
|
||||
.depend
|
||||
5
BUGS
Executable file → Normal file
5
BUGS
Executable file → Normal file
@@ -1,3 +1,8 @@
|
||||
Asterisk 1.0-RC-1 Known Major Bugs
|
||||
==================================
|
||||
* Some people still have issues with H.323
|
||||
* QuickNet driver still not entirely stable
|
||||
|
||||
Asterisk Bug Tracking Information
|
||||
=================================
|
||||
|
||||
|
||||
11
CREDITS
Executable file → Normal file
11
CREDITS
Executable file → Normal file
@@ -5,6 +5,8 @@ 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
|
||||
@@ -12,6 +14,7 @@ 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
|
||||
@@ -23,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
|
||||
@@ -52,10 +57,16 @@ 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
|
||||
|
||||
306
CHANGES → ChangeLog
Executable file → Normal file
306
CHANGES → ChangeLog
Executable file → Normal file
@@ -1,3 +1,309 @@
|
||||
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.
|
||||
-- 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
|
||||
6
HARDWARE
Executable file → Normal file
6
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.
|
||||
|
||||
222
Makefile
Executable file → Normal file
222
Makefile
Executable file → Normal file
@@ -20,11 +20,31 @@ OSARCH=$(shell uname -s)
|
||||
|
||||
ifeq (${OSARCH},Linux)
|
||||
PROC=$(shell uname -m)
|
||||
else
|
||||
ifeq (${OSARCH},FreeBSD)
|
||||
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
|
||||
endif
|
||||
|
||||
# Pentium Pro Optimize
|
||||
#PROC=i686
|
||||
|
||||
@@ -43,15 +63,18 @@ PWD=$(shell pwd)
|
||||
#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
|
||||
|
||||
# New hangup routines for chan_zap.c
|
||||
# If this flag is uncommented then you need to have new libpri code in your system
|
||||
# You can still use the old libpri if you do "cvs update -D "08/03/03" in libpri source code
|
||||
OPTIONS += -DNEW_PRI_HANGUP
|
||||
# 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 = #-DDEBUG_THREADS #-DDO_CRASH
|
||||
@@ -98,6 +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
|
||||
@@ -105,24 +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)
|
||||
CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi)
|
||||
ifeq (${OSARCH},FreeBSD)
|
||||
CFLAGS+=-pthread
|
||||
INCLUDE+=-I/usr/local/include
|
||||
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
|
||||
|
||||
# Comment this out if you have trouble with Feature B signalling (rare)
|
||||
CFLAGS+=-DOLD_DSP_ROUTINES
|
||||
#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; else if [ -d CVS ]; then echo "CVS-`date +"%D-%T"`"; fi; 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)\"
|
||||
@@ -147,38 +189,50 @@ SUBDIRS=res channels pbx apps codecs formats agi cdr astman stdtime
|
||||
ifeq (${OSARCH},Linux)
|
||||
LIBS=-ldl -lpthread
|
||||
endif
|
||||
ifeq (${OSARCH},OpenBSD)
|
||||
LIBS=-pthread
|
||||
else
|
||||
ifeq (${OSARCH},FreeBSD)
|
||||
LIBS=-pthread
|
||||
else
|
||||
endif
|
||||
endif
|
||||
LIBS+=-lncurses -lm
|
||||
ifeq (${OSARCH},Linux)
|
||||
LIBS+=-lresolv #-lnjamd
|
||||
endif
|
||||
ifeq (${OSARCH},Darwin)
|
||||
ifeq ($(shell uname -r),7.0.0)
|
||||
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 \
|
||||
astmm.o enum.o srv.o dns.o aescrypt.o aestab.o aeskey.o
|
||||
astmm.o enum.o srv.o dns.o aescrypt.o aestab.o aeskey.o \
|
||||
utils.o
|
||||
ifeq (${OSARCH},Darwin)
|
||||
OBJS+=poll.o dlfcn.o
|
||||
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
|
||||
|
||||
@@ -191,7 +245,7 @@ _all: all
|
||||
@echo " + $(MAKE) install +"
|
||||
@echo " +-------------------------------------------+"
|
||||
|
||||
all: depend asterisk subdirs
|
||||
all: depend asterisk subdirs
|
||||
|
||||
editline/config.h:
|
||||
cd editline && unset CFLAGS LIBS && ./configure ; \
|
||||
@@ -228,6 +282,14 @@ 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
|
||||
@@ -245,7 +307,10 @@ stdtime/libtime.a: FORCE
|
||||
fi
|
||||
|
||||
asterisk: editline/libedit.a db1-ast/libdb1.a stdtime/libtime.a $(OBJS)
|
||||
$(CC) $(DEBUG) -o asterisk $(ASTLINK) $(OBJS) $(LIBS) $(LIBEDIT) db1-ast/libdb1.a stdtime/libtime.a
|
||||
$(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
|
||||
@@ -256,6 +321,7 @@ clean:
|
||||
rm -f build.h
|
||||
rm -f ast_expr.c
|
||||
@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
|
||||
|
||||
@@ -263,15 +329,33 @@ datafiles: all
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/digits
|
||||
for x in sounds/digits/*.gsm; do \
|
||||
if grep -q "^%`basename $$x`%" sounds.txt; then \
|
||||
install $$x $(DESTDIR)$(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 $(DESTDIR)$(ASTVARLIBDIR)/sounds ; \
|
||||
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds/letters ; \
|
||||
else \
|
||||
echo "No description for $$x"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
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
|
||||
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; \
|
||||
@@ -280,14 +364,14 @@ datafiles: all
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/mohmp3
|
||||
mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/images
|
||||
for x in images/*.jpg; do \
|
||||
install $$x $(DESTDIR)$(ASTVARLIBDIR)/images ; \
|
||||
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/images ; \
|
||||
done
|
||||
mkdir -p $(DESTDIR)$(AGI_DIR)
|
||||
|
||||
update:
|
||||
@if [ -d CVS ]; then \
|
||||
echo "Updating from CVS..." ; \
|
||||
cvs -q update -Pd; \
|
||||
cvs -q -z3 update -Pd; \
|
||||
rm -f .version; \
|
||||
else \
|
||||
echo "Not CVS"; \
|
||||
@@ -301,14 +385,16 @@ bininstall: all
|
||||
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 $(DESTDIR)$(ASTHEADERDIR)
|
||||
install include/asterisk/*.h $(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 \
|
||||
@@ -318,19 +404,26 @@ bininstall: all
|
||||
rm -f $(DESTDIR)$(ASTSPOOLDIR)/vm; \
|
||||
fi
|
||||
ln -s $(ASTSPOOLDIR)/voicemail/default $(DESTDIR)$(ASTSPOOLDIR)/vm
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/chan_ixj.so
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/chan_tor.so
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/cdr_mysql.so
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/cdr_unixodbc.so
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/codec_mp3_d.so
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/format_mp3.so
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/app_voicemail2.so
|
||||
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 +"
|
||||
@@ -352,6 +445,19 @@ bininstall: all
|
||||
@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
|
||||
|
||||
@@ -371,7 +477,7 @@ samples: all datafiles adsi
|
||||
if [ -f $(DESTDIR)$(ASTETCDIR)/`basename $$x .sample` ]; then \
|
||||
mv -f $(DESTDIR)$(ASTETCDIR)/`basename $$x .sample` $(DESTDIR)$(ASTETCDIR)/`basename $$x .sample`.old ; \
|
||||
fi ; \
|
||||
install $$x $(DESTDIR)$(ASTETCDIR)/`basename $$x .sample` ;\
|
||||
install -m 644 $$x $(DESTDIR)$(ASTETCDIR)/`basename $$x .sample` ;\
|
||||
done
|
||||
echo "[directories]" > $(DESTDIR)$(ASTETCDIR)/asterisk.conf
|
||||
echo "astetcdir => $(ASTETCDIR)" >> $(DESTDIR)$(ASTETCDIR)/asterisk.conf
|
||||
@@ -383,21 +489,22 @@ samples: all datafiles adsi
|
||||
echo "astlogdir => $(ASTLOGDIR)" >> $(DESTDIR)$(ASTETCDIR)/asterisk.conf
|
||||
for x in sounds/demo-*; do \
|
||||
if grep -q "^%`basename $$x`%" sounds.txt; then \
|
||||
install $$x $(DESTDIR)$(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 $(DESTDIR)$(ASTVARLIBDIR)/mohmp3 ; \
|
||||
install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/mohmp3 ; \
|
||||
done
|
||||
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 $(DESTDIR)$(ASTVARLIBDIR)/sounds/$$x.gsm >> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/unavail.gsm ; \
|
||||
done
|
||||
:> $(DESTDIR)$(ASTVARLIBDIR)/sounds/voicemail/default/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 $(DESTDIR)$(ASTVARLIBDIR)/sounds/$$x.gsm >> $(DESTDIR)$(ASTSPOOLDIR)/voicemail/default/1234/busy.gsm ; \
|
||||
done
|
||||
@@ -422,7 +529,6 @@ webvmail:
|
||||
|
||||
mailbox:
|
||||
./contrib/scripts/addmailbox
|
||||
|
||||
|
||||
rpm: __rpm
|
||||
|
||||
@@ -435,10 +541,16 @@ __rpm: _version
|
||||
cp -f redhat/asterisk /tmp/asterisk/etc/rc.d/init.d/ ; \
|
||||
sed "s/^Version:.*/Version: $(RPMVERSION)/g" redhat/asterisk.spec > asterisk.spec ; \
|
||||
rpmbuild --rcfile /usr/lib/rpm/rpmrc:redhat/rpmrc -bb asterisk.spec
|
||||
|
||||
|
||||
progdocs:
|
||||
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 contrib/init.d/rc.redhat.asterisk /etc/rc.d/init.d/asterisk; \
|
||||
@@ -447,7 +559,6 @@ config:
|
||||
install -m 755 init.asterisk /etc/init.d/asterisk; \
|
||||
fi
|
||||
|
||||
|
||||
dont-optimize:
|
||||
$(MAKE) OPTIMIZE= K6OPT= install
|
||||
|
||||
@@ -457,6 +568,21 @@ 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
|
||||
|
||||
84
README
Executable file → Normal file
84
README
Executable file → Normal file
@@ -14,12 +14,17 @@ on the project itself, please visit the Asterisk home page at:
|
||||
|
||||
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.
|
||||
|
||||
Digium, Inc. (formerly Linux Support Services) retains copyright to all
|
||||
of the core Asterisk system, and therefore can grant, at its sole discression,
|
||||
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
|
||||
@@ -29,7 +34,7 @@ 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.
|
||||
@@ -45,13 +50,12 @@ licensing scheme are added to the Asterisk-addons CVS module.
|
||||
== 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 Digium (www.digium.com)
|
||||
* QuickNet Internet PhoneJack and LineJack (http://www.quicknet.net)
|
||||
@@ -60,8 +64,9 @@ you will need one of the following:
|
||||
* 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"
|
||||
@@ -71,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:
|
||||
|
||||
@@ -131,6 +136,67 @@ 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.
|
||||
@@ -143,3 +209,5 @@ you're interested in getting more information.
|
||||
Welcome to the growing worldwide community of Asterisk users!
|
||||
|
||||
Mark Spencer
|
||||
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
138
acl.c
Executable file → Normal file
138
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>
|
||||
@@ -22,6 +21,8 @@
|
||||
#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>
|
||||
@@ -29,15 +30,13 @@
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/ioctl.h>
|
||||
#ifdef __OpenBSD__
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
|
||||
#include <fcntl.h>
|
||||
#include <net/route.h>
|
||||
|
||||
static ast_mutex_t routeseq_lock = AST_MUTEX_INITIALIZER;
|
||||
AST_MUTEX_DEFINE_STATIC(routeseq_lock);
|
||||
#endif
|
||||
|
||||
#define AST_SENSE_DENY 0
|
||||
#define AST_SENSE_ALLOW 1
|
||||
|
||||
struct ast_ha {
|
||||
/* Host access rule */
|
||||
@@ -55,6 +54,7 @@ struct my_ifreq {
|
||||
struct sockaddr_in ifru_addr;
|
||||
};
|
||||
|
||||
/* Free HA structure */
|
||||
void ast_free_ha(struct ast_ha *ha)
|
||||
{
|
||||
struct ast_ha *hal;
|
||||
@@ -65,10 +65,52 @@ 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;
|
||||
@@ -119,6 +161,7 @@ struct ast_ha *ast_append_ha(char *sense, char *stuff, struct ast_ha *path)
|
||||
else
|
||||
ret = ha;
|
||||
}
|
||||
ast_log(LOG_DEBUG, "%s/%s appended to acl for peer\n",stuff, nm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -127,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))
|
||||
@@ -139,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 {
|
||||
@@ -149,12 +200,6 @@ 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;
|
||||
@@ -179,36 +224,37 @@ int ast_lookup_iface(char *iface, struct in_addr *address) {
|
||||
|
||||
int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
|
||||
{
|
||||
#ifdef __OpenBSD__
|
||||
#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 *cp, *p = ast_strdupa(inet_ntoa(*them));
|
||||
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_flags = RTF_UP | RTF_HOST;
|
||||
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_IFA | RTA_DST;
|
||||
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, 0)) < 0) {
|
||||
if ((s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC)) < 0) {
|
||||
ast_log(LOG_ERROR, "Error opening routing socket\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -221,7 +267,7 @@ int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
|
||||
}
|
||||
do {
|
||||
l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
|
||||
} while (l > 0 && (m_rtmsg.m_rtm.rtm_seq != 1 || m_rtmsg.m_rtm.rtm_pid != pid));
|
||||
} 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");
|
||||
@@ -253,7 +299,7 @@ int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
|
||||
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, inet_ntoa(*us));
|
||||
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 ?
|
||||
@@ -279,7 +325,7 @@ int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
|
||||
fgets(line,sizeof(line),PROC);
|
||||
|
||||
while (!feof(PROC)) {
|
||||
char iface[8];
|
||||
char iface[256];
|
||||
unsigned int dest, gateway, mask;
|
||||
int i,fieldnum;
|
||||
char *fields[40];
|
||||
@@ -303,18 +349,21 @@ int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
|
||||
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);
|
||||
sscanf(fields[0],"%s",iface);
|
||||
sscanf(fields[1],"%x",&dest);
|
||||
sscanf(fields[2],"%x",&gateway);
|
||||
sscanf(fields[7],"%x",&mask);
|
||||
#if 0
|
||||
printf("Addr: %s %08x Dest: %08x Mask: %08x\n", inet_ntoa(*them), remote_ip, dest, mask);
|
||||
{ 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;
|
||||
/* Looks simple, but here is the magic */
|
||||
if (((remote_ip & mask) ^ dest) == 0) {
|
||||
res = ast_lookup_iface(iface,us);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(PROC);
|
||||
@@ -329,3 +378,32 @@ int ast_ouraddrfor(struct in_addr *them, struct in_addr *us)
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
0
aescrypt.c
Executable file → Normal file
0
aescrypt.c
Executable file → Normal file
13
aesopt.h
Executable file → Normal file
13
aesopt.h
Executable file → Normal file
@@ -136,6 +136,7 @@
|
||||
#define _AESOPT_H
|
||||
|
||||
#include <asterisk/aes.h>
|
||||
#include "asterisk/endian.h"
|
||||
|
||||
/* CONFIGURATION - USE OF DEFINES
|
||||
|
||||
@@ -146,18 +147,6 @@
|
||||
#if clauses.
|
||||
*/
|
||||
|
||||
/* PLATFORM SPECIFIC INCLUDES */
|
||||
|
||||
#if defined( __FreeBSD__ ) || defined( __OpenBSD__ )
|
||||
# include <sys/endian.h>
|
||||
#elif defined( BSD ) && ( BSD >= 199103 )
|
||||
# include <machine/endian.h>
|
||||
#elif defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
|
||||
# include <endian.h>
|
||||
# include <byteswap.h>
|
||||
#elif defined( linux )
|
||||
# include <endian.h>
|
||||
#endif
|
||||
|
||||
/* BYTE ORDER IN 32-BIT WORDS
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
eagi-test
|
||||
eagi-sphinx-test
|
||||
.depend
|
||||
0
agi/DialAnMp3.agi
Executable file → Normal file
0
agi/DialAnMp3.agi
Executable file → Normal file
8
agi/Makefile
Executable file → Normal file
8
agi/Makefile
Executable file → Normal file
@@ -22,13 +22,13 @@ install: all
|
||||
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 .depend
|
||||
rm -f *.so *.o look .depend eagi-test eagi-sphinx-test
|
||||
|
||||
%.so : %.o
|
||||
$(CC) -shared -Xlinker -x -o $@ $<
|
||||
|
||||
0
agi/agi-test.agi
Executable file → Normal file
0
agi/agi-test.agi
Executable file → Normal file
0
agi/eagi-sphinx-test.c
Executable file → Normal file
0
agi/eagi-sphinx-test.c
Executable file → Normal file
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
780
app.c
Executable file → Normal file
780
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>
|
||||
@@ -27,15 +26,21 @@
|
||||
#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)
|
||||
@@ -131,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);
|
||||
}
|
||||
@@ -153,14 +165,14 @@ int ast_app_has_voicemail(const char *mailbox)
|
||||
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)) {
|
||||
if (!ast_strlen_zero(cur)) {
|
||||
if (ast_app_has_voicemail(cur))
|
||||
return 1;
|
||||
}
|
||||
@@ -202,15 +214,15 @@ int ast_app_messagecount(const char *mailbox, int *newmsgs, int *oldmsgs)
|
||||
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 {
|
||||
@@ -258,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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
.depend
|
||||
26
apps/Makefile
Executable file → Normal file
26
apps/Makefile
Executable file → Normal file
@@ -17,15 +17,19 @@ 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_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_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_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
|
||||
@@ -33,9 +37,11 @@ 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 app_zapscan.so" ; fi)
|
||||
#APPS+=$(shell if [ -f /usr/include/zap.h ]; then echo "app_rpt.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+=-fPIC
|
||||
|
||||
@@ -60,12 +66,7 @@ app_rpt.so : app_rpt.o
|
||||
|
||||
install: all
|
||||
for x in $(APPS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
|
||||
|
||||
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) $(SOLINK) -o $@ $< -L/usr/local/ssl/lib -lssl -lcrypto
|
||||
rm -f $(DESTDIR)$(MODULES_DIR)/app_datetime.so
|
||||
|
||||
app_voicemail.so : app_voicemail.o
|
||||
ifeq ($(USE_MYSQL_VM_INTERFACE),1)
|
||||
@@ -88,7 +89,7 @@ app_sql_odbc.so: app_sql_odbc.o
|
||||
$(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
|
||||
@@ -98,3 +99,6 @@ depend: .depend
|
||||
|
||||
.depend:
|
||||
../mkdep $(CFLAGS) `ls *.c`
|
||||
|
||||
env:
|
||||
env
|
||||
|
||||
33
apps/app_adsiprog.c
Executable file → Normal file
33
apps/app_adsiprog.c
Executable file → Normal file
@@ -19,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>
|
||||
@@ -28,8 +30,6 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "../asterisk.h"
|
||||
#include "../astconf.h"
|
||||
|
||||
@@ -178,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 */
|
||||
@@ -198,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 */
|
||||
@@ -666,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;
|
||||
}
|
||||
@@ -695,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;
|
||||
@@ -831,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 },
|
||||
@@ -1350,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);
|
||||
}
|
||||
}
|
||||
@@ -1435,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);
|
||||
@@ -1459,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);
|
||||
@@ -1483,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);
|
||||
@@ -1527,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))
|
||||
|
||||
0
apps/app_cdr.c
Executable file → Normal file
0
apps/app_cdr.c
Executable file → Normal file
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;
|
||||
}
|
||||
14
apps/app_cut.c
Executable file → Normal file
14
apps/app_cut.c
Executable file → Normal file
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* Copyright (c) 2003 Tilghman Lesher. All rights reserved.
|
||||
*
|
||||
* Tilghman Lesher <app_cut__v002@the-tilghman.com>
|
||||
* Tilghman Lesher <app_cut__v003@the-tilghman.com>
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
@@ -31,10 +31,10 @@ static char *tdesc = "Cuts up variables";
|
||||
|
||||
static char *app_cut = "Cut";
|
||||
|
||||
static char *cut_synopsis = "Cut(newvar=varname|delimiter|fieldspec)";
|
||||
static char *cut_synopsis = "Splits a variable's content using the specified delimiter";
|
||||
|
||||
static char *cut_descrip =
|
||||
"Cut(newvar=varname,delimiter,field)\n"
|
||||
"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"
|
||||
@@ -82,14 +82,14 @@ static int cut_exec(struct ast_channel *chan, void *data)
|
||||
if (args_okay) {
|
||||
char d, ds[2];
|
||||
char *tmp = alloca(strlen(varname) + 4);
|
||||
char *tmp2 = alloca(MAXRESULT);
|
||||
char varvalue[MAXRESULT], *tmp2=varvalue;
|
||||
char retstring[MAXRESULT];
|
||||
|
||||
memset(retstring, 0, MAXRESULT);
|
||||
|
||||
if (tmp && tmp2) {
|
||||
if (tmp) {
|
||||
snprintf(tmp, strlen(varname) + 4, "${%s}", varname);
|
||||
memset(tmp2, 0, sizeof(tmp2));
|
||||
memset(varvalue, 0, sizeof(varvalue));
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Out of memory");
|
||||
return -1;
|
||||
@@ -101,7 +101,7 @@ static int cut_exec(struct ast_channel *chan, void *data)
|
||||
d = '-';
|
||||
|
||||
/* String form of the delimiter, for use with strsep(3) */
|
||||
sprintf(ds,"%c",d);
|
||||
snprintf(ds, sizeof(ds), "%c", d);
|
||||
|
||||
pbx_substitute_variables_helper(chan, tmp, tmp2, MAXRESULT - 1);
|
||||
|
||||
|
||||
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";
|
||||
|
||||
409
apps/app_db.c
Executable file → Normal file
409
apps/app_db.c
Executable file → Normal file
@@ -20,33 +20,31 @@
|
||||
#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";
|
||||
@@ -62,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;
|
||||
}
|
||||
|
||||
685
apps/app_dial.c
Executable file → Normal file
685
apps/app_dial.c
Executable file → Normal file
@@ -3,9 +3,9 @@
|
||||
*
|
||||
* Trivial application to dial a channel and send an URL on answer
|
||||
*
|
||||
* 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
|
||||
@@ -20,9 +20,12 @@
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/say.h>
|
||||
#include <asterisk/parking.h>
|
||||
#include <asterisk/config.h>
|
||||
#include <asterisk/features.h>
|
||||
#include <asterisk/musiconhold.h>
|
||||
#include <asterisk/callerid.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <asterisk/app.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
@@ -33,8 +36,6 @@
|
||||
#include <sys/signal.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Dialing Application";
|
||||
|
||||
static char *app = "Dial";
|
||||
@@ -49,28 +50,54 @@ static char *descrip =
|
||||
"which first answered. All other calls placed by the Dial app will be hung up\n"
|
||||
"If a timeout is not specified, the Dial application will wait indefinitely\n"
|
||||
"until either one of the called channels answers, the user hangs up, or all\n"
|
||||
"channels return busy or error. In general, the dialler will return 0 if it\n"
|
||||
"channels return busy or error. In general, the dialer will return 0 if it\n"
|
||||
"was unable to place the call, or the timeout expired. However, if all\n"
|
||||
"channels were busy, and there exists an extension with priority n+101 (where\n"
|
||||
"n is the priority of the dialler instance), then it will be the next\n"
|
||||
"n is the priority of the dialer instance), then it will be the next\n"
|
||||
"executed extension (this allows you to setup different behavior on busy from\n"
|
||||
"no-answer).\n"
|
||||
" This application returns -1 if the originating channel hangs up, or if the\n"
|
||||
"call is bridged and either of the parties in the bridge terminate the call.\n"
|
||||
"The option string may contain zero or more of the following characters:\n"
|
||||
" 't' -- allow the called user transfer the calling user\n"
|
||||
" 'T' -- to allow the calling user to transfer the call.\n"
|
||||
" 't' -- allow the called user transfer the calling user by hitting #.\n"
|
||||
" 'T' -- allow the calling user to transfer the call by hitting #.\n"
|
||||
" 'f' -- Forces callerid to be set as the extension of the line \n"
|
||||
" making/redirecting the outgoing call. For example, some PSTNs\n"
|
||||
" don't allow callerids from other extensions then the ones\n"
|
||||
" that are assigned to you.\n"
|
||||
" 'r' -- indicate ringing to the calling party, pass no audio until answered.\n"
|
||||
" 'm' -- provide hold music to the calling party until answered.\n"
|
||||
" 'M(x) -- Executes the macro (x) upon connect of the call\n"
|
||||
" 'h' -- allow callee to hang up by hitting *.\n"
|
||||
" 'H' -- allow caller to hang up by hitting *.\n"
|
||||
" 'C' -- reset call detail record for this call.\n"
|
||||
" 'P[(x)]' -- privacy mode, using 'x' as database if provided.\n"
|
||||
" 'g' -- goes on in context if the destination channel hangs up\n"
|
||||
" 'A(x)' -- play an announcement to the called party, using x as file\n"
|
||||
" 'S(x)' -- hangup the call after x seconds AFTER called party picked up\n"
|
||||
" 'D([digits])' -- Send DTMF digit string *after* called party has answered\n"
|
||||
" but before the bridge. (w=500ms sec pause)\n"
|
||||
" 'L(x[:y][:z])' -- Limit the call to 'x' ms warning when 'y' ms are left\n"
|
||||
" repeated every 'z' ms) Only 'x' is required, 'y' and 'z' are optional.\n"
|
||||
" The following special variables are optional:\n"
|
||||
" * LIMIT_PLAYAUDIO_CALLER yes|no (default yes)\n"
|
||||
" Play sounds to the caller.\n"
|
||||
" * LIMIT_PLAYAUDIO_CALLEE yes|no\n"
|
||||
" Play sounds to the callee.\n"
|
||||
" * LIMIT_TIMEOUT_FILE File to play when time is up.\n"
|
||||
" * LIMIT_CONNECT_FILE File to play when call begins.\n"
|
||||
" * LIMIT_WARNING_FILE File to play as warning if 'y' is defined.\n"
|
||||
" 'timeleft' is a special sound macro to auto-say the time \n"
|
||||
" left and is the default.\n\n"
|
||||
" In addition to transferring the call, a call may be parked and then picked\n"
|
||||
"up by another user.\n"
|
||||
" The optionnal URL will be sent to the called party if the channel supports\n"
|
||||
"it.\n";
|
||||
" The optional URL will be sent to the called party if the channel supports it.\n"
|
||||
" This application sets the following channel variables upon completion:\n"
|
||||
" DIALEDTIME Time from dial to answer\n"
|
||||
" ANSWEREDTIME Time for actual call\n"
|
||||
" DIALSTATUS The status of the call as a text string, one of\n"
|
||||
" CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL\n"
|
||||
"";
|
||||
|
||||
/* We define a customer "local user" structure because we
|
||||
use it not only for keeping track of what is in use but
|
||||
@@ -83,7 +110,10 @@ struct localuser {
|
||||
int allowredirect_out;
|
||||
int ringbackonly;
|
||||
int musiconhold;
|
||||
int allowdisconnect;
|
||||
int allowdisconnect_in;
|
||||
int allowdisconnect_out;
|
||||
int forcecallerid;
|
||||
int noforwardhtml;
|
||||
struct localuser *next;
|
||||
};
|
||||
|
||||
@@ -103,43 +133,33 @@ static void hanguptree(struct localuser *outgoing, struct ast_channel *exception
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX 256
|
||||
#define AST_MAX_WATCHERS 256
|
||||
|
||||
static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect)
|
||||
static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect_in, int *allowdisconnect_out, int *noforwardhtml, int *sentringing, char *status, size_t statussize)
|
||||
{
|
||||
struct localuser *o;
|
||||
int found;
|
||||
int numlines;
|
||||
int sentringing = 0;
|
||||
int numbusies = 0;
|
||||
int numbusy = 0;
|
||||
int numcongestion = 0;
|
||||
int numnochan = 0;
|
||||
int orig = *to;
|
||||
struct ast_frame *f;
|
||||
struct ast_channel *peer = NULL;
|
||||
struct ast_channel *watchers[MAX];
|
||||
struct ast_channel *watchers[AST_MAX_WATCHERS];
|
||||
int pos;
|
||||
int single;
|
||||
int moh=0;
|
||||
int ringind=0;
|
||||
struct ast_channel *winner;
|
||||
|
||||
single = (outgoing && !outgoing->next && !outgoing->musiconhold && !outgoing->ringbackonly);
|
||||
|
||||
if (single) {
|
||||
/* Turn off hold music, etc */
|
||||
ast_indicate(in, -1);
|
||||
ast_deactivate_generator(in);
|
||||
/* If we are calling a single channel, make them compatible for in-band tone purpose */
|
||||
ast_channel_make_compatible(outgoing->chan, in);
|
||||
}
|
||||
|
||||
if (outgoing) {
|
||||
moh = outgoing->musiconhold;
|
||||
ringind = outgoing->ringbackonly;
|
||||
if (outgoing->musiconhold) {
|
||||
ast_moh_start(in, NULL);
|
||||
} else if (outgoing->ringbackonly) {
|
||||
ast_indicate(in, AST_CONTROL_RINGING);
|
||||
}
|
||||
}
|
||||
|
||||
while(*to && !peer) {
|
||||
o = outgoing;
|
||||
@@ -157,9 +177,15 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
numlines++;
|
||||
}
|
||||
if (found < 0) {
|
||||
if (numlines == numbusies) {
|
||||
if (numlines == (numbusy + numcongestion + numnochan)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy at this time\n");
|
||||
ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time\n");
|
||||
if (numbusy)
|
||||
strncpy(status, "BUSY", statussize - 1);
|
||||
else if (numcongestion)
|
||||
strncpy(status, "CONGESTION", statussize - 1);
|
||||
else if (numnochan)
|
||||
strncpy(status, "CHANUNAVAIL", statussize - 1);
|
||||
/* See if there is a special busy message */
|
||||
if (ast_exists_extension(in, in->context, in->exten, in->priority + 101, in->callerid))
|
||||
in->priority+=100;
|
||||
@@ -168,12 +194,6 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time\n");
|
||||
}
|
||||
*to = 0;
|
||||
/* if no one available we'd better stop MOH/ringing to */
|
||||
if (moh) {
|
||||
ast_moh_stop(in);
|
||||
} else if (ringind) {
|
||||
ast_indicate(in, -1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
winner = ast_waitfor_n(watchers, pos, to);
|
||||
@@ -186,29 +206,87 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
peer = o->chan;
|
||||
*allowredir_in = o->allowredirect_in;
|
||||
*allowredir_out = o->allowredirect_out;
|
||||
*allowdisconnect = o->allowdisconnect;
|
||||
*allowdisconnect_in = o->allowdisconnect_in;
|
||||
*allowdisconnect_out = o->allowdisconnect_out;
|
||||
*noforwardhtml = o->noforwardhtml;
|
||||
}
|
||||
} else if (o->chan && (o->chan == winner)) {
|
||||
if (strlen(o->chan->call_forward)) {
|
||||
char tmpchan[256];
|
||||
if (!ast_strlen_zero(o->chan->call_forward)) {
|
||||
char tmpchan[256]="";
|
||||
char *stuff;
|
||||
char *tech;
|
||||
strncpy(tmpchan, o->chan->call_forward, sizeof(tmpchan) - 1);
|
||||
if ((stuff = strchr(tmpchan, '/'))) {
|
||||
*stuff = '\0';
|
||||
stuff++;
|
||||
tech = tmpchan;
|
||||
} else {
|
||||
snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
|
||||
stuff = tmpchan;
|
||||
tech = "Local";
|
||||
}
|
||||
/* Before processing channel, go ahead and check for forwarding */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s@%s' (thanks to %s)\n", in->name, o->chan->call_forward, o->chan->context, o->chan->name);
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
|
||||
/* Setup parameters */
|
||||
snprintf(tmpchan, sizeof(tmpchan),"%s@%s", o->chan->call_forward, o->chan->context);
|
||||
ast_hangup(o->chan);
|
||||
o->chan = ast_request("Local", in->nativeformats, tmpchan);
|
||||
o->chan = ast_request(tech, in->nativeformats, stuff);
|
||||
if (!o->chan) {
|
||||
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s'\n", tmpchan);
|
||||
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
|
||||
o->stillgoing = 0;
|
||||
numbusies++;
|
||||
} else if (ast_call(o->chan, tmpchan, 0)) {
|
||||
ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
|
||||
o->stillgoing = 0;
|
||||
ast_hangup(o->chan);
|
||||
o->chan = NULL;
|
||||
numbusies++;
|
||||
numnochan++;
|
||||
} else {
|
||||
if (o->chan->callerid)
|
||||
free(o->chan->callerid);
|
||||
|
||||
o->chan->callerid = NULL;
|
||||
|
||||
if (o->forcecallerid) {
|
||||
char *newcid = NULL;
|
||||
|
||||
if (strlen(in->macroexten))
|
||||
newcid = in->macroexten;
|
||||
else
|
||||
newcid = in->exten;
|
||||
o->chan->callerid = strdup(newcid);
|
||||
strncpy(o->chan->accountcode, winner->accountcode, sizeof(o->chan->accountcode) - 1);
|
||||
o->chan->cdrflags = winner->cdrflags;
|
||||
if (!o->chan->callerid)
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
} else {
|
||||
if (in->callerid) {
|
||||
o->chan->callerid = strdup(in->callerid);
|
||||
if (!o->chan->callerid)
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
}
|
||||
strncpy(o->chan->accountcode, in->accountcode, sizeof(o->chan->accountcode) - 1);
|
||||
o->chan->cdrflags = in->cdrflags;
|
||||
}
|
||||
|
||||
if (in->ani) {
|
||||
if (o->chan->ani)
|
||||
free(o->chan->ani);
|
||||
o->chan->ani = malloc(strlen(in->ani) + 1);
|
||||
if (o->chan->ani)
|
||||
strncpy(o->chan->ani, in->ani, strlen(in->ani));
|
||||
else
|
||||
ast_log(LOG_WARNING, "Out of memory\n");
|
||||
}
|
||||
if (o->chan->rdnis)
|
||||
free(o->chan->rdnis);
|
||||
if (!ast_strlen_zero(in->macroexten))
|
||||
o->chan->rdnis = strdup(in->macroexten);
|
||||
else
|
||||
o->chan->rdnis = strdup(in->exten);
|
||||
if (ast_call(o->chan, tmpchan, 0)) {
|
||||
ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
|
||||
o->stillgoing = 0;
|
||||
ast_hangup(o->chan);
|
||||
o->chan = NULL;
|
||||
numnochan++;
|
||||
}
|
||||
}
|
||||
/* Hangup the original channel now, in case we needed it */
|
||||
ast_hangup(winner);
|
||||
continue;
|
||||
}
|
||||
f = ast_read(winner);
|
||||
@@ -223,7 +301,9 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
peer = o->chan;
|
||||
*allowredir_in = o->allowredirect_in;
|
||||
*allowredir_out = o->allowredirect_out;
|
||||
*allowdisconnect = o->allowdisconnect;
|
||||
*allowdisconnect_in = o->allowdisconnect_in;
|
||||
*allowdisconnect_out = o->allowdisconnect_out;
|
||||
*noforwardhtml = o->noforwardhtml;
|
||||
}
|
||||
break;
|
||||
case AST_CONTROL_BUSY:
|
||||
@@ -235,7 +315,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
o->stillgoing = 0;
|
||||
if (in->cdr)
|
||||
ast_cdr_busy(in->cdr);
|
||||
numbusies++;
|
||||
numbusy++;
|
||||
break;
|
||||
case AST_CONTROL_CONGESTION:
|
||||
if (option_verbose > 2)
|
||||
@@ -246,29 +326,32 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
o->stillgoing = 0;
|
||||
if (in->cdr)
|
||||
ast_cdr_busy(in->cdr);
|
||||
numbusies++;
|
||||
numcongestion++;
|
||||
break;
|
||||
case AST_CONTROL_RINGING:
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
|
||||
if (!sentringing && !moh) {
|
||||
if (!(*sentringing) && !outgoing->musiconhold) {
|
||||
ast_indicate(in, AST_CONTROL_RINGING);
|
||||
sentringing++;
|
||||
ringind++;
|
||||
(*sentringing)++;
|
||||
}
|
||||
break;
|
||||
case AST_CONTROL_PROGRESS:
|
||||
if (option_verbose > 2)
|
||||
ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name);
|
||||
ast_indicate(in, AST_CONTROL_PROGRESS);
|
||||
if (!outgoing->ringbackonly)
|
||||
ast_indicate(in, AST_CONTROL_PROGRESS);
|
||||
break;
|
||||
case AST_CONTROL_OFFHOOK:
|
||||
/* Ignore going off hook */
|
||||
break;
|
||||
case -1:
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
|
||||
ast_indicate(in, -1);
|
||||
if (!(outgoing->ringbackonly || outgoing->musiconhold)) {
|
||||
if (option_verbose > 2)
|
||||
ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
|
||||
ast_indicate(in, -1);
|
||||
(*sentringing) = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
|
||||
@@ -281,7 +364,14 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
!(outgoing->ringbackonly || outgoing->musiconhold)) {
|
||||
if (ast_write(in, f))
|
||||
ast_log(LOG_WARNING, "Unable to forward image\n");
|
||||
} else if (single && (f->frametype == AST_FRAME_TEXT) &&
|
||||
!(outgoing->ringbackonly || outgoing->musiconhold)) {
|
||||
if (ast_write(in, f))
|
||||
ast_log(LOG_WARNING, "Unable to text\n");
|
||||
} else if (single && (f->frametype == AST_FRAME_HTML) && !outgoing->noforwardhtml) {
|
||||
ast_channel_sendhtml(in, f->subclass, f->data, f->datalen);
|
||||
}
|
||||
|
||||
ast_frfree(f);
|
||||
} else {
|
||||
in->hangupcause = o->chan->hangupcause;
|
||||
@@ -303,29 +393,33 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
|
||||
if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
|
||||
/* Got hung up */
|
||||
*to=-1;
|
||||
strncpy(status, "CANCEL", statussize - 1);
|
||||
if (f)
|
||||
ast_frfree(f);
|
||||
return NULL;
|
||||
}
|
||||
if (f && (f->frametype == AST_FRAME_DTMF) && *allowdisconnect &&
|
||||
if (f && (f->frametype == AST_FRAME_DTMF) && *allowdisconnect_out &&
|
||||
(f->subclass == '*')) {
|
||||
if (option_verbose > 3)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
|
||||
*to=0;
|
||||
strcpy(status, "CANCEL");
|
||||
ast_frfree(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (single && f && (f->frametype == AST_FRAME_HTML) && !outgoing->noforwardhtml)
|
||||
ast_channel_sendhtml(outgoing->chan, f->subclass, f->data, f->datalen);
|
||||
|
||||
if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF))) {
|
||||
if (ast_write(outgoing->chan, f))
|
||||
ast_log(LOG_WARNING, "Unable to forward voice\n");
|
||||
ast_frfree(f);
|
||||
}
|
||||
ast_frfree(f);
|
||||
}
|
||||
if (!*to && (option_verbose > 2))
|
||||
ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
|
||||
}
|
||||
if (moh) {
|
||||
ast_moh_stop(in);
|
||||
} else if (ringind) {
|
||||
ast_indicate(in, -1);
|
||||
}
|
||||
|
||||
return peer;
|
||||
|
||||
@@ -335,7 +429,7 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=-1;
|
||||
struct localuser *u;
|
||||
char info[256], *peers, *timeout, *tech, *number, *rest, *cur;
|
||||
char *info, *peers, *timeout, *tech, *number, *rest, *cur;
|
||||
char privdb[256] = "", *s;
|
||||
char announcemsg[256] = "", *ann;
|
||||
struct localuser *outgoing=NULL, *tmp;
|
||||
@@ -343,32 +437,60 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
int to;
|
||||
int allowredir_in=0;
|
||||
int allowredir_out=0;
|
||||
int allowdisconnect=0;
|
||||
int allowdisconnect_in=0;
|
||||
int allowdisconnect_out=0;
|
||||
int noforwardhtml=0;
|
||||
int hasmacro = 0;
|
||||
int privacy=0;
|
||||
int announce=0;
|
||||
int resetcdr=0;
|
||||
int cnt=0;
|
||||
char numsubst[AST_MAX_EXTENSION];
|
||||
char restofit[AST_MAX_EXTENSION];
|
||||
char *transfer = NULL;
|
||||
char *newnum;
|
||||
char callerid[256], *l, *n;
|
||||
char callerid[256] = "", *l, *n;
|
||||
char *url=NULL; /* JDG */
|
||||
struct ast_var_t *current;
|
||||
struct varshead *headp, *newheadp;
|
||||
struct ast_var_t *newvar;
|
||||
int go_on=0;
|
||||
|
||||
unsigned int calldurationlimit=0;
|
||||
char *cdl;
|
||||
time_t now;
|
||||
struct ast_bridge_config config;
|
||||
long timelimit = 0;
|
||||
long play_warning = 0;
|
||||
long warning_freq=0;
|
||||
char *warning_sound=NULL;
|
||||
char *end_sound=NULL;
|
||||
char *start_sound=NULL;
|
||||
char *limitptr;
|
||||
char limitdata[256];
|
||||
char *sdtmfptr;
|
||||
char sdtmfdata[256] = "";
|
||||
char *stack,*var;
|
||||
char *mac = NULL, macroname[256] = "";
|
||||
char status[256]="";
|
||||
char toast[80];
|
||||
int play_to_caller=0,play_to_callee=0;
|
||||
int playargs=0, sentringing=0, moh=0;
|
||||
int digit = 0;
|
||||
time_t start_time, answer_time, end_time;
|
||||
|
||||
if (!data) {
|
||||
ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout)\n");
|
||||
ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout|options)\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(info = ast_strdupa(data))) {
|
||||
ast_log(LOG_WARNING, "Unable to dupe data :(\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
strncpy(info, (char *)data, sizeof(info) - 1);
|
||||
peers = info;
|
||||
if (peers) {
|
||||
|
||||
timeout = strchr(info, '|');
|
||||
if (timeout) {
|
||||
*timeout = '\0';
|
||||
@@ -390,13 +512,150 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
} else
|
||||
timeout = NULL;
|
||||
if (!peers || !strlen(peers)) {
|
||||
if (!peers || ast_strlen_zero(peers)) {
|
||||
ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
if (transfer) {
|
||||
|
||||
/* Extract call duration limit */
|
||||
if ((cdl = strstr(transfer, "S("))) {
|
||||
calldurationlimit=atoi(cdl+2);
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %i seconds.\n",calldurationlimit);
|
||||
}
|
||||
|
||||
/* DTMF SCRIPT*/
|
||||
if ((sdtmfptr = strstr(transfer, "D("))) {
|
||||
strncpy(sdtmfdata, sdtmfptr + 2, sizeof(sdtmfdata) - 1);
|
||||
/* Overwrite with X's what was the sdtmf info */
|
||||
while (*sdtmfptr && (*sdtmfptr != ')'))
|
||||
*(sdtmfptr++) = 'X';
|
||||
if (*sdtmfptr)
|
||||
*sdtmfptr = 'X';
|
||||
/* Now find the end */
|
||||
sdtmfptr = strchr(sdtmfdata, ')');
|
||||
if (sdtmfptr)
|
||||
*sdtmfptr = '\0';
|
||||
else
|
||||
ast_log(LOG_WARNING, "D( Data lacking trailing ')'\n");
|
||||
}
|
||||
|
||||
/* XXX LIMIT SUPPORT */
|
||||
if ((limitptr = strstr(transfer, "L("))) {
|
||||
strncpy(limitdata, limitptr + 2, sizeof(limitdata) - 1);
|
||||
/* Overwrite with X's what was the limit info */
|
||||
while(*limitptr && (*limitptr != ')'))
|
||||
*(limitptr++) = 'X';
|
||||
if (*limitptr)
|
||||
*limitptr = 'X';
|
||||
/* Now find the end */
|
||||
limitptr = strchr(limitdata, ')');
|
||||
if (limitptr)
|
||||
*limitptr = '\0';
|
||||
else
|
||||
ast_log(LOG_WARNING, "Limit Data lacking trailing ')'\n");
|
||||
|
||||
var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
|
||||
play_to_caller = var ? ast_true(var) : 1;
|
||||
|
||||
var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
|
||||
play_to_callee = var ? ast_true(var) : 0;
|
||||
|
||||
if (!play_to_caller && !play_to_callee)
|
||||
play_to_caller=1;
|
||||
|
||||
var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
|
||||
warning_sound = var ? var : "timeleft";
|
||||
|
||||
var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
|
||||
end_sound = var ? var : NULL;
|
||||
|
||||
var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
|
||||
start_sound = var ? var : NULL;
|
||||
|
||||
var=stack=limitdata;
|
||||
|
||||
var = strsep(&stack, ":");
|
||||
if (var) {
|
||||
timelimit = atol(var);
|
||||
playargs++;
|
||||
var = strsep(&stack, ":");
|
||||
if (var) {
|
||||
play_warning = atol(var);
|
||||
playargs++;
|
||||
var = strsep(&stack, ":");
|
||||
if(var) {
|
||||
warning_freq = atol(var);
|
||||
playargs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!timelimit) {
|
||||
timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
|
||||
warning_sound=NULL;
|
||||
}
|
||||
/* undo effect of S(x) in case they are both used */
|
||||
calldurationlimit=0;
|
||||
/* more efficient do it like S(x) does since no advanced opts*/
|
||||
if (!play_warning && !start_sound && !end_sound && timelimit) {
|
||||
calldurationlimit=timelimit/1000;
|
||||
timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
|
||||
} else if (option_verbose > 2) {
|
||||
ast_verbose(VERBOSE_PREFIX_3"Limit Data:\n");
|
||||
ast_verbose(VERBOSE_PREFIX_3"timelimit=%ld\n",timelimit);
|
||||
ast_verbose(VERBOSE_PREFIX_3"play_warning=%ld\n",play_warning);
|
||||
ast_verbose(VERBOSE_PREFIX_3"play_to_caller=%s\n",play_to_caller ? "yes" : "no");
|
||||
ast_verbose(VERBOSE_PREFIX_3"play_to_callee=%s\n",play_to_callee ? "yes" : "no");
|
||||
ast_verbose(VERBOSE_PREFIX_3"warning_freq=%ld\n",warning_freq);
|
||||
ast_verbose(VERBOSE_PREFIX_3"start_sound=%s\n",start_sound ? start_sound : "UNDEF");
|
||||
ast_verbose(VERBOSE_PREFIX_3"warning_sound=%s\n",warning_sound ? warning_sound : "UNDEF");
|
||||
ast_verbose(VERBOSE_PREFIX_3"end_sound=%s\n",end_sound ? end_sound : "UNDEF");
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX ANNOUNCE SUPPORT */
|
||||
if ((ann = strstr(transfer, "A("))) {
|
||||
announce = 1;
|
||||
strncpy(announcemsg, ann + 2, sizeof(announcemsg) - 1);
|
||||
/* Overwrite with X's what was the announce info */
|
||||
while(*ann && (*ann != ')'))
|
||||
*(ann++) = 'X';
|
||||
if (*ann)
|
||||
*ann = 'X';
|
||||
/* Now find the end of the privdb */
|
||||
ann = strchr(announcemsg, ')');
|
||||
if (ann)
|
||||
*ann = '\0';
|
||||
else {
|
||||
ast_log(LOG_WARNING, "Transfer with Announce spec lacking trailing ')'\n");
|
||||
announce = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the macroname from the dial option string */
|
||||
if ((mac = strstr(transfer, "M("))) {
|
||||
hasmacro = 1;
|
||||
strncpy(macroname, mac + 2, sizeof(macroname) - 1);
|
||||
while (*mac && (*mac != ')'))
|
||||
*(mac++) = 'X';
|
||||
if (*mac)
|
||||
*mac = 'X';
|
||||
else {
|
||||
ast_log(LOG_WARNING, "Could not find macro to which we should jump.\n");
|
||||
hasmacro = 0;
|
||||
}
|
||||
mac = strchr(macroname, ')');
|
||||
if (mac)
|
||||
*mac = '\0';
|
||||
else {
|
||||
ast_log(LOG_WARNING, "Macro flag set without trailing ')'\n");
|
||||
hasmacro = 0;
|
||||
}
|
||||
}
|
||||
/* Extract privacy info from transfer */
|
||||
if ((s = strstr(transfer, "P("))) {
|
||||
privacy = 1;
|
||||
@@ -411,7 +670,7 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
if (s)
|
||||
*s = '\0';
|
||||
else {
|
||||
ast_log(LOG_WARNING, "Transfer with privacy lacking trailing '('\n");
|
||||
ast_log(LOG_WARNING, "Transfer with privacy lacking trailing ')'\n");
|
||||
privacy = 0;
|
||||
}
|
||||
} else if (strchr(transfer, 'P')) {
|
||||
@@ -420,28 +679,18 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
} else if (strchr(transfer, 'C')) {
|
||||
resetcdr = 1;
|
||||
}
|
||||
/* XXX ANNOUNCE SUPPORT */
|
||||
else if ((ann = strstr(transfer, "A("))) {
|
||||
announce = 1;
|
||||
strncpy(announcemsg, ann + 2, sizeof(announcemsg) - 1);
|
||||
cnt=0;
|
||||
while(announcemsg[cnt] != ')') {
|
||||
cnt++;
|
||||
}
|
||||
announcemsg[cnt]='\0';
|
||||
}
|
||||
}
|
||||
if (resetcdr && chan->cdr)
|
||||
ast_cdr_reset(chan->cdr, 0);
|
||||
if (!strlen(privdb) && privacy) {
|
||||
if (ast_strlen_zero(privdb) && privacy) {
|
||||
/* If privdb is not specified and we are using privacy, copy from extension */
|
||||
strncpy(privdb, chan->exten, sizeof(privdb) - 1);
|
||||
}
|
||||
if (privacy) {
|
||||
if (chan->callerid)
|
||||
strncpy(callerid, chan->callerid, sizeof(callerid));
|
||||
strncpy(callerid, chan->callerid, sizeof(callerid) - 1);
|
||||
else
|
||||
strcpy(callerid, "");
|
||||
callerid[0] = '\0';
|
||||
ast_callerid_parse(callerid, &n, &l);
|
||||
if (l) {
|
||||
ast_shrink_phone_number(l);
|
||||
@@ -486,10 +735,19 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
tmp->musiconhold = 1;
|
||||
else tmp->musiconhold = 0;
|
||||
if (strchr(transfer, 'H'))
|
||||
allowdisconnect = tmp->allowdisconnect = 1;
|
||||
else allowdisconnect = tmp->allowdisconnect = 0;
|
||||
allowdisconnect_out = tmp->allowdisconnect_out = 1;
|
||||
else allowdisconnect_out = tmp->allowdisconnect_out = 0;
|
||||
if(strchr(transfer, 'h'))
|
||||
allowdisconnect_in = tmp->allowdisconnect_in = 1;
|
||||
else allowdisconnect_in = tmp->allowdisconnect_in = 0;
|
||||
if(strchr(transfer, 'g'))
|
||||
go_on=1;
|
||||
if (strchr(transfer, 'f'))
|
||||
tmp->forcecallerid = 1;
|
||||
else tmp->forcecallerid = 0;
|
||||
if (url)
|
||||
tmp->noforwardhtml = 1;
|
||||
else tmp->noforwardhtml = 0;
|
||||
}
|
||||
strncpy(numsubst, number, sizeof(numsubst)-1);
|
||||
/* If we're dialing by extension, look at the extension to know what to dial */
|
||||
@@ -510,15 +768,29 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
cur = rest;
|
||||
continue;
|
||||
}
|
||||
if (strlen(tmp->chan->call_forward)) {
|
||||
char tmpchan[256];
|
||||
pbx_builtin_setvar_helper(tmp->chan, "DIALEDPEERNUMBER", numsubst);
|
||||
if (!ast_strlen_zero(tmp->chan->call_forward)) {
|
||||
char tmpchan[256]="";
|
||||
char *stuff;
|
||||
char *tech;
|
||||
strncpy(tmpchan, tmp->chan->call_forward, sizeof(tmpchan) - 1);
|
||||
if ((stuff = strchr(tmpchan, '/'))) {
|
||||
*stuff = '\0';
|
||||
stuff++;
|
||||
tech = tmpchan;
|
||||
} else {
|
||||
snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
|
||||
stuff = tmpchan;
|
||||
tech = "Local";
|
||||
}
|
||||
/* Before processing channel, go ahead and check for forwarding */
|
||||
if (option_verbose > 2)
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Forwarding call to '%s@%s'\n", tmp->chan->call_forward, tmp->chan->context);
|
||||
snprintf(tmpchan, sizeof(tmpchan),"%s@%s", tmp->chan->call_forward, tmp->chan->context);
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
|
||||
/* Setup parameters */
|
||||
ast_hangup(tmp->chan);
|
||||
tmp->chan = ast_request("Local", chan->nativeformats, tmpchan);
|
||||
tmp->chan = ast_request(tech, chan->nativeformats, stuff);
|
||||
if (!tmp->chan) {
|
||||
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s'\n", tmpchan);
|
||||
ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff);
|
||||
free(tmp);
|
||||
cur = rest;
|
||||
continue;
|
||||
@@ -527,36 +799,21 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
/* If creating a SIP channel, look for a variable called */
|
||||
/* VXML_URL in the calling channel and copy it to the */
|
||||
/* new channel. */
|
||||
if (strcasecmp(tech,"SIP")==0)
|
||||
{
|
||||
headp=&chan->varshead;
|
||||
AST_LIST_TRAVERSE(headp,current,entries) {
|
||||
if (strcasecmp(ast_var_name(current),"VXML_URL")==0)
|
||||
{
|
||||
newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
|
||||
newheadp=&tmp->chan->varshead;
|
||||
AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for ALERT_INFO in the SetVar list. This is for */
|
||||
/* SIP distinctive ring as per the RFC. For Cisco 7960s, */
|
||||
/* SetVar(ALERT_INFO=<x>) where x is an integer value 1-5. */
|
||||
/* However, the RFC says it should be a URL. -km- */
|
||||
|
||||
if (strcasecmp(tech,"SIP")==0)
|
||||
{
|
||||
headp=&chan->varshead;
|
||||
AST_LIST_TRAVERSE(headp,current,entries) {
|
||||
/* Search for ALERT_INFO */
|
||||
if (strcasecmp(ast_var_name(current),"ALERT_INFO")==0)
|
||||
{
|
||||
newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
|
||||
newheadp=&tmp->chan->varshead;
|
||||
AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
|
||||
break;
|
||||
}
|
||||
headp=&chan->varshead;
|
||||
AST_LIST_TRAVERSE(headp,current,entries) {
|
||||
if (!strcasecmp(ast_var_name(current),"VXML_URL") ||
|
||||
!strcasecmp(ast_var_name(current), "ALERT_INFO") ||
|
||||
!strcasecmp(ast_var_name(current), "OSPTOKEN") ||
|
||||
!strcasecmp(ast_var_name(current), "OSPHANDLE"))
|
||||
{
|
||||
newvar=ast_var_assign(ast_var_name(current),ast_var_value(current));
|
||||
newheadp=&tmp->chan->varshead;
|
||||
AST_LIST_INSERT_HEAD(newheadp,newvar,entries);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -572,8 +829,10 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
else
|
||||
tmp->chan->callerid = NULL;
|
||||
/* Copy language from incoming to outgoing */
|
||||
strcpy(tmp->chan->language, chan->language);
|
||||
if (!strlen(tmp->chan->musicclass))
|
||||
strncpy(tmp->chan->language, chan->language, sizeof(tmp->chan->language) - 1);
|
||||
strncpy(tmp->chan->accountcode, chan->accountcode, sizeof(tmp->chan->accountcode) - 1);
|
||||
tmp->chan->cdrflags = chan->cdrflags;
|
||||
if (ast_strlen_zero(tmp->chan->musicclass))
|
||||
strncpy(tmp->chan->musicclass, chan->musicclass, sizeof(tmp->chan->musicclass) - 1);
|
||||
if (chan->ani)
|
||||
tmp->chan->ani = strdup(chan->ani);
|
||||
@@ -594,7 +853,7 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
if (chan->cdr)
|
||||
ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
|
||||
|
||||
/* check the restuls of ast_call */
|
||||
/* check the results of ast_call */
|
||||
if (res) {
|
||||
/* Again, keep going even if there's an error */
|
||||
if (option_debug)
|
||||
@@ -620,11 +879,31 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
cur = rest;
|
||||
} while(cur);
|
||||
|
||||
if (timeout && strlen(timeout))
|
||||
to = atoi(timeout) * 1000;
|
||||
else
|
||||
if (timeout && !ast_strlen_zero(timeout)) {
|
||||
to = atoi(timeout);
|
||||
if (to > 0)
|
||||
to *= 1000;
|
||||
else
|
||||
ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", timeout);
|
||||
} else
|
||||
to = -1;
|
||||
peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect);
|
||||
|
||||
if (outgoing) {
|
||||
/* Our status will at least be NOANSWER */
|
||||
strncpy(status, "NOANSWER", sizeof(status) - 1);
|
||||
if (outgoing->musiconhold) {
|
||||
moh=1;
|
||||
ast_moh_start(chan, NULL);
|
||||
} else if (outgoing->ringbackonly) {
|
||||
ast_indicate(chan, AST_CONTROL_RINGING);
|
||||
sentringing++;
|
||||
}
|
||||
} else
|
||||
strncpy(status, "CHANUNAVAIL", sizeof(status) - 1);
|
||||
|
||||
time(&start_time);
|
||||
peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect_in, &allowdisconnect_out, &sentringing, &noforwardhtml, status, sizeof(status));
|
||||
|
||||
if (!peer) {
|
||||
if (to)
|
||||
/* Musta gotten hung up */
|
||||
@@ -636,6 +915,12 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
goto out;
|
||||
}
|
||||
if (peer) {
|
||||
time(&answer_time);
|
||||
#ifdef OSP_SUPPORT
|
||||
/* Once call is answered, ditch the OSP Handle */
|
||||
pbx_builtin_setvar_helper(chan, "OSPHANDLE", "");
|
||||
#endif
|
||||
strncpy(status, "ANSWER", sizeof(status) - 1);
|
||||
/* Ah ha! Someone answered within the desired timeframe. Of course after this
|
||||
we will always return with -1 so that it is hung up properly after the
|
||||
conversation. */
|
||||
@@ -646,43 +931,131 @@ static int dial_exec(struct ast_channel *chan, void *data)
|
||||
ast_cdr_setdestchan(chan->cdr, peer->name);
|
||||
if (peer->name)
|
||||
pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
|
||||
if (numsubst)
|
||||
pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", numsubst);
|
||||
/* Make sure channels are compatible */
|
||||
res = ast_channel_make_compatible(chan, peer);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
|
||||
ast_hangup(peer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
|
||||
if (!number)
|
||||
number = numsubst;
|
||||
pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
|
||||
/* JDG: sendurl */
|
||||
if( url && strlen(url) && ast_channel_supports_html(peer) ) {
|
||||
if( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
|
||||
ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
|
||||
ast_channel_sendurl( peer, url );
|
||||
} /* /JDG */
|
||||
if (announce && announcemsg)
|
||||
{
|
||||
int res2;
|
||||
if (announce && announcemsg) {
|
||||
// Start autoservice on the other chan
|
||||
res2 = ast_autoservice_start(chan);
|
||||
res = ast_autoservice_start(chan);
|
||||
// Now Stream the File
|
||||
if (!res2)
|
||||
res2 = ast_streamfile(peer,announcemsg,peer->language);
|
||||
if (!res2)
|
||||
res2 = ast_waitstream(peer,"");
|
||||
if (!res)
|
||||
res = ast_streamfile(peer,announcemsg,peer->language);
|
||||
if (!res) {
|
||||
digit = ast_waitstream(peer, AST_DIGIT_ANY);
|
||||
}
|
||||
// Ok, done. stop autoservice
|
||||
res2 = ast_autoservice_stop(chan);
|
||||
}
|
||||
res = ast_bridge_call(chan, peer, allowredir_in, allowredir_out, allowdisconnect);
|
||||
res = ast_autoservice_stop(chan);
|
||||
if (digit > 0 && !res)
|
||||
res = ast_senddigit(chan, digit);
|
||||
else
|
||||
res = digit;
|
||||
|
||||
if (res != AST_PBX_NO_HANGUP_PEER)
|
||||
} else
|
||||
res = 0;
|
||||
|
||||
if (hasmacro && macroname) {
|
||||
void *app = NULL;
|
||||
|
||||
res = ast_autoservice_start(chan);
|
||||
if (res) {
|
||||
ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
|
||||
res = -1;
|
||||
}
|
||||
|
||||
app = pbx_findapp("Macro");
|
||||
|
||||
if (app && !res) {
|
||||
res = pbx_exec(peer, app, macroname, 1);
|
||||
ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
|
||||
res = 0;
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Could not find application Macro\n");
|
||||
res = -1;
|
||||
}
|
||||
|
||||
if (ast_autoservice_stop(chan) < 0) {
|
||||
ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
|
||||
res = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
if (calldurationlimit > 0) {
|
||||
time(&now);
|
||||
chan->whentohangup = now + calldurationlimit;
|
||||
}
|
||||
if (!ast_strlen_zero(sdtmfdata))
|
||||
res = ast_dtmf_stream(peer,chan,sdtmfdata,250);
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
memset(&config,0,sizeof(struct ast_bridge_config));
|
||||
config.play_to_caller=play_to_caller;
|
||||
config.play_to_callee=play_to_callee;
|
||||
config.allowredirect_in = allowredir_in;
|
||||
config.allowredirect_out = allowredir_out;
|
||||
config.allowdisconnect_in = allowdisconnect_in;
|
||||
config.allowdisconnect_out = allowdisconnect_out;
|
||||
config.timelimit = timelimit;
|
||||
config.play_warning = play_warning;
|
||||
config.warning_freq = warning_freq;
|
||||
config.warning_sound = warning_sound;
|
||||
config.end_sound = end_sound;
|
||||
config.start_sound = start_sound;
|
||||
if (moh) {
|
||||
moh = 0;
|
||||
ast_moh_stop(chan);
|
||||
} else if (sentringing) {
|
||||
sentringing = 0;
|
||||
ast_indicate(chan, -1);
|
||||
}
|
||||
/* Be sure no generators are left on it */
|
||||
ast_deactivate_generator(chan);
|
||||
/* Make sure channels are compatible */
|
||||
res = ast_channel_make_compatible(chan, peer);
|
||||
if (res < 0) {
|
||||
ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
|
||||
ast_hangup(peer);
|
||||
return -1;
|
||||
}
|
||||
res = ast_bridge_call(chan,peer,&config);
|
||||
time(&end_time);
|
||||
snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
|
||||
pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
|
||||
snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
|
||||
pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
|
||||
|
||||
} else
|
||||
res = -1;
|
||||
|
||||
if (res != AST_PBX_NO_HANGUP_PEER) {
|
||||
if (!chan->_softhangup)
|
||||
chan->hangupcause = peer->hangupcause;
|
||||
ast_hangup(peer);
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (moh) {
|
||||
moh = 0;
|
||||
ast_moh_stop(chan);
|
||||
} else if (sentringing) {
|
||||
sentringing = 0;
|
||||
ast_indicate(chan, -1);
|
||||
}
|
||||
hanguptree(outgoing, NULL);
|
||||
pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
|
||||
ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
|
||||
if((go_on>0) && (!chan->_softhangup))
|
||||
if((go_on>0) && (!chan->_softhangup) && (res != AST_PBX_KEEPALIVE))
|
||||
res=0;
|
||||
|
||||
return res;
|
||||
|
||||
229
apps/app_directory.c
Executable file → Normal file
229
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. 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 */
|
||||
@@ -120,18 +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];
|
||||
char fn2[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,59 +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 */
|
||||
/* Check for the VoiceMail2 greeting first */
|
||||
snprintf(fn, sizeof(fn), "%s/voicemail/%s/%s/greet", (char *)ast_config_AST_SPOOL_DIR, context, v->name);
|
||||
/* Otherwise, check for an old-style Voicemail greeting */
|
||||
snprintf(fn2, sizeof(fn2), "%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 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_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;
|
||||
}
|
||||
@@ -232,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);
|
||||
@@ -243,17 +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);
|
||||
|
||||
156
apps/app_disa.c
Executable file → Normal file
156
apps/app_disa.c
Executable file → Normal file
@@ -17,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";
|
||||
|
||||
@@ -83,27 +81,9 @@ STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static float loudness=4096.0;
|
||||
|
||||
static int firstdigittimeout = 20000; /* 20 seconds first digit timeout */
|
||||
static 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 ms_diff(struct timeval *tv1, struct timeval *tv2)
|
||||
{
|
||||
int ms;
|
||||
@@ -113,19 +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];
|
||||
struct {
|
||||
unsigned char offset[AST_FRIENDLY_OFFSET];
|
||||
unsigned char buf[640];
|
||||
} tone_block;
|
||||
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;
|
||||
|
||||
@@ -150,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" */
|
||||
@@ -166,24 +153,31 @@ 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);
|
||||
((k&1) ? "extension" : "password"),chan->name);
|
||||
break;
|
||||
}
|
||||
if ((res = ast_waitfor(chan, -1) < 0)) {
|
||||
@@ -205,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.buf;
|
||||
wf.datalen = f->datalen;
|
||||
make_tone_block(tone_block.buf, 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 */
|
||||
@@ -234,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 */
|
||||
{
|
||||
@@ -287,38 +268,53 @@ 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_ignore_pattern(ourcontext, exten)) {
|
||||
play_dialtone(chan);
|
||||
did_ignore = 1;
|
||||
} else
|
||||
if (did_ignore) {
|
||||
ast_playtones_stop(chan);
|
||||
did_ignore = 0;
|
||||
}
|
||||
|
||||
/* if can do some more, do it */
|
||||
if (!ast_matchmore_extension(chan,ourcontext,exten,1, chan->callerid))
|
||||
if (!ast_matchmore_extension(chan,ourcontext,exten,1, chan->callerid)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (k && ast_exists_extension(chan,ourcontext,exten,1, chan->callerid))
|
||||
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);
|
||||
}
|
||||
strcpy(chan->exten,exten);
|
||||
strcpy(chan->context,ourcontext);
|
||||
strcpy(chan->accountcode,acctcode);
|
||||
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);
|
||||
@@ -326,44 +322,20 @@ static int disa_exec(struct ast_channel *chan, void *data)
|
||||
}
|
||||
|
||||
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(;;)
|
||||
|
||||
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;
|
||||
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;
|
||||
if (k)
|
||||
memset(tone_block.buf, 0x7f, wf.datalen);
|
||||
else
|
||||
make_tone_block(tone_block.buf,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);
|
||||
}
|
||||
ast_playtones_stop(chan);
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return -1;
|
||||
}
|
||||
|
||||
5
apps/app_echo.c
Executable file → Normal file
5
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,6 +49,8 @@ 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;
|
||||
|
||||
14
apps/app_enumlookup.c
Executable file → Normal file
14
apps/app_enumlookup.c
Executable file → Normal file
@@ -20,15 +20,13 @@
|
||||
#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>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "ENUM Lookup";
|
||||
|
||||
static char *app = "EnumLookup";
|
||||
@@ -49,7 +47,7 @@ static char *descrip =
|
||||
|
||||
#define ENUM_CONFIG "enum.conf"
|
||||
|
||||
static char h323driver[80];
|
||||
static char h323driver[80] = "";
|
||||
#define H323DRIVERDEFAULT "H323"
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
@@ -64,7 +62,7 @@ static int enumlookup_exec(struct ast_channel *chan, void *data)
|
||||
char tmp[256];
|
||||
char *c,*t;
|
||||
struct localuser *u;
|
||||
if (!data || !strlen(data)) {
|
||||
if (!data || ast_strlen_zero(data)) {
|
||||
ast_log(LOG_WARNING, "EnumLookup requires an argument (extension)\n");
|
||||
res = 1;
|
||||
}
|
||||
@@ -128,7 +126,7 @@ static int enumlookup_exec(struct ast_channel *chan, void *data)
|
||||
else
|
||||
res = 0;
|
||||
}
|
||||
} else if (strlen(tech)) {
|
||||
} else if (!ast_strlen_zero(tech)) {
|
||||
ast_log(LOG_NOTICE, "Don't know how to handle technology '%s'\n", tech);
|
||||
res = 0;
|
||||
}
|
||||
@@ -150,9 +148,9 @@ static int load_config(void)
|
||||
cfg = ast_load(ENUM_CONFIG);
|
||||
if (cfg) {
|
||||
if (!(s=ast_variable_retrieve(cfg, "general", "h323driver"))) {
|
||||
strcpy(h323driver, H323DRIVERDEFAULT);
|
||||
strncpy(h323driver, H323DRIVERDEFAULT, sizeof(h323driver) - 1);
|
||||
} else {
|
||||
strcpy(h323driver, s);
|
||||
strncpy(h323driver, s, sizeof(h323driver) - 1);
|
||||
}
|
||||
ast_destroy(cfg);
|
||||
return 0;
|
||||
|
||||
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;
|
||||
}
|
||||
45
apps/app_festival.c
Executable file → Normal file
45
apps/app_festival.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
|
||||
@@ -19,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>
|
||||
@@ -34,7 +36,6 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <ctype.h>
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
#define FESTIVAL_CONFIG "festival.conf"
|
||||
@@ -130,7 +131,6 @@ static int send_waveform_to_fd(char *waveform, int length, int fd) {
|
||||
#endif
|
||||
|
||||
write(fd,waveform,length);
|
||||
write(fd,"a",1);
|
||||
close(fd);
|
||||
exit(0);
|
||||
}
|
||||
@@ -155,6 +155,9 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Answer if it's not already going */
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
ast_answer(chan);
|
||||
ast_stopstream(chan);
|
||||
|
||||
owriteformat = chan->writeformat;
|
||||
@@ -195,7 +198,7 @@ static int send_waveform_to_channel(struct ast_channel *chan, char *waveform, in
|
||||
needed = f->samples * 2;
|
||||
if (needed > sizeof(myf.frdata)) {
|
||||
ast_log(LOG_WARNING, "Only able to deliver %d of %d requested samples\n",
|
||||
sizeof(myf.frdata) / 2, needed/2);
|
||||
(int)sizeof(myf.frdata) / 2, needed/2);
|
||||
needed = sizeof(myf.frdata);
|
||||
}
|
||||
res = read(fds[0], myf.frdata, needed);
|
||||
@@ -247,6 +250,7 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
struct localuser *u;
|
||||
struct sockaddr_in serv_addr;
|
||||
struct hostent *serverhost;
|
||||
struct ast_hostent ahp;
|
||||
int fd;
|
||||
FILE *fs;
|
||||
char *host;
|
||||
@@ -263,9 +267,9 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
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;
|
||||
@@ -300,11 +304,9 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
if (!(festivalcommand = ast_variable_retrieve(cfg, "general", "festivalcommand"))) {
|
||||
festivalcommand = "(tts_textasterisk \"%s\" 'file)(quit)\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!vdata || !strlen(vdata)) {
|
||||
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);
|
||||
@@ -322,14 +324,16 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
|
||||
if (fd < 0) {
|
||||
ast_log(LOG_WARNING,"festival_client: can't get socket\n");
|
||||
ast_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);
|
||||
@@ -339,6 +343,7 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
|
||||
if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
|
||||
ast_log(LOG_WARNING,"festival_client: connect to server failed\n");
|
||||
ast_destroy(cfg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -346,21 +351,21 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
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);
|
||||
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);
|
||||
@@ -372,11 +377,12 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
}
|
||||
} else {
|
||||
read(fdesc,&strln,sizeof(int));
|
||||
ast_log(LOG_DEBUG,"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_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");
|
||||
@@ -440,6 +446,7 @@ static int festival_exec(struct ast_channel *chan, void *vdata)
|
||||
}
|
||||
} 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";
|
||||
|
||||
|
||||
91
apps/app_forkcdr.c
Normal file
91
apps/app_forkcdr.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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));
|
||||
newcdr->next = NULL;
|
||||
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;
|
||||
}
|
||||
68
apps/app_hasnewvoicemail.c
Executable file → Normal file
68
apps/app_hasnewvoicemail.c
Executable file → Normal file
@@ -1,8 +1,11 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* HasNewVoicemail application
|
||||
*
|
||||
* 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>
|
||||
@@ -34,56 +37,71 @@
|
||||
#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 <pthread.h>
|
||||
|
||||
#include "../astconf.h"
|
||||
|
||||
static char *tdesc = "Indicator for whether a voice mailbox has new messages.";
|
||||
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 new voicemail"
|
||||
" Optionally sets <varname> to the number of new messages.\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 hasnewvoicemail_exec(struct ast_channel *chan, void *data)
|
||||
static int hasvoicemail_exec(struct ast_channel *chan, void *data)
|
||||
{
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
char vmpath[256], *input, *varname = NULL, *vmbox, *context = "default";
|
||||
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, "HasNewVoicemail requires an argument (vm-box[@context]|varname)\n");
|
||||
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) {
|
||||
if ((vmbox = strsep(&input,"|")))
|
||||
varname = input;
|
||||
else
|
||||
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;
|
||||
|
||||
if (index(vmbox,'@')) {
|
||||
context = vmbox;
|
||||
vmbox = strsep(&context,"@");
|
||||
}
|
||||
|
||||
snprintf(vmpath,sizeof(vmpath), "%s/voicemail/%s/%s/INBOX", (char *)ast_config_AST_SPOOL_DIR, context, vmbox);
|
||||
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 {
|
||||
@@ -97,7 +115,7 @@ static int hasnewvoicemail_exec(struct ast_channel *chan, void *data)
|
||||
/* Set the count in the channel variable */
|
||||
if (varname) {
|
||||
char tmp[12];
|
||||
snprintf(tmp, sizeof(tmp) - 1, "%d", vmcount);
|
||||
snprintf(tmp, sizeof(tmp), "%d", vmcount);
|
||||
pbx_builtin_setvar_helper(chan, varname, tmp);
|
||||
}
|
||||
|
||||
@@ -118,13 +136,19 @@ static int hasnewvoicemail_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app_hasnewvoicemail);
|
||||
res = ast_unregister_application(app_hasvoicemail);
|
||||
res |= ast_unregister_application(app_hasnewvoicemail);
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app_hasnewvoicemail, hasnewvoicemail_exec, hasnewvoicemail_synopsis, hasnewvoicemail_descrip);
|
||||
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)
|
||||
|
||||
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";
|
||||
|
||||
|
||||
10
apps/app_intercom.c
Executable file → Normal file
10
apps/app_intercom.c
Executable file → Normal file
@@ -24,16 +24,16 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef __linux__
|
||||
#include <netinet/in.h>
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <linux/soundcard.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <machine/soundcard.h>
|
||||
#include <sys/soundcard.h>
|
||||
#else
|
||||
#include <soundcard.h>
|
||||
#endif
|
||||
#include <netinet/in.h>
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
#define DEV_DSP "/dev/audio"
|
||||
@@ -58,7 +58,7 @@ STANDARD_LOCAL_USER;
|
||||
|
||||
LOCAL_USER_DECL;
|
||||
|
||||
static ast_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)
|
||||
|
||||
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";
|
||||
|
||||
|
||||
24
apps/app_macro.c
Executable file → Normal file
24
apps/app_macro.c
Executable file → Normal file
@@ -18,13 +18,13 @@
|
||||
#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";
|
||||
@@ -73,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;
|
||||
}
|
||||
@@ -96,7 +96,7 @@ 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;
|
||||
@@ -122,8 +122,9 @@ 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)) {
|
||||
@@ -139,7 +140,8 @@ static int macro_exec(struct ast_channel *chan, void *data)
|
||||
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;
|
||||
@@ -193,8 +195,8 @@ out:
|
||||
pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority);
|
||||
if (save_macro_priority) free(save_macro_priority);
|
||||
if (setmacrocontext) {
|
||||
strcpy(chan->macrocontext, "");
|
||||
strcpy(chan->macroexten, "");
|
||||
chan->macrocontext[0] = '\0';
|
||||
chan->macroexten[0] = '\0';
|
||||
chan->macropriority = 0;
|
||||
}
|
||||
|
||||
@@ -202,7 +204,7 @@ out:
|
||||
/* 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"))) {
|
||||
|
||||
1251
apps/app_meetme.c
Executable file → Normal file
1251
apps/app_meetme.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
6
apps/app_milliwatt.c
Executable file → Normal file
6
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";
|
||||
@@ -64,7 +62,7 @@ static int milliwatt_generate(struct ast_channel *chan, void *data, int len, int
|
||||
|
||||
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, int
|
||||
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++)
|
||||
{
|
||||
|
||||
114
apps/app_mp3.c
Executable file → Normal file
114
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,7 +25,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define LOCAL_MPG_123 "/usr/local/bin/mpg123"
|
||||
@@ -61,36 +60,35 @@ static int mp3play(char *filename, int fd)
|
||||
close(x);
|
||||
}
|
||||
/* Execute mpg123, but buffer if it's a net connection */
|
||||
if (strncmp(filename, "http://", 7)) {
|
||||
if (!strncasecmp(filename, "http://", 7)) {
|
||||
/* Most commonly installed in /usr/local/bin */
|
||||
execl(LOCAL_MPG_123, "mpg123", "-q", "-s", "-b", "1024", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
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", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
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", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
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", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
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", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
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", "--mono", "-r", "8000", filename, (char *)NULL);
|
||||
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)
|
||||
static int timed_read(int fd, void *data, int datalen, int timeout)
|
||||
{
|
||||
int res;
|
||||
fd_set fds;
|
||||
struct timeval tv = { 2, 0 }; /* Wait no more than 2 seconds */
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(fd, &fds);
|
||||
res = ast_select(fd + 1, &fds, NULL, NULL, &tv);
|
||||
struct pollfd fds[1];
|
||||
fds[0].fd = fd;
|
||||
fds[0].events = POLLIN;
|
||||
res = poll(fds, 1, timeout);
|
||||
if (res < 1) {
|
||||
ast_log(LOG_NOTICE, "Selected timed out/errored out with %d\n", res);
|
||||
ast_log(LOG_NOTICE, "Poll timed out/errored out with %d\n", res);
|
||||
return -1;
|
||||
}
|
||||
return read(fd, data, datalen);
|
||||
@@ -105,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;
|
||||
@@ -132,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 = timed_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;
|
||||
@@ -170,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;
|
||||
@@ -180,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;
|
||||
}
|
||||
|
||||
288
apps/app_parkandannounce.c
Executable file → Normal file
288
apps/app_parkandannounce.c
Executable file → Normal file
@@ -21,18 +21,17 @@
|
||||
#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";
|
||||
@@ -42,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"
|
||||
@@ -55,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -231,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;
|
||||
}
|
||||
|
||||
1
apps/app_privacy.c
Executable file → Normal file
1
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"
|
||||
|
||||
|
||||
48
apps/app_qcall.c
Executable file → Normal file
48
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>
|
||||
@@ -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");
|
||||
snprintf(qdir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "qcall");
|
||||
mkdir(qdir,0760);
|
||||
pthread_create(&qcall_thread,NULL,qcall,NULL);
|
||||
ast_pthread_create(&qcall_thread,NULL,qcall,NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
1527
apps/app_queue.c
Executable file → Normal file
1527
apps/app_queue.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
5
apps/app_random.c
Executable file → Normal file
5
apps/app_random.c
Executable file → Normal file
@@ -42,7 +42,7 @@ static int random_exec(struct ast_channel *chan, void *data)
|
||||
int res=0;
|
||||
struct localuser *u;
|
||||
|
||||
char *s, *ts;
|
||||
char *s;
|
||||
char *exten, *pri, *context;
|
||||
char *prob;
|
||||
int probint, priorityint;
|
||||
@@ -54,7 +54,7 @@ static int random_exec(struct ast_channel *chan, void *data)
|
||||
LOCAL_USER_ADD(u);
|
||||
s = ast_strdupa((void *) data);
|
||||
|
||||
prob = strsep(&ts,":");
|
||||
prob = strsep(&s,":");
|
||||
if ((!prob) || (sscanf(prob, "%d", &probint) != 1))
|
||||
probint = 0;
|
||||
|
||||
@@ -106,7 +106,6 @@ int unload_module(void)
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
srandom((unsigned int)getpid() + (unsigned int)time(NULL));
|
||||
return ast_register_application(app_random, random_exec, random_synopsis, random_descrip);
|
||||
}
|
||||
|
||||
|
||||
72
apps/app_read.c
Executable file → Normal file
72
apps/app_read.c
Executable file → Normal file
@@ -20,9 +20,9 @@
|
||||
#include <asterisk/module.h>
|
||||
#include <asterisk/translate.h>
|
||||
#include <asterisk/options.h>
|
||||
#include <asterisk/utils.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Read Variable Application";
|
||||
|
||||
@@ -31,9 +31,17 @@ static char *app = "Read";
|
||||
static char *synopsis = "Read a variable";
|
||||
|
||||
static char *descrip =
|
||||
" Read(variable[|filename]): Reads a '#' terminated string of digits from\n"
|
||||
"the user, optionally playing a given filename first. Returns -1 on hangup or\n"
|
||||
"error and 0 otherwise.\n";
|
||||
" 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;
|
||||
|
||||
@@ -44,32 +52,64 @@ static int read_exec(struct ast_channel *chan, void *data)
|
||||
int res = 0;
|
||||
struct localuser *u;
|
||||
char tmp[256];
|
||||
char tmp2[128]="";
|
||||
char argdata[256] = "";
|
||||
char *varname;
|
||||
char *filename;
|
||||
char *stringp;
|
||||
if (!data || !strlen((char *)data)) {
|
||||
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(tmp, (char *)data, sizeof(tmp)-1);
|
||||
stringp=tmp;
|
||||
strsep(&stringp, "|");
|
||||
strncpy(argdata, (char *)data, sizeof(argdata)-1);
|
||||
stringp=argdata;
|
||||
varname = strsep(&stringp, "|");
|
||||
filename = strsep(&stringp, "|");
|
||||
if (!strlen(tmp)) {
|
||||
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) {
|
||||
/* Answer if the line isn't up. */
|
||||
res = ast_answer(chan);
|
||||
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, tmp2, sizeof(tmp2) - 1, 0);
|
||||
if (!res)
|
||||
pbx_builtin_setvar_helper(chan, tmp, tmp2);
|
||||
ast_verbose(VERBOSE_PREFIX_3 "User entered '%s'\n", tmp2);
|
||||
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;
|
||||
|
||||
147
apps/app_record.c
Executable file → Normal file
147
apps/app_record.c
Executable file → Normal file
@@ -21,7 +21,6 @@
|
||||
#include <asterisk/dsp.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static char *tdesc = "Trivial Record Application";
|
||||
|
||||
@@ -30,10 +29,19 @@ static char *app = "Record";
|
||||
static char *synopsis = "Record to a file";
|
||||
|
||||
static char *descrip =
|
||||
" Record(filename:extension|silence): 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"
|
||||
"'silence' is the number of seconds of silence to allow before returning.\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;
|
||||
@@ -48,7 +56,7 @@ 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;
|
||||
|
||||
@@ -62,64 +70,128 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
int silence = 0; /* amount of silence to allow */
|
||||
int gotsilence = 0; /* did we timeout for silence? */
|
||||
char silencestr[5];
|
||||
int k = 0;
|
||||
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;
|
||||
|
||||
|
||||
vdata = data; /* explained above */
|
||||
|
||||
/* 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) && (vdata[i] != '|'); 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] && (vdata[i] == '|')) i++;
|
||||
for (; vdata[i] && (vdata[i] != '|') && (k < 3) && i < strlen(data); i++, k++)
|
||||
silencestr[k] = vdata[i];
|
||||
silencestr[k] = '\0';
|
||||
if (vdata[i] == '|')
|
||||
i++;
|
||||
|
||||
if (silencestr) {
|
||||
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) {
|
||||
@@ -150,10 +222,21 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
ast_dsp_set_threshold(sildet, 256);
|
||||
}
|
||||
|
||||
s = ast_writefile( tmp, ext, NULL, O_CREAT|O_TRUNC|O_WRONLY , 0, 0644);
|
||||
|
||||
|
||||
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;
|
||||
@@ -206,7 +289,7 @@ static int record_exec(struct ast_channel *chan, void *data)
|
||||
if (gotsilence) {
|
||||
ast_stream_rewind(s, silence-1000);
|
||||
ast_truncstream(s);
|
||||
} else {
|
||||
} else if (!gottimeout) {
|
||||
/* Strip off the last 1/4 second of it */
|
||||
ast_stream_rewind(s, 250);
|
||||
ast_truncstream(s);
|
||||
@@ -218,7 +301,7 @@ 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) {
|
||||
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);
|
||||
|
||||
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
24
apps/app_sayunixtime.c
Executable file → Normal file
24
apps/app_sayunixtime.c
Executable file → Normal file
@@ -27,6 +27,7 @@
|
||||
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";
|
||||
|
||||
@@ -39,6 +40,15 @@ static char *sayunixtime_descrip =
|
||||
" 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;
|
||||
|
||||
@@ -94,13 +104,23 @@ static int sayunixtime_exec(struct ast_channel *chan, void *data)
|
||||
|
||||
int unload_module(void)
|
||||
{
|
||||
int res;
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
return ast_unregister_application(app_sayunixtime);
|
||||
res = ast_unregister_application(app_sayunixtime);
|
||||
if (! res)
|
||||
return ast_unregister_application(app_datetime);
|
||||
else
|
||||
return res;
|
||||
}
|
||||
|
||||
int load_module(void)
|
||||
{
|
||||
return ast_register_application(app_sayunixtime, sayunixtime_exec, sayunixtime_synopsis, sayunixtime_descrip);
|
||||
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)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
42
apps/app_setcdruserfield.c
Executable file → Normal file
42
apps/app_setcdruserfield.c
Executable file → Normal file
@@ -17,7 +17,9 @@
|
||||
#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>
|
||||
|
||||
@@ -59,6 +61,41 @@ 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;
|
||||
@@ -97,6 +134,7 @@ int unload_module(void)
|
||||
STANDARD_HANGUP_LOCALUSERS;
|
||||
res = ast_unregister_application(setcdruserfield_app);
|
||||
res |= ast_unregister_application(appendcdruserfield_app);
|
||||
ast_manager_unregister("SetCDRUserField");
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -105,7 +143,7 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
12
apps/app_setcidnum.c
Executable file → Normal file
12
apps/app_setcidnum.c
Executable file → Normal file
@@ -21,9 +21,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 Number";
|
||||
|
||||
@@ -64,17 +64,17 @@ static int setcallerid_exec(struct ast_channel *chan, void *data)
|
||||
strncpy(oldcid, chan->callerid, sizeof(oldcid) - 1);
|
||||
ast_callerid_parse(oldcid, &n, &l);
|
||||
l = tmp;
|
||||
if (strlen(l)) {
|
||||
if (n && strlen(n))
|
||||
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 && strlen(n)) {
|
||||
} else if (n && !ast_strlen_zero(n)) {
|
||||
strncpy(newcid, n, 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;
|
||||
}
|
||||
|
||||
2
apps/app_skel.c
Executable file → Normal file
2
apps/app_skel.c
Executable file → Normal file
@@ -16,10 +16,10 @@
|
||||
#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 <pthread.h>
|
||||
|
||||
static char *tdesc = "Trivial skeleton Application";
|
||||
static char *app = "skel";
|
||||
|
||||
1236
apps/app_sms.c
Normal file
1236
apps/app_sms.c
Normal file
File diff suppressed because it is too large
Load Diff
10
apps/app_softhangup.c
Executable file → Normal file
10
apps/app_softhangup.c
Executable file → Normal file
@@ -17,14 +17,12 @@
|
||||
#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";
|
||||
@@ -47,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;
|
||||
|
||||
35
apps/app_striplsd.c
Executable file → Normal file
35
apps/app_striplsd.c
Executable file → Normal file
@@ -17,14 +17,12 @@
|
||||
#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 =
|
||||
@@ -47,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)
|
||||
|
||||
13
apps/app_substring.c
Executable file → Normal file
13
apps/app_substring.c
Executable file → Normal file
@@ -18,17 +18,17 @@
|
||||
#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 =
|
||||
" (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"
|
||||
@@ -48,7 +48,7 @@ static char *descrip =
|
||||
|
||||
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;
|
||||
|
||||
@@ -59,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,"=");
|
||||
|
||||
46
apps/app_system.c
Executable file → Normal file
46
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 system_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,14 +80,26 @@ static int system_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)
|
||||
{
|
||||
ast_register_application(app2, trysystem_exec, synopsis2, descrip2);
|
||||
return ast_register_application(app, system_exec, synopsis, descrip);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
5
apps/app_transfer.c
Executable file → Normal file
5
apps/app_transfer.c
Executable file → Normal file
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Asterisk -- A telephony toolkit for Linux.
|
||||
*
|
||||
* Time of day - Report the time of day
|
||||
* Transfer a caller
|
||||
*
|
||||
* Copyright (C) 1999, Mark Spencer
|
||||
*
|
||||
@@ -22,9 +22,6 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
static char *tdesc = "Transfer";
|
||||
|
||||
static char *app = "Transfer";
|
||||
|
||||
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;
|
||||
}
|
||||
3541
apps/app_voicemail.c
Executable file → Normal file
3541
apps/app_voicemail.c
Executable file → Normal file
File diff suppressed because it is too large
Load Diff
6
apps/app_waitforring.c
Executable file → Normal file
6
apps/app_waitforring.c
Executable file → Normal file
@@ -18,14 +18,12 @@
|
||||
#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";
|
||||
@@ -48,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;
|
||||
}
|
||||
}
|
||||
|
||||
116
apps/app_zapscan.c
Executable file → Normal file
116
apps/app_zapscan.c
Executable file → Normal file
@@ -34,8 +34,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 = "Scan Zap channels application";
|
||||
|
||||
static char *app = "ZapScan";
|
||||
@@ -43,8 +47,8 @@ static char *app = "ZapScan";
|
||||
static char *synopsis = "Scan Zap channels to monitor calls";
|
||||
|
||||
static char *descrip =
|
||||
" ZapScan allows a call center manager to monitor\n"
|
||||
"phone conversations in a convenient way.";
|
||||
" ZapScan allows a call center manager to monitor Zap channels in\n"
|
||||
"a convenient way. Use '#' to select the next channel and use '*' to exit\n";
|
||||
|
||||
|
||||
STANDARD_LOCAL_USER;
|
||||
@@ -54,6 +58,22 @@ LOCAL_USER_DECL;
|
||||
|
||||
#define CONF_SIZE 160
|
||||
|
||||
static struct ast_channel *get_zap_channel_locked(int num) {
|
||||
struct ast_channel *c=NULL;
|
||||
char name[80];
|
||||
|
||||
snprintf(name,sizeof(name),"Zap/%d-1",num);
|
||||
c = ast_channel_walk_locked(NULL);
|
||||
while(c) {
|
||||
if (!strcasecmp(c->name, name)) {
|
||||
break;
|
||||
}
|
||||
ast_mutex_unlock(&c->lock);
|
||||
c = ast_channel_walk_locked(c);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
static int careful_write(int fd, unsigned char *data, int len)
|
||||
{
|
||||
int res;
|
||||
@@ -87,6 +107,8 @@ static int conf_run(struct ast_channel *chan, int confno, int confflags)
|
||||
int retryzap;
|
||||
int origfd;
|
||||
int ret = -1;
|
||||
char input[4];
|
||||
int ic=0;
|
||||
|
||||
ZT_BUFFERINFO bi;
|
||||
char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET];
|
||||
@@ -188,11 +210,30 @@ zapretry:
|
||||
f = ast_read(c);
|
||||
if (!f)
|
||||
break;
|
||||
if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
|
||||
ret = 0;
|
||||
if(f->frametype == AST_FRAME_DTMF) {
|
||||
if(f->subclass == '#') {
|
||||
ret = 0;
|
||||
break;
|
||||
} else if (fd != chan->fds[0]) {
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
}
|
||||
else if (f->subclass == '*') {
|
||||
ret = -1;
|
||||
break;
|
||||
|
||||
}
|
||||
else {
|
||||
input[ic++] = f->subclass;
|
||||
}
|
||||
if(ic == 3) {
|
||||
input[ic++] = '\0';
|
||||
ic=0;
|
||||
ret = atoi(input);
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Zapscan: change channel to %d\n",ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fd != chan->fds[0]) {
|
||||
if (f->frametype == AST_FRAME_VOICE) {
|
||||
if (f->subclass == AST_FORMAT_ULAW) {
|
||||
/* Carefully write */
|
||||
careful_write(fd, f->data, f->datalen);
|
||||
@@ -243,33 +284,56 @@ static int conf_exec(struct ast_channel *chan, void *data)
|
||||
struct localuser *u;
|
||||
int confflags = 0;
|
||||
int confno = 0;
|
||||
char confstr[80], *tmp;
|
||||
struct ast_channel *tempchan = NULL, *lastchan = NULL;
|
||||
|
||||
char confstr[80] = "", *tmp;
|
||||
struct ast_channel *tempchan = NULL, *lastchan = NULL,*ichan = NULL;
|
||||
struct ast_frame *f;
|
||||
int input=0;
|
||||
|
||||
LOCAL_USER_ADD(u);
|
||||
|
||||
if (chan->_state != AST_STATE_UP)
|
||||
ast_answer(chan);
|
||||
|
||||
for (;;) {
|
||||
tempchan = ast_channel_walk(tempchan);
|
||||
if ( !tempchan && !lastchan )
|
||||
break;
|
||||
if ( tempchan && (!strcmp(tempchan->type, "Zap")) && (tempchan != chan) ) {
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Zap channel %s is in-use, monitoring...\n", tempchan->name);
|
||||
strcpy(confstr, tempchan->name);
|
||||
if ((tmp = strchr(confstr,'-'))) {
|
||||
*tmp = '\0';
|
||||
if (ast_waitfor(chan, 100) < 0)
|
||||
break;
|
||||
|
||||
f = ast_read(chan);
|
||||
if (!f)
|
||||
break;
|
||||
if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) {
|
||||
ast_frfree(f);
|
||||
break;
|
||||
}
|
||||
confno = atoi(strchr(confstr,'/') + 1);
|
||||
ast_stopstream(chan);
|
||||
ast_say_number(chan, confno, AST_DIGIT_ANY, chan->language);
|
||||
res = conf_run(chan, confno, confflags);
|
||||
if (res<0) break;
|
||||
ast_frfree(f);
|
||||
ichan = NULL;
|
||||
if(input) {
|
||||
ichan = get_zap_channel_locked(input);
|
||||
input = 0;
|
||||
}
|
||||
|
||||
tempchan = ichan ? ichan : ast_channel_walk_locked(tempchan);
|
||||
|
||||
|
||||
if ( !tempchan && !lastchan )
|
||||
break;
|
||||
if ( tempchan && tempchan->type && (!strcmp(tempchan->type, "Zap")) && (tempchan != chan) ) {
|
||||
ast_verbose(VERBOSE_PREFIX_3 "Zap channel %s is in-use, monitoring...\n", tempchan->name);
|
||||
strncpy(confstr, tempchan->name, sizeof(confstr) - 1);
|
||||
ast_mutex_unlock(&tempchan->lock);
|
||||
if ((tmp = strchr(confstr,'-'))) {
|
||||
*tmp = '\0';
|
||||
}
|
||||
confno = atoi(strchr(confstr,'/') + 1);
|
||||
ast_stopstream(chan);
|
||||
ast_say_number(chan, confno, AST_DIGIT_ANY, chan->language, (char *) NULL);
|
||||
res = conf_run(chan, confno, confflags);
|
||||
if (res<0) break;
|
||||
input = res;
|
||||
} else if (tempchan)
|
||||
ast_mutex_unlock(&tempchan->lock);
|
||||
lastchan = tempchan;
|
||||
}
|
||||
lastchan = tempchan;
|
||||
}
|
||||
|
||||
LOCAL_USER_REMOVE(u);
|
||||
return res;
|
||||
}
|
||||
|
||||
0
apps/enter.h
Executable file → Normal file
0
apps/enter.h
Executable file → Normal file
0
apps/leave.h
Executable file → Normal file
0
apps/leave.h
Executable file → Normal file
BIN
apps/rpt_flow.pdf
Normal file
BIN
apps/rpt_flow.pdf
Normal file
Binary file not shown.
257
ast_expr.y
Executable file → Normal file
257
ast_expr.y
Executable file → Normal file
@@ -20,6 +20,13 @@
|
||||
#include <asterisk/ast_expr.h>
|
||||
#include <asterisk/logger.h>
|
||||
|
||||
#ifdef LONG_LONG_MIN
|
||||
#define QUAD_MIN LONG_LONG_MIN
|
||||
#endif
|
||||
#ifdef LONG_LONG_MAX
|
||||
#define QUAD_MAX LONG_LONG_MAX
|
||||
#endif
|
||||
|
||||
# if ! defined(QUAD_MIN)
|
||||
# define QUAD_MIN (-0x7fffffffffffffffL-1)
|
||||
# endif
|
||||
@@ -48,6 +55,7 @@ struct val {
|
||||
struct parser_control {
|
||||
struct val *result;
|
||||
int pipa;
|
||||
char *arg_orig;
|
||||
char *argv;
|
||||
char *ptrptr;
|
||||
int firsttoken;
|
||||
@@ -78,10 +86,30 @@ static struct val *op_rem __P((struct val *, struct val *));
|
||||
static struct val *op_times __P((struct val *, struct val *));
|
||||
static quad_t to_integer __P((struct val *));
|
||||
static void to_string __P((struct val *));
|
||||
static int ast_yyerror __P((const char *));
|
||||
|
||||
/* uh, if I want to predeclare yylex with a YYLTYPE, I have to predeclare the yyltype... sigh */
|
||||
typedef struct yyltype
|
||||
{
|
||||
int first_line;
|
||||
int first_column;
|
||||
|
||||
int last_line;
|
||||
int last_column;
|
||||
} yyltype;
|
||||
|
||||
# define YYLTYPE yyltype
|
||||
# define YYLTYPE_IS_TRIVIAL 1
|
||||
|
||||
static int ast_yyerror __P((const char *,YYLTYPE *, struct parser_control *));
|
||||
|
||||
#define ast_yyerror(x) ast_yyerror(x,&yyloc,kota)
|
||||
|
||||
%}
|
||||
|
||||
%pure-parser
|
||||
%locations
|
||||
/* %debug for when you are having big problems */
|
||||
|
||||
/* %name-prefix="ast_yy" */
|
||||
|
||||
%union
|
||||
@@ -90,7 +118,7 @@ static int ast_yyerror __P((const char *));
|
||||
}
|
||||
|
||||
%{
|
||||
static int ast_yylex __P((YYSTYPE *, struct parser_control *));
|
||||
static int ast_yylex __P((YYSTYPE *, YYLTYPE *, struct parser_control *));
|
||||
%}
|
||||
|
||||
|
||||
@@ -110,21 +138,21 @@ start: expr { ((struct parser_control *)kota)->result = $$; }
|
||||
;
|
||||
|
||||
expr: TOKEN
|
||||
| '(' expr ')' { $$ = $2; }
|
||||
| expr '|' expr { $$ = op_or ($1, $3); }
|
||||
| expr '&' expr { $$ = op_and ($1, $3); }
|
||||
| expr '=' expr { $$ = op_eq ($1, $3); }
|
||||
| expr '>' expr { $$ = op_gt ($1, $3); }
|
||||
| expr '<' expr { $$ = op_lt ($1, $3); }
|
||||
| expr GE expr { $$ = op_ge ($1, $3); }
|
||||
| expr LE expr { $$ = op_le ($1, $3); }
|
||||
| expr NE expr { $$ = op_ne ($1, $3); }
|
||||
| expr '+' expr { $$ = op_plus ($1, $3); }
|
||||
| expr '-' expr { $$ = op_minus ($1, $3); }
|
||||
| expr '*' expr { $$ = op_times ($1, $3); }
|
||||
| expr '/' expr { $$ = op_div ($1, $3); }
|
||||
| expr '%' expr { $$ = op_rem ($1, $3); }
|
||||
| expr ':' expr { $$ = op_colon ($1, $3); }
|
||||
| '(' expr ')' { $$ = $2; @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '|' expr { $$ = op_or ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '&' expr { $$ = op_and ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '=' expr { $$ = op_eq ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '>' expr { $$ = op_gt ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '<' expr { $$ = op_lt ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr GE expr { $$ = op_ge ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr LE expr { $$ = op_le ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr NE expr { $$ = op_ne ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '+' expr { $$ = op_plus ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '-' expr { $$ = op_minus ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '*' expr { $$ = op_times ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '/' expr { $$ = op_div ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr '%' expr { $$ = op_rem ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
| expr ':' expr { $$ = op_colon ($1, $3); @$.first_column = @1.first_column; @$.last_column = @3.last_column; @$.first_line=0; @$.last_line=0;}
|
||||
;
|
||||
|
||||
|
||||
@@ -187,6 +215,7 @@ struct val *vp;
|
||||
}
|
||||
if (vp->type == string || vp->type == numeric_string)
|
||||
free (vp->u.s);
|
||||
free (vp);
|
||||
}
|
||||
|
||||
|
||||
@@ -250,19 +279,92 @@ struct val *vp;
|
||||
return (vp->type == string);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ast_yylex (YYSTYPE *lvalp, struct parser_control *karoto)
|
||||
ast_yylex (YYSTYPE *lvalp, YYLTYPE *yylloc, struct parser_control *karoto)
|
||||
{
|
||||
char *p;
|
||||
|
||||
char *p=0;
|
||||
char *t1=0;
|
||||
char savep = 0;
|
||||
char *savepp = 0;
|
||||
|
||||
if (karoto->firsttoken==1) {
|
||||
p=strtok_r(karoto->argv," ",&(karoto->ptrptr));
|
||||
karoto->firsttoken=0;
|
||||
t1 = karoto->argv;
|
||||
karoto->firsttoken = 0;
|
||||
} else {
|
||||
p=strtok_r(NULL," ",&(karoto->ptrptr));
|
||||
t1 = karoto->ptrptr;
|
||||
}
|
||||
|
||||
|
||||
while(*t1 && *t1 == ' ' ) /* we can remove worries about leading/multiple spaces being present */
|
||||
t1++;
|
||||
karoto->ptrptr = t1;
|
||||
yylloc->first_column = t1 - karoto->argv;
|
||||
|
||||
while( *t1 && *t1 != ' ' && *t1 != '"') /* find the next space or quote */
|
||||
t1++;
|
||||
if( *t1 == ' ' )
|
||||
{
|
||||
*t1 = 0;
|
||||
p = karoto->ptrptr;
|
||||
karoto->ptrptr = t1+1;
|
||||
yylloc->last_column = t1 - karoto->argv;
|
||||
}
|
||||
else if (*t1 == '"' )
|
||||
{
|
||||
/* opening quote. find the closing quote */
|
||||
char *t2=t1+1;
|
||||
while( *t2 && *t2 != '"')
|
||||
t2++;
|
||||
if( *t2 == '"' )
|
||||
{
|
||||
if( *(t2+1) == ' ' || *(t2+1) == 0 )
|
||||
{
|
||||
if( *(t2+1) )
|
||||
{
|
||||
*(t2+1) = 0;
|
||||
karoto->ptrptr = t2+2;
|
||||
}
|
||||
else
|
||||
{
|
||||
karoto->ptrptr = t2+1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* hmmm. what if another token is here? */
|
||||
/* maybe we can insert a space? */
|
||||
savep = *(t2+1);
|
||||
savepp = t2+1;
|
||||
*(t2+1) = 0;
|
||||
karoto->ptrptr = t2+1;
|
||||
}
|
||||
p = t1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NOT GOOD -- no closing quote! */
|
||||
p = t1;
|
||||
karoto->ptrptr = t2;
|
||||
}
|
||||
yylloc->last_column = t2 - karoto->argv;
|
||||
}
|
||||
else if( *t1 == 0 )
|
||||
{
|
||||
if( t1 != karoto->ptrptr )
|
||||
{
|
||||
/* this is the last token */
|
||||
p = karoto->ptrptr;
|
||||
karoto->ptrptr = t1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we are done. That was quick */
|
||||
p = karoto->ptrptr;
|
||||
yylloc->last_column = t1 - karoto->argv;
|
||||
}
|
||||
}
|
||||
if( *p == 0 )
|
||||
p = 0;
|
||||
|
||||
if (p==NULL) {
|
||||
return (0);
|
||||
}
|
||||
@@ -280,6 +382,12 @@ ast_yylex (YYSTYPE *lvalp, struct parser_control *karoto)
|
||||
}
|
||||
|
||||
lvalp->val = make_str (p);
|
||||
if( savep )
|
||||
{
|
||||
*savepp = savep; /* restore the null terminated string */
|
||||
savepp = 0;
|
||||
savep = 0;
|
||||
}
|
||||
return (TOKEN);
|
||||
}
|
||||
|
||||
@@ -306,7 +414,9 @@ char *ast_expr (char *arg)
|
||||
karoto.result = NULL;
|
||||
karoto.firsttoken=1;
|
||||
karoto.argv=kota;
|
||||
|
||||
karoto.arg_orig = arg;
|
||||
/* ast_yydebug = 1; */
|
||||
|
||||
ast_yyparse ((void *)&karoto);
|
||||
|
||||
free(kota);
|
||||
@@ -339,11 +449,31 @@ int main(int argc,char **argv) {
|
||||
|
||||
#endif
|
||||
|
||||
#undef ast_yyerror
|
||||
#define ast_yyerror(x) ast_yyerror(x, YYLTYPE *yylloc, struct parser_control *karoto)
|
||||
|
||||
static int
|
||||
ast_yyerror (s)
|
||||
const char *s;
|
||||
ast_yyerror (const char *s)
|
||||
{
|
||||
ast_log(LOG_WARNING,"ast_yyerror(): syntax error: %s\n",s);
|
||||
char spacebuf[8000]; /* best safe than sorry */
|
||||
char spacebuf2[8000]; /* best safe than sorry */
|
||||
int i=0;
|
||||
spacebuf[0] = 0;
|
||||
|
||||
if( yylloc->first_column > 7990 ) /* if things get out of whack, why crash? */
|
||||
yylloc->first_column = 7990;
|
||||
if( yylloc->last_column > 7990 )
|
||||
yylloc->last_column = 7990;
|
||||
for(i=0;i<yylloc->first_column;i++) spacebuf[i] = ' ';
|
||||
for( ;i<yylloc->last_column;i++) spacebuf[i] = '^';
|
||||
spacebuf[i] = 0;
|
||||
|
||||
for(i=0;i<karoto->ptrptr-karoto->argv;i++) spacebuf2[i] = ' ';
|
||||
spacebuf2[i++]='^';
|
||||
spacebuf2[i]= 0;
|
||||
|
||||
ast_log(LOG_WARNING,"ast_yyerror(): syntax error: %s; Input:\n%s\n%s\n%s\n",s,
|
||||
karoto->arg_orig,spacebuf,spacebuf2);
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -521,19 +651,24 @@ struct val *a, *b;
|
||||
{
|
||||
struct val *r;
|
||||
|
||||
if (!to_integer (a) || !to_integer (b)) {
|
||||
if (!to_integer (a)) {
|
||||
ast_log(LOG_WARNING,"non-numeric argument\n");
|
||||
free_value(a);
|
||||
if (!to_integer (b)) {
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return make_integer(0);
|
||||
} else {
|
||||
free_value(a);
|
||||
return (b);
|
||||
}
|
||||
} else if (!to_integer(b)) {
|
||||
free_value(b);
|
||||
return(NULL);
|
||||
return (a);
|
||||
}
|
||||
|
||||
r = make_integer (/*(quad_t)*/(a->u.i + b->u.i));
|
||||
if (chk_plus (a->u.i, b->u.i, r->u.i)) {
|
||||
ast_log(LOG_WARNING,"overflow\n");
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return(NULL);
|
||||
}
|
||||
free_value (a);
|
||||
free_value (b);
|
||||
@@ -561,19 +696,27 @@ struct val *a, *b;
|
||||
{
|
||||
struct val *r;
|
||||
|
||||
if (!to_integer (a) || !to_integer (b)) {
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
if (!to_integer (a)) {
|
||||
ast_log(LOG_WARNING, "non-numeric argument\n");
|
||||
return(NULL);
|
||||
if (!to_integer (b)) {
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return make_integer(0);
|
||||
} else {
|
||||
r = make_integer(0 - b->u.i);
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return (r);
|
||||
}
|
||||
} else if (!to_integer(b)) {
|
||||
ast_log(LOG_WARNING, "non-numeric argument\n");
|
||||
free_value(b);
|
||||
return (a);
|
||||
}
|
||||
|
||||
r = make_integer (/*(quad_t)*/(a->u.i - b->u.i));
|
||||
if (chk_minus (a->u.i, b->u.i, r->u.i)) {
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
ast_log(LOG_WARNING, "overload\n");
|
||||
return(NULL);
|
||||
ast_log(LOG_WARNING, "overflow\n");
|
||||
}
|
||||
free_value (a);
|
||||
free_value (b);
|
||||
@@ -603,15 +746,12 @@ struct val *a, *b;
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
ast_log(LOG_WARNING, "non-numeric argument\n");
|
||||
return(NULL);
|
||||
return(make_integer(0));
|
||||
}
|
||||
|
||||
r = make_integer (/*(quad_t)*/(a->u.i * b->u.i));
|
||||
if (chk_times (a->u.i, b->u.i, r->u.i)) {
|
||||
ast_log(LOG_WARNING, "overflow\n");
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return(NULL);
|
||||
}
|
||||
free_value (a);
|
||||
free_value (b);
|
||||
@@ -636,26 +776,28 @@ struct val *a, *b;
|
||||
{
|
||||
struct val *r;
|
||||
|
||||
if (!to_integer (a) || !to_integer (b)) {
|
||||
if (!to_integer (a)) {
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
ast_log(LOG_WARNING, "non-numeric argument\n");
|
||||
return(NULL);
|
||||
return make_integer(0);
|
||||
} else if (!to_integer (b)) {
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
ast_log(LOG_WARNING, "non-numeric argument\n");
|
||||
return make_integer(INT_MAX);
|
||||
}
|
||||
|
||||
if (b->u.i == 0) {
|
||||
ast_log(LOG_WARNING, "division by zero\n");
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return(NULL);
|
||||
return make_integer(INT_MAX);
|
||||
}
|
||||
|
||||
r = make_integer (/*(quad_t)*/(a->u.i / b->u.i));
|
||||
if (chk_div (a->u.i, b->u.i)) {
|
||||
ast_log(LOG_WARNING, "overflow\n");
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return(NULL);
|
||||
}
|
||||
free_value (a);
|
||||
free_value (b);
|
||||
@@ -672,14 +814,13 @@ struct val *a, *b;
|
||||
ast_log(LOG_WARNING, "non-numeric argument\n");
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return(NULL);
|
||||
return make_integer(0);
|
||||
}
|
||||
|
||||
if (b->u.i == 0) {
|
||||
ast_log(LOG_WARNING, "div by zero\n");
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return(NULL);
|
||||
return (b);
|
||||
}
|
||||
|
||||
r = make_integer (/*(quad_t)*/(a->u.i % b->u.i));
|
||||
@@ -704,12 +845,12 @@ struct val *a, *b;
|
||||
to_string(b);
|
||||
|
||||
/* compile regular expression */
|
||||
if ((eval = regcomp (&rp, b->u.s, 0)) != 0) {
|
||||
if ((eval = regcomp (&rp, b->u.s, REG_EXTENDED)) != 0) {
|
||||
regerror (eval, &rp, errbuf, sizeof(errbuf));
|
||||
ast_log(LOG_WARNING,"regcomp() error : %s",errbuf);
|
||||
free_value(a);
|
||||
free_value(b);
|
||||
return(NULL);
|
||||
return make_str("");
|
||||
}
|
||||
|
||||
/* compare string against pattern */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user