IP Adresse aus Hostnamen ermitteln .gethostbyname

NetFH Schreibpuffer wird bei flush immer geleert, auch bei Fehlern
__flusherr wird nach Fehler bei _connect auf False gesetzt
Start des Sync nun sofort mit Sync und dann Wait
Bei ACL Fehlern Exception auslösen
Synctimer wird auf 45% des Timeouts angepasst (Senden nur bei Leerlauf)
__set_systimout setzt auch für bestehenden Socket das Timeout
This commit is contained in:
2018-08-23 15:16:01 +02:00
parent ce590cdd14
commit 18fe2b0477
2 changed files with 92 additions and 26 deletions

View File

@@ -68,9 +68,15 @@ Methods</h3>
<td><a style="color:#0000FF" href="#NetFH.__init__">NetFH</a></td> <td><a style="color:#0000FF" href="#NetFH.__init__">NetFH</a></td>
<td>Init NetFH-class.</td> <td>Init NetFH-class.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#NetFH.__check_acl">__check_acl</a></td>
<td>Pueft ob ACL auf RevPi den Vorgang erlaubt oder wirft exception.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#NetFH.__del__">__del__</a></td> <td><a style="color:#0000FF" href="#NetFH.__del__">__del__</a></td>
<td>NetworkFileHandler beenden.</td> <td>NetworkFileHandler beenden.</td>
</tr><tr> </tr><tr>
<td><a style="color:#0000FF" href="#NetFH.__set_systimeout">__set_systimeout</a></td>
<td>Systemfunktion fuer Timeoutberechnung.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#NetFH._connect">_connect</a></td> <td><a style="color:#0000FF" href="#NetFH._connect">_connect</a></td>
<td>Stellt die Verbindung zu einem RevPiSlave her.</td> <td>Stellt die Verbindung zu einem RevPiSlave her.</td>
</tr><tr> </tr><tr>
@@ -131,18 +137,35 @@ Init NetFH-class.
</p><dl> </p><dl>
<dt><i>address</i></dt> <dt><i>address</i></dt>
<dd> <dd>
IP Adresse des RevPi IP Adresse, Port des RevPi als <class 'tuple'>
</dd><dt><i>timeout</i></dt> </dd><dt><i>timeout</i></dt>
<dd> <dd>
Timeout in Millisekunden der Verbindung Timeout in Millisekunden der Verbindung
</dd> </dd>
</dl><a NAME="NetFH.__del__" ID="NetFH.__del__"></a> </dl><a NAME="NetFH.__check_acl" ID="NetFH.__check_acl"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
NetFH.__check_acl</h3>
<b>__check_acl</b>(<i>bytecode</i>)
<p>
Pueft ob ACL auf RevPi den Vorgang erlaubt oder wirft exception.
</p><a NAME="NetFH.__del__" ID="NetFH.__del__"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
NetFH.__del__</h3> NetFH.__del__</h3>
<b>__del__</b>(<i></i>) <b>__del__</b>(<i></i>)
<p> <p>
NetworkFileHandler beenden. NetworkFileHandler beenden.
</p><a NAME="NetFH._connect" ID="NetFH._connect"></a> </p><a NAME="NetFH.__set_systimeout" ID="NetFH.__set_systimeout"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000">
NetFH.__set_systimeout</h3>
<b>__set_systimeout</b>(<i>value</i>)
<p>
Systemfunktion fuer Timeoutberechnung.
</p><dl>
<dt><i>value</i></dt>
<dd>
Timeout in Millisekunden 100 - 60000
</dd>
</dl><a NAME="NetFH._connect" ID="NetFH._connect"></a>
<h3 style="background-color:#FFFFFF;color:#FF0000"> <h3 style="background-color:#FFFFFF;color:#FF0000">
NetFH._connect</h3> NetFH._connect</h3>
<b>_connect</b>(<i></i>) <b>_connect</b>(<i></i>)

View File

