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