mirror of
https://github.com/pragma-/pbot.git
synced 2024-11-23 04:19:27 +01:00
Refactor SelectHandler to use PBot::IRC's select loop
This commit is contained in:
parent
8b093d313c
commit
06d986e11e
17
PBot/PBot.pm
17
PBot/PBot.pm
@ -100,7 +100,7 @@ sub initialize {
|
||||
my ($item, $value) = split /=/, $arg, 2;
|
||||
|
||||
if (not defined $item or not defined $value) {
|
||||
print STDERR "Fatal error: unknown argument `$arg`; arguments must be in the form of `section.key=value` (e.g.: irc.botnick=newnick)\n";
|
||||
print STDERR "Fatal error: unknown argument `$arg`; arguments must be in the form of `section.key=value` or `path_dir=value` (e.g.: irc.botnick=newnick or data_dir=path)\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
@ -174,8 +174,11 @@ sub initialize {
|
||||
exit;
|
||||
}
|
||||
|
||||
# prepare the IRC engine
|
||||
$self->{irc} = PBot::IRC->new;
|
||||
|
||||
# prepare remaining core PBot modules -- do not change this order
|
||||
$self->{timer} = PBot::Timer->new(pbot => $self, timeout => 10, name => 'PBot Timer', %conf);
|
||||
$self->{timer} = PBot::Timer->new(pbot => $self, timeout => 10, name => 'PBot Timer', %conf);
|
||||
$self->{event_dispatcher} = PBot::EventDispatcher->new(pbot => $self, %conf);
|
||||
$self->{users} = PBot::Users->new(pbot => $self, filename => "$conf{data_dir}/users", %conf);
|
||||
$self->{antiflood} = PBot::AntiFlood->new(pbot => $self, %conf);
|
||||
@ -188,7 +191,6 @@ sub initialize {
|
||||
$self->{functions} = PBot::Functions->new(pbot => $self, %conf);
|
||||
$self->{refresher} = PBot::Refresher->new(pbot => $self);
|
||||
$self->{ignorelist} = PBot::IgnoreList->new(pbot => $self, filename => "$conf{data_dir}/ignorelist", %conf);
|
||||
$self->{irc} = PBot::IRC->new();
|
||||
$self->{irchandlers} = PBot::IRCHandlers->new(pbot => $self, %conf);
|
||||
$self->{interpreter} = PBot::Interpreter->new(pbot => $self, %conf);
|
||||
$self->{lagchecker} = PBot::LagChecker->new(pbot => $self, %conf);
|
||||
@ -332,16 +334,17 @@ sub exit {
|
||||
|
||||
# main loop
|
||||
sub do_one_loop {
|
||||
my $self = shift;
|
||||
$self->{irc}->do_one_loop() if $self->{connected};
|
||||
$self->{select_handler}->do_select;
|
||||
my ($self) = @_;
|
||||
$self->{irc}->do_one_loop();
|
||||
}
|
||||
|
||||
# main entry point
|
||||
sub start {
|
||||
my $self = shift;
|
||||
|
||||
$self->connect;
|
||||
|
||||
while (1) {
|
||||
$self->connect if not $self->{connected};
|
||||
$self->do_one_loop;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
# File: SelectHandler.pm
|
||||
#
|
||||
# Purpose: Invokes select() system call and handles its events.
|
||||
# Purpose: Adds/removes file handles to/from PBot::IRC's select loop
|
||||
# and contains handlers for select events.
|
||||
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
@ -11,87 +12,75 @@ use parent 'PBot::Class';
|
||||
|
||||
use PBot::Imports;
|
||||
|
||||
use IO::Select;
|
||||
|
||||
sub initialize {
|
||||
my ($self, %conf) = @_;
|
||||
$self->{select} = IO::Select->new();
|
||||
$self->{readers} = {};
|
||||
$self->{buffers} = {};
|
||||
# nothing to initialize
|
||||
}
|
||||
|
||||
sub add_reader {
|
||||
my ($self, $handle, $subref) = @_;
|
||||
$self->{select}->add($handle);
|
||||
$self->{readers}->{$handle} = $subref;
|
||||
|
||||
# add file handle to PBot::IRC's select loop
|
||||
$self->{pbot}->{irc}->addfh($handle, sub { $self->on_select_read($handle, $subref) }, 'r');
|
||||
|
||||
# create read buffer for this handle
|
||||
$self->{buffers}->{$handle} = '';
|
||||
}
|
||||
|
||||
sub remove_reader {
|
||||
my ($self, $handle) = @_;
|
||||
$self->{select}->remove($handle);
|
||||
delete $self->{readers}->{$handle};
|
||||
|
||||
# remove file handle from PBot::IRC's select loop
|
||||
$self->{pbot}->{irc}->removefh($handle);
|
||||
|
||||
# delete this handle's read buffer
|
||||
delete $self->{buffers}->{$handle};
|
||||
}
|
||||
|
||||
sub do_select {
|
||||
my ($self) = @_;
|
||||
sub on_select_read {
|
||||
my ($self, $handle, $subref) = @_;
|
||||
|
||||
# maximum read length
|
||||
my $length = 8192;
|
||||
|
||||
# check if any readers can read
|
||||
my @ready = $self->{select}->can_read(.1);
|
||||
# read from handle
|
||||
my $ret = sysread($handle, my $buf, $length);
|
||||
|
||||
foreach my $fh (@ready) {
|
||||
# read from handle
|
||||
my $ret = sysread($fh, my $buf, $length);
|
||||
# error reading
|
||||
if (not defined $ret) {
|
||||
$self->{pbot}->{logger}->log("SelectHandler: Error reading $handle: $!\n");
|
||||
$self->remove_reader($handle);
|
||||
return;
|
||||
}
|
||||
|
||||
# error reading
|
||||
if (not defined $ret) {
|
||||
$self->{pbot}->{logger}->log("SelectHandler: Error reading $fh: $!\n");
|
||||
$self->remove_reader($fh);
|
||||
next;
|
||||
# reader closed
|
||||
if ($ret == 0) {
|
||||
# is there anything in reader's buffer?
|
||||
if (length $self->{buffers}->{$handle}) {
|
||||
# send buffer to reader subref
|
||||
$self->{readers}->{$handle}->($self->{buffers}->{$handle});
|
||||
}
|
||||
|
||||
# reader closed
|
||||
if ($ret == 0) {
|
||||
# is there anything in reader's buffer?
|
||||
if (length $self->{buffers}->{$fh}) {
|
||||
# send buffer to reader subref
|
||||
$self->{readers}->{$fh}->($self->{buffers}->{$fh});
|
||||
}
|
||||
# remove reader
|
||||
$self->remove_reader($handle);
|
||||
return;
|
||||
}
|
||||
|
||||
# remove reader
|
||||
$self->remove_reader($fh);
|
||||
# accumulate input into reader's buffer
|
||||
$self->{buffers}->{$handle} .= $buf;
|
||||
|
||||
# skip to next reader
|
||||
next;
|
||||
}
|
||||
# if we read less than max length bytes then this is probably
|
||||
# a complete message so send it to reader now, otherwise we'll
|
||||
# continue to accumulate input into reader's buffer and then send
|
||||
# the buffer when reader closes.
|
||||
#
|
||||
# FIXME: this should be line-based or some protocol.
|
||||
|
||||
# sanity check for missing reader
|
||||
if (not exists $self->{readers}->{$fh}) {
|
||||
$self->{pbot}->{logger}->log("Error: no reader for $fh\n");
|
||||
if ($ret < $length) {
|
||||
# send reader's buffer to reader's consumer subref
|
||||
$subref->($self->{buffers}->{$handle});
|
||||
|
||||
# skip to next reader
|
||||
next;
|
||||
}
|
||||
|
||||
# accumulate input into reader's buffer
|
||||
$self->{buffers}->{$fh} .= $buf;
|
||||
|
||||
# if we read less than max length bytes then this is probably
|
||||
# a complete message so send it to reader now, otherwise we'll
|
||||
# continue to accumulate input into reader's buffer and then send
|
||||
# the buffer when reader closes.
|
||||
|
||||
if ($ret < $length) {
|
||||
# send reader's buffer to reader subref
|
||||
$self->{readers}->{$fh}->($self->{buffers}->{$fh});
|
||||
|
||||
# clear out reader's buffer
|
||||
$self->{buffers}->{$fh} = '';
|
||||
}
|
||||
# clear out reader's buffer
|
||||
$self->{buffers}->{$handle} = '';
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user