2021-06-19 06:23:34 +02:00
|
|
|
# File: SelectHandler.pm
|
|
|
|
#
|
2021-06-21 05:31:47 +02:00
|
|
|
# Purpose: Adds/removes file handles to/from PBot::IRC's select loop
|
|
|
|
# and contains handlers for select events.
|
2021-06-19 06:23:34 +02:00
|
|
|
|
2021-07-11 00:00:22 +02:00
|
|
|
# SPDX-FileCopyrightText: 2021 Pragmatic Software <pragma78@gmail.com>
|
|
|
|
# SPDX-License-Identifier: MIT
|
2017-03-05 22:33:31 +01:00
|
|
|
|
2014-03-14 06:51:15 +01:00
|
|
|
package PBot::SelectHandler;
|
2020-02-08 20:04:13 +01:00
|
|
|
use parent 'PBot::Class';
|
2014-03-14 06:51:15 +01:00
|
|
|
|
2021-06-19 06:23:34 +02:00
|
|
|
use PBot::Imports;
|
2019-07-11 03:40:53 +02:00
|
|
|
|
2014-03-14 06:51:15 +01:00
|
|
|
sub initialize {
|
2021-06-21 05:31:47 +02:00
|
|
|
# nothing to initialize
|
2014-03-14 06:51:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
sub add_reader {
|
2021-06-07 04:12:14 +02:00
|
|
|
my ($self, $handle, $subref) = @_;
|
2021-06-21 05:31:47 +02:00
|
|
|
|
|
|
|
# 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
|
2021-06-07 04:12:14 +02:00
|
|
|
$self->{buffers}->{$handle} = '';
|
2014-03-14 06:51:15 +01:00
|
|
|
}
|
|
|
|
|
2014-03-16 02:47:16 +01:00
|
|
|
sub remove_reader {
|
2020-02-15 23:38:32 +01:00
|
|
|
my ($self, $handle) = @_;
|
2021-06-21 05:31:47 +02:00
|
|
|
|
|
|
|
# remove file handle from PBot::IRC's select loop
|
|
|
|
$self->{pbot}->{irc}->removefh($handle);
|
|
|
|
|
|
|
|
# delete this handle's read buffer
|
2020-02-15 23:38:32 +01:00
|
|
|
delete $self->{buffers}->{$handle};
|
2014-03-16 02:47:16 +01:00
|
|
|
}
|
|
|
|
|
2021-06-21 05:31:47 +02:00
|
|
|
sub on_select_read {
|
|
|
|
my ($self, $handle, $subref) = @_;
|
2021-06-07 04:12:14 +02:00
|
|
|
|
|
|
|
# maximum read length
|
2020-02-15 23:38:32 +01:00
|
|
|
my $length = 8192;
|
2021-06-07 04:12:14 +02:00
|
|
|
|
2021-06-21 05:31:47 +02:00
|
|
|
# read from handle
|
|
|
|
my $ret = sysread($handle, my $buf, $length);
|
2020-07-15 20:07:35 +02:00
|
|
|
|
2021-06-21 05:31:47 +02:00
|
|
|
# error reading
|
|
|
|
if (not defined $ret) {
|
|
|
|
$self->{pbot}->{logger}->log("SelectHandler: Error reading $handle: $!\n");
|
|
|
|
$self->remove_reader($handle);
|
|
|
|
return;
|
|
|
|
}
|
2021-06-07 04:12:14 +02:00
|
|
|
|
2021-06-21 05:31:47 +02:00
|
|
|
# reader closed
|
|
|
|
if ($ret == 0) {
|
|
|
|
# is there anything in reader's buffer?
|
|
|
|
if (length $self->{buffers}->{$handle}) {
|
2021-06-21 16:30:42 +02:00
|
|
|
# send buffer to reader's consumer subref
|
|
|
|
$subref->($self->{buffers}->{$handle});
|
2021-06-07 04:12:14 +02:00
|
|
|
}
|
|
|
|
|
2021-06-21 05:31:47 +02:00
|
|
|
# remove reader
|
|
|
|
$self->remove_reader($handle);
|
|
|
|
return;
|
|
|
|
}
|
2014-03-14 06:51:15 +01:00
|
|
|
|
2021-06-21 05:31:47 +02:00
|
|
|
# accumulate input into reader's buffer
|
|
|
|
$self->{buffers}->{$handle} .= $buf;
|
2014-03-14 06:51:15 +01:00
|
|
|
|
2021-06-21 05:31:47 +02:00
|
|
|
# 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.
|
2021-06-07 04:12:14 +02:00
|
|
|
|
2021-06-21 05:31:47 +02:00
|
|
|
if ($ret < $length) {
|
|
|
|
# send reader's buffer to reader's consumer subref
|
|
|
|
$subref->($self->{buffers}->{$handle});
|
2021-06-07 04:12:14 +02:00
|
|
|
|
2021-06-21 05:31:47 +02:00
|
|
|
# clear out reader's buffer
|
|
|
|
$self->{buffers}->{$handle} = '';
|
2014-03-14 06:51:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
1;
|