/usr/local/CPAN/Net-Gnutella/Net/Gnutella/Server.pm
package Net::Gnutella::Server;
use Net::Gnutella::Connection;
use IO::Socket;
use Carp;
use strict;
use vars qw/$VERSION $AUTOLOAD/;
$VERSION = $VERSION = "0.1";
# Use AUTOHANDLER to supply generic attribute methods
#
sub AUTOLOAD {
my $self = shift;
my $attr = $AUTOLOAD;
$attr =~ s/.*:://;
return unless $attr =~ /[^A-Z]/; # skip DESTROY and all-cap methods
croak sprintf "invalid attribute method: %s->%s()", ref($self), $attr unless exists $self->{_attr}->{lc $attr};
$self->{_attr}->{lc $attr} = shift if @_;
return $self->{_attr}->{lc $attr};
}
sub accept {
my $self = shift;
my $server = IO::Socket::INET->new(
Listen => SOMAXCONN,
LocalAddr => $self->server,
LocalPort => $self->port,
Reuse => 1,
);
unless (defined $server) {
$self->error("Couldn't bind to port: $!");
return;
}
$self->socket($server);
$self->server($server->sockhost);
$self->port($server->sockport);
$self->parent->_add_fh($self->socket, $self->can("_accept"), "r", $self);
}
sub connections {
my $self = shift;
my @ret;
foreach my $key (keys %{ $self->{_connhash} }) {
my $conn = $self->{_connhash}->{$key};
next unless $conn->connected;
push @ret, $conn;
}
return @ret;
}
sub new {
my $proto = shift;
my $parent = shift;
my %args = @_;
my $self = {
_attr => {
parent => $parent,
debug => $parent->debug,
timeout => $parent->timeout,
error => '',
socket => '',
server => undef,
port => 6346,
allow => 0,
},
};
bless $self, $proto;
foreach my $key (keys %args) {
my $lkey = lc $key;
$self->$lkey($args{$key});
}
$self->accept;
return $self;
}
sub _accept {
my $self = shift;
my $sock = $self->socket->accept || return;
printf STDERR "+ Accepted connection from '%s'\n", $sock->peerhost if $self->debug;
my $conn = Net::Gnutella::Connection->new($self->parent,
Debug => $self->debug,
Timeout => $self->timeout,
Allow => $self->allow,
Socket => $sock,
Ip => $sock->peerhost,
Connected => 2,
);
$self->{_connhash}->{$sock} = $conn;
}
1;