From 1b5b987f9ebf91cd1976bdb143d17fabb7554090 Mon Sep 17 00:00:00 2001 From: Pragmatic Software Date: Fri, 9 Jul 2021 23:12:29 -0700 Subject: [PATCH] Refactor SSL behavior --- PBot/IRC/Connection.pm | 44 ++++++++++++++++++++++++++++++++++-------- PBot/PBot.pm | 38 ++++++++++++++++++++++++++---------- 2 files changed, 64 insertions(+), 18 deletions(-) diff --git a/PBot/IRC/Connection.pm b/PBot/IRC/Connection.pm index ed29a7f1..263ea523 100644 --- a/PBot/IRC/Connection.pm +++ b/PBot/IRC/Connection.pm @@ -260,7 +260,7 @@ sub connect { if ($self->connected) { $self->quit("Changing servers"); } if ($self->ssl) { - require IO::Socket::SSL; + use IO::Socket::SSL; if ($self->ssl_ca_file) { $self->socket( @@ -294,9 +294,7 @@ sub connect { ) ); } - } else { - $self->socket( IO::Socket::INET->new( PeerAddr => $self->server, @@ -308,14 +306,25 @@ sub connect { } if (!$self->socket) { - carp( - sprintf "Can't connect to %s:%s!", - $self->server, $self->port - ); + if ($self->ssl) { + carp( + sprintf "Can't connect to %s:%s: error=$! SSL_ERROR=$SSL_ERROR", + $self->server, $self->port + ); + } else { + carp( + sprintf "Can't connect to %s:%s: $!", + $self->server, $self->port + ); + } $self->error(1); return; } + if ($self->ssl) { + $self->socket->blocking(0); + } + # send CAP LS first $self->sl("CAP LS 302"); @@ -831,7 +840,26 @@ sub parse { my ($self) = shift; my ($from, $type, $message, @stuff, $itype, $ev, @lines, $line); - if (defined($self->ssl ? $self->socket->read($line, 10240) : $self->socket->recv($line, 10240, 0)) and (length($self->{_frag}) + length($line)) > 0) { + my $n; + + if ($self->ssl) { + $n = sysread($self->socket, $line, 32767); + + if (not defined $n) { + if ($!{EWOULDBLOCK}) { + if ($SSL_ERROR == SSL_WANT_READ or $SSL_ERROR = SSL_WANT_WRITE) { + return; + } + + print STDERR "SSL broke: $SSL_ERROR\n"; + } + } + + } else { + $n = $self->socket->recv($line, 32767, 0); + } + + if (defined $n and (length($self->{_frag}) + length($line)) > 0) { # grab any remnant from the last go and split into lines my $chunk = $self->{_frag} . $line; @lines = split /\012/, $chunk; diff --git a/PBot/PBot.pm b/PBot/PBot.pm index b0a79617..03a382f4 100644 --- a/PBot/PBot.pm +++ b/PBot/PBot.pm @@ -244,14 +244,15 @@ sub connect { # TODO: disconnect, clean-up, etc } - my $server = $self->{registry}->get_value('irc', 'server'); - my $port = $self->{registry}->get_value('irc', 'port'); - my $delay = $self->{registry}->get_value('irc', 'reconnect_delay') // 10; + my $server = $self->{registry}->get_value('irc', 'server'); + my $port = $self->{registry}->get_value('irc', 'port'); + my $delay = $self->{registry}->get_value('irc', 'reconnect_delay') // 10; + my $retries = $self->{registry}->get_value('irc', 'reconnect_retries') // 10; $self->{logger}->log("Connecting to $server:$port\n"); - while ( - not $self->{conn} = $self->{irc}->newconn( + for (my $attempt = 0; $attempt < $retries; $attempt++) { + my %config = ( Nick => $self->{registry}->get_value('irc', 'randomize_nick') ? $self->random_nick : $self->{registry}->get_value('irc', 'botnick'), Username => $self->{registry}->get_value('irc', 'username'), Ircname => $self->{registry}->get_value('irc', 'realname'), @@ -260,13 +261,30 @@ sub connect { Pacing => 1, UTF8 => 1, SSL => $self->{registry}->get_value('irc', 'ssl'), - SSL_ca_file => $self->{registry}->get_value('irc', 'ssl_ca_file'), - SSL_ca_path => $self->{registry}->get_value('irc', 'ssl_ca_path'), Debug => $self->{registry}->get_value('irc', 'debug'), PBot => $self, - ) - ) - { + ); + + # set SSL stuff + my $ssl_ca_file = $self->{registry}->get_value('irc', 'ssl_ca_file'); + + if (length $ssl_ca_file and $ssl_ca_file ne 'none') { + $config{SSL_ca_file} = $ssl_ca_file; + } + + my $ssl_ca_path = $self->{registry}->get_value('irc', 'ssl_ca_path'); + + if (length $ssl_ca_file and $ssl_ca_file ne 'none') { + $config{SSL_ca_file} = $ssl_ca_file; + } + + # attempt to connect + $self->{conn} = $self->{irc}->newconn(%config); + + # connection succeeded + last if $self->{conn}; + + # connection failed $self->{logger}->log("$0: Can't connect to $server:$port: $!\nRetrying in $delay seconds...\n"); sleep $delay; }