[Koha-patches] [PATCH] Bug 7787: Make the SIP server much more robust.
Colin Campbell
colin.campbell at ptfs-europe.com
Tue Jun 19 13:55:15 CEST 2012
From: Marc Balmer <marc at msys.ch>
Be liberal in what we accept, but strict in what we send:
Never exit the server process, but send a SC_RESEND message (96)
to the client if we received anything we don't understand.
This is consistent with SIP server implementations of other ILSs.
Signed-off-by: Colin Campbell <colin.campbell at ptfs-europe.com>
---
C4/SIP/SIPServer.pm | 55 ++++++++++++++++++---------------------------------
C4/SIP/Sip.pm | 8 --------
C4/SIP/Sip/MsgType.pm | 4 +++-
3 files changed, 22 insertions(+), 45 deletions(-)
diff --git a/C4/SIP/SIPServer.pm b/C4/SIP/SIPServer.pm
index bab51e8..a23c713 100644
--- a/C4/SIP/SIPServer.pm
+++ b/C4/SIP/SIPServer.pm
@@ -35,7 +35,6 @@ BEGIN {
my %transports = (
RAW => \&raw_transport,
telnet => \&telnet_transport,
- # http => \&http_transport, # for http just use the OPAC
);
#
@@ -126,31 +125,18 @@ sub raw_transport {
my $self = shift;
my ($input);
my $service = $self->{service};
- my $strikes = 3;
- eval {
- local $SIG{ALRM} = sub { die "raw_transport Timed Out!\n"; };
- syslog("LOG_DEBUG", "raw_transport: timeout is %d", $service->{timeout});
- while ($strikes--) {
- alarm $service->{timeout};
- $input = Sip::read_SIP_packet(*STDIN);
- alarm 0;
- if (!$input) {
- # EOF on the socket
- syslog("LOG_INFO", "raw_transport: shutting down: EOF during login");
- return;
- }
- $input =~ s/[\r\n]+$//sm; # Strip off trailing line terminator(s)
- last if Sip::MsgType::handle($input, $self, LOGIN);
- }
- };
-
- if (length $@) {
- syslog("LOG_ERR", "raw_transport: LOGIN ERROR: '$@'");
- die "raw_transport: login error (timeout? $@), exiting";
- } elsif (!$self->{account}) {
- syslog("LOG_ERR", "raw_transport: LOGIN FAILED");
- die "raw_transport: Login failed (no account), exiting";
+ while (!$self->{account}) {
+ local $SIG{ALRM} = sub { die "raw_transport Timed Out!\n"; };
+ syslog("LOG_DEBUG", "raw_transport: timeout is %d", $service->{timeout});
+ $input = Sip::read_SIP_packet(*STDIN);
+ if (!$input) {
+ # EOF on the socket
+ syslog("LOG_INFO", "raw_transport: shutting down: EOF during login");
+ return;
+ }
+ $input =~ s/[\r\n]+$//sm; # Strip off trailing line terminator(s)
+ last if Sip::MsgType::handle($input, $self, LOGIN);
}
syslog("LOG_DEBUG", "raw_transport: uname/inst: '%s/%s'",
@@ -269,32 +255,29 @@ sub sip_protocol_loop {
# In short, we'll take any valid message here.
#my $expect = SC_STATUS;
my $expect = '';
- my $strikes = 3;
- while ($input = Sip::read_SIP_packet(*STDIN)) {
+ while (1) {
+ $input = Sip::read_SIP_packet(*STDIN);
+ unless ($input) {
+ return; # EOF
+ }
# begin input hacks ... a cheap stand in for better Telnet layer
$input =~ s/^[^A-z0-9]+//s; # Kill leading bad characters... like Telnet handshakers
$input =~ s/[^A-z0-9]+$//s; # Same on the end, should get DOSsy ^M line-endings too.
while (chomp($input)) {warn "Extra line ending on input";}
unless ($input) {
- if ($strikes--) {
- syslog("LOG_ERR", "sip_protocol_loop: empty input skipped");
- next;
- } else {
- syslog("LOG_ERR", "sip_protocol_loop: quitting after too many errors");
- die "sip_protocol_loop: quitting after too many errors";
- }
+ syslog("LOG_ERR", "sip_protocol_loop: empty input skipped");
+ print("96$CR");
+ next;
}
# end cheap input hacks
my $status = Sip::MsgType::handle($input, $self, $expect);
if (!$status) {
syslog("LOG_ERR", "sip_protocol_loop: failed to handle %s",substr($input,0,2));
- die "sip_protocol_loop: failed Sip::MsgType::handle('$input', $self, '$expect')";
}
next if $status eq REQUEST_ACS_RESEND;
if ($expect && ($status ne $expect)) {
# We received a non-"RESEND" that wasn't what we were expecting.
syslog("LOG_ERR", "sip_protocol_loop: expected %s, received %s, exiting", $expect, $input);
- die "sip_protocol_loop: exiting: expected '$expect', received '$status'";
}
# We successfully received and processed what we were expecting
$expect = '';
diff --git a/C4/SIP/Sip.pm b/C4/SIP/Sip.pm
index e9e1392..ba682dd 100644
--- a/C4/SIP/Sip.pm
+++ b/C4/SIP/Sip.pm
@@ -158,7 +158,6 @@ sub read_SIP_packet {
# local $/ = "\r"; # don't need any of these here. use whatever the prevailing $/ is.
local $/ = "\015"; # proper SPEC: (octal) \015 = (hex) x0D = (dec) 13 = (ascii) carriage return
{ # adapted from http://perldoc.perl.org/5.8.8/functions/readline.html
- for ( my $tries = 1 ; $tries <= 3 ; $tries++ ) {
undef $!;
$record = readline($fh);
if ( defined($record) ) {
@@ -173,14 +172,7 @@ sub read_SIP_packet {
while ( chomp($record) ) { 1; }
$record and last; # success
- } else {
- if ($!) {
- syslog( "LOG_DEBUG", "read_SIP_packet (try #$tries) ERROR: $! $@" );
- # die "read_SIP_packet ERROR: $!";
- warn "read_SIP_packet ERROR: $! $@";
- }
}
- }
}
if ($record) {
my $len2 = length($record);
diff --git a/C4/SIP/Sip/MsgType.pm b/C4/SIP/Sip/MsgType.pm
index cc6b6d5..1682812 100644
--- a/C4/SIP/Sip/MsgType.pm
+++ b/C4/SIP/Sip/MsgType.pm
@@ -405,7 +405,9 @@ sub handle {
}
unless ($self->{handler}) {
syslog("LOG_WARNING", "No handler defined for '%s'", $msg);
- return undef;
+ $last_response = REQUEST_SC_RESEND;
+ print("$last_response\r");
+ return REQUEST_ACS_RESEND;
}
return($self->{handler}->($self, $server)); # FIXME
# FIXME: Use of uninitialized value in subroutine entry
--
1.7.11
More information about the Koha-patches
mailing list