-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathpayphone.agi
More file actions
executable file
·129 lines (105 loc) · 2.96 KB
/
payphone.agi
File metadata and controls
executable file
·129 lines (105 loc) · 2.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/usr/bin/perl
use Asterisk::AGI;
use Cwd "realpath";
use File::Basename;
use Time::HiRes;
use strict;
use constant {
# where we live
SOUND_DIR => dirname(realpath($0)),
# outbound context we'll send calls to (since our current context should
# only allow dialing 0 from the ATA)
OUTBOUND_CONTEXT => "payphone-outbound",
# timeout in seconds to wait to get a number or a coin
TIMEOUT => 30,
# amount required to make a call
CALL_CENTS => 25,
# numbers allowed to be dialed without requiring coins
FREE_CALLS => qr/^(1?(8[02345678]{2})[0-9]{7}|911)/,
# valid numbers which will immediately dial instead of timing out
VALID_NUMBER => qr/^(1?[2-8][0-9]{9}|911)/,
};
my $AGI = new Asterisk::AGI;
my $last_activity = time();
my @last_coins;
my $inserted = 0;
my $dialed = "";
# generate dialtone while we wait for coins
$AGI->exec("Playtones", "dial");
my $dialtone = 1;
while (1) {
my $dig = $AGI->wait_for_digit(1000);
if ($dig >= 1) {
if ($dig == ord('$')) {
$AGI->verbose("got coin tone at " . Time::HiRes::time, 4);
# shift out old coins
my @new_coins;
for (my $x = 0; $x <= $#last_coins; $x++) {
if (Time::HiRes::time - $last_coins[$x] < 0.5) {
push(@new_coins, $last_coins[$x]);
}
}
@last_coins = @new_coins;
push(@last_coins, Time::HiRes::time);
# if we've heard 3 coin tones in close proximity, always count it
# as 5 since we might not hear the other 2
if ($#last_coins == 2) {
$inserted += 15;
$AGI->verbose("got 5-cent tone, counting as 15 cents (now "
. $inserted . " cents)", 4);
# provide some audible feedback that it's ok to make a call
$AGI->exec("Playtones", "stutter");
}
elsif ($#last_coins > 2) {
$AGI->verbose("ignoring 4th or 5th 5-cent tone of 25-cents "
. "(still " . $inserted . " cents)", 4);
}
else {
$inserted += 5;
$AGI->verbose("got 5-cent tone (now " . $inserted . " cents)",
4);
}
}
else {
if ($dialtone) {
$AGI->exec("StopPlaytones", "dial");
$dialtone = 0;
}
$dialed .= chr($dig);
$AGI->verbose("dialed " . chr($dig) . " (now " . $dialed . ")", 4);
}
$last_activity = time();
}
my $elapsed = time() - $last_activity;
if ($dialed =~ FREE_CALLS) {
$AGI->verbose("connecting to " . $dialed . " (free call)", 1);
dial($dialed);
exit;
}
elsif ($dialed =~ VALID_NUMBER) {
if ($inserted < CALL_CENTS) {
$AGI->verbose("need " . CALL_CENTS . " cents to dial " . $dialed
. ", have " . $inserted, 4);
$AGI->stream_file(SOUND_DIR . "/not_deposited", "0");
}
else {
$AGI->verbose("connecting to " . $dialed . " (inserted "
. $inserted . " cents)", 1);
dial($dialed);
}
exit;
}
elsif ($elapsed >= TIMEOUT) {
$AGI->verbose("timed out waiting for coins or digits", 1);
if ($dialed ne "") {
$AGI->stream_file(SOUND_DIR . "/invalid_number", "0");
}
exit;
}
}
sub dial {
my ($number) = @_;
$AGI->set_context(OUTBOUND_CONTEXT);
$AGI->set_extension($dialed);
$AGI->exec("Goto", "1");
}