diff --git a/LaunchScript/VirtualAcousticStarterConfig.ITC16100.json b/LaunchScript/VirtualAcousticStarterConfig.ITC16100.json new file mode 100644 index 0000000000000000000000000000000000000000..2a4a1cbe4891b617ee78591bdfb6e571d7944c0a --- /dev/null +++ b/LaunchScript/VirtualAcousticStarterConfig.ITC16100.json @@ -0,0 +1,20 @@ +{ + "sLocalIP": "10.0.1.240", + "nLocalPort": 41578, + "nDefaultSleep": 5, + + "tVirtualAcousticVersions" = { + "20160906.aixcave" : { "file": "bin/VAServer.exe", "dir": "D:/Demos/VA_20160906/Binaries", "params": "10.0.1.240:12340 conf/VACore.aixcave.ini" }, + "20160906.aixcave.barrend" : { "file": "bin/VAServer.exe", "dir": "D:/Demos/VA_20160906/Binaries", "params": "10.0.1.240:12340 conf/VACore.aixcave.barrend.ini" }, + + "20161206.aixcave" : { "file": "bin/VAServer.exe", "dir": "D:/Demos/VA_20161206", "params": "10.0.1.240:12340 conf/VACore.aixcave.ini" }, + "20161206.aixcave.barrend" : { "file": "bin/VAServer.exe", "dir": "D:/Demos/VA_20161206", "params": "10.0.1.240:12340 conf/VACore.aixcave.barrend.ini" }, + + "2018.a" : { "file": "bin/VAServer.exe", "dir": "D:/VAServer-git/v2018.a", "params": "10.0.1.240:12340 conf/VACore.aixCAVE.ini" }, + "2019.a" : { "file": "bin/VAServer.exe", "dir": "D:/VAServer-git/v2019.a_dev", "params": "10.0.1.240:12340 conf/VACore.aixCAVE.ini" }, + "2020.a" : { "file": "bin/VAServer.exe", "dir": "D:/VAServer-git/v2020.a", "params": "10.0.1.240:12340 conf/VACore.aixCAVE.ini" }, + "2020.a_AirTraffic" : { "file": "bin/VAServer.exe", "dir": "D:/VAServer-git/v2020.a", "params": "10.0.1.240:12340 conf/VACore.aixCAVE.ATNRenderer.ini" } + } +} + + diff --git a/LaunchScript/VirtualAcousticStarterConfig.ITC16100.py b/LaunchScript/VirtualAcousticStarterConfig.ITC16100.py deleted file mode 100644 index 15fc904bcfb9a279bfafdc798d1d56a7573f799f..0000000000000000000000000000000000000000 --- a/LaunchScript/VirtualAcousticStarterConfig.ITC16100.py +++ /dev/null @@ -1,19 +0,0 @@ - -sLocalIP = "10.0.1.240" -nLocalPort = 41578 -nDefaultSleep = 5 - -tVirtualAcousticVersions = { - "20160906.aixcave" : { "file" : 'bin/VAServer.exe', "dir" : 'D:/Demos/VA_20160906/Binaries', "params" : '10.0.1.240:12340 conf/VACore.aixcave.ini' }, - "20160906.aixcave.barrend" : { "file" : 'bin/VAServer.exe', "dir" : 'D:/Demos/VA_20160906/Binaries', "params" : '10.0.1.240:12340 conf/VACore.aixcave.barrend.ini' }, - - "20161206.aixcave" : { "file" : 'bin/VAServer.exe', "dir" : 'D:/Demos/VA_20161206', "params" : '10.0.1.240:12340 conf/VACore.aixcave.ini' }, - "20161206.aixcave.barrend" : { "file" : 'bin/VAServer.exe', "dir" : 'D:/Demos/VA_20161206', "params" : '10.0.1.240:12340 conf/VACore.aixcave.barrend.ini' }, - - "2018.a" : { "file" : 'bin/VAServer.exe', "dir" : 'D:/VAServer-git/v2018.a', "params" : '10.0.1.240:12340 conf/VACore.aixCAVE.ini' }, - "2019.a" : { "file" : 'bin/VAServer.exe', "dir" : 'D:/VAServer-git/v2019.a_dev', "params" : '10.0.1.240:12340 conf/VACore.aixCAVE.ini' }, - "2020.a" : { "file" : 'bin/VAServer.exe', "dir" : 'D:/VAServer-git/v2020.a', "params" : '10.0.1.240:12340 conf/VACore.aixCAVE.ini' }, - "2020.a_AirTraffic" : { "file" : 'bin/VAServer.exe', "dir" : 'D:/VAServer-git/v2020.a', "params" : '10.0.1.240:12340 conf/VACore.aixCAVE.ATNRenderer.ini' } -} - - diff --git a/LaunchScript/VirtualAcousticStarterConfig.json b/LaunchScript/VirtualAcousticStarterConfig.json new file mode 100644 index 0000000000000000000000000000000000000000..30e763fd8686f84d58746e86c807d4d8fed6c329 --- /dev/null +++ b/LaunchScript/VirtualAcousticStarterConfig.json @@ -0,0 +1,14 @@ +{ + "sLocalIP": "0.0.0.0", + "nLocalPort": 41578, + "nDefaultSleep": 3, + + "tVirtualAcousticVersions": { + "2018.a": { "file": "bin/VAServer.exe", "dir": "../v2018.a", "params": "localhost:12340 conf/VACore.ini" }, + "2019.a": { "file": "bin/VAServer.exe", "dir": "../v2019.a", "params": "localhost:12340 conf/VACore.ini" }, + "2020.a": { "file": "bin/VAServer.exe", "dir": "../v2020.a", "params": "localhost:12340 conf/VACore.ini" }, + "2020.a_AirTraffic": { "file": "bin/VAServer.exe", "dir": "../v2020.a", "params": "localhost:12340 conf/VACore.ATNRenderer.ini" } + } +} + + diff --git a/LaunchScript/VirtualAcousticStarterConfig.py b/LaunchScript/VirtualAcousticStarterConfig.py deleted file mode 100644 index 78d4cd52ff1ba25359061606ebe3641039754115..0000000000000000000000000000000000000000 --- a/LaunchScript/VirtualAcousticStarterConfig.py +++ /dev/null @@ -1,13 +0,0 @@ - -sLocalIP = "0.0.0.0" -nLocalPort = 41578 -nDefaultSleep = 3 - -tVirtualAcousticVersions = { - "2018.a" : { "file" : 'bin/VAServer.exe', "dir" : '../v2018.a', "params" : 'localhost:12340 conf\VACore.ini' }, - "2019.a" : { "file" : 'bin/VAServer.exe', "dir" : '../v2019.a', "params" : 'localhost:12340 conf\VACore.ini' }, - "2020.a" : { "file" : 'bin/VAServer.exe', "dir" : '../v2020.a', "params" : 'localhost:12340 conf\VACore.ini' }, - "2020.a_AirTraffic" : { "file" : 'bin/VAServer.exe', "dir" : '../v2020.a', "params" : 'localhost:12340 conf\VACore.ATNRenderer.ini' } -} - - diff --git a/LaunchScript/VirtualAcousticsStarterServer.py b/LaunchScript/VirtualAcousticsStarterServer.py index 081fbcb087bc996c6501a79ba75c8f373a7ac806..3e49abd556f49b86b7935b03fc4e483929361478 100644 --- a/LaunchScript/VirtualAcousticsStarterServer.py +++ b/LaunchScript/VirtualAcousticsStarterServer.py @@ -1,226 +1,285 @@ -import sys, socket, subprocess, time, os - -oProcess = None - -print( "VirtualAcoustics Starter script - press ctrl+c to quit" ) - -sHostConfigurationFile = "VirtualAcousticStarterConfig." + socket.gethostname() + ".py" -sGeneralConfigurationFile = "VirtualAcousticStarterConfig.py" -sCurrentScriptsDirectory = os.path.dirname( os.path.realpath( sys.argv[0] ) ) - -if os.path.isfile( sHostConfigurationFile ): - exec( compile( open( sHostConfigurationFile, "rb" ).read(), sHostConfigurationFile, 'exec' ) ) - print("Using config: " + sHostConfigurationFile) -elif os.path.isfile( sCurrentScriptsDirectory + "/" + sHostConfigurationFile ): - exec( compile( open( sCurrentScriptsDirectory + "/" + sHostConfigurationFile, "rb" ).read(), sCurrentScriptsDirectory + "/" + sHostConfigurationFile, 'exec' ) ) - print("Using config: " + sCurrentScriptsDirectory + "/" + sHostConfigurationFile) -elif os.path.isfile( sGeneralConfigurationFile ): - exec( compile( open( sGeneralConfigurationFile, "rb" ).read(), sGeneralConfigurationFile, 'exec' ) ) - print("Using config: " + sGeneralConfigurationFile) -elif os.path.isfile( sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile ): - exec( compile( open( sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile, "rb" ).read(), sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile, 'exec' ) ) - print("Using config: " + sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile) -else: - print( "ERROR: No configuration file found - please create " + sHostConfigurationFile + " or " + sGeneralConfigurationFile ) - sys.exit( 4 ) - -try: - tVirtualAcousticVersions - sLocalIP - nLocalPort - nDefaultSleep -except NameError: - print( "ERROR: configuration did not define required variables: tVirtualAcousticVersions, sLocalIP, nLocalPort, nDefaultSleep" ) - sys.exit( 5 ) - -print( "Creating server socket at " + sLocalIP + ":" + str( nLocalPort ) ) - -oServer = socket.socket() -if sLocalIP == "": - sLocalIP = socket.gethostname() -try: - oServer.bind( ( sLocalIP, nLocalPort ) ) - oServer.listen( 3 ) -except socket.error: - print( "Error on binding socket" ) - sys.exit( 1 ) - -try: - - oServer.settimeout( 0.5 ) - while True: - print( "Waiting for connection..." ) - oConnection = None - while not oConnection: - try: - oConnection, sAddress = oServer.accept() - except socket.timeout: - oConnection = None - except socket.error: - print( "Error while listening for connection" ) - sys.exit( 2 ) - except (KeyboardInterrupt, SystemExit): - raise - - print( "Connection received from " + sAddress[0] ) +import sys, socket, subprocess, time, os, json +from enum import Enum + + +class ErrorCodes(Enum): + NO_ERROR = 0 + ERROR_NO_CONFIG_FOUND = 1 + ERROR_INCOMPLETE_CONFIG = 2 + ERROR_BINDING_SOCKET = 3 + ERROR_CONNECTING_SOCKET = 4 + +class VirtualAcousticsLauncher: + def __init__(self): + print("init") + self.oVAProcess = None + self.oLauncherServerSocket = None + self.oLauncherConnection = None + self.sCurrentScriptsDirectory = os.path.dirname( os.path.realpath( sys.argv[0] ) ) + + self.start() + + + + def start(self): + print( "VirtualAcoustics Starter script - press ctrl+c to quit" ) + self.readConfig() + self.openLauncherServerSocket() + self.runLauncher() + + + + def readConfig(self): + sHostConfigurationFile = "VirtualAcousticStarterConfig." + socket.gethostname() + ".json" + sGeneralConfigurationFile = "VirtualAcousticStarterConfig.json" + + sUsedConfigFile = "" + + #check which config file exists and load it + if os.path.isfile( sHostConfigurationFile ): + sUsedConfigFile = sHostConfigurationFile + elif os.path.isfile( self.sCurrentScriptsDirectory + "/" + sHostConfigurationFile ): + sUsedConfigFile = self.sCurrentScriptsDirectory + "/" + sHostConfigurationFile + elif os.path.isfile( sGeneralConfigurationFile ): + sUsedConfigFile = sGeneralConfigurationFile + elif os.path.isfile( self.sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile ): + sUsedConfigFile = self.sCurrentScriptsDirectory + "/" + sGeneralConfigurationFile + else: + print( "ERROR: No configuration file found - please create " + sHostConfigurationFile + " or " + sGeneralConfigurationFile ) + sys.exit( ErrorCodes.ERROR_NO_CONFIG_FOUND ) + + print("Using config: " + sUsedConfigFile) + with open( sUsedConfigFile) as json_file: + json_config = json.load(json_file) + + try: + self.tVirtualAcousticVersions = json_config["tVirtualAcousticVersions"] + self.sLocalIP = json_config["sLocalIP"] + self.nLocalPort = json_config["nLocalPort"] + self.nDefaultSleep = json_config["nDefaultSleep"] + except KeyError as e: + print( "ERROR reading the json config. Missing " + str(e.args[0]) ) + sys.exit( ErrorCodes.ERROR_INCOMPLETE_CONFIG ) + + + def openLauncherServerSocket(self): + print( "Creating server socket at " + self.sLocalIP + ":" + str( self.nLocalPort ) ) - if oProcess: - print( "Closing current VA instance" ) - oProcess.kill() - oProcess = None - - # read variant to start + self.oLauncherServerSocket = socket.socket() + if self.sLocalIP == "": + self.sLocalIP = socket.gethostname() try: - sVariantName = oConnection.recv( 512 ) - if type( sVariantName ) is bytes: - sVariantName = sVariantName.decode( 'utf-8' ) - print( "received start request for variant: " + sVariantName ) + self.oLauncherServerSocket.bind( ( self.sLocalIP, self.nLocalPort ) ) + self.oLauncherServerSocket.listen( 3 ) + except socket.error: + print( "Error on binding socket" ) + sys.exit( ErrorCodes.ERROR_BINDING_SOCKET ) + self.oLauncherServerSocket.settimeout( 1.0 ) + + + + def runLauncher(self): + try: + while True: + print( "Waiting for launcher connection..." ) + + self.oLauncherConnection = None + + while not self.oLauncherConnection: + try: + self.oLauncherConnection, sAddress = self.oLauncherServerSocket.accept() + except socket.timeout: + self.oLauncherConnection = None + except socket.error: + print( "Error while listening for launcher connection" ) + sys.exit( ErrorCodes.ERROR_CONNECTING_SOCKET ) + except (KeyboardInterrupt, SystemExit): + raise #re-raising the received exception + + print( "Connection received from " + sAddress[0] ) + + if self.oVAProcess: + print( "Closing current VA instance" ) + self.oVAProcess.kill() + self.oVAProcess = None + + tInstanceToStart = self.ReadVariantToStart() + if not tInstanceToStart: + continue + + self.StartRequestedVAServer(tInstanceToStart) + except KeyboardInterrupt: + print( "Caught keyboard interrupt, quitting" ) + + self.oLauncherServerSocket.close() + + + + def ReadVariantToStart(self): + try: + self.sVariantName = self.oLauncherConnection.recv( 512 ) + if type( self.sVariantName ) is bytes: + self.sVariantName = self.sVariantName.decode( 'utf-8' ) + print( "Received launch request for variant: " + self.sVariantName ) except socket.error: print( "Error while reading variant" ) - oConnection.close() - except (KeyboardInterrupt, SystemExit): - raise + self.oLauncherConnection.close() + return None else: try: - tInstance = tVirtualAcousticVersions[sVariantName] + tInstance = self.tVirtualAcousticVersions[self.sVariantName] except KeyError: tInstance = None - + if not tInstance: - print( 'Requested VA Instance "' + sVariantName + '" not available' ) - oConnection.send( b'f' ) - oConnection.close() - else: - try: - sWorkingDir = tInstance["dir"] - except KeyError: - sWorkingDir = None - - try: - sFile = tInstance["file"] - if not os.path.isfile( sFile ): - if sWorkingDir and os.path.isfile( sWorkingDir + "/" + sFile ): - sFile = sWorkingDir + "/" + sFile - else: - print( "ERROR: Invalid config for " + sVariantName + " -- file " + sFile + " does not exist" ) - oConnection.send( b'n' ) - elif sWorkingDir == None: - sWorkingDir = os.path.dirname( sFile ) - except KeyError: - sFile = None - print( "ERROR: config for " + sVariantName + " has no valid \"file\" entry" ) - oConnection.send( b'i' ) - oConnection.close() - - if sFile: - sCommand = sFile - try: - sParams = tInstance["params"] - sCommand = sCommand + ' ' + sParams - except KeyError: - sParams = None + print( 'Requested VA Instance "' + self.sVariantName + '" not available' ) + self.oLauncherConnection.send( b'f' ) #answer 'requested version not available + self.oLauncherConnection.close() + return None - try: - nSleep = tInstance["sleep"] - except KeyError: - nSleep = nDefaultSleep + return tInstance + + def StartRequestedVAServer(self, tInstance): + try: + sWorkingDir = tInstance["dir"] + except KeyError: + sWorkingDir = None + + try: + self.sVAExecutableFile = tInstance["file"] + if not os.path.isfile( self.sVAExecutableFile ): + if sWorkingDir and os.path.isfile( sWorkingDir + "/" + self.sVAExecutableFile ): + self.sVAExecutableFile = sWorkingDir + "/" + self.sVAExecutableFile + else: + print( "ERROR: Invalid config for " + self.sVariantName + " -- file " + self.sVAExecutableFile + " does not exist" ) + self.oLauncherConnection.send( b'n' ) #answer 'binary file cannot be found or invalid' + return + elif sWorkingDir == None: + sWorkingDir = os.path.dirname( self.sVAExecutableFile ) + except KeyError: + self.sVAExecutableFile = None + print( "ERROR: config for " + self.sVariantName + " has no valid \"file\" entry" ) + self.oLauncherConnection.send( b'i' ) #answer 'invalid file entry in the config' + self.oLauncherConnection.close() + return + + if not self.sVAExecutableFile: + return + + sCommand = self.sVAExecutableFile + try: + sParams = tInstance["params"] + sCommand = sCommand + ' ' + sParams + except KeyError: + sParams = None + + try: + nSleep = tInstance["sleep"] + except KeyError: + nSleep = self.nDefaultSleep - # start instance - print( 'executing "' + sCommand + '"' ) - - oProcess = subprocess.Popen( sCommand, cwd = sWorkingDir, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP ) + # start instance + print( 'executing "' + sCommand + '"' ) - # wait for requested duration before sending the go signal - time.sleep( nSleep ) - - if oProcess.poll() != None: - print( "VA Process died - sending abort token" ) - oConnection.send( b'a' ) + self.oVAProcess = subprocess.Popen( sCommand, cwd = sWorkingDir, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP ) + + # wait for requested duration before sending the go signal + time.sleep( nSleep ) + + if self.oVAProcess.poll() != None: + print( "VA Process died - sending abort token" ) + self.oLauncherConnection.send( b'a' ) #answer 'VAServer was aborted + self.oLauncherConnection.close() + return + else: + print( "sending go token" ) + self.oLauncherConnection.send( b'g' )#answer 'go, VAServer is correctly started' + + self.ListenForRequestsByVAServer() + + #if the above terminates a quit request was received: + # kill VA instance + print( "Closing VA instance" ) + self.oVAProcess.terminate() + time.sleep( 1 ) + self.oVAProcess.kill() + self.oVAProcess = None + + def ListenForRequestsByVAServer(self): + while True: + try: + sResult = self.oLauncherConnection.recv( 128 ) + + if sResult != '': + #check whether we are about to reveive a file + sMessage = sResult.decode("utf-8") + if sMessage.startswith("file"): + self.ReceiveFile(sMessage) + else: #NOT sMessage.startswith("file") + print( "Received quit event: "+sMessage ) + break + + except socket.timeout: + # timeouts are okay + print( "Launcher Socket timeout, keep running anyways" ) + except socket.error: + print( "Launcher Connection terminated unexpectedly" ) + break + except (KeyboardInterrupt, SystemExit): + raise #re-raise for higher instance to catch + + def ReceiveFile(self, sMessage): + aMessageParts = sMessage.split(":") + iBytesToReceive = int(aMessageParts[2]) + Path, Filename = os.path.split(aMessageParts[1]) + ProjectName = aMessageParts[3] + Fullpath = os.path.join(self.sCurrentScriptsDirectory, "..", "tmp", ProjectName, Path, "") + print("Should receive file: "+Filename+" in path "+Fullpath+ " with "+str(iBytesToReceive)+" bytes") + + #check whether the file with this exact size already exists + if os.path.isfile(Fullpath+Filename) and os.stat(Fullpath+Filename).st_size==iBytesToReceive: + self.oLauncherConnection.send( b'exists' ) + print("File already exists with this size, so no need for resending") + + else: #file need to be received + #create dir if it does not exist + if not os.path.exists(Fullpath): + os.makedirs(Fullpath) + + #send acceptance + self.oLauncherConnection.send( b'ack' ) + + #receive file + iBytesReceived = 0 + with open(Fullpath+Filename, "wb") as f: + bReceivingFile = True + while bReceivingFile: + # read 1024 bytes from the socket (receive) + bytes_read = self.oLauncherConnection.recv(1024) + if not bytes_read: + # nothing is received + # file transmitting is done + bReceivingFile = False else: - - print( "sending go token" ) - oConnection.send( b'g' ) - - #wait until quit command arrives, or the connection closes - bContinue = True - oConnection.settimeout( 1.0 ) - while bContinue: - try: - sResult = oConnection.recv( 128 ) - - if sResult != '': - #check whether we are about to reveive a file - sMessage = sResult.decode("utf-8") - if sMessage.startswith("file"): - aMessageParts = sMessage.split(":") - iBytesToReceive = int(aMessageParts[2]) - Path, Filename = os.path.split(aMessageParts[1]) - ProjectName = aMessageParts[3] - Fullpath = os.path.join(sCurrentScriptsDirectory, "..", "tmp", ProjectName, Path, "") - print("Should receive file: "+Filename+" in path "+Fullpath+ " with "+str(iBytesToReceive)+" bytes") - - #check whether the file with this exact size already exists - if os.path.isfile(Fullpath+Filename) and os.stat(Fullpath+Filename).st_size==iBytesToReceive: - oConnection.send( b'exists' ) - print("File already exists with this size, so no need for resending") - - else: #file need to be received - #create dir if it does not exist - if not os.path.exists(Fullpath): - os.makedirs(Fullpath) - - #send acceptance - oConnection.send( b'ack' ) - #print("Send ack") - - #receive file - iBytesReceived = 0 - with open(Fullpath+Filename, "wb") as f: - bReceivingFile = True - while bReceivingFile: - # read 1024 bytes from the socket (receive) - bytes_read = oConnection.recv(1024) - #print("Read 1024 bytes") - if not bytes_read: - # nothing is received - # file transmitting is done - bReceivingFile = False - else: - # write to the file the bytes we just received - f.write(bytes_read) - iBytesReceived += len(bytes_read) - if iBytesReceived == iBytesToReceive: - bReceivingFile = False - f.close() - - #check whether received file seems ok - if iBytesReceived == iBytesToReceive: - oConnection.send( b'ack' ) #send acceptance - print("File received successfully") - else: - oConnection.send( b'fail' ) #send failure - print("File receive failed") - else: #NOT sMessage.startswith("file") - print( "Received quit event: "+sMessage ) - bContinue = False - - except socket.timeout: - bContinue = True # timeouts are okay - except socket.error: - print( "Connection terminated unexpectedly" ) - bContinue = False - except (KeyboardInterrupt, SystemExit): - raise - - # kill VA instance - print( "Closing VA instance" ) - oProcess.terminate() - time.sleep( 1 ) - oProcess.kill() - oProcess = None + # write to the file the bytes we just received + f.write(bytes_read) + iBytesReceived += len(bytes_read) + if iBytesReceived == iBytesToReceive: + bReceivingFile = False + f.close() + + #check whether received file seems ok + if iBytesReceived == iBytesToReceive: + self.oLauncherConnection.send( b'ack' ) #send acceptance + print("File received successfully") + else: + self.oLauncherConnection.send( b'fail' ) #send failure + print("File receive failed") + + +#create an instance of the class +oLauncher = VirtualAcousticsLauncher() + + -except KeyboardInterrupt: - print( "Caught keyboard interrupt, quitting" ) - -oServer.close()