def WorkerProc(self, fnKillSignalled, userData): lastUpdate = 0 interval = Configuration.get().GetConnectionUpdateInterval() buffer = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" buffer = buffer + "<Oscar Type=\"ConnectionInformation\">" buffer = buffer + "<Version>1.0</Version>" buffer = buffer + "<OscarVersion>" + VersionMgr.ReadVer( ) + "</OscarVersion>" buffer = buffer + "<ID>" + Configuration.get().GetID() + "</ID>" buffer = buffer + "<Port>" + str(Configuration.get( ).GetDownstreamConnection().getPort()) + "</Port>" buffer = buffer + "</Oscar>" #<?xml version="1.0" encoding="utf-8"?> #<Oscar Type="ConnectionInformation"> # <Version>1.0</Version> # <ID>Foo</Foo> # <Port>Port</Port> #</Oscar> while not fnKillSignalled( ): # run until signalled to end - call passed function to check for the signal if lastUpdate < Time.GetCurrMS() - interval: TargetManager.GetTargetManager().BroadcastDownstream( buffer, True, None ) # send Connection Data to all downstream things (Oscars & Marvins) lastUpdate = Time.GetCurrMS() Configuration.get().RescanTargets() else: Sleep.Sleep(0.25) TargetManager.GetTargetManager( ).CheckForRemovalOfDynamicMarvins()
def updateGui(self): targets = TargetManager.GetTargetManager().GetDownstreamTargets() # was a channge in number (maybe a dynamci marvin went away) so just clear the tree and re-poplualte if len(targets) != self.PreviousTargetCount: self.PreviousTargetCount = len(targets) self.tree.delete(*self.tree.get_children()) for key in targets: target = TargetManager.GetTargetManager().GetDownstreamTarget(key) strPackets = str(target.m_PacketsSent) strBytes = str(target.m_BytestSent) strType = target.getTypeStr() try: self.tree.set(key, 'Packets', strPackets) self.tree.set(key, 'Bytes', strBytes) self.tree.set(key, 'Type', strType) if True == target.m_hasTimedOut: self.tree.set(key, 'IP', "*" + target.getIP()) else: self.tree.set(key, 'IP', target.getIP()) except Exception as Ex: try: self.tree.insert('', 'end', key, values=(target.getIP(), str(target.getPort()), strType, strPackets, strBytes)) except Exception as Ex: Log.getLogger().error(str(Ex))
def HandleIncomingMinionConnectionInformation(self, node, rawData, fromAddr): #<?xml version="1.0" encoding="utf-8"?> #<Minion Type="ConnectionInformation"> # <Version>1.0</Version>" # <MinionVersion>17.02.12 Build 3</MinionVersion>" # <Namespace>NamespaceFoo</Namespace> # <Port>12345</Port> #</Minion> try: version = node.getElementsByTagName( 'Version')[0].firstChild.nodeValue except Exception as Ex: Statistics.GetStatistics().OnMalformedPacketReceived( "Received invalid Minion Connection Information Packet : " + rawData) return try: namespace = node.getElementsByTagName( 'Namespace')[0].firstChild.nodeValue namespace = namespace.lower() except Exception as Ex: Statistics.GetStatistics().OnMalformedPacketReceived( "Received invalid Minion ConnectionInformation Packet : " + rawData) return try: port = node.getElementsByTagName('Port')[0].firstChild.nodeValue except Exception as Ex: Statistics.GetStatistics().OnMalformedPacketReceived( "Received invalid Minion ConnectionInformation Packet : " + rawData) return IP = fromAddr[0].lower() TargetID = namespace + ":" + IP + ":" + port CP = TargetManager.GetTargetManager().GetUpstreamTarget(TargetID) if None == CP: objUpstreamTarget = Target.Target( IP, port, ConnectionPoint.ConnectionType.Minion, False) TargetManager.GetTargetManager().AddUpstreamTarget( objUpstreamTarget, TargetID) # add it as a upstream target for tasks and such try: minionVersion = node.getElementsByTagName( 'MinionVersion')[0].firstChild.nodeValue Log.getLogger().info("Received Connection from Minion " + TargetID + " version: " + minionVersion) except Exception as Ex: pass elif CP.Type != ConnectionPoint.ConnectionType.Minion: Statistics.GetStatistics().OnMalformedPacketReceived( "Unexpected Connection Type: " + str(CP.Type))
def HandleBullhornAnnouncement(self,node,rawData,fromAddr): #<?xml version="1.0" encoding="utf-8"?> #<Marvin Type="Bullhorn"> # <Version>1.0</Version> # <UniqueID>3236</UniqueID> # <Hostname>pgkutch.beervana.net</Hostname> # <Key>md5 hash</Key> # <Port>5000</Port> #</Marvin> try: version = node.getElementsByTagName('Version')[0].firstChild.nodeValue Hash = node.getElementsByTagName('Key')[0].firstChild.nodeValue Port = node.getElementsByTagName('Port')[0].firstChild.nodeValue UniqueID = node.getElementsByTagName('UniqueID')[0].firstChild.nodeValue IP = fromAddr[0].lower() Hostname = node.getElementsByTagName('Hostname')[0].firstChild.nodeValue except Exception as _: Statistics.GetStatistics().OnMalformedPacketReceived("Received invalid Marvin Bullhorn Packet : " + rawData) return RemoteKey = Configuration.get().GetMarvinAutoConnectKeyFromHash(Hash) strID = Hostname + ":[" + IP + ":" + Port +"]" if None == RemoteKey: #don't have anything configured that matches Log.getLogger().warning("Received Marvin Dynamic Connection Message, with no corropsonding Key from: " + strID) return strID += " Key=" + RemoteKey HashMapKey = IP + ":" + str(Port) objExisting = TargetManager.GetTargetManager().GetDownstreamTarget(HashMapKey) if None == objExisting: # could be NDS name not resolved, so try by IP address objExisting = TargetManager.GetTargetManager().GetDownstreamTargetEx(IP,Port) if None != objExisting: if hasattr(objExisting,'_ReceivedOnUniqueID') and UniqueID != objExisting._ReceivedOnUniqueID: Log.getLogger().warning("Received Marvin Dynamic Connection Message, for already active connection: " + strID) else: pass # is simply the additional packets (marvin sends multiples as it is UDP traffic) return # doesn't already exist, so let's to add! if "1.0" == version: objTarget = Target.Target(IP,Port,ConnectionType.DynamicMarvin,True) else: objTarget = Target.Target(IP,Port,ConnectionType.DynamicOscar,True) objTarget._ReceivedOnUniqueID = UniqueID # so we can filter out dups due to UDP objTarget._UserKey = RemoteKey TargetManager.GetTargetManager().AddDownstreamTarget(objTarget,HashMapKey) Log.getLogger().info("Creating Dynamic Connection:" + strID) return
def HandleIncomingWatchdogPacket(self,node,rawData,fromAddr): #<?xml version="1.0" encoding="utf-8"?> #<Marvin Type="WatchdogTimer"> # <Version>1.0</Version> # <MarvinVersion>17.12.22</MarvinVersion> # <UniqueID>3236</UniqueID> # <Port>5000</Port> #</Marvin> Statistics.GetStatistics().OnPacketReceivedFromDownstream(rawData) try: _ = node.getElementsByTagName('Version')[0].firstChild.nodeValue IP = fromAddr[0].lower() Port = node.getElementsByTagName('Port')[0].firstChild.nodeValue UniqueID = node.getElementsByTagName('UniqueID')[0].firstChild.nodeValue except Exception as _: Statistics.GetStatistics().OnMalformedPacketReceived("Received invalid Marvin WatchdogTimer Packet : " + rawData) return try: marvinVersion = node.getElementsByTagName('MarvinVersion')[0].firstChild.nodeValue except Exception: marvinVersion='Unknown' Key = IP + ":" + Port objTarget = TargetManager.GetTargetManager().GetDownstreamTarget(Key) if None == objTarget: objTarget = TargetManager.GetTargetManager().GetDownstreamTargetEx(IP,Port) # if using DNS, do lookup based on real IP, not DNS name if None == objTarget: Sleep.Sleep(50) #give it another shot, other thread may be doing a DNS resolution objTarget = TargetManager.GetTargetManager().GetDownstreamTargetEx(IP,Port) # if using DNS, do lookup based on real IP, not DNS name if None == objTarget: Log.getLogger().warning("Received Marvin Watchdog for unknown downstream Target: " +IP+":"+Port + " Version: " + marvinVersion) return if objTarget.getType() != ConnectionType.Marvin and objTarget.getType() != ConnectionType.DynamicMarvin : # would not know what this is until you hear back (could be another Oscar) objTarget.Type = ConnectionType.Marvin Log.getLogger().info("Connection established with Marvin Target: "+ IP + ":" + Port + " Version: " + marvinVersion) try: _ = node.getElementsByTagName('RefreshRequested')[0].firstChild.nodeValue objTarget.ReArmRefreshRequest(UniqueID) # Asked to refresh! except Exception as _: pass objTarget.StrokeWatchdogTimer()
def HandleIncomingOscarConnectionInformation(self, node, rawData, fromAddress): #<?xml version="1.0" encoding="utf-8"?> #<Oscar Type="ConnectionInformation"> # <Version>1.0</Version> # <OccarVersion>16.11.21 Build 2</OscarVersion> # <ID>Foo</Foo> # <Port>Port</Port> #</Oscar> try: version = node.getElementsByTagName( 'Version')[0].firstChild.nodeValue ID = node.getElementsByTagName('ID')[0].firstChild.nodeValue Port = int( node.getElementsByTagName('Port')[0].firstChild.nodeValue) except Exception as Ex: Statistics.GetStatistics().OnMalformedPacketReceived( "Received invalid Oscar Connection Information Packet : " + rawData) return try: oscarVersion = node.getElementsByTagName( 'OscarVersion')[0].firstChild.nodeValue except Exception: oscarVersion = 'Unknown' IP = fromAddress[0].lower() Key = "Oscar:" + ID objTarget = TargetManager.GetTargetManager().GetUpstreamTarget( Key) # Chained Oscar, from Upstream # if None == objTarget: # objTarget = TargetManager.GetTargetManager().GetDownstreamTargetEx(IP,Port) # if using DNS, do lookup based on real IP, not DNS name if None == objTarget: Log.getLogger().info("Adding Upstream Oscar: " + Key + " version- " + oscarVersion) objTarget = Target.Target(IP, Port, ConnectionType.UpstreamOscar, False) TargetManager.GetTargetManager().AddUpstreamTarget(objTarget, Key) elif IP != objTarget.getIP() or Port != objTarget.getPort( ): #hmm, doesn't match, Oscar ID's current connection inf should be unique, so assume is an update from a restart of Oscar strOld = str(objTarget) objTarget.IP = IP objTarget.Port = Port Log.getLogger().warning( "Received a Oscar Connection Information Packet, with Different Connection Info from previously configured [" + ID + "] " + strOld + "--> " + str(objTarget))
def HandleIncomingGroupPacket(self, rawData, node, fromAddress): from Helpers import Configuration if Configuration.get().GetBITW_Active(): rawData = Configuration.get().HandleBITWBuffer( rawData) # handle Bump in the wire if 0 != TargetManager.GetTargetManager().BroadcastDownstream( rawData, False, node, True): # send to all - towards a Marvin Statistics.GetStatistics().OnPacketChainedDownstream(rawData) # Break up packet and do bump in the wire. # If BITW not active, maybe we don't need to do this could be a lot of processing for nothing.... objGroupPacket = MarvinGroupData.MarvinDataGroup( "", "", "", 0, "1.0", True) for packet in node.getElementsByTagName('Oscar'): objMarvinPacket = self.CreateMarvinData(packet, rawData, fromAddress) if None == objMarvinPacket: return objGroupPacket.AddPacket(objMarvinPacket) # objData = MarvinData.MarvinData(namespace,ID,value,0,version,True) GuiMgr.OnDataPacketSentDownstream(objGroupPacket, "Chained") Recorder.get().AddData(objGroupPacket)
def HandleMinionTask(self,rawData,node): Statistics.GetStatistics().OnMinionTaskReceived() TargetManager.GetTargetManager().BroadcastUpstream(rawData) # I could filter out based upon Namespace, but with chained Oscars it got harder, so now let minion filter it out try: TaskNode = node.getElementsByTagName('Task')[0] Log.getLogger().debug("Passing Minion Task --> ID: " + TaskNode.attributes['ID'].nodeValue + " Namespace: " + TaskNode.attributes['Namespace'].nodeValue) except: pass
def PerformInsertBookmark(self,Params): #<?xml version="1.0" encoding="utf-8"?> #<Marvin Type="OscarTask"> # <Version>1.0</Version> # <OscarID>DemoOscar</OscarID> # <UniqueID>1233456</UniqueID> # <Task>InsertBookmark</Task> # <Param>Namespace=foo</Param> # <Param>ID=TestMarker</Param> # <Param>Data=StartTest</Param> # <Param>Propagate=True</Param> -- if True, the data is sent back upstream towards Marvin #</Marvin> if len(Params) >= 3: fPropagate = False for param in Params: parts = param.split("=") if len(parts)==2: if parts[0].lower()=='namespace': namespace = Alias.Alias(parts[1]) elif parts[0].lower()=='id': id = Alias.Alias(parts[1]) elif parts[0].lower()=='data': data = Alias.Alias(parts[1]) elif parts[0].lower()=='propagate': propagate = Alias.Alias(parts[1]) if propagate.lower() == "true": fPropagate = True else: Log.getLogger().error("Received invalid InsertBookmark task parameter: " + str(param)) return else: Log.getLogger().error("Received invalid InsertBookmark task. Insufficient Parameters.") return if None == namespace: Log.getLogger().error("Received invalid InsertBookmark task. Namespace not specified.") return if None == id: Log.getLogger().error("Received invalid InsertBookmark task. ID not specified.") return if None == data: Log.getLogger().error("Received invalid InsertBookmark task. Data not specified.") return eTime = Time.GetCurrMS() objData = MarvinData.MarvinData(namespace,id,data,eTime,1.0) if None != objData: Recorder.get().AddData(objData) GuiMgr.OnDataPacketSentDownstream(objData,"Minion") if fPropagate: TargetManager.GetTargetManager().BroadcastDownstream(objData.ToXML(),False,None)
def StrokeWatchdogTimer(self): if True == self.m_CanTimeout: self.m_lastHeartbeat = Time.GetCurrMS() self.m_hasTimedOut = False if False == self.m_InitialRefreshSent: self.m_InitialRefreshSent = True buffer = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" buffer = buffer + "<Oscar Type=\"Refresh\">" buffer = buffer + "<Version>1.0</Version>" uID = str(random.randint(0, 500000)) buffer = buffer + "<UniqueID>" + uID + "</UniqueID>" buffer = buffer + "</Oscar>" from Helpers import TargetManager if TargetManager.GetTargetManager().BroadcastUpstream(buffer): Log.getLogger().info("Sending Refresh Request to Minions [" + uID + ']') TargetManager.GetTargetManager().BroadcastUpstream( buffer ) # is UDP, so send a couple more times, dups will be filtered on Minion TargetManager.GetTargetManager().BroadcastUpstream(buffer)
def HandleIncomingWatchdogPacket(self, node, rawData, fromAddress): #<?xml version="1.0" encoding="utf-8"?> #<Oscar Type=?WatchdogTimer"> # <Version>1.0</Version> # <Port>5000</Port> #</Oscar> Statistics.GetStatistics().OnPacketReceivedFromDownstream(rawData) try: version = node.getElementsByTagName( 'Version')[0].firstChild.nodeValue IP = fromAddress[0].lower() Port = node.getElementsByTagName('Port')[0].firstChild.nodeValue except Exception as Ex: Statistics.GetStatistics().OnMalformedPacketReceived( "Received invalid Oscar WatchdogTimer Packet : " + rawData) return Key = IP + ":" + Port objTarget = TargetManager.GetTargetManager().GetDownstreamTarget( Key) # Chained Oscar if None == objTarget: objTarget = TargetManager.GetTargetManager().GetDownstreamTargetEx( IP, Port) # Chained Oscar, used resolved IP if None == objTarget: Log.getLogger().warning( "Received Oscar Watchdog for unknown downstream Target: ", IP + ":" + Port) return if objTarget.getType( ) != ConnectionType.DownstreamOscar: # would not know what this is until you hear back objTarget.Type = ConnectionType.DownstreamOscar objTarget.StrokeWatchdogTimer()
def HandleIncomingMinionData(self, rawData, node, fromAddress): # <?xml version="1.0" encoding="utf-8"?> # <Minion> # <Version>1</Version> # <PacketNumber>44</PacketNumber> # <Namespace>Namespace_Foo</Namespace> # <Name>CPU_UTIL_CORE0</Name> # <Value>33.2</Value> # <Normalized>False</Normalized> # <ElapsedTime>253</ElapsedTime> # </Minion> objData = self.CreateMarvinPacket(rawData, node, fromAddress) if None != objData: TargetManager.GetTargetManager().BroadcastDownstream( objData.ToXML(), False, node) GuiMgr.OnDataPacketSentDownstream(objData, "Minion") Recorder.get().AddData(objData)
def HandleIncomingOscarDatapacket(self, node, rawData, fromAddress): from Helpers import Configuration # Use this object to update the gui and for recording # is also where BITW check update of checked map occurs objData = self.CreateMarvinData(node, rawData, fromAddress) if Configuration.get().GetBITW_Active(): rawData = Configuration.get().HandleBITWBuffer( rawData) # handle Bump in the wire if 0 != TargetManager.GetTargetManager().BroadcastDownstream( rawData, False, node): # send to all - towards a Marvin Statistics.GetStatistics().OnPacketChainedDownstream(rawData) if None != objData: GuiMgr.OnDataPacketSentDownstream(objData, "Chained") Recorder.get().AddData(objData)
def __ReadDownstreamTargets(self, domDoc): retList = [] nodeList = domDoc.getElementsByTagName("TargetConnection") if None != nodeList and len(nodeList) > 0: for node in nodeList: attributes = node.attributes if "IP" in attributes: IP = Alias.Alias(attributes["IP"].nodeValue) else: Log.getLogger().error("No Target IP specified") return False if "PORT" in attributes: try: Port = int(Alias.Alias(attributes["PORT"].nodeValue)) except Exception as Ex: Log.getLogger().error(str(Ex)) Log.getLogger().error( "Invalid Port set for Target Connection") return False else: Log.getLogger().error("No Target IP specified") return False connType = ConnectionType.Unknown objTarget = Target.Target( IP, Port, connType, True) # could be Marvin or another Oscar Key = IP + ":" + str(Port) TargetManager.GetTargetManager().AddDownstreamTarget( objTarget, Key) retList.append(Target) elif None == self.__DynamicConnectMarvinMap: Log.getLogger().error("TargetConnection not defined") return retList
def WatchdogProc(self, fnKillSignalled, userData): lastUpdate = 0 interval = Configuration.get().GetTimeoutPeriod( ) * 0.25 # send a watchdog at 4x rate of timeout buffer = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" buffer = buffer + "<Oscar Type=\"WatchdogTimer\">" buffer = buffer + "<Version>1.0</Version>" buffer = buffer + "<Port>" + str( Configuration.get().GetUpstreamConnection().getPort()) + "</Port>" buffer = buffer + "</Oscar>" while not fnKillSignalled( ): # run until signalled to end - call passed function to check for the signal if lastUpdate < Time.GetCurrMS() - interval: TargetManager.GetTargetManager().BroadcastUpstreamToType( buffer, ConnectionType.UpstreamOscar ) # send heartbeat to all upstream Oscars lastUpdate = Time.GetCurrMS() Sleep.Sleep(0.25) #snooze for 250 ms
def HandleFoghornPacket(self, node, rawData, fromAddr): #<?xml version="1.0" encoding="utf-8"?> #<Foghorn> # <Version>1.0</Version> # <ConfigAddress>Kutch.system.foo.com</ConfigAddress> # <NewIPAddress>129.234.1.22</NewIPAddress> # <Port>Port</Port> #</Foghorn> try: _ = node.getElementsByTagName('Version')[0].firstChild.nodeValue ConfigAddr = node.getElementsByTagName( 'ConfigAddress')[0].firstChild.nodeValue NewAddr = node.getElementsByTagName( 'NewIPAddress')[0].firstChild.nodeValue except Exception as _: Statistics.GetStatistics().OnMalformedPacketReceived( "Received invalid Oscar Connection Information Packet : " + rawData) return TargetManager.GetTargetManager().UpdateDownstreamTarget( ConfigAddr, NewAddr)
def HandleIncomingGroupPacket(self, rawData, node, fromAddress): # <?xml version="1.0" encoding="utf-8"?> # <MinionGroup> # <Minion> # <Version>1</Version> # <PacketNumber>44</PacketNumber> # <Namespace>Namespace_Foo</Namespace> # <Name>CPU_UTIL_CORE0</Name> # <Value>33.2</Value> # <Normalized>False</Normalized> # <ElapsedTime>253</ElapsedTime> # </Minion> # <Minion> # <Version>1</Version> # <PacketNumber>45</PacketNumber> # <Namespace>Namespace_Foo</Namespace> # <Name>CPU_UTIL_CORE1</Name> # <Value>3.2</Value> # <Normalized>False</Normalized> # <ElapsedTime>273</ElapsedTime> # </Minion> # </MinionGroup> objGroupPacket = MarvinGroupData.MarvinDataGroup( "", "", "", 0, "1.0", True) for packet in node.getElementsByTagName('Minion'): objMarvinPacket = self.CreateMarvinPacket(rawData, packet, fromAddress) if None == objMarvinPacket: return objGroupPacket.AddPacket(objMarvinPacket) GuiMgr.OnDataPacketSentDownstream(objGroupPacket, "Minion") TargetManager.GetTargetManager().BroadcastDownstream( objGroupPacket.ToXML(), False, None, True) Recorder.get().AddData(objGroupPacket)
def _secondaryInit(self): self.__clients = [] # Get messages to send towards Marvin self.m_Name = "ProxyTCP Server:" + str(self) #TargetManager.GetTargetManager().AddDownstreamTarget(self,self.m_Name) TargetManager.GetTargetManager().AddUpstreamTarget(self, self.m_Name)
def HandleRefresh(self): TargetManager.GetTargetManager().DebugRefresh()
def RescanTargets(self): try: if self.GetConfFileModificationInfo( ) == Configuration.modification_date(self.GetConfigFilename()): return filename = self.GetConfigFilename() Log.getLogger().info("Re-scanning config file: " + filename) self.__ConfigFileTimeStamp = Configuration.modification_date( filename) filename = self.GetConfigFilename() #open the xml file for reading: file = open(filename, 'r') #convert to string: data = file.read() #close file because we dont need it anymore: file.close() except: return try: domDoc = xml.dom.minidom.parseString(data) except Exception as ex: self.__HandleInvalidXML("Bad Content - XML error: " + str(ex)) return nodeList = domDoc.getElementsByTagName("TargetConnection") if None != nodeList and len(nodeList) > 0: for node in nodeList: attributes = node.attributes if "IP" in attributes: IP = Alias.Alias(attributes["IP"].nodeValue) else: Log.getLogger().error("No Target IP specified") return False if "PORT" in attributes: try: Port = int(Alias.Alias(attributes["PORT"].nodeValue)) except Exception as Ex: Log.getLogger().error(str(Ex)) Log.getLogger().error( "Invalid Port set for Target Connection") return False else: Log.getLogger().error("No Target IP specified") return False objTarget = Target.Target( IP, Port, ConnectionType.Unknown, True) # could be Marvin or another Oscar #Key = socket.gethostbyname(IP) + ":" +str(Port) Key = IP + ":" + str(Port) if not TargetManager.GetTargetManager().GetDownstreamTarget( Key): Log.getLogger().info("Adding new Downstream target: " + Key) TargetManager.GetTargetManager().AddDownstreamTarget( objTarget, Key)
def HandleChainedRefresh(self, rawData): Log.getLogger().info("Sending Refresh from another Oscar") TargetManager.GetTargetManager().BroadcastUpstream(rawData)
def _secondaryInit(self): self.__clients = [] # Get messages to send towards Minion self.m_Name = "ProxyTCP Client:" + str(self) TargetManager.GetTargetManager().AddDownstreamTarget(self, self.m_Name)
def HandleRemoteMarvinTask(self, rawData): Statistics.GetStatistics().OnMarvinTaskReceived() TargetManager.GetTargetManager().BroadcastDownstream( rawData, False, none)
def __workerProc(self, fnKillSignalled, userData): from Helpers import GuiMgr self.CurrentIndex = self.startIndex self.StartTime = None xmlList = [] while not fnKillSignalled( ): # run until signalled to end - call passed function to check for the signal if self.Paused or self.Stopped: Sleep.SleepMs(100) continue if None == self.StartTime: self.StartTime = int( self.PlaybackData[self.CurrentIndex].ArrivalTime ) - 10 # can't remember why I subract 10ms... objData = self.PlaybackData[self.CurrentIndex] sleepVal = (int(objData.ArrivalTime) - self.StartTime) / self.PlaybackSpeed Sleep.SleepMs(sleepVal) try: # when looping, this data will be here after the 1st loop xmlData = self.PlaybackData[self.CurrentIndex].xmlData node = self.PlaybackData[self.CurrentIndex].firstNode except: xmlData = objData.ToXML( ) # be more efficient if I create a list of already created xmldata self.PlaybackData[ self. CurrentIndex].xmlData = xmlData # LOVe how you can just add stuff to an object in Python! if Configuration.get().GetShunting(): try: dom = xml.dom.minidom.parseString(rawData) node = dom._get_firstChild() except Exception as ex: Log.getLogger().error( "Error Something bad in Trying to re-encode saved data" ) else: node = None self.PlaybackData[self.CurrentIndex].firstNode = node TargetManager.GetTargetManager().BroadcastDownstream( xmlData, False, node) GuiMgr.OnDataPacketSentDownstream(objData, "Playback") try: self.StartTime = int( self.PlaybackData[self.CurrentIndex].ArrivalTime) except Exception: self.StartTime = None # just in case get an out of bounds error self.CurrentIndex += 1 if None == self.endIndex: self.endIndex = len(self.PlaybackData) - 1 if self.CurrentIndex >= self.endIndex: preProcessingDone = True if self.LoopMode == RepeatMode.NONE: GuiMgr.OnStopPlayback() if Configuration.get().GetExitAfterAutoPlay(): Log.getLogger().info( "Playback finished, exiting application per arguments" ) GuiMgr.Quit() elif self.LoopMode == RepeatMode.REPEAT: self.CurrentIndex = 0 self.LoopCount += 1 elif self.LoopMode == RepeatMode.LOOP: self.CurrentIndex = self.startIndex self.LoopCount += 1 self.StartTime = None