forked from shaba/openuds
added idle checking
This commit is contained in:
parent
633671d12c
commit
97e84c968a
@ -30,8 +30,9 @@
|
||||
'''
|
||||
import threading
|
||||
import time
|
||||
import typing
|
||||
import datetime
|
||||
import signal
|
||||
import typing
|
||||
|
||||
from PyQt5.QtWidgets import QApplication, QMessageBox
|
||||
from PyQt5.QtCore import QByteArray, QBuffer, QIODevice, pyqtSignal
|
||||
@ -90,8 +91,11 @@ class UDSActorClient(threading.Thread):
|
||||
_running: bool
|
||||
_forceLogoff: bool
|
||||
_qApp: UDSClientQApp
|
||||
api: rest.UDSClientApi
|
||||
_listener: client.HTTPServerThread
|
||||
_loginInfo: typing.Optional[types.LoginResultInfoType]
|
||||
_notified: bool
|
||||
_sessionStartTime: datetime.datetime
|
||||
api: rest.UDSClientApi
|
||||
|
||||
def __init__(self, qApp: QApplication):
|
||||
super().__init__()
|
||||
@ -101,6 +105,8 @@ class UDSActorClient(threading.Thread):
|
||||
self._running = False
|
||||
self._forceLogoff = False
|
||||
self._listener = client.HTTPServerThread(self)
|
||||
self._loginInfo = None
|
||||
self._notified = False
|
||||
|
||||
# Capture stop signals..
|
||||
logger.debug('Setting signals...')
|
||||
@ -111,20 +117,66 @@ class UDSActorClient(threading.Thread):
|
||||
logger.info('Stop signal received')
|
||||
self.stop()
|
||||
|
||||
def checkDeadLine(self):
|
||||
if self._userInfo is None or not self._userInfo.dead_line: # No deadline check
|
||||
return
|
||||
|
||||
remainingTime = self._loginInfo.dead_line - (datetime.datetime.now() - self._sessionStartTime).total_seconds()
|
||||
logger.debug('Remaining time: {}'.format(remainingTime))
|
||||
|
||||
if not self._notified and remainingTime < 300: # With five minutes, show a warning message
|
||||
self._notified = True
|
||||
self._showMessage('Your session will expire in less that 5 minutes. Please, save your work and disconnect.')
|
||||
return
|
||||
|
||||
if remainingTime <= 0:
|
||||
logger.debug('Session dead line reached. Logging out')
|
||||
self._running = False
|
||||
self._forceLogoff = True
|
||||
|
||||
def checkIdle(self):
|
||||
if self._userInfo is None or not self._userInfo.max_idle: # No idle check
|
||||
return
|
||||
|
||||
idleTime = platform.operations.getIdleDuration()
|
||||
remainingTime = self._loginInfo.max_idle - idleTime
|
||||
|
||||
if remainingTime > 120: # Reset show Warning dialog if we have more than 5 minutes left
|
||||
self._notified = False
|
||||
return
|
||||
|
||||
logger.debug('User has been idle for: {}'.format(idleTime))
|
||||
|
||||
if not self._idleNotified and remainingTime < 120: # With two minutes, show a warning message
|
||||
self._notified = True
|
||||
self._showMessage('You have been idle for too long. The session will end if you don\'t resume operations.')
|
||||
|
||||
if remainingTime <= 0:
|
||||
logger.info('User has been idle for too long, exiting from session')
|
||||
self._running = False
|
||||
self._forceLogoff = True
|
||||
|
||||
def run(self):
|
||||
logger.debug('UDS Actor thread')
|
||||
self._listener.start() # async listener for service
|
||||
self._running = True
|
||||
|
||||
self._sessionStartTime = datetime.datetime.now()
|
||||
|
||||
time.sleep(0.4) # Wait a bit before sending login
|
||||
|
||||
try:
|
||||
# Notify loging and mark it
|
||||
self.api.login(platform.operations.getCurrentUser())
|
||||
self._loginInfo = self.api.login(platform.operations.getCurrentUser())
|
||||
|
||||
while self._running:
|
||||
time.sleep(1.1) # Sleeps between loop iterations
|
||||
|
||||
# Check Idle & dead line
|
||||
self.checkIdle()
|
||||
self.checkDeadLine()
|
||||
|
||||
self._loginInfo = None
|
||||
self.api.logout(platform.operations.getCurrentUser())
|
||||
except Exception as e:
|
||||
logger.error('Error on client loop: %s', e)
|
||||
@ -135,6 +187,7 @@ class UDSActorClient(threading.Thread):
|
||||
QApplication.quit()
|
||||
|
||||
if self._forceLogoff:
|
||||
time.sleep(1.3) # Wait a bit before forcing logoff
|
||||
platform.operations.loggoff()
|
||||
|
||||
def _showMessage(self, message: str) -> None:
|
||||
|
@ -41,12 +41,12 @@ class UDSActorClientPool:
|
||||
def __init__(self) -> None:
|
||||
self._clientUrl = []
|
||||
|
||||
def _post(self, method: str, data: typing.MutableMapping[str, str]) -> typing.List[requests.Response]:
|
||||
def _post(self, method: str, data: typing.MutableMapping[str, str], timeout=2) -> typing.List[requests.Response]:
|
||||
removables: typing.List[str] = []
|
||||
result: typing.List[typing.Any] = []
|
||||
for clientUrl in self._clientUrl:
|
||||
try:
|
||||
result.append(requests.post(clientUrl + '/' + method, data=json.dumps(data), verify=False))
|
||||
result.append(requests.post(clientUrl + '/' + method, data=json.dumps(data), verify=False, timeout=timeout))
|
||||
except Exception as e:
|
||||
# If cannot request to a clientUrl, remove it from list
|
||||
logger.info('Could not coneect with client %s: %s. Removed from registry.', e, clientUrl)
|
||||
@ -68,7 +68,7 @@ class UDSActorClientPool:
|
||||
self._clientUrl = list((i for i in self._clientUrl if i != clientUrl))
|
||||
|
||||
def executeScript(self, script: str) -> None:
|
||||
self._post('script', {'script': script})
|
||||
self._post('script', {'script': script}, timeout=30)
|
||||
|
||||
def logout(self) -> None:
|
||||
self._post('logout', {})
|
||||
@ -77,11 +77,11 @@ class UDSActorClientPool:
|
||||
self._post('message', {'message': message})
|
||||
|
||||
def ping(self) -> bool:
|
||||
self._post('ping', {})
|
||||
self._post('ping', {}, timeout=1)
|
||||
return bool(self._clientUrl) # if no clients available
|
||||
|
||||
def screenshot(self) -> typing.Optional[str]: # Screenshot are returned as base64
|
||||
for r in self._post('screenshot', {}):
|
||||
for r in self._post('screenshot', {}, timeout=3):
|
||||
try:
|
||||
return r.json()['result']
|
||||
except Exception:
|
||||
|
@ -86,8 +86,8 @@ class UDSActorSvc(daemon.Daemon, CommonService):
|
||||
while self._isAlive:
|
||||
counter += 1
|
||||
try:
|
||||
if counter % 10 == 0:
|
||||
self.checkIpsChanged()
|
||||
if counter % 5 == 0:
|
||||
self.loop()
|
||||
except Exception as e:
|
||||
logger.error('Got exception on main loop: %s', e)
|
||||
# In milliseconds, will break
|
||||
|
@ -324,6 +324,16 @@ class CommonService: # pylint: disable=too-many-instance-attributes
|
||||
if platform.operations.renameComputer(name):
|
||||
self.reboot()
|
||||
|
||||
def loop(self):
|
||||
# Main common luop
|
||||
|
||||
# Checks if ips has changed
|
||||
self.checkIpsChanged()
|
||||
|
||||
# Now check if every registered client is already there (if logged in OFC)
|
||||
if self._loggedIn and self._clientsPool.ping():
|
||||
self.logout('client_unavailable')
|
||||
|
||||
# ******************************************************
|
||||
# Methods that can be overriden by linux & windows Actor
|
||||
# ******************************************************
|
||||
|
@ -257,9 +257,8 @@ class UDSActorSvc(win32serviceutil.ServiceFramework, CommonService):
|
||||
# Process SENS messages, This will be a bit asyncronous (1 second delay)
|
||||
pythoncom.PumpWaitingMessages() # pylint: disable=no-member
|
||||
|
||||
if counter >= 10: # Once every 10 seconds
|
||||
counter = 0
|
||||
self.checkIpsChanged()
|
||||
if counter % 5 == 0: # Once every 5 seconds
|
||||
self.loop()
|
||||
|
||||
except Exception as e:
|
||||
logger.error('Got exception on main loop: %s', e)
|
||||
|
@ -62,7 +62,7 @@ def _requestActor(
|
||||
|
||||
if version >= '3.0.0':
|
||||
js = js['result']
|
||||
logger.debug('Requested %s to actor. Url=%s, Result=%s', method, url, js)
|
||||
logger.debug('Requested %s to actor. Url=%s', method, url)
|
||||
except Exception as e:
|
||||
logger.warning('Request %s failed: %s. Check connection on destination machine: %s', method, e, url)
|
||||
js = None
|
||||
|
Loading…
x
Reference in New Issue
Block a user