ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/Socket.pm
Revision: 1.5
Committed: Mon Apr 28 09:27:47 2008 UTC (16 years, 2 months ago) by elmex
Branch: MAIN
CVS Tags: rel-3_41, rel-3_4
Changes since 1.4: +1 -1 lines
Log Message:
disabled warnings

File Contents

# Content
1 package AnyEvent::Socket;
2
3 no warnings;
4 use strict;
5
6 use Carp;
7 use Errno qw/ENXIO ETIMEDOUT/;
8 use Socket;
9 use IO::Socket::INET;
10 use AnyEvent;
11 use AnyEvent::Util;
12 use AnyEvent::Handle;
13
14 our @ISA = qw/AnyEvent::Handle/;
15
16 =head1 NAME
17
18 AnyEvent::Socket - Connecting sockets for non-blocking I/O
19
20 =head1 SYNOPSIS
21
22 use AnyEvent;
23 use AnyEvent::Socket;
24
25 my $cv = AnyEvent->condvar;
26
27 my $ae_sock =
28 AnyEvent::Socket->new (
29 PeerAddr => "www.google.de:80",
30 on_eof => sub { $cv->broadcast },
31 on_connect => sub {
32 my ($ae_sock, $error) = @_;
33 if ($error) {
34 warn "couldn't connect: $!";
35 return;
36 } else {
37 print "connected to ".$ae_sock->fh->peerhost.":".$ae_sock->fh->peerport."\n";
38 }
39
40 $ae_sock->on_read (sub {
41 my ($ae_sock) = @_;
42 print "got data: [".${$ae_sock->rbuf}."]\n";
43 $ae_sock->rbuf = '';
44 });
45
46 $ae_sock->write ("GET / HTTP/1.0\015\012\015\012");
47 }
48 );
49
50 $cv->wait;
51
52 =head1 DESCRIPTION
53
54 L<AnyEvent::Socket> provides method to connect sockets and accept clients
55 on listening sockets.
56
57 =head1 EXAMPLES
58
59 See the C<eg/> directory of the L<AnyEvent> distribution for examples and also
60 the tests in C<t/handle/> can be helpful.
61
62 =head1 METHODS
63
64 =over 4
65
66 =item B<new (%args)>
67
68 The constructor gets the same arguments as the L<IO::Socket::INET> constructor.
69 Except that blocking will always be disabled and the hostname lookup is done by
70 L<AnyEvent::Util::inet_aton> before the socket (currently a L<IO::Socket::INET> instance)
71 is created.
72
73 Additionally you can set the callbacks that can be set in the L<AnyEvent::Handle>
74 constructor and these:
75
76 =over 4
77
78 =item on_connect => $cb
79
80 Installs a connect callback, that will be called when the name was successfully
81 resolved and the connection was successfully established or an error occured in
82 the lookup or connect.
83
84 The first argument to the callback C<$cb> will be the L<AnyEvent::Socket> itself
85 and the second is either a true value in case an error occured or undef.
86 The variable C<$!> will be set to one of these values:
87
88 =over 4
89
90 =item ENXIO
91
92 When the DNS lookup failed.
93
94 =item ETIMEDOUT
95
96 When the connect timed out.
97
98 =item *
99
100 Or any other errno as set by L<IO::Socket::INET> when it's constructor
101 failed or the connection couldn't be established for any other reason.
102
103 =back
104
105 =item on_accept
106
107 This sets the C<on_accept> callback by calling the C<on_accept> method.
108 See also below.
109
110 =back
111
112 =cut
113
114 sub new {
115 my $this = shift;
116 my $class = ref($this) || $this;
117 my %args = @_;
118 my %self_args;
119
120 $self_args{$_} = delete $args{$_}
121 for grep { /^on_/ } keys %args;
122
123 my $self = $class->SUPER::new (%self_args);
124 $self->{sock_args} = \%args;
125
126 if (exists $args{PeerAddr} || exists $args{PeerHost}) {
127 $self->{on_connect} ||= sub {
128 Carp::croak "Couldn't connect to $args{PeerHost}:$args{PeerPort}: $!"
129 if $_[1];
130 };
131 $self->_connect;
132 }
133
134 if ($self->{on_accept}) {
135 $self->on_accept ($self->{on_accept});
136 }
137
138 return $self
139 }
140
141 sub _connect {
142 my ($self) = @_;
143
144 if (defined $self->{sock_args}->{Listen}) {
145 Carp::croak "connect can be done on a socket that has 'Listen' set!";
146 }
147
148 if ($self->{sock_args}->{PeerAddr} =~ /^([^:]+)(?::(\d+))?$/) {
149 $self->{sock_args}->{PeerHost} = $1;
150 $self->{sock_args}->{PeerPort} = $2 if defined $2;
151 delete $self->{sock_args}->{PeerAddr};
152
153 $self->_lookup ($1);
154 return;
155
156 } elsif (my $h = $self->{sock_args}->{PeerHost}) {
157 $self->_lookup ($h);
158 return;
159
160 } else {
161 Carp::croak "no PeerAddr or PeerHost provided!";
162 }
163 }
164
165 =item B<on_accept ($cb)>
166
167 When the socket is run in listening mode (the C<Listen> argument of the socket
168 is set) this callback will be called when a new client connected.
169 The first argument to the callback will be the L<AnyEvent::Socket> object itself,
170 the second the L<AnyEvent::Handle> of the client socket and the third
171 is the peer address (depending on what C<accept> of L<IO::Socket> gives you>).
172
173 =cut
174
175 sub on_accept {
176 my ($self, $cb) = @_;
177
178 unless (defined $self->{sock_args}->{Listen}) {
179 $self->{sock_args}->{Listen} = 10;
180 }
181
182 $self->{fh} =
183 IO::Socket::INET->new (%{$self->{sock_args}}, Blocking => 0)
184 or Carp::croak ("couldn't create listening socket: $!");
185
186 $self->{list_w} =
187 AnyEvent->io (poll => 'r', fh => $self->{fh}, cb => sub {
188 my ($new_sock, $paddr) = $self->{fh}->accept ();
189 unless ($new_sock) {
190 $cb->($self);
191 delete $self->{list_w};
192 return;
193 }
194 my $ae_hdl = AnyEvent::Handle->new (fh => $new_sock);
195 $cb->($self, $ae_hdl, $paddr);
196 });
197 }
198
199 sub _lookup {
200 my ($self, $host) = @_;
201
202 AnyEvent::Util::inet_aton ($host, sub {
203 my ($addr) = @_;
204
205 if ($addr) {
206 $self->{sock_args}->{PeerHost} = inet_ntoa $addr;
207 $self->_real_connect;
208
209 } else {
210 $! = ENXIO;
211 $self->{on_connect}->($self, 1);
212 }
213 });
214 }
215
216 sub _real_connect {
217 my ($self) = @_;
218
219 if (defined $self->{sock_args}->{Timeout}) {
220 $self->{dns_tmout} =
221 AnyEvent->timer (after => $self->{sock_args}->{Timeout}, cb => sub {
222 $! = ETIMEDOUT;
223 $self->{on_connect}->($self, 1);
224 });
225 }
226
227 $self->{fh} = IO::Socket::INET->new (%{$self->{sock_args}}, Blocking => 0);
228 unless ($self->{fh}) {
229 $self->{on_connect}->($self, 1);
230 return;
231 }
232
233 $self->{con_w} =
234 AnyEvent->io (poll => 'w', fh => $self->{fh}, cb => sub {
235 delete $self->{con_w};
236
237 if ($! = $self->{fh}->sockopt (SO_ERROR)) {
238 $self->{on_connect}->($self, 1);
239
240 } else {
241 $self->{on_connect}->($self);
242 }
243 });
244 }
245
246 =back
247
248 =head1 AUTHOR
249
250 Robin Redeker, C<< <elmex at ta-sa.org> >>
251
252 =cut
253
254 1; # End of AnyEvent