From cd773c26cf585fb97c8ee0277e3b9e4574815f34 Mon Sep 17 00:00:00 2001 From: Galen Charlton Date: Mon, 7 Jul 2014 12:01:41 -0700 Subject: [PATCH] LP#1338731: support clients that send 99 then 93 when starting a raw connection This patch adds the option, for raw transports, to allow clients to send the SC Status (99) message first, then the Login (93) message. It's arguable whether such behavior is standard or not, but at least one SIP2 client (Relais), inflexibly requires such behavior. This option is enabled using the service-level attribute "allow_sc_status_then_login". Signed-off-by: Galen Charlton --- SIPServer.pm | 7 ++++ SIPconfig.xml | 1 + Sip/Configuration/Service.pm | 5 +++ Sip/MsgType.pm | 73 +++++++++++++++++++++++------------- 4 files changed, 60 insertions(+), 26 deletions(-) diff --git a/SIPServer.pm b/SIPServer.pm index 1aba170..a1ab98c 100755 --- a/SIPServer.pm +++ b/SIPServer.pm @@ -185,6 +185,13 @@ sub raw_transport { next; } $input =~ s/[\r\n]+$//sm; # Strip off trailing line terminator + if ($input =~ /^99/) { # SC Status + unless ($service->allow_sc_status_then_login()) { + die 'raw_transport: sending SC status before login not enabled, exiting'; + } + Sip::MsgType::handle($input, $self, SC_STATUS); + next; + } last if Sip::MsgType::handle($input, $self, LOGIN); } }; diff --git a/SIPconfig.xml b/SIPconfig.xml index e5feefd..873f074 100644 --- a/SIPconfig.xml +++ b/SIPconfig.xml @@ -45,6 +45,7 @@ port="127.0.0.1:6001/tcp" transport="RAW" protocol="SIP/2.00" + allow_sc_status_then_login="disabled" timeout="60" /> diff --git a/Sip/Configuration/Service.pm b/Sip/Configuration/Service.pm index 1c1fb7f..88fe971 100644 --- a/Sip/Configuration/Service.pm +++ b/Sip/Configuration/Service.pm @@ -39,4 +39,9 @@ sub timeout { return $self->{timeout} || $self->SUPER::timeout(); } +sub allow_sc_status_then_login { + my $self = shift; + return $self->{'allow_sc_status_then_login'} =~ /true|yes|enabled/i ? 1 : 0; +} + 1; diff --git a/Sip/MsgType.pm b/Sip/MsgType.pm index 1c4b080..eec6b70 100644 --- a/Sip/MsgType.pm +++ b/Sip/MsgType.pm @@ -771,6 +771,21 @@ sub handle_sc_status { $protocol_version = $new_proto; } + unless (exists $self->{account}) { + # If we haven't logged in yet, go ahead and + # return the SC status anyway, arbitrarily using the + # first account in Perl string sort order to specify + # the account, institution, and ILS. This supports + # raw clients such as Relais that insist on sending 99 first + # before 93. + syslog('LOG_INFO', 'sending SC status without logging in first'); + my $mock_server; + $mock_server->{config} = $server->{config}; + my $uid = (sort keys %{ $server->{config}->{accounts} })[0]; + _load_ils_handler($mock_server, $uid); + return send_acs_status($self, $mock_server) ? SC_STATUS : ''; + } + if ($status == SC_STATUS_PAPER) { syslog("LOG_WARNING", "Self-Check unit '%s@%s' out of paper", $self->{account}->{id}, $self->{account}->{institution}); @@ -832,32 +847,7 @@ sub handle_login { syslog("LOG_WARNING", "MsgType::handle_login: Invalid password for login '$uid'"); $status = 0; } else { - # Store the active account someplace handy for everybody else to find. - $server->{account} = $server->{config}->{accounts}->{$uid}; - $inst = $server->{account}->{institution}; - $server->{institution} = $server->{config}->{institutions}->{$inst}; - $server->{policy} = $server->{institution}->{policy}; - - - syslog("LOG_INFO", "Successful login for '%s' of '%s'", $server->{account}->{id}, $inst); - # - # initialize connection to ILS - # - my $module = $server->{config}->{institutions}->{$inst}->{implementation}; - $module->use; - - if ($@) { - syslog("LOG_ERR", "%s: Loading ILS implementation '%s' for institution '%s' failed", - $server->{service}, $module, $inst); - die("Failed to load ILS implementation '$module'"); - } - - $server->{ils} = $module->new($server->{institution}, $server->{account}); - - if (!$server->{ils}) { - syslog("LOG_ERR", "%s: ILS connection to '%s' failed", $server->{service}, $inst); - die("Unable to connect to ILS '$inst'"); - } + _load_ils_handler($server, $uid); } $self->write_msg(LOGIN_RESP . $status); @@ -865,6 +855,37 @@ sub handle_login { return $status ? LOGIN : ''; } +sub _load_ils_handler { + my ($server, $uid) = @_; + + # Store the active account someplace handy for everybody else to find. + $server->{account} = $server->{config}->{accounts}->{$uid}; + my $inst = $server->{account}->{institution}; + $server->{institution} = $server->{config}->{institutions}->{$inst}; + $server->{policy} = $server->{institution}->{policy}; + + + syslog("LOG_INFO", "Successful login for '%s' of '%s'", $server->{account}->{id}, $inst); + # + # initialize connection to ILS + # + my $module = $server->{config}->{institutions}->{$inst}->{implementation}; + $module->use; + + if ($@) { + syslog("LOG_ERR", "%s: Loading ILS implementation '%s' for institution '%s' failed", + $server->{service}, $module, $inst); + die("Failed to load ILS implementation '$module'"); + } + + $server->{ils} = $module->new($server->{institution}, $server->{account}); + + if (!$server->{ils}) { + syslog("LOG_ERR", "%s: ILS connection to '%s' failed", $server->{service}, $inst); + die("Unable to connect to ILS '$inst'"); + } +} + # # Build the detailed summary information for the Patron # Information Response message based on the first 'Y' that appears -- 2.43.2