Jabber-Lite
view release on metacpan or search on metacpan
lib/Jabber/Lite.pm view on Meta::CPAN
my $self = shift;
# Do the ordering of hosts in this function.
# The results have been stored in a hash:
# $self->{'_resolved'}{'hostname'}
# Each of these contains another hash, of @'srv' and $'address',
# amongst others.
my @list = ();
# Run through the hosts, and see if any have 'srv' records. There
# should only be one, and it holds indirections to other hosts.
my $srvrec = undef;
foreach my $host( keys %{$self->{'_resolved'}} ){
next unless( defined( $self->{'_resolved'}{$host}{'srv'} ) );
$srvrec = $host;
}
if( ! defined( $srvrec ) ){
foreach my $host( keys %{$self->{'_resolved'}} ){
next unless( defined( $self->{'_resolved'}{$host}{'address'} ) );
next if( $self->{'_resolved'}{$host}{'address'} =~ /^\s*$/ );
push @list, $self->{'_resolved'}{$host}{'address'};
}
}else{
# Run through the srv listing in order.
my %uhosts = ();
foreach my $prio ( sort { $a <=> $b } keys %{$self->{'_resolved'}{$srvrec}{'srv'}} ){
# Collect all of the weights.
my %weights = ();
my $wghtcnt = scalar @{$self->{'_resolved'}{$srvrec}{'srv'}{$prio}};
my $wghthigh = 0;
foreach my $wghtrec( @{$self->{'_resolved'}{$srvrec}{'srv'}{$prio}} ){
next unless( $wghtrec =~ /^\s*(\d+)\s+(\d+)\s+(\S+)\s*$/ );
my $wghtnum = $1;
my $port = $2;
my $host = $3;
if( $wghtnum > $wghthigh ){
$wghthigh = $wghtnum;
}
}
# Run through again, now that we know the highest
# weight.
my $posmax = 0;
foreach my $wghtrec( @{$self->{'_resolved'}{$srvrec}{'srv'}{$prio}} ){
next unless( $wghtrec =~ /^\s*(\d+)\s+(\d+)\s+(\S+)\s*$/ );
my $wghtnum = $1;
my $port = $2;
my $host = $3;
# Work out a position for this weight, between
# 0 and $wghtcnt (inclusive).
my $wghtpos = abs( int( rand( $wghtcnt + 1 ) + ( $wghthigh - $wghtnum ) ) );
my $trycnt = 0;
while( defined( $weights{"$wghtpos"} ) && $trycnt < $wghtcnt ){
$wghtpos = abs( int( rand( $wghtcnt + 1 ) + ( $wghthigh - $wghtnum ) ) );
$trycnt++;
}
# Did the loop exit due to success, or because
# of too many iterations?
if( defined( $weights{"$wghtpos"} ) ){
# Count up until we find one.
$wghtpos = 0;
while( defined( $weights{"$wghtpos"} ) ){
$wghtpos++;
}
}
# Save the port and host.
$weights{"$wghtpos"} = "$port $host";
if( $wghtpos > $posmax ){
$posmax = $wghtpos;
}
# print "Found SRV $srvrec and priority $prio and weight $wghtnum and pos $wghtpos and port $port and host $host\n";
}
# Now output the hosts seen in the semi-random
# order chosen.
foreach my $weightkey ( sort { $b <= $a } keys %weights ){
next unless( defined( $weights{"$weightkey"} ) );
next unless( $weights{"$weightkey"} =~ /^\s*(\d+)\s+(\S+)\s*$/ );
my $port = $1;
my $host = $2;
next unless( defined( $self->{'_resolved'}{$host}{'address'} ) );
next if( $self->{'_resolved'}{$host}{'address'} =~ /^\s*$/ );
# addresses can be multiple!
foreach my $address( @{$self->{'_resolved'}{$host}{'address'}} ){
# Only output a given IP and port combination once.
next if( defined( $uhosts{$port . $address} ) );
push @list, $address . "," . $port;
$uhosts{$port . $address}++;
}
}
}
}
return( @list );
}
=head2 bgresolve
As per ->resolve, but submit in the background. This returns 1 if the query
could be submitted, and 0 if not.
( Actually, ->resolve is simply a wrapper around ->bgresolve and ->bgresolved )
=cut
sub bgresolve {
my $self = shift;
my %args = ( Domain => undef,
Type => 'client',
Protocol => 'tcp',
Timeout => 90,
@_,
);
my $retval = 0;
# Wipe out previous resolution records.
delete( $self->{'_resolved'} );
( run in 1.560 second using v1.01-cache-2.11-cpan-71847e10f99 )