Author: bdonlan
Date: 2005-07-18 00:32:51 -0400 (Mon, 18 Jul 2005)
New Revision: 868
Modified:
trunk/perl/client/lib/Haver/Client/POE.pm
Log:
async dns resolution
Modified: trunk/perl/client/lib/Haver/Client/POE.pm
===================================================================
--- trunk/perl/client/lib/Haver/Client/POE.pm 2005-07-18 00:40:46 UTC (rev
867)
+++ trunk/perl/client/lib/Haver/Client/POE.pm 2005-07-18 04:32:51 UTC (rev
868)
@@ -124,20 +124,23 @@
### SETUP
-=head2 spawn($alias)
+=head2 spawn($alias [, $Z<>resolver])
Creates a new Haver::Client::POE session, and sets its alias to the given
-value.
+value. Optionally, $resolver may be passed in, which should be an alias for
+a session of POE::Component::Client::DNS, which will then be used for
+asynchronous DNS lookups.
=cut
sub spawn {
- my ($pkg, $alias) = @_;
+ my ($pkg, $alias, $resolver) = @_;
my $heap = {
reg => {},
state => S_IDLE,
alias => $alias,
+ resolver => $resolver
};
POE::Session->create(
@@ -174,6 +177,8 @@
_cleanup
_err
_force_down
+ _dns_resp
+ _do_connect
}
]],
heap => $heap,
@@ -208,15 +213,70 @@
} else {
$heap->{state} = S_CONN;
$heap->{name} = $opts{Name};
- $heap->{wheel} = POE::Wheel::SocketFactory->new(
- RemoteAddress => $opts{Host},
- RemotePort => $opts{Port},
- SuccessEvent => '_conn_ok',
- FailureEvent => '_conn_fail',
- );
+ $heap->{port} = $opts{Port};
+ if (!$heap->{resolver}) {
+ _call('_do_connect', $opts{Host});
+ } else {
+ my $resp = $heap->{resolver}->resolve(
+ host => $opts{Host},
+ context => {},
+ event => '_dns_resp',
+ );
+ if ($resp) {
+ _call('_dns_resp', $resp);
+ }
+ }
}
}
+sub _do_connect {
+ my ($heap, $addr) = @_[HEAP,ARG0];
+ my $port = delete $heap->{port};
+ if ($heap->{state} == S_DYING) {
+ _call('_cleanup');
+ return;
+ }
+ $heap->{wheel} = POE::Wheel::SocketFactory->new(
+ RemoteAddress => $addr,
+ RemotePort => $port,
+ SuccessEvent => '_conn_ok',
+ FailureEvent => '_conn_fail',
+ );
+}
+
+BEGIN {
+ eval {
+ require List::Util;
+ List::Util->import(qw(shuffle));
+ };
+ eval {
+ shuffle();
+ };
+ if ($@) {
+ *shuffle = sub { return @_; }
+ }
+}
+
+sub _dns_resp {
+ my ($heap, $packet) = @_[HEAP,ARG0];
+ if ($packet->{response}) {
+ my $resp = $packet->{response};
+ my @answer = shuffle($resp->answer);
+ foreach my $record (@answer) {
+ if ($record->type eq 'A') {
+ # XXX: ipv6 support
+ $poe_kernel->yield('_do_connect', $record->address);
+ return;
+ }
+ }
+ # dns fail
+ _dispatch('connect_fail', 'dns');
+ _call('_cleanup');
+ } else {
+ _dispatch('connect_fail', 'dns', $packet->{error});
+ }
+}
+
sub _conn_fail {
my $heap = $_[HEAP];
_dispatch('connect_fail', @_[ARG0..ARG2]);
@@ -225,6 +285,10 @@
sub _conn_ok {
my ($kernel, $heap, $sock) = @_[KERNEL,HEAP,ARG0];
+ if ($heap->{state} == S_DYING) {
+ _call('_cleanup');
+ return;
+ }
_dispatch('connected');
$heap->{state} = S_INIT;
$heap->{wheel} = new POE::Wheel::ReadWrite(
@@ -261,9 +325,9 @@
sub disconnect {
my $heap = $_[HEAP];
+ _call('send_raw', 'BYE');
$heap->{state} = S_DYING;
$poe_kernel->delay('_force_down', 5);
- _call('send_raw', 'BYE');
}
sub _force_down {
@@ -292,6 +356,10 @@
sub send_raw {
my ($heap, @args) = @_[HEAP,ARG0..$#_];
+ if ($heap->{state} == S_IDLE || $heap->{state} == S_CONN ||
+ $heap->{state} == S_DYING) {
+ return;
+ }
print STDERR "C: ", join("\t", @args), "\n";
$heap->{wheel}->put([EMAIL PROTECTED]);
}
@@ -516,7 +584,6 @@
unshift @args, [$heap->{alias}];
foreach my $id (@ids) {
- print "$id\n";
$kernel->post($id, "haver_$evname", @args);
}
}