@@ -43,8 +43,15 @@ class NetFH(Thread):
def __init__(self, address, timeout=500): def __init__(self, address, timeout=500):
"""Init NetFH-class. """Init NetFH-class.
@param address IP Adresse des RevPi @param address IP Adresse, Port des RevPi als <class 'tuple'>
@param timeout Timeout in Millisekunden der Verbindung""" @param timeout Timeout in Millisekunden der Verbindung"""
if not isinstance(address, tuple):
raise ValueError(
"parameter address must be <class 'tuple'> ('IP', PORT)"
)
if not isinstance(timeout, int):
raise ValueError("parameter timeout must be <class 'int'>")
super().__init__() super().__init__()
self.daemon = True self.daemon = True
@@ -60,11 +67,11 @@ class NetFH(Thread):
self.__trigger = False self.__trigger = False
self.__waitsync = None self.__waitsync = None
self.__set_systimeout(timeout)
# Verbindung herstellen # Verbindung herstellen
self._address = address self._address = address
self._slavesock = None self._slavesock = None
self.__set_systimeout(timeout)
self._connect() self._connect()
if self._slavesock is None: if self._slavesock is None:
@@ -78,16 +85,35 @@ class NetFH(Thread):
"""NetworkFileHandler beenden.""" """NetworkFileHandler beenden."""
self.close() self.close()
def __check_acl(self, bytecode):
"""Pueft ob ACL auf RevPi den Vorgang erlaubt oder wirft exception."""
if bytecode == b'\x18':
# Alles beenden, wenn nicht erlaubt
self.__sockend = True
self.__sockerr.set()
self._slavesock.close()
raise RuntimeError(
"write access to the process image is not permitted - use "
"monitoring=True or check aclplcslave.conf on RevPi and "
"reload revpipyload!"
)
def __set_systimeout(self, value): def __set_systimeout(self, value):
"""Systemfunktion fuer Timeoutberechnung. """Systemfunktion fuer Timeoutberechnung.
@param value Timeout in Millisekunden 100 - 60000""" @param value Timeout in Millisekunden 100 - 60000"""
if isinstance(value, int) and (100 <= value <= 60000): if isinstance(value, int) and (100 <= value <= 60000):
self.__timeout = value / 1000 self.__timeout = value / 1000
socket.setdefaulttimeout(self.__timeout) socket.setdefaulttimeout(self.__timeout)
# 70 Prozent vom Timeout für Synctimer verwenden # Timeouts in Socket setzen
self.__waitsync = self.__timeout / 10 * 7 if self._slavesock is not None:
self._slavesock.settimeout(self.__timeout)
# 45 Prozent vom Timeout für Synctimer verwenden
self.__waitsync = self.__timeout / 10 * 4.5
else: else:
raise ValueError("value must between 10 and 60000 milliseconds") raise ValueError("value must between 10 and 60000 milliseconds")
@@ -108,6 +134,7 @@ class NetFH(Thread):
self._slavesock = so self._slavesock = so
self.__sockerr.clear() self.__sockerr.clear()
self.__flusherr = False
# Timeout setzen # Timeout setzen
self.set_timeout(int(self.__timeout * 1000)) self.set_timeout(int(self.__timeout * 1000))
@@ -136,6 +163,10 @@ class NetFH(Thread):
check = self._slavesock.recv(1) check = self._slavesock.recv(1)
if check != b'\x1e': if check != b'\x1e':
# ACL prüfen und ggf Fehler werfen
self.__check_acl(check)
self.__sockerr.set() self.__sockerr.set()
raise IOError("clear dirtybytes error on network") raise IOError("clear dirtybytes error on network")
@@ -149,6 +180,9 @@ class NetFH(Thread):
def close(self): def close(self):
"""Verbindung trennen.""" """Verbindung trennen."""
if self.__sockend:
return
self.__sockend = True self.__sockend = True
self.__sockerr.set() self.__sockerr.set()
@@ -176,17 +210,22 @@ class NetFH(Thread):
# Rückmeldebyte auswerten # Rückmeldebyte auswerten
blockok = self._slavesock.recv(1) blockok = self._slavesock.recv(1)
# Puffer immer leeren
self.__int_buff = 0
self.__by_buff = b''
if blockok != b'\x1e': if blockok != b'\x1e':
self.__sockerr.set()
# ACL prüfen und ggf Fehler werfen
self.__check_acl(blockok)
self.__flusherr = True self.__flusherr = True
self.__sockerr.set()
raise IOError("flush error on network") raise IOError("flush error on network")
else: else:
self.__flusherr = False self.__flusherr = False
# Puffer leeren
self.__int_buff = 0
self.__by_buff = b''
self.__trigger = True self.__trigger = True
def get_closed(self): def get_closed(self):
@@ -260,20 +299,18 @@ class NetFH(Thread):
"""Handler fuer Synchronisierung.""" """Handler fuer Synchronisierung."""
while not self.__sockend: while not self.__sockend:
# Auf Fehlermeldung warten # Bei Fehlermeldung neu verbinden
if self.__sockerr.wait(self.__waitsync): if self.__sockerr.is_set():
if not self.__sockend: self._connect()
# Im Fehlerfall neu verbinden
self._connect()
elif not self.__sockend: else:
# Kein Fehler aufgetreten, sync durchführen wenn socket frei # Kein Fehler aufgetreten, sync durchführen wenn socket frei
if not self.__trigger and \ if not self.__trigger and \
self.__socklock.acquire(blocking=False): self.__socklock.acquire(blocking=False):
try: try:
self._slavesock.send(_syssync) self._slavesock.send(_syssync)
data = self._slavesock.recv(2) data = self._slavesock.recv(2)
except IOError: except IOError as e:
warnings.warn( warnings.warn(
"network error in sync of NetFH", RuntimeWarning "network error in sync of NetFH", RuntimeWarning
) )
@@ -286,8 +323,12 @@ class NetFH(Thread):
self.__sockerr.set() self.__sockerr.set()
self.__socklock.release() self.__socklock.release()
self.__trigger = False self.__trigger = False
# Warten nach Sync damit Instantiierung funktioniert
self.__sockerr.wait(self.__waitsync)
def seek(self, position): def seek(self, position):
"""Springt an angegebene Position. """Springt an angegebene Position.
@param position An diese Position springen""" @param position An diese Position springen"""
@@ -313,6 +354,10 @@ class NetFH(Thread):
check = self._slavesock.recv(1) check = self._slavesock.recv(1)
if check != b'\x1e': if check != b'\x1e':
# ACL prüfen und ggf Fehler werfen
self.__check_acl(check)
self.__sockerr.set() self.__sockerr.set()
raise IOError("set dirtybytes error on network") raise IOError("set dirtybytes error on network")
@@ -330,9 +375,6 @@ class NetFH(Thread):
# Timeoutwert verarbeiten (könnte Exception auslösen) # Timeoutwert verarbeiten (könnte Exception auslösen)
self.__set_systimeout(value) self.__set_systimeout(value)
# Timeouts in Socket setzen
self._slavesock.settimeout(self.__timeout)
with self.__socklock: with self.__socklock:
self._slavesock.send( self._slavesock.send(
b'\x01CF' + b'\x01CF' +
@@ -439,11 +481,12 @@ class RevPiNetIO(_RevPiModIO):
# IP-Adresse prüfen und ggf. auflösen # IP-Adresse prüfen und ggf. auflösen
if check_ip.match(self._address[0]) is None: if check_ip.match(self._address[0]) is None:
try: try:
ipv4 = socket.gethostname(self._address[0]) ipv4 = socket.gethostbyname(self._address[0])
self._address = (ipv4, self._address[1]) self._address = (ipv4, self._address[1])
except: except Exception:
raise ValueError( raise ValueError(
"ip '{}' is no valid ip address".format(self._address[0]) "ip '{0}' is no valid IPv4 address"
"".format(self._address[0])
) )
# Vererben # Vererben