aclstatus von str() auf int() geändert

RevPiSlave self.so im __init__ angelegt
accept logging verbessert
Threadliste von toten Threads reinigen
re.fullmatch für alte python verson auf wheezy nachgestellt
Neues NetFH-Protokoll implementiert
This commit is contained in:
2017-07-24 09:02:00 +02:00
parent bf75bba281
commit 1c19115157
3 changed files with 158 additions and 69 deletions

View File

@@ -66,6 +66,9 @@ Functions</h3>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#_zeroprocimg">_zeroprocimg</a></td> <td><a style="color:#0000FF" href="#_zeroprocimg">_zeroprocimg</a></td>
<td>Setzt Prozessabbild auf NULL.</td> <td>Setzt Prozessabbild auf NULL.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#refullmatch">refullmatch</a></td>
<td>re.fullmatch wegen alter python version aus wheezy nachgebaut.</td>
</tr> </tr>
</table> </table>
<hr /><hr /> <hr /><hr />
@@ -850,7 +853,7 @@ Methods</h3>
<td>Konfiguriert die FileHandler auf neue Logdatei.</td> <td>Konfiguriert die FileHandler auf neue Logdatei.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#RevPiSlave.run">run</a></td> <td><a style="color:#0000FF" href="#RevPiSlave.run">run</a></td>
<td></td> <td>Startet Serverkomponente fuer die Annahme neuer Verbindungen.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#RevPiSlave.stop">stop</a></td> <td><a style="color:#0000FF" href="#RevPiSlave.stop">stop</a></td>
<td>Beendet Slaveausfuehrung.</td> <td>Beendet Slaveausfuehrung.</td>
@@ -885,7 +888,9 @@ Konfiguriert die FileHandler auf neue Logdatei.
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlave.run</h3> RevPiSlave.run</h3>
<b>run</b>(<i></i>) <b>run</b>(<i></i>)
<a NAME="RevPiSlave.stop" ID="RevPiSlave.stop"></a> <p>
Startet Serverkomponente fuer die Annahme neuer Verbindungen.
</p><a NAME="RevPiSlave.stop" ID="RevPiSlave.stop"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlave.stop</h3> RevPiSlave.stop</h3>
<b>stop</b>(<i></i>) <b>stop</b>(<i></i>)
@@ -915,13 +920,13 @@ Methods</h3>
<table> <table>
<tr> <tr>
<td><a style="color:#0000FF" href="#RevPiSlaveDev.__init__">RevPiSlaveDev</a></td> <td><a style="color:#0000FF" href="#RevPiSlaveDev.__init__">RevPiSlaveDev</a></td>
<td></td> <td>Init RevPiSlaveDev-Class.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#RevPiSlaveDev.run">run</a></td> <td><a style="color:#0000FF" href="#RevPiSlaveDev.run">run</a></td>
<td></td> <td>Verarbeitet Anfragen von Remoteteilnehmer.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#RevPiSlaveDev.stop">stop</a></td> <td><a style="color:#0000FF" href="#RevPiSlaveDev.stop">stop</a></td>
<td></td> <td>Beendet Verbindungsthread.</td>
</tr> </tr>
</table> </table>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
@@ -933,15 +938,32 @@ Static Methods</h3>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlaveDev (Constructor)</h3> RevPiSlaveDev (Constructor)</h3>
<b>RevPiSlaveDev</b>(<i>devcon, deadtime, acl</i>) <b>RevPiSlaveDev</b>(<i>devcon, deadtime, acl</i>)
<a NAME="RevPiSlaveDev.run" ID="RevPiSlaveDev.run"></a> <p>
Init RevPiSlaveDev-Class.
</p><dl>
<dt><i>devcon</i></dt>
<dd>
Tuple der Verbindung
</dd><dt><i>deadtime</i></dt>
<dd>
Timeout der Vararbeitung
</dd><dt><i>acl</i></dt>
<dd>
Berechtigungslevel
</dd>
</dl><a NAME="RevPiSlaveDev.run" ID="RevPiSlaveDev.run"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlaveDev.run</h3> RevPiSlaveDev.run</h3>
<b>run</b>(<i></i>) <b>run</b>(<i></i>)
<a NAME="RevPiSlaveDev.stop" ID="RevPiSlaveDev.stop"></a> <p>
Verarbeitet Anfragen von Remoteteilnehmer.
</p><a NAME="RevPiSlaveDev.stop" ID="RevPiSlaveDev.stop"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
RevPiSlaveDev.stop</h3> RevPiSlaveDev.stop</h3>
<b>stop</b>(<i></i>) <b>stop</b>(<i></i>)
<p>
Beendet Verbindungsthread.
</p>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div> <div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr /> <hr /><hr />
<a NAME="_ipmatch" ID="_ipmatch"></a> <a NAME="_ipmatch" ID="_ipmatch"></a>
@@ -972,5 +994,26 @@ int() ACL Wert oder -1 wenn nicht gefunden
Setzt Prozessabbild auf NULL. Setzt Prozessabbild auf NULL.
</p> </p>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div> <div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr />
<a NAME="refullmatch" ID="refullmatch"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">refullmatch</h2>
<b>refullmatch</b>(<i>regex, string</i>)
<p>
re.fullmatch wegen alter python version aus wheezy nachgebaut.
</p><dl>
<dt><i>regex</i></dt>
<dd>
RegEx Statement
</dd><dt><i>string</i></dt>
<dd>
Zeichenfolge gegen die getestet wird
</dd>
</dl><dl>
<dt>Returns:</dt>
<dd>
True, wenn komplett passt sonst False
</dd>
</dl>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /> <hr />
</body></html> </body></html>

