self-service keepalives
[freeside.git] / FS / bin / freeside-selfservice-server
index 1071039..a83664d 100644 (file)
@@ -8,14 +8,15 @@
 # Proc::Daemon or somesuch
 
 use strict;
-use vars qw( $Debug %kids $kids $max_kids $shutdown $log_file $ssh_pid );
+use vars qw( $Debug %kids $kids $max_kids $shutdown $log_file $ssh_pid
+             $keepalives );
 use subs qw( lock_write unlock_write );
 use Fcntl qw(:flock);
 use POSIX qw(:sys_wait_h setsid);
 use IO::Handle;
 use IO::Select;
 use IO::File;
-use Storable qw(nstore_fd fd_retrieve);
+use Storable 2.09 qw(nstore_fd fd_retrieve);
 use Net::SSH qw(sshopen2);
 use FS::UID qw(adminsuidsetup forksuidsetup);
 use FS::ClientAPI;
@@ -24,17 +25,20 @@ use FS::Conf;
 use FS::cust_bill;
 use FS::cust_pkg;
 
-$Debug = 2; # >= 2 will log packet contents, including potentially compromising
+$Debug = 1; # >= 2 will log packet contents, including potentially compromising
             # information
 
 $shutdown = 0;
 $max_kids = '10'; #?
+$keepalives = 0; #let clientd turn it on, so we don't barf on old ones
 $kids = 0;
 
 my $user = shift or die &usage;
 my $machine = shift or die &usage;
-my $pid_file = "/var/run/freeside-selfservice-server.$user.pid";
-#my $pid_file = "/var/run/freeside-selfservice-server.$user.pid"; $FS::UID::datasrc not posible, but should include machine name at least, hmm
+my $tag = scalar(@ARGV) ? shift : '';
+
+# $FS::UID::datasrc not posible
+my $pid_file = "/var/run/freeside-selfservice-server.$user.$machine.pid";
 
 my $lock_file = "/usr/local/etc/freeside/selfservice.$machine.writelock";
 open(LOCKFILE,">$lock_file") or die "can't open $lock_file: $!";
@@ -50,12 +54,13 @@ while (1) {
   my($writer,$reader,$error) = (new IO::Handle, new IO::Handle, new IO::Handle);
   warn "connecting to $machine\n" if $Debug;
 
-  $ssh_pid = sshopen2($machine,$reader,$writer,$clientd);
+  $ssh_pid = sshopen2($machine,$reader,$writer,$clientd,$tag);
 
 #  nstore_fd(\*writer, {'hi'=>'there'});
 
   warn "entering main loop\n" if $Debug;
   my $undisp = 0;
+  my $keepalive_count = 0;
   my $s = IO::Select->new( $reader );
   while (1) {
 
@@ -66,6 +71,10 @@ while (1) {
     my @handles = $s->can_read(5);
     unless ( @handles ) {
       &shutdown if $shutdown;
+      if ( $keepalives && $keepalive_count++ > 10 ) {
+        $keepalive_count = 0;
+        nstore_fd( { _token => '_keepalive' }, $writer );
+      }
       next;
     }
 
@@ -73,11 +82,28 @@ while (1) {
 
     warn "receiving packet from client\n" if $Debug;
 
-    my $packet = fd_retrieve($reader);
+    my $packet = eval { fd_retrieve($reader); };
+    if ( $@ ) {
+      warn "Storable error receiving packet from client".
+           " (assuming lost connection): $@\n"
+        if $Debug;
+      if ( $ssh_pid ) {
+        warn "sending TERM signal to ssh process $ssh_pid\n" if $Debug;
+        kill 'TERM', $ssh_pid;
+        $ssh_pid = 0;
+      }
+      last;
+    }
     warn "packet received\n".
          join('', map { " $_=>$packet->{$_}\n" } keys %$packet )
       if $Debug > 1;
 
+    if ( $packet->{_packet} eq '_enable_keepalive' ) {
+      warn "enabling keep alives\n" if $Debug;
+      $keepalives=1;
+      next;
+    }
+
     #prevent runaway forking
     my $warnkids = 0;
     while ( $kids >= $max_kids ) {
@@ -94,9 +120,12 @@ while (1) {
       warn "child $pid spawned\n" if $Debug;
     } else { #kid time
 
-      #get new db handle
-      $FS::UID::dbh->{InactiveDestroy} = 1;
-      forksuidsetup($user);
+      ##get new db handle
+      #$FS::UID::dbh->{InactiveDestroy} = 1;
+      #forksuidsetup($user);
+
+      #get db handle
+      adminsuidsetup($user);
 
       my $type = $packet->{_packet};
       warn "calling $type handler\n" if $Debug; 
@@ -119,6 +148,9 @@ while (1) {
 
   }
 
+  warn "connection lost, reconnecting\n" if $Debug;
+  sleep 3;
+
 }
 
 ###
@@ -179,7 +211,7 @@ sub init {
   #eslaf
 
   $ENV{HOME} = (getpwuid($>))[7]; #for ssh
-  adminsuidsetup $user;
+  #adminsuidsetup $user;
 
   #$log_file = "/usr/local/etc/freeside/selfservice.". $FS::UID::datasrc; #MACHINE NAME
   $log_file = "/usr/local/etc/freeside/selfservice.$machine.log";