| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Net::Peep::BC; |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
require 5.00503; |
|
4
|
3
|
|
|
3
|
|
61
|
use strict; |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
113
|
|
|
5
|
|
|
|
|
|
|
# use warnings; # commented out for 5.005 compatibility |
|
6
|
3
|
|
|
3
|
|
17
|
use Carp; |
|
|
3
|
|
|
|
|
6
|
|
|
|
3
|
|
|
|
|
221
|
|
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
require Exporter; |
|
9
|
|
|
|
|
|
|
|
|
10
|
3
|
|
|
3
|
|
15
|
use vars qw{ @ISA %EXPORT_TAGS @EXPORT_OK @EXPORT $VERSION }; |
|
|
3
|
|
|
|
|
6
|
|
|
|
3
|
|
|
|
|
524
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
@ISA = qw(Exporter); |
|
13
|
|
|
|
|
|
|
%EXPORT_TAGS = ( 'all' => [ qw( ) ] ); |
|
14
|
|
|
|
|
|
|
@EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
|
15
|
|
|
|
|
|
|
@EXPORT = qw( ); |
|
16
|
|
|
|
|
|
|
$VERSION = do { my @r = (q$Revision: 1.10 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; |
|
17
|
|
|
|
|
|
|
|
|
18
|
3
|
|
|
3
|
|
17
|
use Socket; |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
2064
|
|
|
19
|
3
|
|
|
3
|
|
1799
|
use Sys::Hostname; |
|
|
3
|
|
|
|
|
17233
|
|
|
|
3
|
|
|
|
|
230
|
|
|
20
|
3
|
|
|
3
|
|
1916
|
use Net::Peep::Parser; |
|
|
3
|
|
|
|
|
8
|
|
|
|
3
|
|
|
|
|
164
|
|
|
21
|
3
|
|
|
3
|
|
18
|
use Net::Peep::Conf; |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
109
|
|
|
22
|
3
|
|
|
3
|
|
16
|
use Net::Peep::Log; |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
102
|
|
|
23
|
3
|
|
|
3
|
|
1133
|
use Net::Peep::Scheduler; |
|
|
3
|
|
|
|
|
8
|
|
|
|
3
|
|
|
|
|
147
|
|
|
24
|
|
|
|
|
|
|
|
|
25
|
3
|
|
|
3
|
|
17
|
use vars qw{ %Leases %Servers %Defaults $Scheduler $Alarmtime }; |
|
|
3
|
|
|
|
|
7
|
|
|
|
3
|
|
|
|
|
439
|
|
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
%Leases = %Servers = (); |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
%Defaults = ( |
|
30
|
|
|
|
|
|
|
type => 0, |
|
31
|
|
|
|
|
|
|
location => 128, |
|
32
|
|
|
|
|
|
|
priority => 0, |
|
33
|
|
|
|
|
|
|
volume => 128, |
|
34
|
|
|
|
|
|
|
dither => 0, |
|
35
|
|
|
|
|
|
|
sound => 0 |
|
36
|
|
|
|
|
|
|
); |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
$Scheduler = new Net::Peep::Scheduler; |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
$Alarmtime = 30; |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
# Peep protocol constants |
|
43
|
3
|
|
|
3
|
|
17
|
use constant PROT_MAJORVER => 1; |
|
|
3
|
|
|
|
|
18
|
|
|
|
3
|
|
|
|
|
196
|
|
|
44
|
3
|
|
|
3
|
|
15
|
use constant PROT_MINORVER => 0; |
|
|
3
|
|
|
|
|
6
|
|
|
|
3
|
|
|
|
|
123
|
|
|
45
|
3
|
|
|
3
|
|
15
|
use constant PROT_BCSERVER => 0; |
|
|
3
|
|
|
|
|
5
|
|
|
|
3
|
|
|
|
|
107
|
|
|
46
|
3
|
|
|
3
|
|
16
|
use constant PROT_BCCLIENT => 1; |
|
|
3
|
|
|
|
|
11
|
|
|
|
3
|
|
|
|
|
130
|
|
|
47
|
3
|
|
|
3
|
|
17
|
use constant PROT_SERVERSTILLALIVE => 2; |
|
|
3
|
|
|
|
|
4
|
|
|
|
3
|
|
|
|
|
127
|
|
|
48
|
3
|
|
|
3
|
|
14
|
use constant PROT_CLIENTSTILLALIVE => 3; |
|
|
3
|
|
|
|
|
6
|
|
|
|
3
|
|
|
|
|
125
|
|
|
49
|
3
|
|
|
3
|
|
15
|
use constant PROT_CLIENTEVENT => 4; |
|
|
3
|
|
|
|
|
4
|
|
|
|
3
|
|
|
|
|
319
|
|
|
50
|
3
|
|
|
3
|
|
16
|
use constant PROT_CLASSDELIM => '!'; |
|
|
3
|
|
|
|
|
7
|
|
|
|
3
|
|
|
|
|
11483
|
|
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
sub new { |
|
53
|
|
|
|
|
|
|
|
|
54
|
3
|
|
|
3
|
0
|
7
|
my $self = shift; |
|
55
|
3
|
|
33
|
|
|
17
|
my $class = ref($self) || $self; |
|
56
|
3
|
|
|
|
|
8
|
my $this = {}; |
|
57
|
3
|
|
|
|
|
10
|
bless $this, $class; |
|
58
|
|
|
|
|
|
|
|
|
59
|
3
|
|
|
|
|
19
|
$this->initialize(@_); |
|
60
|
|
|
|
|
|
|
|
|
61
|
3
|
|
|
|
|
16
|
return $this; |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
} # end sub new |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
sub initialize { |
|
66
|
|
|
|
|
|
|
|
|
67
|
3
|
|
|
3
|
0
|
7
|
my $self = shift; |
|
68
|
3
|
|
33
|
|
|
11
|
my $client = shift || confess "Error: Client not found"; |
|
69
|
3
|
|
33
|
|
|
12
|
my $configuration = shift || confess "Error: Configuration not found"; |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
# put the configuration object in a place where all the other |
|
72
|
|
|
|
|
|
|
# methods can find it |
|
73
|
3
|
|
|
|
|
14
|
$self->setConfiguration($configuration); |
|
74
|
|
|
|
|
|
|
|
|
75
|
3
|
|
|
|
|
18
|
my %options = $configuration->getOptionsHash($client); |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# FIXIT: This is silly and redundant. The object that instantiates |
|
78
|
|
|
|
|
|
|
# the Net::Peep::BC object already has all of the options set and a |
|
79
|
|
|
|
|
|
|
# configuration object. Net::Peep::BC shouldn't need to build its own |
|
80
|
|
|
|
|
|
|
# stable of options. Deal with it later .... |
|
81
|
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
# Populate the object attributes either by the class default |
|
83
|
|
|
|
|
|
|
# attributes or the options arguments passed in |
|
84
|
|
|
|
|
|
|
|
|
85
|
3
|
|
|
|
|
22
|
for my $key (keys %Defaults) { |
|
86
|
18
|
100
|
|
|
|
45
|
if ($key ne 'dither') { |
|
87
|
15
|
50
|
|
|
|
30
|
if (exists $options{$key}) { |
|
88
|
0
|
|
|
|
|
0
|
$self->setOption($key,$options{$key}); |
|
89
|
|
|
|
|
|
|
} else { |
|
90
|
15
|
|
|
|
|
51
|
$self->setOption($key,$Defaults{$key}); |
|
91
|
|
|
|
|
|
|
} |
|
92
|
|
|
|
|
|
|
} |
|
93
|
|
|
|
|
|
|
} |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# Make allowances for the two possible meanings of dither |
|
96
|
|
|
|
|
|
|
# dither is based exclusively on the value of 'type' |
|
97
|
3
|
50
|
|
|
|
16
|
$self->getOption('type') ? $self->setOption('dither',255) : $self->setOption('dither',0); |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
# Now initialize our socket |
|
100
|
3
|
|
|
|
|
20
|
my $port = $configuration->getClientPort($client); |
|
101
|
3
|
|
|
|
|
42
|
$self->logger()->debug(7,"Initializing socket on port $port ..."); |
|
102
|
3
|
|
|
|
|
9
|
my $addr = INADDR_ANY; |
|
103
|
3
|
|
|
|
|
8255
|
my $proto = getprotobyname('udp'); |
|
104
|
3
|
|
|
|
|
8911
|
my $paddr = sockaddr_in($port, $addr); |
|
105
|
3
|
50
|
|
|
|
447
|
socket(SOCKET, PF_INET, SOCK_DGRAM, $proto) or confess "Socket error: $!"; |
|
106
|
3
|
50
|
|
|
|
26
|
if ($configuration->getOption($client,'autodiscovery')) { |
|
107
|
0
|
0
|
|
|
|
0
|
bind(SOCKET, $paddr) or confess "Bind error: $!"; |
|
108
|
|
|
|
|
|
|
} |
|
109
|
3
|
|
|
|
|
17
|
$self->logger()->debug(7,"\tSocket initialized."); |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
#Set the socket option for the broadcast |
|
112
|
3
|
|
|
|
|
31
|
setsockopt SOCKET, SOL_SOCKET, SO_BROADCAST | SO_REUSEADDR, 1; |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
#Let everyone know we're alive |
|
115
|
3
|
|
|
|
|
27
|
$self->hello( PROT_BCCLIENT ); |
|
116
|
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
#Start up the alarm. Once this handler gets started, we'll have it |
|
118
|
|
|
|
|
|
|
#work concurrently with the program to handle host lists |
|
119
|
3
|
50
|
|
|
|
16
|
if ($configuration->getOption($client,'autodiscovery')) { |
|
120
|
|
|
|
|
|
|
$Scheduler->schedulerAddEvent( |
|
121
|
|
|
|
|
|
|
$self->getConfiguration()->client(), |
|
122
|
|
|
|
|
|
|
$Alarmtime, |
|
123
|
|
|
|
|
|
|
0.0, |
|
124
|
|
|
|
|
|
|
'client', |
|
125
|
0
|
|
|
0
|
|
0
|
sub { $self->handlealarm( PROT_CLIENTSTILLALIVE ) }, |
|
126
|
0
|
|
|
|
|
0
|
'', |
|
127
|
|
|
|
|
|
|
1 # 1 => repeated event, 0 => single event |
|
128
|
|
|
|
|
|
|
); |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
} # end sub initialize |
|
132
|
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
sub hello { |
|
134
|
|
|
|
|
|
|
|
|
135
|
3
|
|
|
3
|
0
|
6
|
my $self = shift; |
|
136
|
3
|
|
|
|
|
7
|
my $constant = shift; |
|
137
|
3
|
|
33
|
|
|
15
|
my $configuration = $self->getConfiguration() || confess "Error: Configuration not found"; |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
# Send out our broadcast to let everybody know we're alive |
|
140
|
|
|
|
|
|
|
# Note - we want to send these broadcasts to the servers within |
|
141
|
|
|
|
|
|
|
# the class definition. So, we use getServer() - Mike |
|
142
|
3
|
|
|
|
|
24
|
for my $class ($configuration->getClassList()) { |
|
143
|
3
|
|
|
|
|
11
|
$self->logger()->debug(7,"Getting broadcast for class [$class]"); |
|
144
|
3
|
|
|
|
|
20
|
my $broadcasts = $configuration->getServer($class); |
|
145
|
|
|
|
|
|
|
|
|
146
|
3
|
|
|
|
|
39
|
for my $broadcast (@$broadcasts) { |
|
147
|
3
|
|
|
|
|
14
|
my ($zone, $port) = ($broadcast->{'name'}, $broadcast->{'port'}); |
|
148
|
3
|
|
|
|
|
10
|
$self->logger()->debug(7,"Socketing to zone [$zone] and port [$port] ..."); |
|
149
|
3
|
|
|
|
|
875
|
my $iaddr = inet_aton($zone); |
|
150
|
3
|
|
|
|
|
19
|
my $bcaddr = sockaddr_in($port, $iaddr); |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
#Assemble the packet and send it |
|
153
|
3
|
|
|
|
|
40
|
my $packet = $self->assemble_bc_packet($constant); |
|
154
|
3
|
50
|
33
|
|
|
27
|
if (defined($constant) && $constant == PROT_CLIENTSTILLALIVE) { |
|
155
|
0
|
|
|
|
|
0
|
$self->logger()->debug(7,"Letting [$zone:$port] know we're still alive ..."); |
|
156
|
|
|
|
|
|
|
} else { |
|
157
|
3
|
|
|
|
|
12
|
$self->logger()->debug(7,"Sending a friendly hello to address [$zone:$port] ..."); |
|
158
|
|
|
|
|
|
|
} |
|
159
|
3
|
50
|
|
|
|
283
|
if (defined(send(SOCKET, $packet, 0, $bcaddr))) { |
|
160
|
3
|
|
|
|
|
14
|
$self->logger()->debug(9,"\tPacket of length ".length($packet)." sent."); |
|
161
|
|
|
|
|
|
|
} else { |
|
162
|
0
|
|
|
|
|
0
|
$self->logger()->log("Send broadcast error: $!"); |
|
163
|
|
|
|
|
|
|
} |
|
164
|
|
|
|
|
|
|
} |
|
165
|
|
|
|
|
|
|
} |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
} # end sub hello |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
sub getConfiguration { |
|
170
|
|
|
|
|
|
|
|
|
171
|
9
|
|
|
9
|
0
|
15
|
my $self = shift; |
|
172
|
9
|
50
|
|
|
|
27
|
confess "Error retrieving configuration: The configuration has not been set yet." |
|
173
|
|
|
|
|
|
|
unless exists $self->{"__CONFIGURATOR"}; |
|
174
|
9
|
|
|
|
|
39
|
return $self->{"__CONFIGURATOR"}; |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
} # end sub getConfiguration |
|
177
|
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
sub setConfiguration { |
|
179
|
|
|
|
|
|
|
|
|
180
|
3
|
|
|
3
|
0
|
7
|
my $self = shift; |
|
181
|
3
|
50
|
|
|
|
12
|
if (@_) { |
|
182
|
3
|
|
|
|
|
22
|
$self->{"__CONFIGURATOR"} = shift; |
|
183
|
|
|
|
|
|
|
} else { |
|
184
|
0
|
|
|
|
|
0
|
confess "Cannot set configuration: No configuration object found."; |
|
185
|
|
|
|
|
|
|
} |
|
186
|
3
|
|
|
|
|
14
|
return 1; |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
} # end sub setConfiguration |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
# Function to assemble a broadcast packet with an appropriate |
|
191
|
|
|
|
|
|
|
# identifier string |
|
192
|
|
|
|
|
|
|
sub assemble_bc_packet { |
|
193
|
|
|
|
|
|
|
|
|
194
|
3
|
|
|
3
|
0
|
8
|
my $self = shift; |
|
195
|
3
|
|
|
|
|
6
|
my $constant = shift; |
|
196
|
3
|
|
|
|
|
9
|
my $configuration = $self->getConfiguration(); |
|
197
|
3
|
|
|
|
|
13
|
my $identifier = join PROT_CLASSDELIM, ($configuration->getClassList()); |
|
198
|
3
|
|
|
|
|
8
|
$identifier .= PROT_CLASSDELIM; |
|
199
|
3
|
|
|
|
|
31
|
return pack("CCCCA128", |
|
200
|
|
|
|
|
|
|
PROT_MAJORVER, |
|
201
|
|
|
|
|
|
|
PROT_MINORVER, |
|
202
|
|
|
|
|
|
|
$constant, |
|
203
|
|
|
|
|
|
|
0, |
|
204
|
|
|
|
|
|
|
$identifier); |
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
} # end sub assemble_bc_packet |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
# returns a logging object |
|
209
|
|
|
|
|
|
|
sub logger { |
|
210
|
|
|
|
|
|
|
|
|
211
|
30
|
|
|
30
|
0
|
44
|
my $self = shift; |
|
212
|
30
|
100
|
|
|
|
78
|
if ( ! exists $self->{'__LOGGER'} ) { $self->{'__LOGGER'} = new Net::Peep::Log } |
|
|
3
|
|
|
|
|
25
|
|
|
213
|
30
|
|
|
|
|
253
|
return $self->{'__LOGGER'}; |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
} # end sub logger |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
sub close { |
|
218
|
|
|
|
|
|
|
|
|
219
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
|
220
|
0
|
|
|
|
|
0
|
close SOCKET; |
|
221
|
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
} # end sub close |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
# Send out a packet |
|
225
|
|
|
|
|
|
|
sub send { |
|
226
|
|
|
|
|
|
|
|
|
227
|
3
|
|
|
3
|
0
|
5
|
my $self = shift; |
|
228
|
3
|
|
|
|
|
11
|
my $client = shift; |
|
229
|
3
|
|
|
|
|
28
|
my %options = @_; |
|
230
|
|
|
|
|
|
|
|
|
231
|
3
|
|
|
|
|
26
|
$self->logger()->debug(7,"Sending packet to server(s) ..."); |
|
232
|
|
|
|
|
|
|
|
|
233
|
3
|
|
|
|
|
9
|
my $configuration = $self->getConfiguration(); |
|
234
|
|
|
|
|
|
|
|
|
235
|
3
|
50
|
|
|
|
21
|
my $type = exists($options{'type'}) ? $options{'type'} : $self->getOption('type'); |
|
236
|
3
|
50
|
|
|
|
15
|
my $location = exists($options{'location'}) ? $options{'location'} : $self->getOption('location'); |
|
237
|
3
|
50
|
|
|
|
12
|
my $priority = exists($options{'priority'}) ? $options{'priority'} : $self->getOption('priority'); |
|
238
|
3
|
50
|
|
|
|
14
|
my $volume = exists($options{'volume'}) ? $options{'volume'} : $self->getOption('volume'); |
|
239
|
3
|
50
|
|
|
|
12
|
my $dither = exists($options{'dither'}) ? $options{'dither'} : $self->getOption('dither'); |
|
240
|
3
|
50
|
|
|
|
12
|
my $sound = exists($options{'sound'}) ? $options{'sound'} : $self->getOption('sound'); |
|
241
|
|
|
|
|
|
|
|
|
242
|
3
|
|
|
|
|
12
|
$self->logger()->debug(9,"type=[$type] location=[$location] priority=[$priority] volume=[$volume] dither=[$dither] sound=[$sound]"); |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
#Now convert the sound name into the number if it isn't a number already |
|
245
|
3
|
50
|
|
|
|
23
|
if ($sound !~ /\d+/) { |
|
246
|
0
|
|
|
|
|
0
|
my $hash; |
|
247
|
0
|
0
|
|
|
|
0
|
$hash = $configuration->getEvent($sound) if $configuration->isEvent($sound); |
|
248
|
0
|
0
|
|
|
|
0
|
$hash = $configuration->getState($sound) if $configuration->isState($sound); |
|
249
|
|
|
|
|
|
|
|
|
250
|
0
|
0
|
|
|
|
0
|
if (ref($hash)) { |
|
251
|
0
|
|
|
|
|
0
|
my $index = $hash->{'index'}; |
|
252
|
0
|
|
|
|
|
0
|
$self->logger()->debug(5,"Sound [$sound] reassigned: Now it is [$index]"); |
|
253
|
0
|
|
|
|
|
0
|
$sound = $index; |
|
254
|
|
|
|
|
|
|
} else { |
|
255
|
0
|
|
|
|
|
0
|
$self->logger()->log(ref($self),": Warning: Asking Peep to play a non existent sound: [$sound]"); |
|
256
|
0
|
|
|
|
|
0
|
return; |
|
257
|
|
|
|
|
|
|
} |
|
258
|
|
|
|
|
|
|
} |
|
259
|
|
|
|
|
|
|
|
|
260
|
3
|
50
|
|
|
|
12
|
if ($configuration->getOption($client,'autodiscovery')) { |
|
261
|
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
# Now sendout to all the servers in our server list |
|
263
|
0
|
|
|
|
|
0
|
for my $server (keys %Servers) { |
|
264
|
0
|
|
|
|
|
0
|
my ($serverport,$serverip) = unpack_sockaddr_in($server); |
|
265
|
0
|
|
|
|
|
0
|
$serverip = inet_ntoa($serverip); |
|
266
|
0
|
|
|
|
|
0
|
$self->logger()->debug(7,"Notifying server [$serverip:$serverport] of event or sound [$sound] ..."); |
|
267
|
0
|
|
|
|
|
0
|
$self->sendout($type, $sound, $location, $priority, $volume, $dither, $server); |
|
268
|
|
|
|
|
|
|
} |
|
269
|
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
} else { |
|
271
|
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
# Just send a packet to the server and port specified on the command-line |
|
273
|
3
|
|
33
|
|
|
15
|
my $port = $configuration->getOption($client,'port') || confess "Error: Expecting nonzero port!"; |
|
274
|
3
|
|
33
|
|
|
14
|
my $host = $configuration->getOption($client,'server') || confess "Error: Expecting nonzero host!"; |
|
275
|
3
|
|
|
|
|
12
|
$self->logger()->debug(7,"Notifying server [$host:$port] of event or sound [$sound] ..."); |
|
276
|
3
|
|
|
|
|
277
|
$host = inet_aton($host); |
|
277
|
3
|
|
|
|
|
14
|
my $server = sockaddr_in($port,$host); |
|
278
|
3
|
|
|
|
|
42
|
$self->sendout($type, $sound, $location, $priority, $volume, $dither, $server); |
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
} |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
} # end sub send |
|
283
|
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
sub sendout { |
|
285
|
|
|
|
|
|
|
|
|
286
|
3
|
|
|
3
|
0
|
9
|
my $self = shift; |
|
287
|
3
|
|
|
|
|
13
|
my ($type,$sound,$location,$priority,$volume,$dither,$server) |
|
288
|
|
|
|
|
|
|
= @_; |
|
289
|
3
|
|
|
|
|
8
|
my $mix_in_time = 0; |
|
290
|
|
|
|
|
|
|
|
|
291
|
3
|
|
|
|
|
16
|
my ($serverport,$serverip) = unpack_sockaddr_in($server); |
|
292
|
3
|
|
|
|
|
27
|
$serverip = inet_ntoa($serverip); |
|
293
|
3
|
|
|
|
|
13
|
$self->logger()->debug(7,"type=[$type] sound=[$sound] location=[$location] priority=[$priority] volume=[$volume] dither=[$dither] server=[$serverip:$serverport]") ; |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
#Now we need to build the appropriate network packet |
|
296
|
3
|
|
|
|
|
18
|
my $packet = pack("CCCCC8", |
|
297
|
|
|
|
|
|
|
PROT_MAJORVER, |
|
298
|
|
|
|
|
|
|
PROT_MINORVER, |
|
299
|
|
|
|
|
|
|
PROT_CLIENTEVENT, |
|
300
|
|
|
|
|
|
|
0, |
|
301
|
|
|
|
|
|
|
$type, $sound, $location, $priority, $volume, $dither); |
|
302
|
|
|
|
|
|
|
|
|
303
|
3
|
50
|
|
|
|
109
|
if (not defined(CORE::send(SOCKET, $packet, 0, $server))) { |
|
304
|
0
|
|
|
|
|
0
|
$self->logger()->debug(7,"Error sending packet to [$serverip:$serverport]: $!"); |
|
305
|
0
|
|
|
|
|
0
|
$self->logger()->debug(7,"You may want to check that the server is accepting connections on port [$serverport]."); |
|
306
|
|
|
|
|
|
|
} |
|
307
|
|
|
|
|
|
|
|
|
308
|
3
|
|
|
|
|
26
|
return 1; |
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
} # end sub sendout |
|
311
|
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
sub setOption { |
|
313
|
|
|
|
|
|
|
|
|
314
|
18
|
|
|
18
|
0
|
24
|
my $self = shift; |
|
315
|
18
|
|
33
|
|
|
51
|
my $option = shift || confess "option not found"; |
|
316
|
18
|
|
|
|
|
21
|
my $value = shift; |
|
317
|
18
|
50
|
|
|
|
38
|
confess "value not found" unless defined $value; |
|
318
|
18
|
|
|
|
|
46
|
$self->{"__OPTIONS"}->{$option} = $value; |
|
319
|
18
|
|
|
|
|
38
|
return 1; |
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
} # end sub setOption |
|
322
|
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
sub getOption { |
|
324
|
|
|
|
|
|
|
|
|
325
|
3
|
|
|
3
|
0
|
6
|
my $self = shift; |
|
326
|
3
|
|
33
|
|
|
13
|
my $option = shift || confess "option not found"; |
|
327
|
|
|
|
|
|
|
|
|
328
|
3
|
50
|
|
|
|
22
|
if (exists $self->{"__OPTIONS"}->{$option}) { |
|
329
|
3
|
|
|
|
|
20
|
return $self->{"__OPTIONS"}->{$option}; |
|
330
|
|
|
|
|
|
|
} else { |
|
331
|
0
|
|
|
|
|
|
confess "Cannot get the option '$option': It has not yet been set."; |
|
332
|
|
|
|
|
|
|
} |
|
333
|
|
|
|
|
|
|
|
|
334
|
0
|
|
|
|
|
|
return 0; |
|
335
|
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
} # end sub setOption |
|
337
|
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
sub handlealarm { |
|
339
|
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
#Every tick, we wait until we have some input to respond to, then update |
|
341
|
|
|
|
|
|
|
#our server list. Finally, we purge the server list of any impurities and |
|
342
|
|
|
|
|
|
|
#carry on with out business |
|
343
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
|
344
|
0
|
|
|
|
|
|
my $constant = shift; |
|
345
|
|
|
|
|
|
|
|
|
346
|
0
|
|
|
|
|
|
$self->hello($constant); |
|
347
|
0
|
|
|
|
|
|
$self->updateserverlist(); |
|
348
|
0
|
|
|
|
|
|
$self->purgeserverlist(); |
|
349
|
|
|
|
|
|
|
|
|
350
|
0
|
0
|
|
|
|
|
if (scalar(keys %Servers)) { |
|
351
|
0
|
|
|
|
|
|
$self->logger()->debug(9,"Known servers:"); |
|
352
|
0
|
|
|
|
|
|
for my $server (sort keys %Servers) { |
|
353
|
0
|
|
|
|
|
|
my ($serverport,$serverip) = unpack_sockaddr_in($server); |
|
354
|
0
|
|
|
|
|
|
$serverip = inet_ntoa($serverip); |
|
355
|
0
|
|
|
|
|
|
$self->logger()->debug(9,"\t[$serverip:$serverport]"); |
|
356
|
|
|
|
|
|
|
} |
|
357
|
|
|
|
|
|
|
} else { |
|
358
|
0
|
|
|
|
|
|
$self->logger()->debug(9,"There are currently no known servers."); |
|
359
|
|
|
|
|
|
|
} |
|
360
|
|
|
|
|
|
|
|
|
361
|
0
|
|
|
|
|
|
return 1; |
|
362
|
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
} # end sub handlealarm |
|
364
|
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
sub updateserverlist { |
|
366
|
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
#Poll to see if we've received anything so we can update the server list |
|
368
|
|
|
|
|
|
|
#before we send. Then, send out the packet. |
|
369
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
|
370
|
|
|
|
|
|
|
|
|
371
|
0
|
|
|
|
|
|
$self->logger()->debug(9,"Updating server list ..."); |
|
372
|
|
|
|
|
|
|
|
|
373
|
0
|
|
|
|
|
|
my $rin = ""; |
|
374
|
0
|
|
|
|
|
|
my $rout; |
|
375
|
0
|
|
|
|
|
|
vec($rin, fileno(SOCKET), 1) = 1; |
|
376
|
|
|
|
|
|
|
|
|
377
|
0
|
0
|
|
|
|
|
if (select($rout = $rin, undef, undef, 0.1)) { |
|
378
|
0
|
|
|
|
|
|
my $packet; |
|
379
|
|
|
|
|
|
|
|
|
380
|
0
|
|
|
|
|
|
$self->logger()->debug(9,"\tReading from socket ..."); |
|
381
|
|
|
|
|
|
|
|
|
382
|
0
|
|
|
|
|
|
my $server = recv(SOCKET, $packet, 256, 0); # 256 is safe amount to read |
|
383
|
|
|
|
|
|
|
# Adding a defined argument here because recv can produce errors if |
|
384
|
|
|
|
|
|
|
# a broadcast isn't responded to. Plus, we want to continue anyway. |
|
385
|
0
|
0
|
0
|
|
|
|
if (defined($server) and $server ne '') { |
|
386
|
0
|
|
|
|
|
|
my ($serverport,$serverip) = unpack_sockaddr_in($server); |
|
387
|
0
|
|
|
|
|
|
$serverip = inet_ntoa($serverip); |
|
388
|
|
|
|
|
|
|
|
|
389
|
0
|
|
|
|
|
|
$self->logger()->debug(7,"\tJust received a packet from [$serverip:$serverport] ..."); |
|
390
|
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
#Verify that this is a server bc packet |
|
392
|
0
|
|
|
|
|
|
my ($majorver, $minorver, $type, $padding) = unpack("CCCC", $packet); |
|
393
|
|
|
|
|
|
|
|
|
394
|
0
|
0
|
|
|
|
|
$self->addnewserver($server, $packet) if $type == PROT_BCSERVER; |
|
395
|
0
|
0
|
|
|
|
|
$self->logger()->debug(7,"\tUpdating server with profile [$majorver:$minorver:$type]") if $type == PROT_SERVERSTILLALIVE; |
|
396
|
0
|
0
|
|
|
|
|
$self->updateserver($server, $packet) if $type == PROT_SERVERSTILLALIVE; |
|
397
|
|
|
|
|
|
|
} |
|
398
|
|
|
|
|
|
|
} |
|
399
|
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
} # end updateserverlist |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
sub purgeserverlist { |
|
403
|
|
|
|
|
|
|
|
|
404
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
|
405
|
|
|
|
|
|
|
|
|
406
|
0
|
|
|
|
|
|
$self->logger()->debug(9,"Purging server list ..."); |
|
407
|
|
|
|
|
|
|
|
|
408
|
0
|
|
|
|
|
|
for my $server (keys %Servers) { |
|
409
|
0
|
0
|
|
|
|
|
if ($Servers{$server}->{'expires'} <= time()) { |
|
410
|
0
|
|
|
|
|
|
delete $Servers{$server}; |
|
411
|
0
|
|
|
|
|
|
$self->logger()->debug(7,"\tServer purged. Number of known servers: " . scalar (keys %Servers)); |
|
412
|
|
|
|
|
|
|
|
|
413
|
0
|
|
|
|
|
|
for my $known (keys %Net::Peep::Servers) { |
|
414
|
0
|
|
|
|
|
|
my ($serverport,$serverip) = unpack_sockaddr_in($server); |
|
415
|
0
|
|
|
|
|
|
$serverip = inet_ntoa($serverip); |
|
416
|
0
|
|
|
|
|
|
$self->logger()->debug(7,"\t\t$serverip:$serverport"); |
|
417
|
|
|
|
|
|
|
} |
|
418
|
|
|
|
|
|
|
} |
|
419
|
|
|
|
|
|
|
} |
|
420
|
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
} # end sub purgeserverlist |
|
422
|
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
sub addnewserver { |
|
424
|
|
|
|
|
|
|
|
|
425
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
|
426
|
|
|
|
|
|
|
|
|
427
|
0
|
|
|
|
|
|
my ($server, $packet) = @_; |
|
428
|
|
|
|
|
|
|
|
|
429
|
0
|
|
|
|
|
|
my $configuration = $self->getConfiguration(); |
|
430
|
|
|
|
|
|
|
|
|
431
|
0
|
|
|
|
|
|
my ($serverport,$serverip) = unpack_sockaddr_in($server); |
|
432
|
|
|
|
|
|
|
|
|
433
|
0
|
|
|
|
|
|
$serverip = inet_ntoa($serverip); |
|
434
|
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
# Check if this server already exists - because then we shouldn't be |
|
436
|
|
|
|
|
|
|
# doing an add... so abort. This can happen because when the client |
|
437
|
|
|
|
|
|
|
# registers with the server, the server always sends a BC response |
|
438
|
|
|
|
|
|
|
# directly back to the client to make sure that the client really |
|
439
|
|
|
|
|
|
|
# has the server in its hostlist |
|
440
|
0
|
0
|
|
|
|
|
if (exists $Servers{$server}) { |
|
441
|
0
|
|
|
|
|
|
$self->logger()->debug(7,"\tServer [$serverip:$serverport] won't be added to the server list: It is already in the list."); |
|
442
|
0
|
|
|
|
|
|
return; |
|
443
|
|
|
|
|
|
|
} |
|
444
|
|
|
|
|
|
|
|
|
445
|
0
|
|
|
|
|
|
my ($majorver, $minorver, $type, $padding, $min, $sec, $id) = unpack("CCCCCCA128", $packet); |
|
446
|
0
|
|
|
|
|
|
my $delim = PROT_CLASSDELIM; |
|
447
|
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
#Clean up the ID string |
|
449
|
0
|
|
|
|
|
|
$id =~ /([A-Za-z0-9!\-]*)/; |
|
450
|
0
|
|
|
|
|
|
my $realid = $1; |
|
451
|
|
|
|
|
|
|
|
|
452
|
0
|
|
|
|
|
|
foreach my $class ($configuration->getClassList()) { |
|
453
|
0
|
|
|
|
|
|
my $str = quotemeta($class.$delim); |
|
454
|
0
|
|
|
|
|
|
$self->logger()->debug(7,"\tChecking server id [$realid] against class descriptor [$class$delim] ...."); |
|
455
|
|
|
|
|
|
|
|
|
456
|
0
|
0
|
|
|
|
|
if ($realid =~ /$str/) { |
|
457
|
0
|
|
|
|
|
|
$self->logger()->debug(7,"\tMatch found: Adding server [$serverip:$serverport] to the server list."); |
|
458
|
0
|
|
|
|
|
|
$self->addserver($server, $min, $sec); |
|
459
|
|
|
|
|
|
|
} else { |
|
460
|
0
|
|
|
|
|
|
$self->logger()->debug(7,"\tNo match found. Nothing added to server list."); |
|
461
|
|
|
|
|
|
|
} |
|
462
|
|
|
|
|
|
|
} |
|
463
|
|
|
|
|
|
|
|
|
464
|
0
|
|
|
|
|
|
return 1; |
|
465
|
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
} # end sub addnewserver |
|
467
|
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
sub addserver { |
|
469
|
|
|
|
|
|
|
|
|
470
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
|
471
|
0
|
|
|
|
|
|
my ($server,$leasemin,$leasesec) = @_; |
|
472
|
|
|
|
|
|
|
|
|
473
|
0
|
|
|
|
|
|
$Servers{$server}->{'IP'} = $server; |
|
474
|
0
|
|
|
|
|
|
$Servers{$server}->{'expires'} = time() + $leasemin*60 + $leasesec; |
|
475
|
|
|
|
|
|
|
|
|
476
|
0
|
|
|
|
|
|
$self->logger()->debug(7,"\tServer added. Number of known servers: " . scalar(keys %Servers)); |
|
477
|
0
|
|
|
|
|
|
for my $known (keys %Net::Peep::Servers) { |
|
478
|
0
|
|
|
|
|
|
my ($serverport,$serverip) = unpack_sockaddr_in($known); |
|
479
|
0
|
|
|
|
|
|
$serverip = inet_ntoa($serverip); |
|
480
|
0
|
|
|
|
|
|
$self->logger()->debug(7,"\t\t$serverip:$serverport"); |
|
481
|
|
|
|
|
|
|
} |
|
482
|
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
#Let's send it a "BC" to tell it to add us as well |
|
484
|
0
|
|
|
|
|
|
my ($serverport,$serverip) = unpack_sockaddr_in($server); |
|
485
|
0
|
|
|
|
|
|
$serverip = inet_ntoa($serverip); |
|
486
|
0
|
|
|
|
|
|
$self->logger()->debug(7,"\tSending client BC packet to [$serverip:$serverport] ..."); |
|
487
|
0
|
0
|
|
|
|
|
defined(CORE::send(SOCKET, $self->assemble_bc_packet(PROT_BCCLIENT), 0, $server)) or confess "Send clientbc error: $!"; |
|
488
|
0
|
|
|
|
|
|
$self->logger()->debug(7,"\tClient BC packet sent successfully."); |
|
489
|
|
|
|
|
|
|
|
|
490
|
0
|
|
|
|
|
|
return 1; |
|
491
|
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
} # end sub addserver |
|
493
|
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
sub updateserver { |
|
495
|
|
|
|
|
|
|
|
|
496
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
|
497
|
0
|
|
|
|
|
|
my $server = shift; |
|
498
|
0
|
|
|
|
|
|
my $packet = shift; |
|
499
|
0
|
|
|
|
|
|
my ($majorver, $minorver, $type, $padding, $min, $sec) = unpack("CCCCCC", $packet); |
|
500
|
|
|
|
|
|
|
|
|
501
|
0
|
|
|
|
|
|
$self->logger()->debug(7,"\tServer updated. Number of known servers: " . scalar(keys %Servers)); |
|
502
|
|
|
|
|
|
|
|
|
503
|
0
|
|
|
|
|
|
$Servers{$server}->{'expires'} = time() + $min*60 + $sec; |
|
504
|
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
# New send out a client alive |
|
506
|
0
|
|
|
|
|
|
my $net_packet = pack ("CCCC", |
|
507
|
|
|
|
|
|
|
PROT_MAJORVER, |
|
508
|
|
|
|
|
|
|
PROT_MINORVER, |
|
509
|
|
|
|
|
|
|
PROT_CLIENTSTILLALIVE, |
|
510
|
|
|
|
|
|
|
0); |
|
511
|
|
|
|
|
|
|
|
|
512
|
0
|
|
|
|
|
|
$self->logger()->debug(7,"\tSending client still alive packet ..."); |
|
513
|
0
|
0
|
|
|
|
|
defined(CORE::send(SOCKET, $net_packet, 0, $server)) or confess "Send client still alive error: $!"; |
|
514
|
0
|
|
|
|
|
|
$self->logger()->debug(7,"\tClient still alive packet sent successfully."); |
|
515
|
|
|
|
|
|
|
|
|
516
|
0
|
|
|
|
|
|
return 1; |
|
517
|
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
} # end sub updateserver |
|
519
|
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
1; |
|
521
|
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
__END__ |