View File

@@ -76,3 +76,4 @@ revpipyload.procimg?7
revpipyload.pyloadverion?7 revpipyload.pyloadverion?7
revpipyload.rapcatalog?7 revpipyload.rapcatalog?7
revpipyload.re_ipacl?7 revpipyload.re_ipacl?7
revpipyload.refullmatch?4(regex, string)

View File

@@ -42,7 +42,7 @@ import zipfile
from concurrent import futures from concurrent import futures
from configparser import ConfigParser from configparser import ConfigParser
from json import loads as jloads from json import loads as jloads
from re import fullmatch as refullmatch from re import match as rematch
from shutil import rmtree from shutil import rmtree
from sys import stdout as sysstdout from sys import stdout as sysstdout
from tempfile import mkstemp from tempfile import mkstemp
@@ -71,9 +71,21 @@ def _ipmatch(ipaddress, dict_acl):
""" """
for aclip in sorted(dict_acl, reverse=True): for aclip in sorted(dict_acl, reverse=True):
regex = aclip.replace(".", "\\.").replace("*", "\\d{1,3}") regex = aclip.replace(".", "\\.").replace("*", "\\d{1,3}")
if refullmatch(regex, ipaddress) is not None: if refullmatch(regex, ipaddress):
return str(dict_acl[aclip]) return dict_acl[aclip]
return "-1" return -1
def refullmatch(regex, string):
"""re.fullmatch wegen alter python version aus wheezy nachgebaut.
@param regex RegEx Statement
@param string Zeichenfolge gegen die getestet wird
@return True, wenn komplett passt sonst False
"""
m = rematch(regex, string)
return m is not None and m.end() == len(string)
def _zeroprocimg(): def _zeroprocimg():
@@ -464,6 +476,7 @@ class RevPiSlave(Thread):
self._evt_exit = Event() self._evt_exit = Event()
self.exitcode = None self.exitcode = None
self._port = port self._port = port
self.so = None
self._th_dev = [] self._th_dev = []
self.zeroonerror = False self.zeroonerror = False
self.zeroonexit = False self.zeroonexit = False
@@ -473,13 +486,14 @@ class RevPiSlave(Thread):
for host in acl.split(): for host in acl.split():
aclsplit = host.split(",") aclsplit = host.split(",")
self.dict_acl[aclsplit[0]] = \ self.dict_acl[aclsplit[0]] = \
"0" if len(aclsplit) == 1 else aclsplit[1] 0 if len(aclsplit) == 1 else int(aclsplit[1])
def newlogfile(self): def newlogfile(self):
"""Konfiguriert die FileHandler auf neue Logdatei.""" """Konfiguriert die FileHandler auf neue Logdatei."""
pass pass
def run(self): def run(self):
"""Startet Serverkomponente fuer die Annahme neuer Verbindungen."""
proginit.logger.debug("enter RevPiSlave.run()") proginit.logger.debug("enter RevPiSlave.run()")
# Socket öffnen und konfigurieren # Socket öffnen und konfigurieren
@@ -494,6 +508,7 @@ class RevPiSlave(Thread):
break break
self.so.listen(15) self.so.listen(15)
# Mit Socket arbeiten
while not self._evt_exit.is_set(): while not self._evt_exit.is_set():
self.exitcode = -1 self.exitcode = -1
@@ -502,12 +517,13 @@ class RevPiSlave(Thread):
try: try:
tup_sock = self.so.accept() tup_sock = self.so.accept()
except: except:
proginit.logger.exception("after accept") if not self._evt_exit.is_set():
proginit.logger.exception("accept exception")
continue continue
# ACL prüfen # ACL prüfen
aclstatus = _ipmatch(tup_sock[1][0], self.dict_acl) aclstatus = _ipmatch(tup_sock[1][0], self.dict_acl)
if aclstatus == "-1": if aclstatus == -1:
tup_sock[0].close() tup_sock[0].close()
proginit.logger.warning( proginit.logger.warning(
"host ip '{}' does not match revpiacl - disconnect" "host ip '{}' does not match revpiacl - disconnect"
@@ -519,7 +535,10 @@ class RevPiSlave(Thread):
th.start() th.start()
self._th_dev.append(th) self._th_dev.append(th)
# TODO: tote Threads entfernen # Liste von toten threads befreien
self._th_dev = [
th_check for th_check in self._th_dev if th_check.is_alive()
]
# Alle Threads beenden # Alle Threads beenden
for th in self._th_dev: for th in self._th_dev:
@@ -527,6 +546,8 @@ class RevPiSlave(Thread):
# Socket schließen # Socket schließen
self.so.close() self.so.close()
self.so = None
self.exitcode = 0 self.exitcode = 0
proginit.logger.debug("leave RevPiSlave.run()") proginit.logger.debug("leave RevPiSlave.run()")
@@ -536,6 +557,7 @@ class RevPiSlave(Thread):
proginit.logger.debug("enter RevPiSlave.stop()") proginit.logger.debug("enter RevPiSlave.stop()")
self._evt_exit.set() self._evt_exit.set()
if self.so is not None:
self.so.shutdown(socket.SHUT_RDWR) self.so.shutdown(socket.SHUT_RDWR)
proginit.logger.debug("leave RevPiSlave.stop()") proginit.logger.debug("leave RevPiSlave.stop()")
@@ -544,18 +566,22 @@ class RevPiSlave(Thread):
class RevPiSlaveDev(Thread): class RevPiSlaveDev(Thread):
def __init__(self, devcon, deadtime, acl): def __init__(self, devcon, deadtime, acl):
"""Init RevPiSlaveDev-Class.
@param devcon Tuple der Verbindung
@param deadtime Timeout der Vararbeitung
@param acl Berechtigungslevel
"""
super().__init__() super().__init__()
self._acl = acl self._acl = acl
self.daemon = True self.daemon = True
self._deadtime = deadtime self._deadtime = deadtime
self._devcon, self._addr = devcon self._devcon, self._addr = devcon
self._evt_exit = Event() self._evt_exit = Event()
self._startvalr = 0
self._lenvalr = 0
self._startvalw = 0
self._lenvalw = 0
def run(self): def run(self):
"""Verarbeitet Anfragen von Remoteteilnehmer."""
proginit.logger.debug("enter RevPiSlaveDev.run()") proginit.logger.debug("enter RevPiSlaveDev.run()")
proginit.logger.info( proginit.logger.info(
@@ -564,30 +590,79 @@ class RevPiSlaveDev(Thread):
) )
# CMDs anhand ACL aufbauen # CMDs anhand ACL aufbauen
msgcli = [b'DATA', b'PICT'] msgcli = [b'DA', b'PI', b'\x06\x16']
if self._acl == "1": if self._acl == 1:
msgcli.append(b'SEND') msgcli.append(b'SD')
# Prozessabbild öffnen # Prozessabbild öffnen
fh_proc = open(procimg, "r+b", 0) fh_proc = open(procimg, "r+b", 0)
while not self._evt_exit.is_set(): while not self._evt_exit.is_set():
# Meldung erhalten
try:
netcmd = self._devcon.recv(16)
# proginit.logger.debug("command {}".format(netcmd))
except:
break
# Laufzeitberechnung starten # Laufzeitberechnung starten
ot = default_timer() ot = default_timer()
# Meldung erhalten
try:
netcmd = self._devcon.recv(16)
except:
break
# Wenn Meldung ungültig ist aussteigen # Wenn Meldung ungültig ist aussteigen
cmd = netcmd[:4] if netcmd[0:1] != b'\x01' or netcmd[-1:] != b'\x17':
if netcmd != b'':
proginit.logger.error(
"net cmd not valid {}".format(netcmd)
)
break
# CMD prüfen
cmd = netcmd[1:3]
if cmd not in msgcli: if cmd not in msgcli:
break break
if cmd == b'PICT': if cmd == b'\x06\x16':
# Just sync
pass
elif cmd == b'DA':
# Processabbild übertragen
# bCMiiii00000000b = 16
position = int.from_bytes(netcmd[3:5], byteorder="little")
length = int.from_bytes(netcmd[5:7], byteorder="little")
fh_proc.seek(position)
try:
self._devcon.sendall(fh_proc.read(length))
except:
proginit.logger.error("error while send read data")
break
elif cmd == b'SD':
# Ausgänge empfangen
# bCMiiii00000000b = 16
position = int.from_bytes(netcmd[3:5], byteorder="little")
length = int.from_bytes(netcmd[5:7], byteorder="little")
try:
block = self._devcon.recv(length)
except:
proginit.logger.error("error while recv data to write")
break
fh_proc.seek(position)
# Länge der Daten prüfen
if len(block) == length:
fh_proc.write(block)
else:
proginit.logger.error("got wrong length to write")
break
# Record seperator character
self._devcon.send(b'\x1e')
elif cmd == b'PI':
# piCtory Konfiguration senden # piCtory Konfiguration senden
proginit.logger.debug( proginit.logger.debug(
"transfair pictory configuration: {}".format(configrsc) "transfair pictory configuration: {}".format(configrsc)
@@ -601,40 +676,10 @@ class RevPiSlaveDev(Thread):
fh_pic.close() fh_pic.close()
break break
# Abschlussmeldung # End-of-Transmission character
self._devcon.send(b'PICOK') self._devcon.send(b'\x04')
continue continue
if cmd == b'DATA':
# Processabbild übertragen
# CMD_|POS_|LEN_|RSVE = 16
position = int(netcmd[4:8])
length = int(netcmd[8:12])
fh_proc.seek(position)
try:
self._devcon.sendall(fh_proc.read(length))
except:
break
if cmd == b'SEND':
# Ausgänge empfangen
# CMD_|POS_|LEN_|RSVE = 16
position = int(netcmd[4:8])
length = int(netcmd[8:12])
# try:
block = self._devcon.recv(length)
# except:
# break
fh_proc.seek(position)
fh_proc.write(block)
# Record seperator
self._devcon.send(b'\x1e')
# Verarbeitungszeit prüfen # Verarbeitungszeit prüfen
comtime = default_timer() - ot comtime = default_timer() - ot
if comtime > self._deadtime: if comtime > self._deadtime:
@@ -643,7 +688,6 @@ class RevPiSlaveDev(Thread):
int(self._deadtime * 1000), int(comtime * 1000) int(self._deadtime * 1000), int(comtime * 1000)
) )
) )
# break
fh_proc.close() fh_proc.close()
self._devcon.close() self._devcon.close()
@@ -653,6 +697,7 @@ class RevPiSlaveDev(Thread):
proginit.logger.debug("leave RevPiSlaveDev.run()") proginit.logger.debug("leave RevPiSlaveDev.run()")
def stop(self): def stop(self):
"""Beendet Verbindungsthread."""
proginit.logger.debug("enter RevPiSlaveDev.stop()") proginit.logger.debug("enter RevPiSlaveDev.stop()")
self._evt_exit.set() self._evt_exit.set()
@@ -764,7 +809,7 @@ class RevPiPyLoad():
# PLC Slave ACL laden und prüfen # PLC Slave ACL laden und prüfen
plcslaveacl = \ plcslaveacl = \
self.globalconfig["DEFAULT"].get("plcslaveacl", "") self.globalconfig["DEFAULT"].get("plcslaveacl", "")
if len(plcslaveacl) > 0 and refullmatch(re_ipacl, plcslaveacl) is None: if len(plcslaveacl) > 0 and not refullmatch(re_ipacl, plcslaveacl):
self.plcslaveacl = "" self.plcslaveacl = ""
proginit.logger.warning("can not load plcslaveacl - wrong format") proginit.logger.warning("can not load plcslaveacl - wrong format")
else: else:
@@ -781,7 +826,7 @@ class RevPiPyLoad():
# TODO: xmlrpcacl auswerten # TODO: xmlrpcacl auswerten
xmlrpcacl = \ xmlrpcacl = \
self.globalconfig["DEFAULT"].get("xmlrpcacl", "") self.globalconfig["DEFAULT"].get("xmlrpcacl", "")
if len(xmlrpcacl) > 0 and refullmatch(re_ipacl, xmlrpcacl) is None: if len(xmlrpcacl) > 0 and not refullmatch(re_ipacl, xmlrpcacl):
self.xmlrpcacl = "" self.xmlrpcacl = ""
proginit.logger.warning("can not load xmlrpcacl - wrong format") proginit.logger.warning("can not load xmlrpcacl - wrong format")
else: else:
@@ -1263,7 +1308,7 @@ class RevPiPyLoad():
# Werte übernehmen # Werte übernehmen
for key in keys: for key in keys:
if key in dc: if key in dc:
if refullmatch(keys[key], str(dc[key])) is None: if not refullmatch(keys[key], str(dc[key])):
proginit.logger.error( proginit.logger.error(
"got wrong setting '{}' with value '{}'".format( "got wrong setting '{}' with value '{}'".format(
key, dc[key] key, dc[key]