File Coverage

blib/lib/Net/SNPP.pm
Criterion Covered Total %
statement 97 178 54.4
branch 29 110 26.3
condition 9 50 18.0
subroutine 30 61 49.1
pod 15 28 53.5
total 180 427 42.1


line stmt bran cond sub pod time code
1             # Net::SNPP.pm
2             #
3             # Copyright (c) 1995-2001 Graham Barr.
4             # Copyright (c) 2001 Derek J. Balling .
5             # All rights reserved. This program is free software; you can
6             # redistribute it and/or modify it under the same terms as Perl itself.
7             #
8              
9             package Net::SNPP;
10              
11             require 5.001;
12              
13 3     3   34293 use strict;
  3         7  
  3         174  
14 3     3   19 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  3         7  
  3         1781  
15 3     3   2847 use Socket 1.3;
  3         13132  
  3         3373  
16 3     3   31 use Carp;
  3         6  
  3         255  
17 3     3   3976 use IO::Socket;
  3         65178  
  3         15  
18 3     3   5648 use Net::Cmd;
  3         6562  
  3         267  
19 3     3   3177 use Net::Config;
  3         8456  
  3         10184  
20              
21             $VERSION = "1.17"; # $Id: SNPP.pm,v 1.9 2004/01/27 22:18:32 tobeya Exp $
22             @ISA = qw(Net::Cmd IO::Socket::INET);
23             @EXPORT = (qw(CMD_2WAYERROR CMD_2WAYOK CMD_2WAYQUEUED), @Net::Cmd::EXPORT);
24              
25             sub CMD_2WAYERROR () { 7 }
26             sub CMD_2WAYOK () { 8 }
27             sub CMD_2WAYQUEUED () { 9 }
28              
29             sub new
30             {
31 1     1 1 824 my $self = shift;
32 1   33     40 my $type = ref($self) || $self;
33 1 50       5 my $host = shift if @_ % 2;
34 1         23 my %arg = @_;
35 1 50       24 my $hosts = defined $host ? [ $host ] : $NetConfig{snpp_hosts};
36 1         8 my $obj;
37              
38             my $h;
39 1         5 foreach $h (@{$hosts})
  1         10  
40             {
41 1 50 50     119 $obj = $type->SUPER::new(PeerAddr => ($host = $h),
    50          
42             PeerPort => $arg{Port} || 'snpp(444)',
43             Proto => 'tcp',
44             Timeout => defined $arg{Timeout}
45             ? $arg{Timeout}
46             : 120
47             ) and last;
48             }
49              
50             return undef
51 1 50       10707 unless defined $obj;
52              
53 1         10 ${*$obj}{'net_snpp_host'} = $host;
  1         6  
54              
55 1         9 $obj->autoflush(1);
56              
57 1 50       102 $obj->debug(exists $arg{Debug} ? $arg{Debug} : undef);
58              
59 1 50       60 unless ($obj->response() == CMD_OK)
60             {
61 0         0 $obj->close();
62 0         0 return undef;
63             }
64              
65 1         78 $obj;
66             }
67              
68             ##
69             ## User interface methods
70             ##
71              
72             sub pager_id
73             {
74 1 50   1 0 449 @_ == 2 or croak 'usage: $snpp->pager_id( PAGER_ID )';
75 1         5 shift->_PAGE(@_);
76             }
77              
78             sub content
79             {
80 0 0   0 0 0 @_ == 2 or croak 'usage: $snpp->content( MESSAGE )';
81 0         0 shift->_MESS(@_);
82             }
83              
84             sub send
85             {
86 1     1 0 595 my $me = shift;
87              
88 1 50       6 if(@_)
89             {
90 1         13 my %arg = @_;
91              
92 1 50       5 if(exists $arg{Pager})
93             {
94 1 50       8 my $pagers = ref($arg{Pager}) ? $arg{Pager} : [ $arg{Pager} ];
95 1         2 my $pager;
96 1         10 foreach $pager (@$pagers)
97             {
98 1 50       5 $me->_PAGE($pager) || return 0
99             }
100             }
101 1 50 50     52 $me->_MESS($arg{Message}) || return 0
102             if(exists $arg{Message});
103              
104 1 50 50     34 $me->hold($arg{Hold}) || return 0
105             if(exists $arg{Hold});
106              
107 1 50 0     24 $me->hold($arg{HoldLocal},1) || return 0
108             if(exists $arg{HoldLocal});
109              
110 1 50 0     6 $me->_COVE($arg{Coverage}) || return 0
111             if(exists $arg{Coverage});
112              
113 1 50 50     10 $me->_ALER($arg{Alert} ? 1 : 0) || return 0
    50          
114             if(exists $arg{Alert});
115              
116 1 50 0     23 $me->service_level($arg{ServiceLevel}) || return 0
117             if(exists $arg{ServiceLevel});
118             }
119              
120 1         6 $me->_SEND();
121             }
122              
123             sub data
124             {
125 1     1 0 438 my $me = shift;
126              
127 1   33     5 my $ok = $me->_DATA() && $me->datasend(@_);
128              
129 1 50 33     215 return $ok
130             unless($ok && @_);
131              
132 1         31 $me->dataend;
133             }
134              
135             sub login
136             {
137 0 0 0 0 0 0 @_ == 2 || @_ == 3 or croak 'usage: $snpp->login( USER [, PASSWORD ])';
138 0         0 shift->_LOGI(@_);
139             }
140              
141             sub help
142             {
143 0 0   0 1 0 @_ == 1 or croak 'usage: $snpp->help()';
144 0         0 my $me = shift;
145              
146 0 0       0 return $me->_HELP() ? $me->message
147             : undef;
148             }
149              
150             sub xwho
151             {
152 0 0   0 0 0 @_ == 1 or croak 'usage: $snpp->xwho()';
153 0         0 my $me = shift;
154              
155 0 0       0 $me->_XWHO or return undef;
156              
157 0         0 my(%hash,$line);
158 0         0 my @msg = $me->message;
159 0         0 pop @msg; # Remove command complete line
160              
161 0         0 foreach $line (@msg) {
162 0 0       0 $line =~ /^\s*(\S+)\s*(.*)/ and $hash{$1} = $2;
163             }
164              
165 0         0 \%hash;
166             }
167              
168             sub service_level
169             {
170 0 0   0 0 0 @_ == 2 or croak 'usage: $snpp->service_level( LEVEL )';
171 0         0 my $me = shift;
172 0         0 my $level = int(shift);
173              
174 0 0 0     0 if($level < 0 || $level > 11)
175             {
176 0         0 $me->set_status(550,"Invalid Service Level");
177 0         0 return 0;
178             }
179              
180 0         0 $me->_LEVE($level);
181             }
182              
183             sub alert
184             {
185 0 0 0 0 0 0 @_ == 1 || @_ == 2 or croak 'usage: $snpp->alert( VALUE )';
186 0         0 my $me = shift;
187 0 0 0     0 my $value = (@_ == 1 || shift) ? 1 : 0;
188              
189 0         0 $me->_ALER($value);
190             }
191              
192             sub coverage
193             {
194 0 0   0 0 0 @_ == 1 or croak 'usage: $snpp->coverage( AREA )';
195 0         0 shift->_COVE(@_);
196             }
197              
198             sub hold
199             {
200 1 50 33 1 0 7 @_ == 2 || @_ == 3 or croak 'usage: $snpp->hold( TIME [, LOCAL ] )';
201 1         2 my $me = shift;
202 1         2 my $time = shift;
203 1 50       11 my $local = (shift) ? "" : " +0000";
204              
205 1         21 my @g = reverse((gmtime($time))[0..5]);
206 1         3 $g[1] += 1;
207 1         4 $g[0] %= 100;
208              
209 1         24 $me->_HOLD( sprintf("%02d%02d%02d%02d%02d%02d%s",@g,$local));
210             }
211              
212             sub caller_id
213             {
214 0 0   0 0 0 @_ == 2 or croak 'usage: $snpp->caller_id( CALLER_ID )';
215 0         0 shift->_CALL(@_);
216             }
217              
218             sub subject
219             {
220 0 0   0 0 0 @_ == 2 or croak 'usage: $snpp->subject( SUBJECT )';
221 0         0 shift->_SUBJ(@_);
222             }
223              
224             sub site
225             {
226 0 0   0 1 0 @_ == 2 or croak 'usage: $snpp->site( CMD )';
227 0         0 shift->_SITE(@_);
228             }
229              
230             sub two_way
231             {
232 1 50   1 0 642 @_ == 1 or croak 'usage: $snpp->two_way()';
233 1         5 shift->_2WAY();
234             }
235              
236             sub ping
237             {
238 1 50   1 1 5 @_ == 2 or croak 'usage: $snpp->ping( PAGER_ID )';
239 1         13 shift->_PING(@_);
240             }
241              
242             sub noqueue
243             {
244 0 0   0 1 0 @_ == 1 or croak 'usage: $snpp->noqueue()';
245 0         0 shift->_NOQU();
246             }
247              
248             sub expire_time
249             {
250 0 0   0 1 0 @_ == 2 or croak 'usage: $snpp->expire_time( HOURS )';
251 0         0 shift->_EXPT(@_);
252             }
253              
254             sub read_ack
255             {
256 0 0   0 1 0 @_ == 2 or croak 'usage: $snpp->read_ack( TRUEFALSE )';
257 0         0 shift->_ACKR(@_);
258             }
259              
260             # 4.6.7 MCREsponse <2-byte_Code> Response_Text
261             sub message_response
262             {
263 4 50   4 1 2062 @_ == 3 or croak 'usage: $snpp->message_response( INT, RESPONSE )';
264 4         14 shift->_MCRE(@_);
265             }
266              
267             # 4.6.10 MSTAtus
268             sub message_status
269             {
270 0 0   0 1 0 @_ == 3 or croak 'usage: $snpp->message_status( Message_Tag, Pass_Code )';
271 0         0 my $me = shift;
272 0         0 my @out = ();
273 0         0 my $resp = $me->command("MSTA", @_)->response();
274 0         0 $out[4] = $me->code();
275 0 0 0     0 if ($resp == CMD_2WAYQUEUED || $resp == CMD_2WAYOK || $resp == CMD_2WAYERROR)
      0        
276             {
277             # 860 Delivered, Awaiting Read Confirmation
278             # this regex doesn't count on every server putting the +/-GMT tag
279             # on the timestamp
280 0         0 my $msg = $me->message(); chomp( $msg );
  0         0  
281             #if ($msg =~ /^(\d+)\s+(\d+)(.*)\s+(.*)$/)
282 0 0       0 if ($msg =~ /^\s*(\d+)\s+(\d+)([+-]?\d*)\s+(.*)$/)
283             {
284 0         0 splice(@out, 0, 4, ($1,$2,$3,$4));
285             }
286             else
287             {
288 0         0 $me->debug_print( undef, "server reply for MCRE '$msg' did not match regex" );
289             }
290             }
291 0 0       0 return wantarray ? @out : \@out;
292             }
293              
294             # 4.6.9 SEND (Level 3)
295             sub send_two_way
296             {
297 0 0   0 1 0 @_ == 1 or croak 'usage: $snpp->send_two_way()';
298 0         0 my $me = shift;
299 0         0 my @out = ();
300 0         0 $out[3] = $me->command("SEND")->response();
301             # rfc1861 specifies that a 2way SEND can return 8xx or 9xx when successful
302             # i.e.
303             # 860 Delivered, Awaiting Read Ack
304             # 960 OK, Message QUEUED for Delivery
305 0 0 0     0 if ($out[3] == CMD_2WAYQUEUED || $out[3] == CMD_2WAYOK)
306             {
307 0         0 $me->message() =~ m/^(\d+)\s+(\d+)\s*(.*)$/;
308 0         0 splice(@out, 0, 3, ($1,$2,$3));
309             }
310 0 0       0 return wantarray ? @out : \@out;
311             }
312              
313             sub reset
314             {
315 1 50   1 1 672 @_ == 1 or croak 'usage: $snpp->reset()';
316 1         6 shift->_RESE();
317             }
318              
319             sub reply_type
320             {
321 0 0   0 1 0 @_ == 2 or croak 'usage: $snpp->reply_type( TYPE_CODE )';
322 0         0 shift->_RTYP(uc (@_));
323             }
324              
325             sub quit
326             {
327 1 50   1 1 290 @_ == 1 or croak 'usage: $snpp->quit()';
328 1         3 my $snpp = shift;
329              
330 1         5 $snpp->_QUIT;
331 1         45 $snpp->close;
332             }
333              
334              
335              
336             ##
337             ## IO/perl methods
338             ##
339              
340             sub DESTROY
341             {
342 1     1   433 my $snpp = shift;
343 1 50       7 defined(fileno($snpp)) && $snpp->quit;
344 1         2 delete ${*$snpp}{'net_snpp_host'};
  1         226  
345             }
346              
347             ##
348             ## Over-ride methods (Net::Cmd)
349             ##
350              
351             sub debug_text
352             {
353 0     0 1 0 $_[2] =~ s/^((logi|page)\s+\S+\s+)\S+/$1 xxxx/io;
354 0         0 $_[2];
355             }
356              
357             sub parse_response
358             {
359             return ()
360 17 50   17 1 54691 unless $_[1] =~ s/^(\d\d\d)(.?)//o;
361 17         83 my($code,$more) = ($1, $2 eq "-");
362              
363 17   33     90 $more ||= $code == 214;
364              
365 17         84 ($code,$more);
366             }
367              
368             ##
369             ## RFC1861 commands
370             ##
371              
372             # Level 1
373              
374 2     2   11 sub _PAGE { shift->command("PAGE", @_)->response() == CMD_OK }
375 1     1   15 sub _MESS { shift->command("MESS", @_)->response() == CMD_OK }
376 1     1   5 sub _RESE { shift->command("RESE")->response() == CMD_OK }
377             # level 3 SEND returns 8xx or 9xx for successful responses
378 1     1   4 sub _SEND { shift->command("SEND")->response() == CMD_OK }
379 1     1   4 sub _QUIT { shift->command("QUIT")->response() == CMD_OK }
380 0     0   0 sub _HELP { shift->command("HELP")->response() == CMD_OK }
381 1     1   5 sub _DATA { shift->command("DATA")->response() == CMD_MORE }
382 0     0   0 sub _SITE { shift->command("SITE",@_)->response() == CMD_OK }
383              
384             # Level 2
385              
386 0     0   0 sub _LOGI { shift->command("LOGI", @_)->response() == CMD_OK }
387 0     0   0 sub _LEVE { shift->command("LEVE", @_)->response() == CMD_OK }
388 1     1   5 sub _ALER { shift->command("ALER", @_)->response() == CMD_OK }
389 0     0   0 sub _COVE { shift->command("COVE", @_)->response() == CMD_OK }
390 1     1   5 sub _HOLD { shift->command("HOLD", @_)->response() == CMD_OK }
391 0     0   0 sub _CALL { shift->command("CALL", @_)->response() == CMD_OK }
392 0     0   0 sub _SUBJ { shift->command("SUBJ", @_)->response() == CMD_OK }
393              
394             # Level 3
395 1     1   6 sub _2WAY { shift->command("2WAY")->response() == CMD_OK }
396 1     1   53 sub _PING { shift->command("PING", @_)->response() == CMD_OK }
397 0     0   0 sub _ACKR { shift->command("ACKR", @_)->response() == CMD_OK }
398 0     0   0 sub _EXPT { shift->command("EXPT", @_)->response() == CMD_OK }
399 0     0   0 sub _KTAG { shift->command("KTAG", @_)->response() == CMD_OK }
400 4     4   19 sub _MCRE { shift->command("MCRE", @_)->response() == CMD_OK }
401             # MSTA here is not RFC compliant (returns 8xx or 9xx on success)
402 0     0     sub _MSTA { shift->command("MSTA", @_)->response() == CMD_OK }
403 0     0     sub _NOQU { shift->command("NOQU")->response() == CMD_OK }
404 0     0     sub _RTYP { shift->command("RTYP", @_)->response() == CMD_OK }
405              
406             # NonStandard
407              
408 0     0     sub _XWHO { shift->command("XWHO")->response() == CMD_OK }
409              
410             1;
411             __END__