2017-03-05 22:33:31 +01:00
|
|
|
# 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
|
|
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
2014-03-14 06:51:15 +01:00
|
|
|
package PBot::SelectHandler;
|
|
|
|
|
|
|
|
use warnings;
|
|
|
|
use strict;
|
|
|
|
|
2019-07-11 03:40:53 +02:00
|
|
|
use feature 'unicode_strings';
|
|
|
|
|
2014-03-14 06:51:15 +01:00
|
|
|
use IO::Select;
|
|
|
|
use Carp ();
|
|
|
|
|
|
|
|
sub new {
|
2019-05-28 18:19:42 +02:00
|
|
|
if (ref($_[1]) eq 'HASH') {
|
2014-03-14 06:51:15 +01:00
|
|
|
Carp::croak("Options to SelectHandler should be key/value pairs, not hash reference");
|
|
|
|
}
|
|
|
|
|
|
|
|
my ($class, %conf) = @_;
|
|
|
|
|
|
|
|
my $self = bless {}, $class;
|
|
|
|
$self->initialize(%conf);
|
|
|
|
return $self;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub initialize {
|
|
|
|
my ($self, %conf) = @_;
|
|
|
|
|
|
|
|
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference in SelectHandler");
|
|
|
|
$self->{select} = IO::Select->new();
|
|
|
|
$self->{readers} = {};
|
2017-10-10 23:31:31 +02:00
|
|
|
$self->{buffers} = {};
|
2014-03-14 06:51:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
sub add_reader {
|
|
|
|
my ($self, $handle, $sub) = @_;
|
|
|
|
$self->{select}->add($handle);
|
|
|
|
$self->{readers}->{$handle} = $sub;
|
2017-10-10 23:31:31 +02:00
|
|
|
$self->{buffers}->{$handle} = "";
|
2014-03-14 06:51:15 +01:00
|
|
|
}
|
|
|
|
|
2014-03-16 02:47:16 +01:00
|
|
|
sub remove_reader {
|
|
|
|
my ($self, $handle) = @_;
|
|
|
|
$self->{select}->remove($handle);
|
|
|
|
delete $self->{readers}->{$handle};
|
2017-10-10 23:31:31 +02:00
|
|
|
delete $self->{buffers}->{$handle};
|
2014-03-16 02:47:16 +01:00
|
|
|
}
|
|
|
|
|
2014-03-14 06:51:15 +01:00
|
|
|
sub do_select {
|
|
|
|
my ($self) = @_;
|
2017-10-10 23:31:31 +02:00
|
|
|
my $length = 8192;
|
2015-02-16 05:23:07 +01:00
|
|
|
my @ready = $self->{select}->can_read(0);
|
2014-03-14 06:51:15 +01:00
|
|
|
foreach my $fh (@ready) {
|
2017-10-10 23:31:31 +02:00
|
|
|
my $ret = sysread($fh, my $buf, $length);
|
2014-03-14 06:51:15 +01:00
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if (not defined $ret) {
|
2014-05-18 22:09:05 +02:00
|
|
|
$self->{pbot}->{logger}->log("Error with $fh: $!\n");
|
2014-03-16 02:47:16 +01:00
|
|
|
$self->remove_reader($fh);
|
2014-03-14 06:51:15 +01:00
|
|
|
next;
|
|
|
|
}
|
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if ($ret == 0) {
|
2017-10-10 23:31:31 +02:00
|
|
|
if (length $self->{buffers}->{$fh}) {
|
|
|
|
$self->{readers}->{$fh}->($self->{buffers}->{$fh});
|
|
|
|
}
|
2014-03-16 02:47:16 +01:00
|
|
|
$self->remove_reader($fh);
|
2014-03-14 06:51:15 +01:00
|
|
|
next;
|
|
|
|
}
|
|
|
|
|
2017-10-10 23:31:31 +02:00
|
|
|
$self->{buffers}->{$fh} .= $buf;
|
2014-03-14 06:51:15 +01:00
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if (not exists $self->{readers}->{$fh}) {
|
2014-05-18 22:09:05 +02:00
|
|
|
$self->{pbot}->{logger}->log("Error: no reader for $fh\n");
|
2014-03-14 06:51:15 +01:00
|
|
|
} else {
|
2017-10-10 23:31:31 +02:00
|
|
|
if ($ret < $length) {
|
|
|
|
$self->{readers}->{$fh}->($self->{buffers}->{$fh});
|
|
|
|
$self->{buffers}->{$fh} = "";
|
|
|
|
}
|
2014-03-14 06:51:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
1;
|