diff --git a/fhem/CHANGED b/fhem/CHANGED
index f3f53b2b6..9e8c59183 100644
--- a/fhem/CHANGED
+++ b/fhem/CHANGED
@@ -1,5 +1,6 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it.
+ - change: 93_Log2Syslog: some code changes and reviews
- bugfix: 70_DENON_AVR: fixed HTTP 403 (thx justme1968)
- bugfix : 73_AutoShuttersControl: fix shading drive if current position under
shading position
diff --git a/fhem/FHEM/93_Log2Syslog.pm b/fhem/FHEM/93_Log2Syslog.pm
index ad4ab2f90..b410e3adc 100644
--- a/fhem/FHEM/93_Log2Syslog.pm
+++ b/fhem/FHEM/93_Log2Syslog.pm
@@ -44,6 +44,7 @@ eval "use FHEM::Meta;1" or my $mod
# Versions History intern:
my %Log2Syslog_vNotesIntern = (
+ "5.10.2" => "08.04.2020 code changes to stabilize send process, minor fixes ",
"5.10.1" => "06.04.2020 support time-secfrac of RFC 3339, minor fix ",
"5.10.0" => "04.04.2020 new attribute 'timeSpec', send and parse messages according to UTC or Local time, some minor fixes (e.g. for Octet Count) ",
"5.9.0" => "01.04.2020 Parser UniFi Controller Syslog (BSD Format) and Netconsole messages, more code review (e.g. remove prototypes) ",
@@ -531,10 +532,14 @@ sub Log2Syslog_Read {
$i++;
$ocount = $+{ocount};
$tail = $+{tail};
+ next if(!$tail);
$msg = substr($tail,0,$ocount);
push @load, $msg;
- next if(!$tail);
- $tail = substr($tail,$ocount);
+ if(length($tail) >= $ocount) {
+ $tail = substr($tail,$ocount);
+ } else {
+ $tail = "";
+ }
Log2Syslog_Log3slog ($hash, 5, "Log2Syslog $name -> OCTETCOUNT$i: $ocount");
Log2Syslog_Log3slog ($hash, 5, "Log2Syslog $name -> MSG$i : $msg");
@@ -736,7 +741,7 @@ sub Log2Syslog_parsePayload {
my $pp = AttrVal($name, "parseProfile", $hash->{PROFILE});
my $severity = "";
my $facility = "";
- my @evf = split(",",AttrVal($name, "outputFields", "FAC,SEV,ID,CONT")); # auszugebene Felder im Event/Reading
+ my @evf = split q{,},AttrVal($name, "outputFields", "FAC,SEV,ID,CONT"); # auszugebene Felder im Event/Reading
my $ignore = 0;
my ($to,$Mmm,$dd,$day,$ietf,$err,$pl,$tail);
@@ -1381,7 +1386,7 @@ sub Log2Syslog_Get {
$ret .= "
";
$ret .= "";
if($prop && $prop =~ /[\d]+/) {
- my @hints = split(",",$prop);
+ my @hints = split q{,},$prop;
foreach (@hints) {
if(AttrVal("global","language","EN") eq "DE") {
$hs{$_} = $Log2Syslog_vHintsExt_de{$_};
@@ -1423,12 +1428,11 @@ sub Log2Syslog_Get {
$ret .= "
";
$i = 0;
for my $key (Log2Syslog_sortVersion("desc",keys %Log2Syslog_vNotesExtern)) {
- ($val0,$val1) = split(/\s/,$Log2Syslog_vNotesExtern{$key},2);
- $ret .= sprintf("$key | $val0 | $val1 | " );
- $ret .= "
";
+ ($val0,$val1) = split q{\s+},$Log2Syslog_vNotesExtern{$key},2;
+ $ret .= sprintf("$key | $val0 | $val1 | " );
+ $ret .= "";
$i++;
- if ($i & 1) {
- # $i ist ungerade
+ if ($i & 1) { # $i ist ungerade
$ret .= "";
} else {
$ret .= "
";
@@ -1523,19 +1527,25 @@ sub Log2Syslog_Attr {
InternalTimer(gettimeofday()+5, "Log2Syslog_trate", $hash, 0);
}
- if ($cmd eq "set" && $aName =~ /port|timeout/) {
- if($aVal !~ m/^\d+$/) { return " The Value of \"$aName\" is not valid. Use only figures !";}
+ if ($cmd eq "set") {
+ if($aName =~ /port/) {
+ if($aVal !~ m/^\d+$/) { return " The Value of \"$aName\" is not valid. Use only figures !";}
+
+ $hash->{HELPER}{MEMLOCK} = 1;
+ InternalTimer(gettimeofday()+2, "Log2Syslog_deleteMemLock", $hash, 0);
+
+ if($hash->{MODEL} =~ /Collector/ && $init_done) {
+ return qq{$aName "$aVal" is not valid because off privileged ports are only usable by super users. Use a port number grater than 1023.} if($aVal < 1024);
+ Log2Syslog_downServer($hash,1); # Serversocket schließen
+ InternalTimer(gettimeofday()+0.5, "Log2Syslog_initServer", "$name,global", 0);
+ readingsSingleUpdate ($hash, 'Parse_Err_No', 0, 1); # Fehlerzähler für Parse-Errors auf 0
+ } elsif ($hash->{MODEL} !~ /Collector/) {
+ Log2Syslog_closesock($hash,1); # Clientsocket schließen
+ }
+ }
- $hash->{HELPER}{MEMLOCK} = 1;
- InternalTimer(gettimeofday()+2, "Log2Syslog_deleteMemLock", $hash, 0);
-
- if($aName =~ /port/ && $hash->{MODEL} =~ /Collector/ && $init_done) {
- return qq{$aName "$aVal" is not valid because off privileged ports are only usable by super users. Use a port number grater than 1023.} if($aVal < 1024);
- Log2Syslog_downServer($hash,1); # Serversocket schließen
- InternalTimer(gettimeofday()+0.5, "Log2Syslog_initServer", "$name,global", 0);
- readingsSingleUpdate ($hash, 'Parse_Err_No', 0, 1); # Fehlerzähler für Parse-Errors auf 0
- } elsif ($aName =~ /port/ && $hash->{MODEL} !~ /Collector/) {
- Log2Syslog_closesock($hash,1); # Clientsocket schließen
+ if($aName =~ /timeout/) {
+ if($aVal !~ m/^\d+(.\d+)?$/) { return qq{The value of "$aName" is not valid. Use only integer or fractions of numbers like "0.7".}; }
}
}
@@ -1547,7 +1557,7 @@ sub Log2Syslog_Attr {
InternalTimer(gettimeofday()+2, "Log2Syslog_deleteMemLock", $hash, 0);
if($hash->{MODEL} eq "Collector") {
- Log2Syslog_downServer($hash,1); # Serversocket schließen
+ Log2Syslog_downServer($hash,1); # Serversocket schließen
InternalTimer(gettimeofday()+0.5, "Log2Syslog_initServer", "$name,global", 0);
readingsSingleUpdate ($hash, 'Parse_Err_No', 0, 1); # Fehlerzähler für Parse-Errors auf 0
} else {
@@ -1627,6 +1637,7 @@ sub Log2Syslog_eventlog {
my $rex = $hash->{HELPER}{EVNTLOG};
my $st = ReadingsVal($name,"state","active");
my $sendsev = AttrVal($name, "respectSeverity", ""); # Nachrichten welcher Schweregrade sollen gesendet werden
+ my $uef = AttrVal($name, "useEOF", 0);
my ($prival,$data,$sock,$pid,$sevAstxt);
if(IsDisabled($name)) {
@@ -1647,44 +1658,36 @@ sub Log2Syslog_eventlog {
my $max = int(@{$events});
my $tn = $dev->{NTFY_TRIGGERTIME};
my $ct = $dev->{CHANGETIME};
+
+ for (my $i = 0; $i < $max; $i++) {
+ my $txt = $events->[$i];
+ $txt = "" if(!defined($txt));
+ $txt = Log2Syslog_charfilter($hash,$txt);
+ my $tim = (($ct && $ct->[$i]) ? $ct->[$i] : $tn);
+ my ($date,$time) = split q{ }, $tim;
- ($sock,$st) = Log2Syslog_opensock($hash,0);
-
- if($sock) {
- for (my $i = 0; $i < $max; $i++) {
- my $txt = $events->[$i];
- $txt = "" if(!defined($txt));
- $txt = Log2Syslog_charfilter($hash,$txt);
- my $tim = (($ct && $ct->[$i]) ? $ct->[$i] : $tn);
- my ($date,$time) = split(" ",$tim);
-
- if($n =~ m/^$rex$/ || "$n:$txt" =~ m/^$rex$/ || "$tim:$n:$txt" =~ m/^$rex$/) {
- my $otp = "$n $txt";
- $otp = "$tim $otp" if AttrVal($name,'addTimestamp',0);
- ($prival,$sevAstxt) = Log2Syslog_setprival($hash,$txt);
- if($sendsev && $sendsev !~ m/$sevAstxt/) {
- # nicht senden wenn Severity nicht in "respectSeverity" enthalten
- Log2Syslog_Log3slog($name, 5, "Log2Syslog $name - Warning - Payload NOT sent due to Message Severity not in attribute \"respectSeverity\"\n");
- next;
- }
-
- ($data,$pid) = Log2Syslog_setpayload($hash,$prival,$date,$time,$otp,"event");
- next if(!$data);
-
- my $ret = syswrite ($sock,$data);
- if($ret && $ret > 0) {
- Log2Syslog_Log3slog($name, 4, "Log2Syslog $name - Payload sequence $pid sent\n");
- } else {
- my $err = $!;
- Log2Syslog_Log3slog($name, 3, "Log2Syslog $name - Warning - Payload sequence $pid NOT sent: $err\n");
- $st = "write error: $err";
- }
+ if($n =~ m/^$rex$/ || "$n:$txt" =~ m/^$rex$/ || "$tim:$n:$txt" =~ m/^$rex$/) {
+ my $otp = "$n $txt";
+ $otp = "$tim $otp" if AttrVal($name,'addTimestamp',0);
+ ($prival,$sevAstxt) = Log2Syslog_setprival($hash,$txt);
+ if($sendsev && $sendsev !~ m/$sevAstxt/) { # nicht senden wenn Severity nicht in "respectSeverity" enthalten
+ Log2Syslog_Log3slog($name, 5, "Log2Syslog $name - Warning - Payload NOT sent due to Message Severity not in attribute \"respectSeverity\"\n");
+ next;
}
- }
-
- my $uef = AttrVal($name, "useEOF", 0);
- Log2Syslog_closesock($hash) if($st =~ /^write error:.*/ || $uef);
- }
+
+ ($data,$pid) = Log2Syslog_setpayload($hash,$prival,$date,$time,$otp,"event");
+ next if(!$data);
+
+ ($sock,$st) = Log2Syslog_opensock($hash,0);
+
+ if ($sock) {
+ my $err = Log2Syslog_writeToSocket ($name,$sock,$data,$pid);
+ $st = $err if($err);
+
+ Log2Syslog_closesock($hash) if($uef);
+ }
+ }
+ }
my $evt = ($st eq $hash->{HELPER}{OLDSTATE})?0:1;
readingsSingleUpdate($hash, "state", $st, $evt);
@@ -1702,6 +1705,7 @@ sub Log2Syslog_fhemlog {
my $rex = $hash->{HELPER}{FHEMLOG};
my $st = ReadingsVal($name,"state","active");
my $sendsev = AttrVal($name, "respectSeverity", ""); # Nachrichten welcher Schweregrade sollen gesendet werden
+ my $uef = AttrVal($name, "useEOF", 0);
my ($prival,$sock,$err,$ret,$data,$pid,$sevAstxt);
if(IsDisabled($name)) {
@@ -1736,17 +1740,10 @@ sub Log2Syslog_fhemlog {
($sock,$st) = Log2Syslog_opensock($hash,0);
if ($sock) {
- $ret = syswrite($sock,$data) if($data);
- if($ret && $ret > 0) {
- Log2Syslog_Log3slog($name, 4, "Log2Syslog $name - Payload sequence $pid sent\n");
- } else {
- $err = $!;
- $st = "write error: $err";
- Log2Syslog_Log3slog($name, 3, "Log2Syslog $name - Warning - Payload sequence $pid NOT sent: $err\n");
- }
+ my $err = Log2Syslog_writeToSocket ($name,$sock,$data,$pid);
+ $st = $err if($err);
- my $uef = AttrVal($name, "useEOF", 0);
- Log2Syslog_closesock($hash) if($st =~ /^write error:.*/ || $uef);
+ Log2Syslog_closesock($hash) if($uef);
}
}
@@ -1774,7 +1771,7 @@ sub Log2Syslog_sendTestMsg {
} else {
$ts = TimeNow();
- ($date,$time) = split(" ",$ts);
+ ($date,$time) = split q{ }, $ts;
$date =~ s/\./-/g;
$tim = $date." ".$time;
@@ -1800,7 +1797,7 @@ sub Log2Syslog_sendTestMsg {
}
my $uef = AttrVal($name, "useEOF", 0);
- Log2Syslog_closesock($hash) if($st =~ /^write error:.*/ || $uef);
+ Log2Syslog_closesock($hash) if($uef);
}
my $evt = ($st eq $hash->{HELPER}{OLDSTATE})?0:1;
@@ -1817,7 +1814,7 @@ sub Log2Syslog_setidrex {
my ($hash,$a) = @_;
$hash->{HELPER}{EVNTLOG} = (split("event:",$a))[1] if(lc($a) =~ m/^event:.*/);
- $hash->{HELPER}{FHEMLOG} = (split("fhem:",$a))[1] if(lc($a) =~ m/^fhem:.*/);
+ $hash->{HELPER}{FHEMLOG} = (split("fhem:", $a))[1] if(lc($a) =~ m/^fhem:.*/);
$hash->{HELPER}{IDENT} = (split("ident:",$a))[1] if(lc($a) =~ m/^ident:.*/);
return;
@@ -1850,19 +1847,26 @@ return($txt);
sub Log2Syslog_opensock {
my ($hash,$supresslog) = @_;
my $name = $hash->{NAME};
- my $host = $hash->{PEERHOST};
- my $port = AttrVal($name, "TLS", 0)?AttrVal($name, "port", 6514):AttrVal($name, "port", 514);
my $protocol = lc(AttrVal($name, "protocol", "udp"));
+ my $port = AttrVal($name, "TLS", 0)?AttrVal($name, "port", 6514):AttrVal($name, "port", 514);
my $st = "active";
- my $timeout = AttrVal($name, "timeout", 0.5);
- my $ssldbg = AttrVal($name, "ssldebug", 0);
- my ($sock,$lo,$lof,$sslver,$sslalgo);
+
+ if($hash->{CLIENTSOCKET}) {
+ if($protocol eq "tcp") {
+ my $sock = $hash->{CLIENTSOCKET};
+ return($hash->{CLIENTSOCKET},$st) if($sock->connected());
+ Log2Syslog_closesock ($hash);
+ } else {
+ return($hash->{CLIENTSOCKET},$st);
+ }
+ }
return if($init_done != 1 || $hash->{MODEL} !~ /Sender/);
- if($hash->{CLIENTSOCKET}) {
- return($hash->{CLIENTSOCKET},$st);
- }
+ my $host = $hash->{PEERHOST};
+ my $timeout = AttrVal($name, "timeout", 0.5);
+ my $ssldbg = AttrVal($name, "ssldebug", 0);
+ my ($sock,$lo,$lof,$sslver,$sslalgo);
Log2Syslog_Log3slog ($hash, 3, "Log2Syslog $name - Opening client socket on port \"$port\" ...") if(!$supresslog);
@@ -1934,7 +1938,7 @@ sub Log2Syslog_opensock {
$hash->{HELPER}{SSLALGO} = $sslalgo;
}
- Log2Syslog_Log3slog($name, 3, "Log2Syslog $name - $lo") if($lo);
+ Log2Syslog_Log3slog($name, 3, "Log2Syslog $name - $lo") if($lo);
Log2Syslog_Log3slog($name, 3, "Log2Syslog $name - $lof") if($lof && !$supresslog && !$hash->{CLIENTSOCKET});
$hash->{CLIENTSOCKET} = $sock if($sock);
@@ -1942,6 +1946,32 @@ sub Log2Syslog_opensock {
return($sock,$st);
}
+################################################################
+# schreibt Daten in geöffneten Socket
+################################################################
+sub Log2Syslog_writeToSocket {
+ my ($name,$sock,$data,$pid) = @_;
+ my $hash = $defs{$name};
+
+ use bytes;
+ my $err = "";
+ my $ld = length $data;
+ my $ret = syswrite ($sock,$data);
+
+ if(defined $ret && $ret == $ld) {
+ Log2Syslog_Log3slog($name, 4, "Log2Syslog $name - Payload sequence $pid sent. ($ret bytes)\n");
+ } elsif (defined $ret && $ret != $ld) {
+ Log2Syslog_Log3slog($name, 3, "Log2Syslog $name - Warning - Payload sequence $pid NOT completely sent: $ret of $ld bytes \n");
+ } else {
+ my $e = $!;
+ $err = "write error: $e";
+ Log2Syslog_Log3slog($name, 3, "Log2Syslog $name - Warning - Payload sequence $pid NOT sent: $e\n");
+ delete($hash->{CLIENTSOCKET});
+ }
+
+return ($err);
+}
+
###############################################################################
# Socket schließen
###############################################################################
@@ -1952,19 +1982,25 @@ sub Log2Syslog_closesock {
my $evt;
my $sock = $hash->{CLIENTSOCKET};
- if($sock) {
- Log2Syslog_Log3slog ($hash, 3, "Log2Syslog $name - Closing client socket ...") if($dolog);
- shutdown($sock, 1);
- if(AttrVal($hash->{NAME}, "TLS", 0) && ReadingsVal($name,"SSL_Algorithm", "n.a.") ne "n.a.") {
- $sock->close(SSL_no_shutdown => 1);
- $hash->{HELPER}{SSLVER} = "n.a.";
- $hash->{HELPER}{SSLALGO} = "n.a.";
- readingsSingleUpdate($hash, "SSL_Version", "n.a.", 1);
- readingsSingleUpdate($hash, "SSL_Algorithm", "n.a.", 1);
- } else {
+
+ if($sock) {
+ if (!$sock->connected()) {
$sock->close();
+ Log2Syslog_Log3slog ($hash, 3, "Log2Syslog $name - Client socket already disconnected ... closed.") if($dolog);
+ } else {
+ Log2Syslog_Log3slog ($hash, 3, "Log2Syslog $name - Closing client socket ...") if($dolog);
+ shutdown($sock, 1);
+ if(AttrVal($hash->{NAME}, "TLS", 0) && ReadingsVal($name,"SSL_Algorithm", "n.a.") ne "n.a.") {
+ $sock->close(SSL_no_shutdown => 1);
+ $hash->{HELPER}{SSLVER} = "n.a.";
+ $hash->{HELPER}{SSLALGO} = "n.a.";
+ readingsSingleUpdate($hash, "SSL_Version", "n.a.", 1);
+ readingsSingleUpdate($hash, "SSL_Algorithm", "n.a.", 1);
+ } else {
+ $sock->close();
+ }
+ Log2Syslog_Log3slog ($hash, 3, "Log2Syslog $name - Client socket closed ...") if($dolog);
}
- Log2Syslog_Log3slog ($hash, 3, "Log2Syslog $name - Client socket closed ...") if($dolog);
delete($hash->{CLIENTSOCKET});