File Coverage

blib/lib/Net/MSN/Base.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             # Net::MSN::Base - Base class used by Net::MSN and Net::MSN::SB.
2             # Originally written by:
3             # Adam Swann - http://www.adamswann.com/library/2002/msn-perl/
4             # Modified by:
5             # David Radunz - http://www.boxen.net/
6             #
7             # $Id: Base.pm,v 1.6 2003/07/09 16:51:50 david Exp $
8            
9             package Net::MSN::Base;
10            
11 1     1   5 use strict;
  1         1  
  1         25  
12 1     1   4 use warnings;
  1         2  
  1         21  
13            
14             BEGIN {
15             # Modules
16             # CPAN
17 1     1   865 use IO::Socket;
  1         277207  
  1         5  
18 1     1   148979 use IO::Select;
  1         1882  
  1         166  
19 1     1   1824 use Hash::Merge qw( merge );
  0            
  0            
20            
21             # Package specific
22             use Net::MSN::Debug;
23            
24             use vars qw($VERSION);
25            
26             $VERSION = do { my @r=(q$Revision: 1.6 $=~/\d+/g); sprintf "%d."."%03d"x$#r,@r };
27            
28             # construct global Select
29             $__PACKAGE__::Select = IO::Select->new();
30            
31             # construct global Socks
32             $__PACKAGE__::Socks = {};
33            
34             # Unique Transmission ID
35             $__PACKAGE__::TrID = -1;
36             }
37            
38             sub new {
39             my ($class, %args) = @_;
40            
41             my $self = bless({
42             'Version' => $VERSION,
43             'Debug' => 0,
44             'Debug_Lvl' => 0,
45             'Debug_Log' => '',
46             'Debug_STDERR' => 1,
47             'Debug_STDOUT' => 0,
48             'Debug_LogCaller' => 1,
49             'Debug_LogTime' => 1,
50             'Debug_LogLvl' => 1,
51             '_L' => '',
52             '_Log' => '',
53             '_Type' => 'NS'
54             }, ref($class) || $class);
55            
56             $self->set_options(\%args);
57             $self->_new_Log_obj();
58            
59             return $self;
60             }
61            
62             sub set_options {
63             my ($self, $opts) = @_;
64            
65             my %opts = %$opts;
66             foreach my $key (keys %opts) {
67             if (ref $opts{$key} eq 'HASH') {
68             $self->{$key} =
69             \%{ merge($opts{$key}, $self->{$key}) };
70             } else {
71             $self->{$key} = $opts{$key};
72             }
73             }
74             }
75            
76             sub _new_Log_obj {
77             my ($self) = @_;
78            
79             return if ((defined $self->{_L} && $self->{_L}) ||
80             (defined $self->{_Log} && $self->{_Log}));
81            
82             # Create a new Net::MSN::Debug object for debug
83             $self->{_L} = new Net::MSN::Debug(
84             'Debug' => $self->{Debug},
85             'Level' => $self->{Debug_Lvl},
86             'LogFile' => $self->{Debug_Log},
87             'STDERR' => $self->{Debug_STDERR},
88             'STDOUT' => $self->{Debug_STDOUT},
89             'LogCaller' => $self->{Debug_LogCaller},
90             'LogTime' => $self->{Debug_LogTime},
91             'LogLevel' => $self->{Debug_LogLvl}
92             );
93            
94             die "Unable to create L obj!\n"
95             unless (defined $self->{_L} && $self->{_L});
96            
97             $self->{_Log} = $self->{_L}->get_log_obj();
98            
99             die "Unable to create Log obj!\n"
100             unless (defined ($self->{_Log} && $self->{_Log}));
101             }
102            
103             sub merge_opts {
104             my ($self, $defaults, $args) = @_;
105            
106             return unless ((defined $defaults && ref $defaults eq 'HASH') ||
107             (defined $args && ref $args eq 'HASH'));
108            
109             my %opts = %$defaults;
110             foreach my $key (keys %$args) {
111             if (ref $args->{$key} eq 'HASH') {
112             $opts{$key} =
113             \%{ merge($args->{$key}, $defaults->{$key}) };
114             } else {
115             $opts{$key} = $args->{$key};
116             }
117             }
118            
119             return %opts;
120             }
121            
122             sub construct_socket {
123             my ($self) = @_;
124            
125             $self->{Socket} = $self->connect_socket(
126             $self->{_Host}, $self->{_Port}
127             );
128            
129             $__PACKAGE__::Select->add($self->{Socket});
130            
131             $__PACKAGE__::Socks->{$self->{Socket}->fileno} = \$self;
132             }
133            
134             sub remove_socket {
135             my ($self) = @_;
136            
137             if (defined $self->{Socket} && $self->{Socket}) {
138             my $fn = $self->{Socket}->fileno;
139             $__PACKAGE__::Select->remove($self->{Socket});
140             delete($__PACKAGE__::Socks->{$fn})
141             if (defined $fn && defined $__PACKAGE__::Socks->{$fn});
142            
143             if ($self->{_Type} eq 'SB') {
144             $self->{_Log}('Disconnected from Switch Board: '. $self->{_Host}. ':'.
145             $self->{_Port}. ' (Handle: '. $self->{Handle}.
146             ', Socket: '. $fn. ')', 2);
147             } else {
148             if (defined $self->{_LastHost} && defined $self->{_LastPort}) {
149             $self->{_Log}('Disconnected from Notification Server: '.
150             $self->{_LastHost}. ':'. $self->{_LastPort}.
151             ' (Socket: '. $fn. ')', 2);
152             undef($self->{_LastHost});
153             undef($self->{_LastPort});
154             } else {
155             $self->{_Log}('Disconnected from Notification Server: '.
156             $self->{_Host}. ':'. $self->{_Port}.
157             ' (Socket: '. $fn. ')', 2);
158             }
159             }
160            
161             return $fn;
162             } else {
163             $self->{_Log}('Cant Disconnect, no socket is open!', 1);
164             }
165             }
166            
167             sub disconnect_socket {
168             my ($self) = @_;
169            
170             if (defined $self->{Socket} && $self->{Socket}) {
171             $self->remove_socket();
172             $self->{Socket}->close();
173             }
174             }
175            
176             sub connect_socket {
177             my ($self, $host, $port) = @_;
178            
179             my $socket = IO::Socket::INET->new(
180             PeerAddr => $host,
181             PeerPort => $port,
182             Proto => 'tcp'
183             ) or die "$!";
184            
185             my $fn = $socket->fileno;
186            
187             if ($self->{_Type} eq 'SB') {
188             $self->{_Log}('Connected to Switch Board: '. $host. ':'.
189             $port. ' (Handle: '. $self->{Handle}. ', Socket: '. $fn. ')', 2);
190             } else {
191             $self->{_Log}('Connected to Notification Server: '. $host. ':'.
192             $port. ' (Socket: '. $fn. ')', 2);
193             }
194            
195             return $socket;
196             }
197            
198             sub cycle_socket {
199             my ($self, $host, $port) = @_;
200            
201             ($self->{_LastHost}, $self->{_LastPort}) =
202             ($self->{_Host}, $self->{_Port});
203             ($self->{_Host}, $self->{_Port}) = ($host, $port);
204            
205             $self->disconnect_socket();
206             $self->construct_socket();
207             }
208            
209             sub send {
210             my ($self, $cmd, $data) = @_;
211            
212             die "MSN->send: No command specified!\n"
213             unless (defined $cmd && $cmd);
214            
215             $cmd = (defined $cmd) ? $cmd : '';
216             $data = (defined $data) ? $data : '';
217            
218             my $datagram = $cmd. ' '. ++$__PACKAGE__::TrID. ' '. $data. "\r\n";
219            
220             $self->{Socket}->print($datagram);
221             chomp($datagram);
222            
223             my $fn = $self->{Socket}->fileno;
224            
225             $self->{_Log}('('. $fn. ')TX: '. $datagram, 3);
226            
227             return length($datagram);
228             }
229            
230             sub sendraw {
231             my ($self, $cmd, $data) = @_;
232            
233             die "MSN->send: No command specified!\n"
234             unless (defined $cmd && $cmd);
235            
236             $cmd = (defined $cmd) ? $cmd : '';
237             $data = (defined $data) ? $data : '';
238            
239             my $datagram = $cmd. ' '. ++$__PACKAGE__::TrID. ' '. $data;
240            
241             $self->{Socket}->print($datagram);
242             chomp($datagram);
243            
244             my $fn = $self->{Socket}->fileno;
245            
246             $self->{_Log}('('. $fn. ')TX: '. $datagram, 3);
247            
248             return length($datagram);
249             }
250            
251             sub sendnotrid {
252             my ($self, $cmd, $message) = @_;
253            
254             die "MSN->send: No command specified!\n"
255             unless (defined $cmd && $cmd);
256            
257             my $datagram = $cmd;
258             $datagram .= ' '. $message if (defined $message && $message);
259             $datagram .= "\r\n";
260            
261             $self->{Socket}->print($datagram);
262             chomp($datagram);
263            
264             my $fn = $self->{Socket}->fileno;
265            
266             $self->{_Log}('('. $fn. ')TX: '. $datagram, 3);
267            
268             return length($datagram);
269             }
270            
271             return 1;