diff --git a/spykhanat.py b/spykhanat.py index d97ada9..768e803 100755 --- a/spykhanat.py +++ b/spykhanat.py @@ -233,6 +233,7 @@ class SpyPcap(): """ actions = [] properties = [] + notices = {} try: while True: property = {} @@ -242,17 +243,20 @@ class SpyPcap(): if msgin.needRead() < 8: logging.getLogger(LOGGER).debug("too small no decodeVisualProperties [{0} > {1}]".format(msgin.sizeRead() + (8*8 ), msgin.sizeData() * 8 )) logging.getLogger(LOGGER).debug("properties:%s" % str(properties)) - return properties + return properties, notices logging.getLogger(LOGGER).debug("too small no decodeVisualProperties [{0} > {1}]".format(msgin.sizeRead() + (8*8 ), msgin.sizeData() * 8 )) slot = msgin.readUint8("Slot") property['slot'] = slot + hearder = 'VisualProperty/Slot'+str(slot) + '/' associationBits = msgin.readSerial(2, "associationBits") + notices.setdefault(hearder + 'associationBits', associationBits) property['associationBits'] = associationBits logging.getLogger(LOGGER).debug("slot:{0} (associationBits:{1})".format(slot, associationBits)) if self.client_state[clientid]['PropertyDecoder'] .associationBitsHaveChanged( slot, associationBits ) and (slot==0): if self.client_state[clientid]['PropertyDecoder'] .isUsed( slot ): sheet = self.client_state[clientid]['PropertyDecoder'] .getSheet(slot) property['sheet'] = sheet + notices.setdefault(hearder + 'sheet', sheet) logging.getLogger(LOGGER).debug("sheet:{0}".format(sheet)) # TODO - remove sheet found in the list timestampIsThere = msgin.readBool("timestampIsThere") @@ -264,6 +268,7 @@ class SpyPcap(): timestamp = self.client_state[clientid]['CurrentReceivedNumber'] logging.getLogger(LOGGER).debug("timestamp:{0}".format(timestamp)) property['timestamp'] = timestamp + notices.setdefault(hearder + 'timestamp', timestamp) property.setdefault('Actions', []) # Tree # currentNode->a() @@ -274,9 +279,13 @@ class SpyPcap(): # Create a new action cActionPosition = CAction.CActionPosition(slot, Enum.TActionCode.ACTION_POSITION_CODE, self.client_state[clientid]['world']) cActionPosition.set_name('POSITION_CODE') + cActionPosition.set_header_notice(hearder + 'POSITION_CODE') self.client_state[clientid]['PropertyDecoder'] .receive(cActionPosition) cActionPosition.unpack(msgin) actions.append(cActionPosition) + for key in cActionPosition.notice: + notices.setdefault(key, cActionPosition.notice[key]) + #notice.setdefault(hearder + 'POSITION_CODE', cActionPosition) property['Actions'] .append(cActionPosition) # currentNode->b() BranchHasPayload = msgin.readBool("BranchHasPayload [_VisualPropertyTreeRoot.VPB]") @@ -288,15 +297,20 @@ class SpyPcap(): if BranchHasPayload: # Create a new action -> PROPERTY_ORIENTATION cActionOrientation= CAction.CActionSint64(slot, Enum.TPropIndex.PROPERTY_ORIENTATION, self.client_state[clientid]['world']) + cActionOrientation.set_header_notice(hearder + 'Sint64') cActionOrientation.setNbBits(Enum.TPropIndex.PROPERTY_ORIENTATION, 'PROPERTY_ORIENTATION') cActionOrientation.set_name('PROPERTY_ORIENTATION') cActionOrientation.unpack(msgin) #self.client_state[clientid]['PropertyDecoder'] .receive(cActionPosition) actions.append(cActionOrientation) + for key in cActionOrientation.notice: + notices.setdefault(key, cActionOrientation.notice[key]) property['Actions'] .append(cActionOrientation) # Discreet properties # _VisualPropertyTreeRoot->b()->b() - actions = self.client_state[clientid]['VisualPropertyTreeRoot'].decodeDiscreetPropertiesVpbVpb(clientid, msgin, slot, self.client_state[clientid]['world']) + actions, addnotices = self.client_state[clientid]['VisualPropertyTreeRoot'].decodeDiscreetPropertiesVpbVpb(clientid, msgin, slot, self.client_state[clientid]['world']) + for key in addnotices: + notices.setdefault(hearder + key, addnotices[key]) for action in actions: property['Actions'] .append(action) #self.decodeDiscreetProperties(clientid, msgin) @@ -306,7 +320,7 @@ class SpyPcap(): except: # Detect end of stream (little hard to close) pass - return properties + return properties, notices def decode_server(self, clientid, msgin, receivedPacket, receivedAck, nextSentPacket=0): """ @@ -359,8 +373,8 @@ class SpyPcap(): logging.getLogger(LOGGER).debug("append Code:%s" % str(action.Code)) self.add_registered_action(clientid, action) # khanat-opennel-code/code/ryzom/client/src/network_connection.cpp:1512 void CNetworkConnection::decodeVisualProperties( CBitMemStream& msgin ) - properties = self.decodeVisualProperties(clientid, msgin) - return actions, properties + properties, notices = self.decodeVisualProperties(clientid, msgin) + return actions, properties, notices def decode_client_send_normal_message(self, msgin, clientid, dst, sequenceid, name, Reference): ''' @@ -499,7 +513,7 @@ class SpyPcap(): properties = [] impulses = [] databases = [] - importantinfo = {} + notices = {} CurrentSendNumber = msgin.readSint32('CurrentSendNumber') logging.getLogger(LOGGER).debug("[Server -> Client] {CurrentSendNumber:%d, src:%s, dst:%s}" % (CurrentSendNumber, src, dst)) SystemMode = msgin.readBool('SystemMode') @@ -509,7 +523,7 @@ class SpyPcap(): if not SystemMode: _LastReceivedAck = msgin.readSint32('LastReceivedAck'); logging.getLogger(LOGGER).debug("[Server -> Client] Normal Mode {CurrentSendNumber:%d, src:%s, dst:%s, _LastReceivedAck:%d}" % (CurrentSendNumber, src, dst, _LastReceivedAck)) - actions, properties = self.decode_server(dst, msgin, CurrentSendNumber, CurrentSendNumber-1) + actions, properties, notices = self.decode_server(dst, msgin, CurrentSendNumber, CurrentSendNumber-1) if actions: logging.getLogger(LOGGER).debug('list actions: [' + str(len(actions)) + '] ' +','.join( [ str(x) for x in actions] ) ) else: @@ -694,7 +708,7 @@ class SpyPcap(): #cActionFactory.unpack(msgin) logging.getLogger(LOGGER).debug("[Server -> Client] msg:%s" % msgin.showAllData()) #logging.getLogger(LOGGER).info("impulses:%s" % str(impulses)) - return actions, impulses, databases, properties, importantinfo + return actions, impulses, databases, properties, notices def read(self): logging.getLogger(LOGGER).info("Conversion => Start") @@ -769,11 +783,11 @@ class SpyPcap(): if (self.khanat_host_service and self.khanat_host_service.match(src)) or ( not self.khanat_host_service and khanat_host == src): _provenance = 'Server -> Client' logging.getLogger(LOGGER).debug("[%s] (message received) [%s] %s" % (_provenance, datetime.fromtimestamp(pkt.timestamp).strftime("%Y/%m/%d %H:%M:%S"), msgin.showAllData())) - actions_servers, impulses_servers, databases_servers, properties_servers, importantinfo = self.decode_khanat_message(msgin, src, dst, sequenceid, list_host[dst], Reference, list_host[src]) + actions_servers, impulses_servers, databases_servers, properties_servers, notices = self.decode_khanat_message(msgin, src, dst, sequenceid, list_host[dst], Reference, list_host[src]) else: _provenance = 'Client -> Server' logging.getLogger(LOGGER).debug("[%s] (message received) [%s] %s" % (_provenance, datetime.fromtimestamp(pkt.timestamp).strftime("%Y/%m/%d %H:%M:%S"), msgin.showAllData())) - actions_clients, impulses_clients, databases_clients, importantinfo = self.decode_client_message(msgin, src, dst, sequenceid, list_host[dst], Reference, list_host[src]) + actions_clients, impulses_clients, databases_clients, notices = self.decode_client_message(msgin, src, dst, sequenceid, list_host[dst], Reference, list_host[src]) if not msgin.checkOnlyZeroAtEnd(): # msgin.needRead() > 7: moredata = "message partially decoded" fullconverted = False @@ -781,7 +795,7 @@ class SpyPcap(): moredata = 'message decoded' if self.show_message_decoded: logging.getLogger(LOGGER).debug("[%s] (%s) %s" % (_provenance, moredata, msgin.showAllData())) - if importantinfo: + if notices: havedata = True else: havedata = False @@ -807,9 +821,8 @@ class SpyPcap(): break if havedata: print(datetime.fromtimestamp(pkt.timestamp).strftime("%Y/%m/%d %H:%M:%S"), "[", Reference, "]", list_host[src], "->", list_host[dst]) - if importantinfo: - for key in importantinfo: - print(" " * 3, key, ":", importantinfo[key]) + for key in notices: + print(" " * 3, key, ":", notices[key]) for action in actions_servers: data = action.get_notice() for key in data: @@ -828,8 +841,8 @@ class SpyPcap(): print(" " * 3, key, ":", data[key]) print("") if self.outcsv: - for key in importantinfo: - self.outcsv.write("%s,%s,%s,%s,%s,%s\n" % (datetime.fromtimestamp(pkt.timestamp).strftime("%Y/%m/%d %H:%M:%S"), Reference, list_host[src], list_host[dst], key, importantinfo[key])) + for key in notices: + self.outcsv.write("%s,%s,%s,%s,%s,%s\n" % (datetime.fromtimestamp(pkt.timestamp).strftime("%Y/%m/%d %H:%M:%S"), Reference, list_host[src], list_host[dst], key, notices[key])) for action in actions_servers: data = action.get_notice() for key in data: diff --git a/tools/CAction.py b/tools/CAction.py index f6dab7f..95299cc 100644 --- a/tools/CAction.py +++ b/tools/CAction.py @@ -184,7 +184,7 @@ class CActionPosition(CAction): ret.setdefault("Position", ', '.join([str(x) for x in self.Position])) ret.setdefault("Position16", ', '.join([str(x) for x in self.Position16])) ret.setdefault("IsRelative", str(self.IsRelative)) - ret.setdefault("IsRelative", str(self.IsRelative)) + ret.setdefault("Interior", str(self.Interior)) return ret def unpack(self, message): @@ -196,8 +196,8 @@ class CActionPosition(CAction): self.add_notice('px', self.Position16[0] ) self.add_notice('py', self.Position16[1] ) self.add_notice('pz', self.Position16[2] ) - self.add_notice('IsRelative', self.Position16[2] & 0x1 ) - self.add_notice('Interior', self.Position16[2] & 0x2 ) + self.add_notice('IsRelative', (self.Position16[2] & 0x1) != 0 ) + self.add_notice('Interior', (self.Position16[2] & 0x2) != 0 ) # message.serialAndLog1( Position16[0] ); # message.serialAndLog1( Position16[1] ); @@ -465,6 +465,7 @@ class CActionSint64(CAction): TPropIndex.TPropIndex.PROPERTY_PVP_CLAN: 32 , TPropIndex.TPropIndex.PROPERTY_OWNER_PEOPLE: 3 , # 4 races and unknow TPropIndex.TPropIndex.PROPERTY_OUTPOST_INFOS: 16 } # 15+1 + self.set_header_notice("Action/Sint64") def get_parameter(self): ret = super().get_parameter() @@ -479,6 +480,7 @@ class CActionSint64(CAction): logging.getLogger(LOGGER).debug("msgin:%s" % msgin.showAllData()) # self.value = msgin.readSerial( self.NbBits, 'value') self.value = msgin.readSerialUint64( self.NbBits, self.NameProperty) + self.add_notice(self.NameProperty, self.value) logging.getLogger(LOGGER).debug("msgin:%s" % msgin.showAllData()) #self.NbBits = msgin.readUint32('NbBits') logging.getLogger(LOGGER).debug("value:%u" % self.value) diff --git a/tools/TVPNodeBase.py b/tools/TVPNodeBase.py index 6b09d72..7ebe527 100644 --- a/tools/TVPNodeBase.py +++ b/tools/TVPNodeBase.py @@ -193,6 +193,7 @@ class TVPNodeBase(): def decodeDiscreetProperty(self, msgin, propIndex, slot, world): # khanat-opennel-code/code/ryzom/client/src/network_connection.cpp:1746 void CNetworkConnection::decodeDiscreetProperty logging.getLogger(LOGGER).debug("decodeDiscreetProperty") + notices = {} action = None if propIndex == Enum.TPropIndex.PROPERTY_TARGET_LIST: logging.getLogger(LOGGER).debug("PROPERTY_TARGET_LIST") @@ -204,10 +205,11 @@ class TVPNodeBase(): d1 = msgin.readUint8( "TargetSlots_{0}".format(i)); logging.getLogger(LOGGER).debug("data:{0}".format(d1)) # Update property - return [] + return [], notices logging.getLogger(LOGGER).debug("CActionFactory : {0}".format(slot)) action = CActionFactory.CActionFactory(world).createByPropIndex(slot, self.PropIndex, self.NameProperty) + action.set_header_notice("-") logging.getLogger(LOGGER).debug("unpack: {0}".format(slot)) action.unpack(msgin) if self.PropIndex == Enum.TPropIndex.PROPERTY_SHEET: @@ -221,7 +223,9 @@ class TVPNodeBase(): else: pass logging.getLogger(LOGGER).debug("[decodeDiscreetProperty] (%s)" % (msgin.showAllData())) - return action + for key in action.notice: + notices.setdefault(key[2:], action.notice[key]) + return action, notices def decodeDiscreetProperties(self, clientid, msgin, slot, world): @@ -229,23 +233,30 @@ class TVPNodeBase(): logging.getLogger(LOGGER).debug("decodeDiscreetProperties " + self.Name) self.BranchHasPayload = msgin.readBool("BranchHasPayload [{0}, NameProperty:{1}]".format(self.Name, self.NameProperty)) actions = [] + notices = {} if self.BranchHasPayload: if self.isLeaf(): # SlotContext.NetworkConnection->decodeDiscreetProperty( msgin, PropIndex ); logging.getLogger(LOGGER).debug("isLeaf") - action = self.decodeDiscreetProperty(msgin, self.PropIndex, slot, world) + action, addnotices = self.decodeDiscreetProperty(msgin, self.PropIndex, slot, world) + for key in addnotices: + notices.setdefault(key, addnotices[key]) if action: actions.append(action) else: if self.VPA: - tmp = self.VPA.decodeDiscreetProperties(clientid, msgin, slot, world) + tmp, addnotices = self.VPA.decodeDiscreetProperties(clientid, msgin, slot, world) + for key in addnotices: + notices.setdefault(key, addnotices[key]) for action in tmp: actions.append(action) if self.VPB: - tmp = self.VPB.decodeDiscreetProperties(clientid, msgin, slot, world) + tmp, addnotices = self.VPB.decodeDiscreetProperties(clientid, msgin, slot, world) + for key in addnotices: + notices.setdefault(key, addnotices[key]) for action in tmp: actions.append(action) - return actions + return actions, notices def decodeDiscreetPropertiesVpbVpb(self, clientid, msgin, slot, world):