From 2e500c7188888a754e423ee39fa18567a512989d Mon Sep 17 00:00:00 2001 From: Colin Campbell Date: Wed, 23 Dec 2015 10:46:46 +0000 Subject: [PATCH] Bug 15418 Use Fork Net::Server personality for sip Merge in changes PTFS-Europe has been running in production Changes the Net::Server personality to Fork resourcs are now allocated on a per connection basis and freed on the client disconnecting. Some cleanup has been done to the conns loop in the sipserver to better check the status. The loop can probably be further improved. For added stability expecially if connections are running round the clock. I would recommend specifying pid_file in the config and sending a sighup to the pid therein when the system is inactive it will cause the controller to close current connections and reread the configuration. This should avoid problems with database handles which have "gone stale" and need restarting --- C4/SIP/SIPServer.pm | 114 +++++++++++++++++++++++++++++++--------------------- etc/SIPconfig.xml | 20 ++++----- 2 files changed, 80 insertions(+), 54 deletions(-) diff --git a/C4/SIP/SIPServer.pm b/C4/SIP/SIPServer.pm index 8722ab6..0aa30fe 100755 --- a/C4/SIP/SIPServer.pm +++ b/C4/SIP/SIPServer.pm @@ -6,7 +6,6 @@ use warnings; use FindBin qw($Bin); use lib "$Bin"; use Sys::Syslog qw(syslog); -use Net::Server::PreFork; use IO::Socket::INET; use Socket qw(:DEFAULT :crlf); require UNIVERSAL::require; @@ -17,7 +16,7 @@ use C4::SIP::Sip::Checksum qw(checksum verify_cksum); use C4::SIP::Sip::MsgType qw( handle login_core ); use C4::SIP::Sip qw( read_SIP_packet ); -use base qw(Net::Server::PreFork); +use base qw(Net::Server::Fork); use constant LOG_SIP => "local6"; # Local alias for the logging facility @@ -124,28 +123,26 @@ sub process_request { sub raw_transport { my $self = shift; - my ($input); my $service = $self->{service}; while (!$self->{account}) { - local $SIG{ALRM} = sub { die "raw_transport Timed Out!\n"; }; - syslog("LOG_DEBUG", "raw_transport: timeout is %d", $service->{timeout}); - $input = read_SIP_packet(*STDIN); - if (!$input) { - # EOF on the socket - syslog("LOG_INFO", "raw_transport: shutting down: EOF during login"); - return; - } - $input =~ s/[\r\n]+$//sm; # Strip off trailing line terminator(s) - last if C4::SIP::Sip::MsgType::handle($input, $self, LOGIN); + my $input = read_request(); + if (!$input) { + # EOF on the socket + syslog("LOG_INFO", "raw_transport: shutting down: EOF during login"); + return; + } + $input =~ s/[\r\n]+$//sm; # Strip off trailing line terminator(s) + last if C4::SIP::Sip::MsgType::handle($input, $self, LOGIN); } syslog("LOG_DEBUG", "raw_transport: uname/inst: '%s/%s'", - $self->{account}->{id}, - $self->{account}->{institution}); + $self->{account}->{id}, + $self->{account}->{institution}); $self->sip_protocol_loop(); syslog("LOG_INFO", "raw_transport: shutting down"); + return; } sub get_clean_string { @@ -230,6 +227,7 @@ sub telnet_transport { syslog("LOG_DEBUG", "telnet_transport: uname/inst: '%s/%s'", $account->{id}, $account->{institution}); $self->sip_protocol_loop(); syslog("LOG_INFO", "telnet_transport: shutting down"); + return; } # @@ -241,8 +239,6 @@ sub sip_protocol_loop { my $self = shift; my $service = $self->{service}; my $config = $self->{config}; - my $timeout = $self->{service}->{timeout} || $config->{timeout} || 30; - my $input; # The spec says the first message will be: # SIP v1: SC_STATUS @@ -258,37 +254,65 @@ sub sip_protocol_loop { # # In short, we'll take any valid message here. #my $expect = SC_STATUS; - local $SIG{ALRM} = sub { die "SIP Timed Out!\n"; }; - my $expect = ''; - while (1) { - alarm $timeout; - $input = read_SIP_packet(*STDIN); - unless ($input) { - return; # EOF + while ( my $inputbuf = read_request() ) { + if ( !defined $inputbuf ) { + return; # EOF } - # begin input hacks ... a cheap stand in for better Telnet layer - $input =~ s/^[^A-z0-9]+//s; # Kill leading bad characters... like Telnet handshakers - $input =~ s/[^A-z0-9]+$//s; # Same on the end, should get DOSsy ^M line-endings too. - while (chomp($input)) {warn "Extra line ending on input";} - unless ($input) { - syslog("LOG_ERR", "sip_protocol_loop: empty input skipped"); + + unless ($inputbuf) { + syslog( "LOG_ERR", "sip_protocol_loop: empty input skipped" ); print("96$CR"); next; - } - # end cheap input hacks - my $status = handle($input, $self, $expect); - if (!$status) { - syslog("LOG_ERR", "sip_protocol_loop: failed to handle %s",substr($input,0,2)); - } - next if $status eq REQUEST_ACS_RESEND; - if ($expect && ($status ne $expect)) { - # We received a non-"RESEND" that wasn't what we were expecting. - syslog("LOG_ERR", "sip_protocol_loop: expected %s, received %s, exiting", $expect, $input); - } - # We successfully received and processed what we were expecting - $expect = ''; - alarm 0; - } + } + + # end cheap input hacks + my $status = C4::SIP::Sip::MsgType::handle( $inputbuf, $self, q{} ); + if ( !$status ) { + syslog( + "LOG_ERR", + "sip_protocol_loop: failed to handle %s", + substr( $inputbuf, 0, 2 ) + ); + } + next if $status eq REQUEST_ACS_RESEND; + } + return; +} + +sub read_request { + my $raw_length; + local $/ = "\015"; + + # proper SPEC: (octal) \015 = (hex) x0D = (dec) 13 = (ascii) carriage return + my $buffer = ; + if ( defined $buffer ) { + STDIN->flush(); # clear an extra linefeed + chomp $buffer; + syslog( "LOG_INFO", "read_SIP_packet, INPUT MSG: '$buffer'" ); + $raw_length = length $buffer; + $buffer =~ s/^\s*[^A-z0-9]+//s; +# Every line must start with a "real" character. Not whitespace, control chars, etc. + $buffer =~ s/[^A-z0-9]+$//s; + +# Same for the end. Note this catches the problem some clients have sending empty fields at the end, like ||| + $buffer =~ s/\015?\012//g; # Extra line breaks must die + $buffer =~ s/\015?\012//s; # Extra line breaks must die + $buffer =~ s/\015*\012*$//s; + + # treat as one line to include the extra linebreaks we are trying to remove! + } + else { + syslog( 'LOG_DEBUG', 'EOF returned on read' ); + return; + } + my $len = length $buffer; + if ( $len != $raw_length ) { + my $trim = $raw_length - $len; + syslog( "LOG_DEBUG", "read_SIP_packet, trimmed $trim character(s) " ); + } + + syslog( "LOG_INFO", "INPUT MSG: '$buffer'" ); + return $buffer; } 1; diff --git a/etc/SIPconfig.xml b/etc/SIPconfig.xml index 141bc4f..3768ad6 100644 --- a/etc/SIPconfig.xml +++ b/etc/SIPconfig.xml @@ -3,7 +3,7 @@ @@ -13,15 +13,17 @@ log_file='Sys::Syslog' syslog_ident='koha_sip' syslog_facility='local6' + setsid="1" /> + - -- 2.5.0