File Coverage

blib/lib/AnyEvent/IRC/Connection.pm
Criterion Covered Total %
statement 27 77 35.0
branch 0 14 0.0
condition 0 3 0.0
subroutine 9 21 42.8
pod 8 8 100.0
total 44 123 35.7


line stmt bran cond sub pod time code
1             package AnyEvent::IRC::Connection;
2 1     1   1644 use common::sense;
  1         3  
  1         8  
3 1     1   50 use AnyEvent;
  1         2  
  1         20  
4 1     1   1062 use POSIX;
  1         8049  
  1         8  
5 1     1   5899 use AnyEvent::Socket;
  1         54403  
  1         165  
6 1     1   1865 use AnyEvent::Handle;
  1         11816  
  1         50  
7 1     1   15 use AnyEvent::IRC::Util qw/mk_msg parse_irc_msg/;
  1         4  
  1         483  
8 1     1   1398 use Object::Event;
  1         9132  
  1         51  
9 1     1   14 use Scalar::Util qw/weaken/;
  1         2  
  1         130  
10              
11 1     1   6 use base Object::Event::;
  1         2  
  1         1434  
12              
13             =head1 NAME
14              
15             AnyEvent::IRC::Connection - An IRC connection abstraction
16              
17             =head1 SYNOPSIS
18              
19             use AnyEvent;
20             use AnyEvent::IRC::Connection;
21              
22             my $c = AnyEvent->condvar;
23              
24             my $con = new AnyEvent::IRC::Connection;
25              
26             $con->connect ("localhost", 6667);
27              
28             $con->reg_cb (
29             connect => sub {
30             my ($con) = @_;
31             $con->send_msg (NICK => 'testbot');
32             $con->send_msg (USER => 'testbot', '*', '0', 'testbot');
33             },
34             irc_001 => sub {
35             my ($con) = @_;
36             print "$_[1]->{prefix} says I'm in the IRC: $_[1]->{params}->[-1]!\n";
37             $c->broadcast;
38             }
39             );
40              
41             $c->wait;
42              
43             =head1 DESCRIPTION
44              
45             The connection class. Here the actual interesting stuff can be done,
46             such as sending and receiving IRC messages. And it also handles
47             TCP connecting and even enabling of TLS.
48              
49             Please note that CTCP support is available through the functions
50             C<encode_ctcp> and C<decode_ctcp> provided by L<AnyEvent::IRC::Util>.
51              
52             =head2 METHODS
53              
54             =over 4
55              
56             =item $con = AnyEvent::IRC::Connection->new ()
57              
58             This constructor doesn't take any arguments.
59              
60             B<NOTE:> You are free to use the hash member C<heap> (which contains a hash) to
61             store any associated data with this object. For example retry timers or
62             anything else.
63              
64             You can also access that member via the C<heap> method.
65              
66             =cut
67              
68             sub new {
69 0     0 1   my $this = shift;
70 0   0       my $class = ref($this) || $this;
71              
72 0           my $self = $class->SUPER::new (@_, heap => { });
73              
74 0           bless $self, $class;
75              
76             $self->reg_cb (
77             ext_after_send => sub {
78 0     0     my ($self, $mkmsg_args) = @_;
79 0           $self->send_raw (mk_msg (@$mkmsg_args));
80             }
81 0           );
82              
83 0           return $self;
84             }
85              
86             =item $con->connect ($host, $port [, $prepcb_or_timeout])
87              
88             Tries to open a socket to the host C<$host> and the port C<$port>.
89             If an error occurred it will die (use eval to catch the exception).
90              
91             If you want to connect via TLS/SSL you have to call the C<enable_ssl>
92             method before to enable it.
93              
94             C<$prepcb_or_timeout> can either be a callback with the semantics of a prepare
95             callback for the function C<tcp_connect> in L<AnyEvent::Socket> or a simple
96             number which stands for a timeout.
97              
98             =cut
99              
100             sub connect {
101 0     0 1   my ($self, $host, $port, $prep) = @_;
102              
103 0 0         if ($self->{socket}) {
104 0           $self->disconnect ("reconnect requested.");
105             }
106              
107             $self->{con_guard} =
108             tcp_connect $host, $port, sub {
109 0     0     my ($fh) = @_;
110              
111 0           delete $self->{socket};
112              
113 0 0         unless ($fh) {
114 0           $self->event (connect => $!);
115 0           return;
116             }
117              
118 0           $self->{host} = $host;
119 0           $self->{port} = $port;
120              
121             $self->{socket} =
122             AnyEvent::Handle->new (
123             fh => $fh,
124             ($self->{enable_ssl} ? (tls => 'connect') : ()),
125             on_eof => sub {
126 0           $self->disconnect ("EOF from server $host:$port");
127             },
128             on_error => sub {
129 0           $self->disconnect ("error in connection to server $host:$port: $!");
130             },
131             on_read => sub {
132 0           my ($hdl) = @_;
133             # \015* for some broken servers, which might have an extra
134             # carriage return in their MOTD.
135             $hdl->push_read (line => qr{\015*\012}, sub {
136 0           $self->_feed_irc_data ($_[1]);
137 0           });
138             },
139             on_drain => sub {
140 0           $self->event ('buffer_empty');
141             }
142 0 0         );
143              
144 0           $self->{connected} = 1;
145 0           $self->event ('connect');
146 0 0   0     }, (defined $prep ? (ref $prep ? $prep : sub { $prep }) : ());
  0 0          
147             }
148              
149             =item $con->enable_ssl ()
150              
151             This method will enable SSL for new connections that are initiated by C<connect>.
152              
153             =cut
154              
155             sub enable_ssl {
156 0     0 1   my ($self) = @_;
157 0           $self->{enable_ssl} = 1;
158             }
159              
160             =item $con->disconnect ($reason)
161              
162             Unregisters the connection in the main AnyEvent::IRC object, closes
163             the sockets and send a 'disconnect' event with C<$reason> as argument.
164              
165             =cut
166              
167             sub disconnect {
168 0     0 1   my ($self, $reason) = @_;
169              
170 0           delete $self->{con_guard};
171 0           delete $self->{socket};
172 0           $self->event (disconnect => $reason);
173             }
174              
175             =item $con->is_connected
176              
177             Returns true when this connection is connected.
178             Otherwise false.
179              
180             =cut
181              
182             sub is_connected {
183 0     0 1   my ($self) = @_;
184 0 0         $self->{socket} && $self->{connected}
185             }
186              
187             =item $con->heap ()
188              
189             Returns the hash reference stored in the C<heap> member, that is local to this
190             connection object that lets you store any information you want.
191              
192             =cut
193              
194             sub heap {
195 0     0 1   my ($self) = @_;
196 0           return $self->{heap};
197             }
198              
199             =item $con->send_raw ($ircline)
200              
201             This method sends C<$ircline> straight to the server without any
202             further processing done.
203              
204             =cut
205              
206             sub send_raw {
207 0     0 1   my ($self, $ircline) = @_;
208              
209 0 0         return unless $self->{socket};
210 0           $self->{socket}->push_write ($ircline . "\015\012");
211             }
212              
213             =item $con->send_msg ($command, @params)
214              
215             This function sends a message to the server. C<@ircmsg> is the argument list
216             for C<AnyEvent::IRC::Util::mk_msg (undef, $command, @params)>.
217              
218             =cut
219              
220             sub send_msg {
221 0     0 1   my ($self, @msg) = @_;
222              
223 0           $self->event (send => [undef, @msg]);
224 0           $self->event (sent => undef, @msg);
225             }
226              
227             sub _feed_irc_data {
228 0     0     my ($self, $line) = @_;
229              
230             #d# warn "LINE:[" . $line . "][".length ($line)."]";
231              
232 0           my $m = parse_irc_msg ($line);
233             #d# warn "MESSAGE{$m->{params}->[-1]}[".(length $m->{params}->[-1])."]\n";
234             #d# warn "HEX:" . join ('', map { sprintf "%2.2x", ord ($_) } split //, $line)
235             #d# . "\n";
236              
237 0           $self->event (read => $m);
238 0           $self->event ('irc_*' => $m);
239 0           $self->event ('irc_' . (lc $m->{command}), $m);
240             }
241              
242             =back
243              
244             =head2 EVENTS
245              
246             Following events are emitted by this module and shouldn't be emitted
247             from a module user call to C<event>. See also the documents L<Object::Event> about
248             registering event callbacks.
249              
250             =over 4
251              
252             =item connect => $error
253              
254             This event is generated when the socket was successfully connected
255             or an error occurred while connecting. The error is given as second
256             argument (C<$error>) to the callback then.
257              
258             =item disconnect => $reason
259              
260             This event will be generated if the connection is somehow terminated.
261             It will also be emitted when C<disconnect> is called.
262             The second argument to the callback is C<$reason>, a string that contains
263             a clue about why the connection terminated.
264              
265             If you want to reestablish a connection, call C<connect> again.
266              
267             =item send => $ircmsg
268              
269             Emitted when a message is about to be sent. C<$ircmsg> is an array reference
270             to the arguments of C<mk_msg> (see L<AnyEvent::IRC::Util>). You
271             may modify the array reference to change the message or even intercept it
272             completely by calling C<stop_event> (see L<Object::Event> API):
273              
274             $con->reg_cb (
275             send => sub {
276             my ($con, $ircmsg) = @_;
277              
278             if ($ircmsg->[1] eq 'NOTICE') {
279             $con->stop_event; # prevent any notices from being sent.
280              
281             } elsif ($ircmsg->[1] eq 'PRIVMSG') {
282             $ircmsg->[-1] =~ s/sex/XXX/i; # censor any outgoing private messages.
283             }
284             }
285             );
286              
287             =item sent => @ircmsg
288              
289             Emitted when a message (C<@ircmsg>) was sent to the server.
290             C<@ircmsg> are the arguments to C<AnyEvent::IRC::Util::mk_msg>.
291              
292             =item irc_* => $msg
293              
294             =item irc_<lowercase command> => $msg
295              
296             =item read => $msg
297              
298             Emitted when a message (C<$msg>) was read from the server.
299             C<$msg> is the hash reference returned by C<AnyEvent::IRC::Util::parse_irc_msg>;
300              
301             Note: '<lowercase command>' stands for the command of the message in
302             (ASCII) lower case.
303              
304             =item buffer_empty
305              
306             This event is emitted when the write buffer of the underlying connection
307             is empty and all data has been given to the kernel. See also C<samples/notify>
308             about a usage example.
309              
310             Please note that this buffer is NOT the queue mentioned in L<AnyEvent::IRC::Client>!
311              
312             =back
313              
314             =head1 AUTHOR
315              
316             Robin Redeker, C<< <elmex@ta-sa.org> >>
317              
318             =head1 SEE ALSO
319              
320             L<AnyEvent::IRC>
321              
322             L<AnyEvent::IRC::Client>
323              
324             =head1 COPYRIGHT & LICENSE
325              
326             Copyright 2006-2009 Robin Redeker, all rights reserved.
327              
328             This program is free software; you can redistribute it and/or modify it
329             under the same terms as Perl itself.
330              
331             =cut
332              
333             1;