On Thu, 20 Nov 2003 20:54:46 -0800  Andrew Chen wrote:
 +------------------
 | Has anyone come up with an LDAP client in POE?  I remember seeing somewhere 
 | that cfedde was working on one, but I haven't heard anything since 
 | then.  Did it ever get released?  Thanks.
 +------------------

I did some test implementation.  But lacked the gumption to finish
it.  It turns out that the asynch interface is not fully exposed
by Net::LDAP and a POE::Wheel::Run version that wraps the whole API was
just too ugly.   At the same time my need for the module went away.

You are welcome to my test code.  It's been about 6 months since I
looked at it.  The bit of drabble below was used as a load tester.
It had loads more patterns for the search.

--
    Chris Fedde
--

#!/usr/bin/perl  # -*-CPerl-*-
#
# return results from an LDAP search using POE
#

use strict;
use warnings;

use POE qw(Wheel::Run Filter::Reference);
use YAML;
use Net::LDAP;
use Time::HiRes qw( time );
use Getopt::Long;

my $hostname = 'auth.your.net';
my $concurrent = 2 ;
my $debug = 0;

GetOptions (
    'hostname:s' => \$hostname,
    'concurrent:i' => \$concurrent,
    'debug!' => \$debug,
) or die;

#
# Create a queue of datastructures to pass to the child.
#
my @list = map {
    my $s;
    chomp;
    @$s{ 'base', 'filter' } = split (/\s+/);
    $s
} <DATA>;

sub DEBUG () { $debug };

#
# a session to  handle the Wheel::Run child process.
#
sub new_kid {
    return POE::Session->create(
        inline_states => {
            _start => sub {
                my ( $kernel, $heap ) = @_[ KERNEL, HEAP ];

                $heap->{cmd} = POE::Wheel::Run->new(
                    Program     => \&ldap,
                    ErrorEvent  => 'cmd_error',
                    StdoutEvent => 'cmd_stdout',
                    StderrEvent => 'cmd_stderr',
                    StdioFilter => POE::Filter::Reference->new(),

                ) or die "$0: can't POE::Wheel::Run->new";

                @{$heap->{words}} = @list;
                $kernel->yield('next_cmd');
            },

            cmd_stdout => \&cmd_stdout,
            cmd_stderr => \&cmd_stderr,
            cmd_error  => \&cmd_error,

            next_cmd => sub {
                my ( $kernel, $heap, $sess ) = @_[ KERNEL, HEAP, SESSION ];

                # somebody shutdown the wheel
                return 1 unless ( $heap->{cmd} );

                my $c = shift ( @{ $heap->{words} } );
                return 1 unless ($c);

                $heap->{cmd}->put($c);
                $_[KERNEL]->yield('next_cmd');
              }
        }
      )
      or die "$0: POE::Session->create failed $!";
}

#
# Block to build scope for the child subroutine
#
{

    #
    # these two subroutines are used in the child process
    #
    my $filter;

    sub ldap {

        my $raw;
        my $size = 4096;

        $filter = POE::Filter::Reference->new();

        my $ldap = Net::LDAP->new($hostname) or die "$0: $@";

        $ldap->bind(
            dn       => 'cn=root,dc=ldapusers,dc=your,dc=net',
            password => 'somestring',
          )
          or die "$0: $@";

      READ:
        while ( sysread( STDIN, $raw, $size ) ) {

            my $s = $filter->get( [$raw] );

            for my $t (@$s) {

                print STDERR Dump $t;

                last READ if ( $t->{base} eq 'quit' );

                $ldap->search(
                    base     => $t->{base},
                    filter   => $t->{filter},
                    callback => \&ldap_cb,
                );
            }
        }
    }

    #
    # callback for an ldap search
    #
    sub ldap_cb {
        my ( $m, $e ) = @_;
        my $u;

        if ($e) {
            $u = $filter->put( [$e] );
        }
        else {
            $u = $filter->put( [ { last => 1 } ] );
        }

        print STDOUT @$u;

        $m->pop_entry;
    }
}

#
# state subs for the session;
#
sub cmd_error {
    my ( $sess, $hash, $op, $code, $handle ) =
        @_[ SESSION, HEAP, ARG0, ARG1, ARG4 ];

    if ( $op eq 'read' and $code == 0 and $handle eq 'STDOUT' ) {
        printf "session %d child has closed STDOUT\n", $sess->ID;
        delete $hash->{cmd};
    }
}

#
# count the number of elements that match
my $count = 0;
my $now   = time();

sub cmd_stdout {
    my ( $session, $heap, $txt ) = @_[ SESSION, HEAP, ARG0 ];

    printf "session: %d\n", $session->ID if DEBUG;
    print STDOUT Dump $txt if DEBUG; 
    my $rate = $count / ( time() - $now );
    printf STDOUT "session: %d totalcount: %d overallrate: %10.3f\n",
        $session->ID, $count, $rate if ( $count % 100 == 0 );

    $count++;
}

sub cmd_stderr {

    my ( $heap, $txt ) = @_[ HEAP, ARG0 ];
    print "cmd_stderr: $txt\n" if DEBUG;
}

for (1..$concurrent) {
    new_kid();
}
POE::Kernel->run();

exit 0;

__END__
ou=Customers,dc=your,dc=net uid=cfedde
ou=Customers,dc=your,dc=net uid=cmc
ou=Customers,dc=your,dc=net uid=xcmc
ou=Customers,dc=your,dc=net uid=foo
ou=Customers,dc=your,dc=net [EMAIL PROTECTED]
ou=Customers,dc=your,dc=net [EMAIL PROTECTED]

Reply via email to