$ref->{poolObj} = $clientPool; exit 1 if ($clientPool->startPool(baseThreads => 10, moduleName => "SERVER::Main", subName => "clientThreadPool", values => $ref)); #### # Open Server Socket my $sock = IO::Socket::INET->new(Proto => 'tcp', LocalAddr => $servername, LocalPort => $port, Listen => SOMAXCONN, Reuse => 1, Blocking => 0); our $selSock = IO::Select->new($sock); #some more code is here, like initializing our db connection, and log4perl logger while(my @ready = $selSock->can_read) { foreach $_ (@ready) { if ($_ == $sock) { $logger->info("Base socket is " . $sock); $logger->info("Adding new socket"); #create a new socket my $newSock = $sock->accept or die; $logger->info("Added new socket " . $newSock); $selSock->add($newSock); my $fd = fileno $newSock; my $address = inet_ntoa($newSock->peeraddr); # enqueue client connection to be processed my @values = ($fd, $address); if ($clientPool->queueJob(queueValues => \@values)) { $logger->error("Failed to queue client connection"); # trash packets received from client my $trash = <$newSock>; send($newSock, "*** ENQUEUE_FAILED ***", 0); send($newSock, "*** ZERO_BYTES_LEFT ***", 0); $selSock->remove($newSock); shutdown($newSock, 2); close $newSock; } } } } #### my $fd = @$work[0]; our $clientaddr = @$work[1]; my $selSock = $main::selSock; # open file handle to read from... if fail to read error # error can not be reported back to end user # check has been implemented so dev can identify problem by error msg in server log unless (open $fh, '+<&=' . $fd) { $logger->error("Unable to open file handle for socket: $!"); $vars{poolObj}->setDone; next; } # Get the password sent by client my $clientpass = <$fh>; #### # create and add socket file handle so it can be checked within the while loop my $select = IO::Select->new(); $select->add($fh); my $last = 1; while ($last) { my $subroutineCall; my $command; my $completeLine = ""; # check if anything is ready to be received from client my @ready = $select->can_read(.1); next unless (@ready); # loop while receiving from the client untill a full msg has been received as identified by our flags while (defined (my $line = <$fh>)) { if ($line =~ /\*\*\* CLOSE_CONNECTION_CLIENT \*\*\*\n$/) { $logger->info("Client closed connection to the server"); $last = 0; $selSock->remove($fh); shutdown($fh, 2); close $fh; last; } $completeLine .= $line; if ($completeLine =~ /(.+) \*\*\* COMMAND_INPUT \*\*\* (.+) \*\*\* COMMAND_INPUT_END \*\*\*\n$/is) { $subroutineCall = $1; $command = $2; $logger->info("Processing message \"" . $command . "\""); last; } } if ($last) { #checking if the subroutine call is defined, if not, it kills that client connection (for cases of closing out of a client window and it sending the empty string) if(defined($subroutineCall)){ $logger->debug("Calling subroutine '${subroutineCall}'"); my ($string) = executeCommand(subCall => $subroutineCall, command => $command); send($fh, "$string\n*** ZERO_BYTES_LEFT ***" , 0); }else{ $logger->info("Undefined subroutine passed, closing client connection."); $last = 0; $selSock->remove($fh); shutdown($fh, 2); close $fh; last; } } } #### # execute the command and save results in a file handle to reduce memory usage if (($head =~ /.+/) && ($tail =~ /.+/)) { my @lastLines = (); my $length; open (my $fh, $vars{cmd} . " 2>&1|") or die; while (<$fh>) { #$logger->info($fh . " " . $_); if ($_ =~ /$tail/ims) { #found the last line, terminate loop, do not append the output $tailFound = 1; last; } if($headFound){ #the header line is already found and ignored, so safe to apprend output $output .= $_; } if (!$headFound and $_ =~ /$head/ims) { #next lines will be the matched output $headFound = 1; } #keeps track of the most recent N lines push(@lastLines, $_); my $length = @lastLines; if($length >= $vars{lastNLines}){ shift(@lastLines); } #$output .= $_; } unless ($headFound && $tailFound) { $output = "\n\nCould not match command output. Printing the last $vars{lastNLines} lines:\n"; $output .= join("", @lastLines); } close ($fh); } else { open (my $fh, $vars{cmd} . " 2>&1|") or die; while (<$fh>) { #$logger->info($fh . " " . $_); $output .= $_; } close ($fh); }