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);
     }
 }


Reply via email to