line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Net::TL1UDP; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
47142
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
22
|
|
4
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
20
|
|
5
|
1
|
|
|
1
|
|
466
|
use Socket; |
|
1
|
|
|
|
|
2584
|
|
|
1
|
|
|
|
|
331
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
BEGIN { |
8
|
1
|
|
|
1
|
|
6
|
require Exporter; |
9
|
|
|
|
|
|
|
# Set the version for version checking |
10
|
1
|
|
|
|
|
2
|
our $VERSION = 1.02; |
11
|
|
|
|
|
|
|
# Inherit from Exporter to export functions and variables |
12
|
1
|
|
|
|
|
16
|
our @ISA = qw(Exporter); |
13
|
|
|
|
|
|
|
# Functions and variables which are exported by default |
14
|
1
|
|
|
|
|
1043
|
our @EXPORT = qw( |
15
|
|
|
|
|
|
|
node_login |
16
|
|
|
|
|
|
|
tl1_cmd |
17
|
|
|
|
|
|
|
tl1_cmdf |
18
|
|
|
|
|
|
|
debug_file |
19
|
|
|
|
|
|
|
close_debug |
20
|
|
|
|
|
|
|
retrieve_sid |
21
|
|
|
|
|
|
|
retrieve_ctag |
22
|
|
|
|
|
|
|
command_timeout |
23
|
|
|
|
|
|
|
timeout_counter |
24
|
|
|
|
|
|
|
inhibit_messages |
25
|
|
|
|
|
|
|
sarb_retry_limit |
26
|
|
|
|
|
|
|
sarb_retry_delay |
27
|
|
|
|
|
|
|
logoff |
28
|
|
|
|
|
|
|
); |
29
|
|
|
|
|
|
|
} |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
my $currentCTAG = 0; # Initialise the current CTAG value |
32
|
|
|
|
|
|
|
my $sid = ''; # Initialise the SID value |
33
|
|
|
|
|
|
|
my $timeout = 60; # Initialise the response timeout value |
34
|
|
|
|
|
|
|
my $udpPort = 13001; # Initialise UDP port number |
35
|
|
|
|
|
|
|
my $debug = 0; # Initialise the debug status |
36
|
|
|
|
|
|
|
my $deviceIP = ''; # Initialise the device IP address |
37
|
|
|
|
|
|
|
my $to_counter = 0; # Initialise the timeout counter value |
38
|
|
|
|
|
|
|
my $inhibit_msgs = 1; # Initialise the inhibit messages status |
39
|
|
|
|
|
|
|
my $loginOK = 0; # Initialise the logged in state |
40
|
|
|
|
|
|
|
my $sarb_retries = 0; # Initialise the SARB retry limit |
41
|
|
|
|
|
|
|
my $sarb_delay = 0; # Initialise the SARB retry delay value |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
# Function to configure the debug file |
44
|
0
|
|
|
|
|
|
sub debug_file { |
45
|
0
|
|
|
0
|
1
|
|
my $filename = shift; |
46
|
0
|
0
|
|
|
|
|
open (DEBUG, ">$filename") or die "File Error: $!"; |
47
|
0
|
|
|
|
|
|
$debug = 1; |
48
|
1
|
50
|
|
1
|
|
22
|
END { close (DEBUG) if (defined (fileno (DEBUG))); } |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# Function to close the debug file before the script completes |
52
|
|
|
|
|
|
|
sub close_debug { |
53
|
0
|
|
|
0
|
1
|
|
$debug = 0; |
54
|
0
|
0
|
|
|
|
|
close (DEBUG) if (defined (fileno (DEBUG))); |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
# Function to retrieve the SID |
58
|
0
|
|
|
0
|
1
|
|
sub retrieve_sid { return $sid; } |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
# Function to return the current CTAG value |
61
|
0
|
|
|
0
|
1
|
|
sub retrieve_ctag { return $currentCTAG; } |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
# Function to retrieve or set the timeout value |
64
|
|
|
|
|
|
|
sub command_timeout { |
65
|
|
|
|
|
|
|
# If a value has been provided, set the timeout variable |
66
|
0
|
0
|
0
|
0
|
1
|
|
$timeout = $_[0] if (scalar(@_) == 1 && $_[0] =~ /^\d+$/ && $_[0] > 0); |
|
|
|
0
|
|
|
|
|
67
|
0
|
|
|
|
|
|
return $timeout; |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
# Function to retrieve or set the timeout counter value |
71
|
|
|
|
|
|
|
sub timeout_counter { |
72
|
|
|
|
|
|
|
# If a value has been provided, set the counter variable |
73
|
0
|
0
|
0
|
0
|
1
|
|
$to_counter = $_[0] if (scalar(@_) == 1 && $_[0] =~ /^\d+$/ && $_[0] >= 0); |
|
|
|
0
|
|
|
|
|
74
|
0
|
|
|
|
|
|
return $to_counter; |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# Function to retrieve or set the SARB retry limit value |
78
|
|
|
|
|
|
|
sub sarb_retry_limit { |
79
|
|
|
|
|
|
|
# If a value has been provided, set the limit variable |
80
|
0
|
0
|
0
|
0
|
1
|
|
$sarb_retries = $_[0] if (scalar(@_) == 1 && $_[0] =~ /^\d+$/); |
81
|
0
|
|
|
|
|
|
return $sarb_retries; |
82
|
|
|
|
|
|
|
} |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
# Function to retrieve or set the SARB retry delay value |
85
|
|
|
|
|
|
|
sub sarb_retry_delay { |
86
|
|
|
|
|
|
|
# If a value has been provided, set the retry variable |
87
|
0
|
0
|
0
|
0
|
1
|
|
$sarb_delay = $_[0] if (scalar(@_) == 1 && $_[0] =~ /^\d+$/); |
88
|
0
|
|
|
|
|
|
return $sarb_delay; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
# Function to retrieve or set the inhibit messages value |
92
|
|
|
|
|
|
|
sub inhibit_messages { |
93
|
|
|
|
|
|
|
# If a value has been provided, set the inhibit messages value and, |
94
|
|
|
|
|
|
|
# if logged into the node, send the allow or inhibit messages command |
95
|
0
|
0
|
0
|
0
|
1
|
|
if (scalar(@_) == 1 && $_[0] =~ /^[01]$/) { |
96
|
0
|
|
|
|
|
|
$inhibit_msgs = $_[0]; |
97
|
0
|
0
|
|
|
|
|
if ($loginOK) { |
98
|
0
|
0
|
|
|
|
|
&tl1_cmd("INH-MSG-ALL::ALL;") if ($inhibit_msgs == 1); |
99
|
0
|
0
|
|
|
|
|
&tl1_cmd("ALW-MSG-ALL::ALL;") if ($inhibit_msgs == 0); |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
} |
102
|
0
|
|
|
|
|
|
return $inhibit_msgs; |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# Function to log into the device |
106
|
|
|
|
|
|
|
sub node_login { |
107
|
0
|
0
|
0
|
0
|
1
|
|
if (scalar(@_) == 3 && $_[0] =~ /^\w\S+[:]?\d*$/) { |
108
|
0
|
|
|
|
|
|
my ($deviceInfo, $username, $password) = @_; |
109
|
0
|
0
|
|
|
|
|
if ($deviceInfo =~ /:/) { ($deviceIP, $udpPort) = split (/:/, $deviceInfo); } |
|
0
|
|
|
|
|
|
|
110
|
0
|
|
|
|
|
|
else { $deviceIP = $deviceInfo; } |
111
|
0
|
|
|
|
|
|
my $login = &tl1_cmd("ACT-USER::${username}:::${password};"); |
112
|
0
|
0
|
0
|
|
|
|
if ($login && $login =~ /Logged On/i) { |
113
|
0
|
0
|
|
|
|
|
if ($login =~ /\s+\w+\s+\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d/) { |
114
|
0
|
|
|
|
|
|
($sid) = $login =~ /\s+(\w+)\s\d\d-\d\d-\d\d\s\d\d:\d\d:\d\d/; |
115
|
0
|
0
|
|
|
|
|
&tl1_cmd("INH-MSG-ALL::ALL;") if ($inhibit_msgs); |
116
|
|
|
|
|
|
|
} |
117
|
0
|
|
|
|
|
|
$loginOK = 1; |
118
|
|
|
|
|
|
|
} |
119
|
0
|
|
|
|
|
|
else { &tl1_cmd("LOGOFF"); } |
120
|
|
|
|
|
|
|
} |
121
|
0
|
|
|
|
|
|
return $loginOK; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
# Function to log off of the device |
125
|
|
|
|
|
|
|
sub logoff { |
126
|
0
|
0
|
|
0
|
1
|
|
&tl1_cmd("ALW-MSG-ALL::ALL;") if ($inhibit_msgs); |
127
|
0
|
|
|
|
|
|
&tl1_cmd("LOGOFF"); |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
# Function to send a command to, and receive the data from, the socket |
131
|
|
|
|
|
|
|
sub tl1_cmd { |
132
|
0
|
0
|
|
0
|
1
|
|
if ($deviceIP) { |
133
|
|
|
|
|
|
|
# Get the command string |
134
|
0
|
|
|
|
|
|
my $command_string = shift; |
135
|
|
|
|
|
|
|
# Remove the semicolon at the end of the command if it exists |
136
|
0
|
0
|
|
|
|
|
chop $command_string if (substr($command_string, -1) eq ';'); |
137
|
|
|
|
|
|
|
# Assign the command to an array |
138
|
0
|
|
|
|
|
|
my @command = split(/:/, $command_string); |
139
|
|
|
|
|
|
|
# Ensure the array contains at least four elements |
140
|
0
|
|
|
|
|
|
push (@command, '') while (scalar(@command) < 4); |
141
|
|
|
|
|
|
|
# Initialise the SARB retry variable |
142
|
0
|
|
|
|
|
|
my $retries_remaining = $sarb_retries + 1; |
143
|
0
|
|
|
|
|
|
while ($retries_remaining) { |
144
|
|
|
|
|
|
|
# Increment the CTAG value |
145
|
0
|
|
|
|
|
|
$currentCTAG++; |
146
|
|
|
|
|
|
|
# Replace/add the current CTAG in/to the TL-1 command |
147
|
0
|
|
|
|
|
|
$command[3] = $currentCTAG; |
148
|
0
|
|
|
|
|
|
$command_string = join(':', @command); |
149
|
|
|
|
|
|
|
# Add a semicolon to the end of the command |
150
|
0
|
|
|
|
|
|
$command_string .= ';'; |
151
|
|
|
|
|
|
|
# Initialise data |
152
|
0
|
|
|
|
|
|
my $data = ''; my $msg = ''; |
|
0
|
|
|
|
|
|
|
153
|
0
|
|
|
|
|
|
my $packed_ip = inet_aton($deviceIP); |
154
|
|
|
|
|
|
|
# Print the Shelf IP and the TL-1 command in the debug file |
155
|
0
|
0
|
|
|
|
|
print DEBUG "\n\n>>>>> DEVICE = $deviceIP\tCOMMAND = $command_string <<<<<\n\n" if ($debug); |
156
|
0
|
|
|
|
|
|
send(TL1SOCKET, $command_string, 0, sockaddr_in($udpPort, $packed_ip)); |
157
|
0
|
|
|
|
|
|
eval { |
158
|
|
|
|
|
|
|
# Capture alarm signal (to detect timeout) |
159
|
0
|
|
|
0
|
|
|
local $SIG{ALRM} = sub { die "timed_out\n" }; |
|
0
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
# If the shelf does not respond in timeout secs, break out of the loop |
161
|
0
|
|
|
|
|
|
alarm ($timeout); |
162
|
|
|
|
|
|
|
# 5000 is the MAXIMUM data size |
163
|
0
|
|
|
|
|
|
while (my $src = recv(TL1SOCKET, $msg, 5000, 0)) { |
164
|
0
|
|
|
|
|
|
my ($srcPort, $srcAddr) = sockaddr_in($src); |
165
|
|
|
|
|
|
|
# Print ALL received data in the debug file |
166
|
0
|
0
|
|
|
|
|
print DEBUG $msg if ($debug); |
167
|
|
|
|
|
|
|
# Only add data from correct IP address and port to $data |
168
|
0
|
0
|
0
|
|
|
|
if ($srcAddr eq $packed_ip && $srcPort == $udpPort) { |
169
|
0
|
|
|
|
|
|
$data .= $msg; |
170
|
|
|
|
|
|
|
# Break from the loop when a proper response and a ";" |
171
|
|
|
|
|
|
|
# (on a line by itself) is received |
172
|
0
|
0
|
|
|
|
|
if ($msg =~ /^;$/m) { |
173
|
0
|
0
|
|
|
|
|
if ($data =~ /$currentCTAG (COMPLD|DENY).+;/s) { last; } |
|
0
|
|
|
|
|
|
|
174
|
0
|
|
|
|
|
|
else { $data = ""; } |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
# Reset the alarm signal |
177
|
0
|
|
|
|
|
|
alarm ($timeout); |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
# Flag unsolicited responses in the debug file (info only) |
180
|
0
|
0
|
|
|
|
|
else { print DEBUG "\n --- Unsolicited Response ---\n" if ($debug); } |
181
|
|
|
|
|
|
|
} |
182
|
0
|
|
|
|
|
|
alarm (0); |
183
|
|
|
|
|
|
|
}; |
184
|
|
|
|
|
|
|
# If the timeout expired waiting for a response |
185
|
0
|
0
|
|
|
|
|
if ($@) { |
|
|
0
|
|
|
|
|
|
186
|
0
|
0
|
|
|
|
|
print DEBUG "\n\n***** Timeout expired *****\n" if ($debug); |
187
|
|
|
|
|
|
|
# Increment the timeout counter |
188
|
0
|
|
|
|
|
|
$to_counter++; |
189
|
|
|
|
|
|
|
# Set the retries to 0 |
190
|
0
|
|
|
|
|
|
$retries_remaining = 0; |
191
|
|
|
|
|
|
|
# Return 0 |
192
|
0
|
|
|
|
|
|
return 0; |
193
|
|
|
|
|
|
|
} |
194
|
|
|
|
|
|
|
# Else if there was a "Status, All Resources Busy" response |
195
|
|
|
|
|
|
|
elsif ($data =~ /DENY.+SARB/s) { |
196
|
|
|
|
|
|
|
# Decrement the remaining retries counter |
197
|
0
|
|
|
|
|
|
$retries_remaining--; |
198
|
|
|
|
|
|
|
# If the retry limit has not been reached, flag it in the debug file |
199
|
|
|
|
|
|
|
# and, if there is retry delay, sleep for that time period |
200
|
0
|
0
|
|
|
|
|
if ($retries_remaining) { |
201
|
0
|
0
|
|
|
|
|
print DEBUG "\n\n***** SARB Retry - $retries_remaining remaining (waiting $sarb_delay seconds) *****\n" if ($debug); |
202
|
0
|
0
|
|
|
|
|
sleep ($sarb_delay) if ($sarb_delay); |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
# Otherwise return the data |
205
|
|
|
|
|
|
|
else { |
206
|
0
|
|
|
|
|
|
return $data; |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
# Otherwise, set the retries to 0 and return the data |
210
|
|
|
|
|
|
|
else { |
211
|
0
|
|
|
|
|
|
$retries_remaining = 0; |
212
|
0
|
|
|
|
|
|
return $data; |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
} |
216
|
0
|
|
|
|
|
|
else { return 0; } |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
# Function to send a command to, and receive formatted data from, the socket |
220
|
|
|
|
|
|
|
sub tl1_cmdf { |
221
|
0
|
|
|
0
|
1
|
|
my $raw_data = &tl1_cmd(shift); |
222
|
0
|
0
|
|
|
|
|
if ($raw_data) { |
223
|
0
|
0
|
|
|
|
|
if ($raw_data =~ / $currentCTAG DENY.+;/s) { |
224
|
0
|
|
|
|
|
|
return $raw_data; |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
else { |
227
|
0
|
|
|
|
|
|
my @records = $raw_data =~ /\s+["](.+?[^\\])["]/sg; |
228
|
0
|
|
|
|
|
|
for (my $i = 0; $i < scalar(@records); $i++) { |
229
|
|
|
|
|
|
|
# Remove two or more spaces |
230
|
0
|
|
|
|
|
|
$records[$i] =~ s/\s{2,}//g; |
231
|
|
|
|
|
|
|
} |
232
|
0
|
0
|
|
|
|
|
if (scalar(@records)) { return join ("\n", @records); } |
|
0
|
|
|
|
|
|
|
233
|
0
|
|
|
|
|
|
else { return "COMPLD"; } |
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
} |
236
|
0
|
|
|
|
|
|
else { return 0; } |
237
|
|
|
|
|
|
|
} |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
# Create a UDP socket (TL1SOCKET) to communicate with the device |
240
|
|
|
|
|
|
|
socket(TL1SOCKET, PF_INET, SOCK_DGRAM, getprotobyname("udp")) |
241
|
|
|
|
|
|
|
or die "Socket Error: $!"; |
242
|
|
|
|
|
|
|
|
243
|
1
|
|
|
1
|
|
1096
|
END { close (TL1SOCKET); } |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
1; |
246
|
|
|
|
|
|
|
__END__ |