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__ |