LP#1338731: support clients that send 99 then 93 when starting a raw connection user/gmcharlt/lp1338731_permit_99_then_93
authorGalen Charlton <gmc@esilibrary.com>
Mon, 7 Jul 2014 19:01:41 +0000 (12:01 -0700)
committerGalen Charlton <gmc@esilibrary.com>
Mon, 7 Jul 2014 19:01:41 +0000 (12:01 -0700)
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 36f505d..200f2cf 100644 (file)
@@ -169,6 +169,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 4892ca1..657b0ef 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