use Sip::Checksum qw(checksum verify_cksum);
use Sip::MsgType;
+use File::Queue;
+use Storable qw(freeze thaw);
+
+my $mp_fifo = new File::Queue ( "/tmp/SIPServer.mulitplex-fifo.$$");
+END { $mp_fifo->delete };
+
use constant LOG_SIP => "local6"; # Local alias for the logging facility
our $VERSION = 0.02;
}
my %active_connections;
+sub PERMAFROST {
+ while (my $login = $mp_fifo->deq) {
+ $login = thaw($login);
+ if ($$login{success}) {
+ $active_connections{$$login{id}} = $login;
+ } else {
+ delete $active_connections{$$login{id}};
+ }
+ }
+}
+
sub mux_input {
my $mself = shift;
my $mux = shift;
# check for kids that went away
REAPER();
+ # and process any pending logins
+ PERMAFROST();
+
+ my $c = scalar(keys %active_connections);
+ syslog("LOG_DEBUG", "multi: new active connection; $c total");
+
if ($kid_count >= $max_concurrent) {
# XXX should we say something to the client? maybe wait and try again?
syslog('LOG_ERR', "Unwilling to fork new child process, at least $max_concurrent already ongoing");
return;
}
- eval { &$transport($self, $str_fh) };
- if ($@) {
- syslog('LOG_ERR', "ILS login error: $@");
+ # We stick this here, assuming success. Cleanup comes later via PERMAFROST().
+ $active_connections{$conn_id} = { id => $conn_id, transport => $transport };
+
+ my $pid = fork();
+ if (!defined($pid) or $pid < 0) {
+ syslog('LOG_ERR', "Unable to fork new child process $!");
return;
}
- $active_connections{$conn_id} =
- { id => $conn_id,
- transport => $transport,
- net_server => bless({%$self}, ref($self))
- };
-
- # Evergreen, at least, needs a chance to clean up before forking for other requests
- $self->{ils}->disconnect() if (UNIVERSAL::can($self->{ils},'disconnect'));
-
- # Stash the ILS module somewhere handy for later
- $active_connections{$conn_id}->{ils} = ref($self->{ils});
-
- # And, if the ILS module wants to save some state, allow that
- $active_connections{$conn_id}->{state} = $self->{ils}->state() if (UNIVERSAL::can($self->{ils},'state'));;
+ if ($pid == 0) { # in kid
- delete $$self{ils};
+ eval { &$transport($self, $str_fh) };
- my $c = scalar(keys %active_connections);
- syslog("LOG_DEBUG", "multi: new active connection; $c total");
+ my $success = 1;
+ if ($@) {
+ syslog('LOG_ERR', "ILS login error: $@");
+ $success = 0;
+ exit(0);
+ }
+
+ # Evergreen, at least, needs a chance to clean up before forking for other requests
+ $self->{ils}->disconnect() if (UNIVERSAL::can($self->{ils},'disconnect'));
+
+ # Stash the ILS module somewhere handy for later
+ $self->{ils} = ref($self->{ils});
+
+ $mp_fifo->enq(
+ freeze({
+ id => $conn_id,
+ success => $success,
+ transport => $transport,
+ net_server => bless({%$self}, ref($self))
+ })
+ );
+
+ exit(0);
+ }
- return;
+ return; # NEXT CUSTOMER PLEASE STEP UP
}
$self = $active_connections{$conn_id}->{net_server};
die 'raw_transport: sending SC status before login not enabled, exiting';
}
Sip::MsgType::handle($input, $self, SC_STATUS);
+ $strikes++; # it's allowed, don't charge for it
next;
}
last if Sip::MsgType::handle($input, $self, LOGIN);