use Carp;
use Getopt::Long;
-use Time::HiRes qw (gettimeofday tv_interval);
+use Time::HiRes qw (usleep gettimeofday tv_interval);
use POSIX qw(:sys_wait_h errno_h signal_h);
use MIME::Parser;
use PMG::pmgcfg;
use PMG::Utils;
use PMG::Cluster;
+use PMG::ClusterConfig;
use PMG::DBTools;
use PMG::RuleDB;
use PMG::RuleCache;
use PMG::ModGroup;
use PMG::AtomicFile;
+use PMG::LDAPConfig;
use PMG::LDAPSet;
use PMG::Config;
use PMG::MailQueue;
my $opt_commandline = [$0, @ARGV];
my $opt_max_dequeue = 1;
-my $opt_dequeue_time = 60*2;
+my $opt_dequeue_time = 30;
my $opt_ext_port = 10024;
my $opt_int_port = 10023;
my $max_spare_servers = 0;
my $max_requests = 1;
-# create spool directories
-PMG::MailQueue::create_sppoldirs();
-
if (!$opt_testmode) {
my $pmg_cfg = PMG::Config->new();
$self->{pmg_cfg} = PMG::Config->new();
$self->{cinfo} = PVE::INotify::read_file("cluster.conf");
+ # create spool directories
+ PMG::MailQueue::create_spooldirs($self->{cinfo}->{local}->{cid});
+
eval {
my $dbh = PMG::DBTools::open_ruledb ($database);
$self->{ruledb} = PMG::RuleDB->new ($dbh);
}
# create LDAP object
- $self->{ldap} = PMG::LDAPSet->new_from_pmg_cfg($self->{pmg_cfg}, 1);
+ my $ldapconf = PVE::INotify::read_file('pmg-ldap.conf');
+ $self->{ldap} = PMG::LDAPSet->new_from_ldap_cfg($ldapconf, 1);
$self->{reload_config} = 0;
}
$self->{ruledb}->close () if $self->{ruledb};
}
+my $last_dequeue_time = 0;
+
sub run_dequeue {
my $self = shift;
+ my $err;
+
# do database maintainance here
+ # this is called every 30 secends
+ eval {
+ PMG::Utils::update_node_status_rrd();
+ };
+ if ($err = $@) {
+ $self->log(0, "ERROR: $err");
+ # continue
+ }
+
+ my $ctime = time();
+ my $tdiff = $ctime - $last_dequeue_time;
+
+ # return if tdiff less than 2 minutes
+ return if $tdiff < 2*60;
+
+ $last_dequeue_time = $ctime;
+
$self->log (2, "starting database maintainance");
my ($csec, $usec) = gettimeofday ();
eval {
$dbh = PMG::DBTools::open_ruledb($database);
};
- my $err = $@;
-
- if ($err) {
- $self->log (0, msgquote("ERROR: $err"));
+ if ($err = $@) {
+ $self->log (0, "ERROR: $err");
return;
}
my $ptime = int (($csec_end-$csec)*1000 + ($usec_end - $usec)/1000);
if ($err) {
- $self->log (0, msgquote($err));
+ $self->log (0, $err);
} else {
$self->log (2, "end database maintainance ($ptime ms)");
}
$queue = $smtp->{queue};
$queue->{sa} = $self->{sa};
+ $queue->{clamav_heuristic_score} =
+ $opt_testmode ? 100 : $pmg_cfg->get('spam', 'clamav_heuristic_score');
$queue->{lic_valid} = 1;
# test for virus first
- $queue->{vinfo} = PMG::Utils::analyze_virus(
+ my $vinfo = PMG::Utils::analyze_virus(
$queue, $queue->{dataname}, $pmg_cfg, $opt_testmode);
+ if ($vinfo && $vinfo =~ m/^Heuristics\.(.+)$/) {
+ my $hit = $1;
+ $queue->{clamav_heuristic} = $hit;
+ $vinfo = undef;
+ }
+
+ $queue->{vinfo} = $vinfo;
+
# always add this headers to incoming mails
# to enable user to report false negatives
if (!$msginfo->{trusted}) {
eval {
my $dbh = $self->{ruledb}->{dbh};
+
my $where = "";
foreach my $rid (@$matching_rules) {
$where .= $where ? " OR ID = $rid" : "ID = $rid";
}
- if ($where) {
- $dbh->do ("UPDATE Rule " .
- "SET Count = Count + 1 " .
- "WHERE $where");
- }
+
+ $dbh->do ("UPDATE Rule SET Count = Count + 1 WHERE $where") if $where;
my $insert_cmds = "SELECT nextval ('cstatistic_id_seq');INSERT INTO CStatistic " .
"(CID, RID, ID, Time, Bytes, Direction, Spamlevel, VirusInfo, PTime, Sender) VALUES (" .
- "$lcid, currval ('cstatistic_id_seq'), currval ('cstatistic_id_seq'),";
+ "$lcid, currval('cstatistic_id_seq'), currval('cstatistic_id_seq'),";
$insert_cmds .= $queue->{rtime} . ',';
$insert_cmds .= $queue->{bytes} . ',';
- $insert_cmds .= $dbh->quote ($msginfo->{trusted} ? 0 : 1) . ',';
+ $insert_cmds .= $dbh->quote($msginfo->{trusted} ? 0 : 1) . ',';
$insert_cmds .= ($queue->{sa_score} || 0) . ',';
- $insert_cmds .= $dbh->quote ($queue->{vinfo}) . ',';
+ $insert_cmds .= $dbh->quote($queue->{vinfo}) . ',';
$insert_cmds .= $time_total . ',';
- $insert_cmds .= $dbh->quote ($msginfo->{sender}) . ');';
+ $insert_cmds .= $dbh->quote($msginfo->{sender}) . ');';
foreach my $r (@{$msginfo->{targets}}) {
- my $tmp = $dbh->quote ($r);
+ my $tmp = $dbh->quote($r);
my $blocked = $queue->{status}->{$r} eq 'blocked' ? 1 : 0;
$insert_cmds .= "INSERT INTO CReceivers (CStatistic_CID, CStatistic_RID, Receiver, Blocked) " .
"VALUES ($lcid, currval ('cstatistic_id_seq'), $tmp, '$blocked'); ";
}
- $dbh->do ($insert_cmds);
+ $dbh->do($insert_cmds);
};
-
# save $err (because log clears $@)
$err = $@;
my $ptspam = ($queue->{ptime_spam} || 0)/1000;
my $ptclam = ($queue->{ptime_clam} || 0)/1000;
- $self->log (3, "$queue->{logid}: processing time: ${time_total} seconds ($ptspam, $ptclam)");
+ $self->log(3, "$queue->{logid}: processing time: ${time_total} seconds ($ptspam, $ptclam)");
$msginfo->{test_fh}->close if $opt_testmode;
- die $err if ($err);
+ die $err if $err;
}
+my $initial_memory_usage;
sub process_request {
my $self = shift;
kill(15, $prop->{ppid}) if $opt_testmode;
my $mem = PVE::ProcFSTools::read_memory_usage();
+ if (!defined($initial_memory_usage) || ($prop->{requests} < 10)) {
+ $initial_memory_usage = $mem->{resident};
+ }
if ($opt_testmode) {
$self->log (0, "memory usage: $mem->{size} bytes");
if ($self->{errors}) {
$self->log (0, "fast exit because of errors (free $mem->{size} bytes)");
$self->done (1);
- } elsif ($mem->{size} > (300*1024*1024)) {
- $self->log (0, "fast exit to reduce server load (free $mem->{size} bytes)");
- $self->done (1);
- }
+ } else {
+ my $diff = $mem->{resident} - $initial_memory_usage;
+ if ($diff > 5*1024*1024) {
+ $self->log (0, "fast exit to reduce server load (free $diff bytes)");
+ $self->done (1);
+ }
+ }
}
$self->done (1) if $err;
}
# nicely shutdown childs (give them max 30 seconds to shut down)
- my $previous_alarm = alarm (30);
+ my $previous_alarm = alarm(30);
eval {
local $SIG{ALRM} = sub { die "Timed Out!\n" };
my $pid;
1 while ((($pid = waitpid (-1, 0)) > 0) || ($! == EINTR));
+
+ alarm(0); # avoid race
};
alarm ($previous_alarm);
}
$server->run ();
} else {
if (fork) {
- $server->run ();
+ $server->run();
} else {
- sleep (1);
+
my $sender ='sender@proxtest.com';
my $targets = ['target1@proxtest.com',
'target2@proxtest.com',
'target3@proxtest.com'];
- my $smtp = Net::SMTP->new ('127.0.0.1', Port => 10023);
-
- die "unable to connect $!" if !$smtp;
+ my $smtp;
+ while (!$smtp) {
+ $smtp = Net::SMTP->new ('127.0.0.1', Port => 10023);
+ last if $smtp;
+ usleep(10);
+ }
# syslog ('info', "connected to " . $smtp->domain);