LP#1338731: support clients that send 99 then 93 when starting a raw connection
authorGalen Charlton <gmc@esilibrary.com>
Mon, 7 Jul 2014 19:01:41 +0000 (12:01 -0700)
committerBill Erickson <berick@esilibrary.com>
Fri, 8 Aug 2014 14:08:35 +0000 (10:08 -0400)
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 <gmc@esilibrary.com>
SIPServer.pm
SIPconfig.xml
Sip/Configuration/Service.pm
Sip/MsgType.pm

index a826263..8e5d83e 100644 (file)
@@ -172,6 +172,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);
     }
     };
index e5feefd..873f074 100644 (file)
@@ -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" />
   </listeners>
 
index 1c1fb7f..88fe971 100644 (file)
@@ -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;
index 1c4b080..eec6b70 100644 (file)
@@ -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