From 18fe2b0477217d2bad43f84928745686b51ae8bc Mon Sep 17 00:00:00 2001 From: NaruX Date: Thu, 23 Aug 2018 15:16:01 +0200 Subject: [PATCH] =?UTF-8?q?IP=20Adresse=20aus=20Hostnamen=20ermitteln=20.g?= =?UTF-8?q?ethostbyname=20NetFH=20Schreibpuffer=20wird=20bei=20flush=20imm?= =?UTF-8?q?er=20geleert,=20auch=20bei=20Fehlern=20=5F=5Fflusherr=20wird=20?= =?UTF-8?q?nach=20Fehler=20bei=20=5Fconnect=20auf=20False=20gesetzt=20Star?= =?UTF-8?q?t=20des=20Sync=20nun=20sofort=20mit=20Sync=20und=20dann=20Wait?= =?UTF-8?q?=20Bei=20ACL=20Fehlern=20Exception=20ausl=C3=B6sen=20Synctimer?= =?UTF-8?q?=20wird=20auf=2045%=20des=20Timeouts=20angepasst=20(Senden=20nu?= =?UTF-8?q?r=20bei=20Leerlauf)=20=5F=5Fset=5Fsystimout=20setzt=20auch=20f?= =?UTF-8?q?=C3=BCr=20bestehenden=20Socket=20das=20Timeout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/revpimodio2.netio.html | 29 +++++++++++-- revpimodio2/netio.py | 89 ++++++++++++++++++++++++++++---------- 2 files changed, 92 insertions(+), 26 deletions(-) diff --git a/doc/revpimodio2.netio.html b/doc/revpimodio2.netio.html index 8c1caa9..a130ae8 100644 --- a/doc/revpimodio2.netio.html +++ b/doc/revpimodio2.netio.html @@ -68,9 +68,15 @@ Methods NetFH Init NetFH-class. +__check_acl +Pueft ob ACL auf RevPi den Vorgang erlaubt oder wirft exception. + __del__ NetworkFileHandler beenden. +__set_systimeout +Systemfunktion fuer Timeoutberechnung. + _connect Stellt die Verbindung zu einem RevPiSlave her. @@ -131,18 +137,35 @@ Init NetFH-class.

address
-IP Adresse des RevPi +IP Adresse, Port des RevPi als
timeout
Timeout in Millisekunden der Verbindung
-
+ +

+NetFH.__check_acl

+__check_acl(bytecode) +

+Pueft ob ACL auf RevPi den Vorgang erlaubt oder wirft exception. +

NetFH.__del__

__del__()

NetworkFileHandler beenden. -

+

+

+NetFH.__set_systimeout

+__set_systimeout(value) +

+Systemfunktion fuer Timeoutberechnung. +

+
value
+
+Timeout in Millisekunden 100 - 60000 +
+

NetFH._connect

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