def handleTcpResponse(self): if self.tcpReadState == self.STATE_TCP_READ_LEN: if len(self.tcpData) >= 4: self.tcpResponseLen, self.tcpData = Protocol.extractInt( self.tcpData) self.tcpReadState = self.STATE_TCP_READ_DATA self.handleTcpResponse() elif self.tcpReadState == self.STATE_TCP_READ_DATA: if len(self.tcpData) >= self.tcpResponseLen: # tcpResponseLen should be >= 4 if self.tcpResponseLen < 4: logdebug().error( 'Cannot handle TLV payload of less than 4 bytes') self.tcpData = self.tcpData[self.tcpResponseLen:] self.tcpResponseLen = 0 self.tcpReadState = self.STATE_TCP_READ_LEN self.handleTcpResponse() else: data = self.tcpData[:self.tcpResponseLen] self.tcpData = self.tcpData[self.tcpResponseLen:] seq = Protocol.unpackInt(data[0:4]) self.tcpResponseLen = 0 self.tcpReadState = self.STATE_TCP_READ_LEN self.dispatch(seq, data[4:]) self.handleTcpResponse()
def parseChallengeReceivedResponse(self, data): name, data = Protocol.extractTLV(data) rom, data = Protocol.extractTLV(data) if rom != self.rom or name in self.ignored: return self.challengers.add(name) self.sigChallengeReceived.emit(name)
def parseMessage(self, data): """ Decode and route a message received from server Message is encoded as follows: byte 0-3 - positive integer, 0 for internal messages, 1 for referee messages, otherwise the extension ID of the extension to receive the message. byte 4-7 - extension-defined positive integer byte 8+ - json-packed python object parameter Args: data: Encoded message data """ cmd, data = Protocol.extractTLV(data) extID, cmd = Protocol.extractInt(cmd) prefix, cmd = Protocol.extractInt(cmd) params = None if cmd == '' else json.loads(cmd) # DEBUG dispext = "Extension" if extID == 0 else _ExtensionDict[extID].__name__ dispprefix = self._codeToString.get((extID, prefix), prefix) self.controller.sigStatusMessage.emit( "Ext Rcv: ext=%s, prefix=%s, params=%s" % (dispext, dispprefix, params)) if extID == 0: # internal message if prefix == _Message.InitializationDataResponse: # initialization data received from server # self.referee = ExtensionReferee(gamedata=params[1], extensionIO=self) self.gameVariableData = params[1] self._commandDict = {("/" + chatcommand): extID for chatcommand, extID in params[2]} self._sigInstantiate.emit(params[0]) self._evtInstantiationFinished.wait( ) # Block message loop until extensions are initialized # If it hangs here, the __init__() in some extension is freezing elif prefix == _Message.ChatMessage: self.chatMessage(params) elif prefix == _Message.KillEmulator: self.controller.killEmulator() elif prefix == _Message.BeginMonitoring: if self._monitorThread != None and self._monitorThread.is_alive( ): return self._monitorThread = threading.Thread( target=self._monitorCurrentMatch) self._monitorThread.daemon = True self._monitorThread.start() elif extID in self._instanceDict: # message for another extension if extID in self._instanceDict: self._instanceDict[extID].receiveMessage(prefix, params)
def dispatchInbandData(self, seq, data): if not seq in self.tcpCommandsWaitingForResponse: logdebug().error("Sequence {} data {} not matched".format(seq, data)) return origRequest = self.tcpCommandsWaitingForResponse[seq] del self.tcpCommandsWaitingForResponse[seq] if origRequest == Protocol.AUTH: self.parseAuthResponse(data) elif origRequest == Protocol.MOTD: self.parseMotdResponse(data) elif origRequest == Protocol.LIST_CHANNELS: self.parseListChannelsResponse(data) elif origRequest == Protocol.LIST_USERS: self.parseListUsersResponse(data) elif origRequest == Protocol.SPECTATE: status, data = Protocol.extractInt(data) if status != 0: self.sigStatusMessage.emit("Fail to spectate " + str(status)) elif origRequest in [Protocol.WELCOME, Protocol.JOIN_CHANNEL, Protocol.TOGGLE_AFK, Protocol.SEND_CHALLENGE, Protocol.CHAT, Protocol.ACCEPT_CHALLENGE, Protocol.DECLINE_CHALLENGE, Protocol.CANCEL_CHALLENGE]: if len(data) == 4: status, data = Protocol.extractInt(data) if status != 0: codestr = Protocol.codeToString(origRequest) logdebug().error("{} failed, data {}".format(codestr, repr(data))) self.sigActionFailed.emit(codestr) else: logdebug().error("Unknown response for {}; seq {}; data {}".format( Protocol.codeToString(origRequest), seq, repr(data))) else: logdebug().error("Not handling {} response; seq {}; data {}".format( Protocol.codeToString(origRequest), seq, repr(data)))
def parseMotdResponse(self, data): if not data: return status, data = Protocol.extractInt(data) channel, data = Protocol.extractTLV(data) topic, data = Protocol.extractTLV(data) msg, data = Protocol.extractTLV(data) self.sigMotdReceived.emit(channel, topic, msg)
def sendAcceptChallenge(self, name): isFbaPresent = self.checkInstallation() isRomPresent = self.checkRom() if not isRomPresent or not isFbaPresent: return if name in self.challengers: self.sendAndRemember(Protocol.ACCEPT_CHALLENGE, Protocol.packTLV(name) + Protocol.packTLV(self.rom)) self.challengers.remove(name)
def sendAuth(self, username, password): self.username = username try: port = self.udpSock.getsockname()[1] except: port=6009 authdata = Protocol.packTLV(username) + Protocol.packTLV(password) + Protocol.packInt(port) + Protocol.packInt(copyright.versionNum()) self.sendAndRemember(Protocol.AUTH, authdata)
def sendAuth(self, username, password): self.username = username try: port = self.udpSock.getsockname()[1] except: port = 6009 authdata = Protocol.packTLV(username) + Protocol.packTLV( password) + Protocol.packInt(port) + Protocol.packInt( copyright.versionNum()) self.sendAndRemember(Protocol.AUTH, authdata)
def parseChatResponse(self, data): name, data = Protocol.extractTLV(data) if name in self.ignored: return msg, data = Protocol.extractTLV(data) try: msg = msg.decode('utf-8') except ValueError: msg = msg self.sigChatReceived.emit(name, msg)
def sendChallenge(self, name): self.sendCancelChallenge() isFbaPresent = self.checkInstallation() isRomPresent = self.checkRom() if not isRomPresent or not isFbaPresent: return if (name==self.username): self.runFBA(self.channel) else: self.sendAndRemember(Protocol.SEND_CHALLENGE, Protocol.packTLV(name) + Protocol.packTLV(self.rom)) self.challenged = name
def sendChallenge(self, name): self.sendCancelChallenge() isFbaPresent = self.checkInstallation() isRomPresent = self.checkRom() if not isRomPresent or not isFbaPresent: return if (name==self.username): self.runFBA(self.channel) else: self.sigStatusMessage.emit("Challenging "+name) self.sendAndRemember(Protocol.SEND_CHALLENGE, Protocol.packTLV(name) + Protocol.packTLV(self.rom)) self.challenged = name
def parseChatResponse(self, data): name, data = Protocol.extractTLV(data) if name in self.ignored: return msg, data = Protocol.extractTLV(data) try: msg = msg.decode('utf-8') except ValueError: msg = msg if Settings.USER_LOG_CHAT: loguser().info(u"<{}> {}".format(name, msg)) self.sigChatReceived.emit(name, msg)
def parseChatResponse(self, data): name, data = Protocol.extractTLV(data) if name in self.ignored: return msg, data = Protocol.extractTLV(data) try: msg = msg.decode('utf-8') except ValueError: msg = msg if Settings.value(Settings.USER_LOG_CHAT): loguser().info(u"<{}> {}".format(name, msg)) self.sigChatReceived.emit(name, msg)
def parseListChannelsResponse(self, data): #self.channels = {} if len(data) <= 8: logdebug().error('No channels found') self.sigChannelsLoaded.emit() return status1, data = Protocol.extractInt(data) status2, data = Protocol.extractInt(data) logdebug().info("Load channels header " + repr(status1) + repr(status2)) while len(data) > 4: room, data = Protocol.extractTLV(data) romname, data = Protocol.extractTLV(data) title, data = Protocol.extractTLV(data) users, data = Protocol.extractInt(data) port, data = Protocol.extractInt(data) index, data = Protocol.extractInt(data) # 'sfa3': {'title': 'Street Fighter Alpha 3', 'rom': 'sfa3:sfa3u', 'room': 'sfa3'}, # 'sfa2': {'title': 'Street Fighter Alpha 2', 'rom': 'sfa2', 'room': 'sfa2'}, channel = { 'rom': romname.split(':')[0], 'room': room, 'title': title, 'users': users, 'port': port, } self.channels[room] = channel logdebug().info(repr(self.channels)) self.sigChannelsLoaded.emit() if len(data) > 0: logdebug().error('Channel REMAINING DATA len {} {}'.format( len(data), repr(data)))
def parseListChannelsResponse(self, data): #self.channels = {} if len(data) <= 8: logdebug().error('No channels found') self.sigChannelsLoaded.emit() return status1, data = Protocol.extractInt(data) status2, data = Protocol.extractInt(data) logdebug().info("Load channels header " + repr(status1) + repr(status2)) while len(data) > 4: room, data = Protocol.extractTLV(data) romname, data = Protocol.extractTLV(data) title, data = Protocol.extractTLV(data) users, data = Protocol.extractInt(data) port, data = Protocol.extractInt(data) index, data = Protocol.extractInt(data) # 'sfa3': {'title': 'Street Fighter Alpha 3', 'rom': 'sfa3:sfa3u', 'room': 'sfa3'}, # 'sfa2': {'title': 'Street Fighter Alpha 2', 'rom': 'sfa2', 'room': 'sfa2'}, channel = { 'rom': romname.split(':')[0], 'room': room, 'title': title, 'users': users, 'port': port, } self.channels[room] = channel logdebug().info(repr(self.channels)) self.sigChannelsLoaded.emit() if len(data) > 0: logdebug().error('Channel REMAINING DATA len {} {}'.format(len(data), repr(data)))
def parseChatResponse(self, data): name, data = Protocol.extractTLV(data) if name in self.ignored: return msg, data = Protocol.extractTLV(data) if hasattr(name, 'decode'): name = name.decode() if hasattr(msg, 'decode'): msg = msg.decode() if Settings.value(Settings.USER_LOG_CHAT): loguser().info(u"<{}> {}".format(name, msg)) self.sigChatReceived.emit(name, msg)
def parseChallengeDeclinedResponse(self, data): name, data = Protocol.extractTLV(data) if name == self.challenged: self.challenged = None if name in self.ignored: return self.sigChallengeDeclined.emit(name)
def parseChallengeCancelledResponse(self, data): name, data = Protocol.extractTLV(data) if name in list(self.challengers): self.challengers.remove(name) if name in self.ignored: return self.sigChallengeCancelled.emit(name)
def sendCancelChallenge(self, name=None): if (name is None and self.challenged) or (name and name == self.challenged): self.sigStatusMessage.emit("Cancelling challenge") self.sendAndRemember(Protocol.CANCEL_CHALLENGE, Protocol.packTLV(self.challenged)) self.challenged = None
def parseSpectateResponse(self, data): p1, data = Protocol.extractTLV(data) p2, data = Protocol.extractTLV(data) # if the guy I challenged accepted, remove him as challenged if self.challenged and self.challenged in [p1, p2] and self.username in [p1, p2]: self.challenged = None # quark len(53) = 'quark:stream,ssf2t,challenge-07389-1393539605.46,7000' quark, data = Protocol.extractTLV(data) logdebug().info("Quark " + repr(quark)) if quark.startswith('quark:served'): smooth = Settings.value(Settings.SMOOTHING) if smooth: match = re.search(r'[0-9]+', smooth) if match: quark += ',{}'.format(match.group(0)) self.runFBA(quark)
def sendJoinChannelRequest(self, channel=None): if channel: self.channel = channel Settings.setValue(Settings.SELECTED_CHANNEL, channel) if channel in self.channels: if channel != 'lobby': self.rom = self.channels[channel]['rom'] else: self.rom = '' else: logdebug().error("Invalid channel {}".format(channel)) if (int(self.channelport) != int(self.channels[channel]['port'])): self.switchingServer = True self.channelport = int(self.channels[channel]['port']) Settings.setValue(Settings.PORT, self.channelport) self.tcpSock.close() self.sequence = 0x1 self.connectTcp() self.sendWelcome() self.sendAuth(self.username, self.password) if Settings.value(Settings.AWAY): self.sendToggleAFK(1) self.sendAndRemember(Protocol.JOIN_CHANNEL, Protocol.packTLV(self.channel))
def parseStateChangesResponse(self, data): count, data = Protocol.extractInt(data) while count > 0 and len(data) >= 4: state, p1, p2, playerinfo, data = self.__class__.extractStateChangesResponse(data) if state == PlayerStates.PLAYING: self.parsePlayerStartGameResponse(p1, p2, playerinfo) if self.username == p1: self.playingagainst = p2 if self.username == p2: self.playingagainst = p1 if Settings.USER_LOG_PLAYHISTORY and self.username in [p1, p2]: loguser().info(u"[IN A GAME] {} vs {}".format(p1, p2)) elif state == PlayerStates.AVAILABLE: self.parsePlayerAvailableResponse(p1, playerinfo) if self.playingagainst == p1: self.playingagainst = '' self.killEmulator() elif state == PlayerStates.AFK: self.parsePlayerAFKResponse(p1, playerinfo) if self.playingagainst == p1: self.playingagainst = '' self.killEmulator() elif state == PlayerStates.QUIT: self.parsePlayerLeftResponse(p1) else: logdebug().error( "Unknown state change payload state: {} {}".format(state, repr(data))) if state == PlayerStates.PLAYING: msg = p1 + ' ' + PlayerStates.codeToString(state) + ' ' + p2 else: msg = p1 + ' ' + PlayerStates.codeToString(state) logdebug().info(msg) count -= 1 if len(data) > 0: logdebug().error("stateChangesResponse, remaining data {}".format(repr(data)))
def parseAuthResponse(self, data): if len(data) < 4: logdebug().error("Unknown auth response {}".format(repr(data))) return result, data = Protocol.extractInt(data) if result == 0: self.selectTimeout = 15 self.sigLoginSuccess.emit() # password incorrect, user incorrect #if result == 0x6 or result == 0x4: else: if self.tcpSock: self.tcpSock.close() self.tcpConnected = False #if self.udpSock: # self.udpSock.close() # self.udpConnected = False self.sigLoginFailed.emit() #self.sigStatusMessage.emit("Login failed {}".format(result)) if result == 6: self.sigStatusMessage.emit("Login failed: wrong password") elif result == 9: self.sigStatusMessage.emit( "Login failed: too many connections") elif result == 4: self.sigStatusMessage.emit( "Login failed: username doesn't exist into database") elif result == 8: self.sigStatusMessage.emit( "Clone connection closed.\nPlease login again.") else: self.sigStatusMessage.emit("Login failed {}".format(result))
def parseStateChangesResponse(self, data): count, data = Protocol.extractInt(data) while count > 0 and len(data) >= 4: state, p1, p2, playerinfo, data = self.__class__.extractStateChangesResponse( data) if state == PlayerStates.PLAYING: self.parsePlayerStartGameResponse(p1, p2, playerinfo) if Settings.USER_LOG_PLAYHISTORY and self.username in [p1, p2]: loguser().info(u"[IN A GAME] {} vs {}".format(p1, p2)) elif state == PlayerStates.AVAILABLE: self.parsePlayerAvailableResponse(p1, playerinfo) elif state == PlayerStates.AFK: self.parsePlayerAFKResponse(p1, playerinfo) elif state == PlayerStates.QUIT: self.parsePlayerLeftResponse(p1) else: logdebug().error( "Unknown state change payload state: {} {}".format( state, repr(data))) if state == PlayerStates.PLAYING: msg = p1 + ' ' + PlayerStates.codeToString(state) + ' ' + p2 else: msg = p1 + ' ' + PlayerStates.codeToString(state) logdebug().info(msg) count -= 1 if len(data) > 0: logdebug().error("stateChangesResponse, remaining data {}".format( repr(data)))
def parseAuthResponse(self, data): if len(data) < 4: logdebug().error("Unknown auth response {}".format(repr(data))) return result, data = Protocol.extractInt(data) if result == 0: self.selectTimeout = 15 self.sigLoginSuccess.emit() # password incorrect, user incorrect #if result == 0x6 or result == 0x4: else: if self.tcpSock: self.tcpSock.close() self.tcpConnected = False #if self.udpSock: # self.udpSock.close() # self.udpConnected = False self.sigLoginFailed.emit() #self.sigStatusMessage.emit("Login failed {}".format(result)) if result==6: self.sigStatusMessage.emit("Login failed: wrong password") elif result==9: self.sigStatusMessage.emit("Login failed: too many connections") elif result==4: self.sigStatusMessage.emit("Login failed: username doesn't exist into database") elif result==8: self.sigStatusMessage.emit("Clone connection closed.\nPlease login again.") else: self.sigStatusMessage.emit("Login failed {}".format(result))
def dispatchInbandData(self, seq, data): if not seq in self.tcpCommandsWaitingForResponse: logdebug().error("Sequence {} data {} not matched".format( seq, data)) return origRequest = self.tcpCommandsWaitingForResponse[seq] del self.tcpCommandsWaitingForResponse[seq] if origRequest == Protocol.AUTH: self.parseAuthResponse(data) elif origRequest == Protocol.MOTD: self.parseMotdResponse(data) elif origRequest == Protocol.LIST_CHANNELS: self.parseListChannelsResponse(data) elif origRequest == Protocol.LIST_USERS: self.parseListUsersResponse(data) elif origRequest == Protocol.SPECTATE: status, data = Protocol.extractInt(data) if status != 0: self.sigStatusMessage.emit("Fail to spectate " + str(status)) elif origRequest in [ Protocol.WELCOME, Protocol.JOIN_CHANNEL, Protocol.TOGGLE_AFK, Protocol.SEND_CHALLENGE, Protocol.CHAT, Protocol.ACCEPT_CHALLENGE, Protocol.DECLINE_CHALLENGE, Protocol.CANCEL_CHALLENGE ]: if len(data) == 4: status, data = Protocol.extractInt(data) if status != 0: codestr = Protocol.codeToString(origRequest) logdebug().error("{} failed, data {}".format( codestr, repr(data))) if codestr == "SEND_CHALLENGE": self.sigActionFailed.emit("SEND_CHALLENGE failed") elif codestr == "CANCEL_CHALLENGE": pass else: self.sigActionFailed.emit(codestr) else: logdebug().error( "Unknown response for {}; seq {}; data {}".format( Protocol.codeToString(origRequest), seq, repr(data))) else: logdebug().error( "Not handling {} response; seq {}; data {}".format( Protocol.codeToString(origRequest), seq, repr(data)))
def parseSpectateResponse(self, data): p1, data = Protocol.extractTLV(data) p2, data = Protocol.extractTLV(data) # if the guy I challenged accepted, remove him as challenged if self.challenged and self.challenged in [ p1, p2 ] and self.username in [p1, p2]: self.challenged = None # quark len(53) = 'quark:stream,ssf2t,challenge-07389-1393539605.46,7000' quark, data = Protocol.extractTLV(data) logdebug().info("Quark " + repr(quark)) if quark.startswith('quark:served'): smooth = Settings.value(Settings.SMOOTHING) if smooth: match = re.search(r'[0-9]+', smooth) if match: quark += ',{}'.format(match.group(0)) self.runFBA(quark)
def sendToggleAFK(self, afk): if afk: val = 1 state = True else: val = 0 state = False self.sendAndRemember(Protocol.TOGGLE_AFK, Protocol.packInt(val)) Settings.setBoolean(Settings.AWAY, state)
def sendMessage(self, extID, prefix, params=None): """ Encode a message and send it to the server Args: extID: positive integer. 0 for internal messages, 1 for referee messages, otherwise is an extension ID prefix: extension-defined positive integer params: json-serializable python object """ data = Protocol.packInt(extID) + Protocol.packInt(prefix) + json.dumps( params) self.controller.sendAndRemember(Protocol.EXTENSION_OUTBOUND, Protocol.packTLV(data)) # DEBUG dispext = "Extension" if extID == 0 else _ExtensionDict[extID].__name__ dispprefix = self._codeToString.get((extID, prefix), prefix) self.controller.sigStatusMessage.emit( "Ext Snd: ext=%s, prefix=%s, params=%s" % (dispext, dispprefix, params))
def sendJoinChannelRequest(self, channel=None): if channel: self.channel = channel Settings.setValue(Settings.SELECTED_CHANNEL, channel) if channel in self.channels: if channel != 'lobby': self.rom = self.channels[channel]['rom'] else: logdebug().error("Invalid channel {}".format(channel)) self.sendAndRemember(Protocol.JOIN_CHANNEL, Protocol.packTLV(self.channel))
def handleTcpResponse(self): if self.tcpReadState == self.STATE_TCP_READ_LEN: if len(self.tcpData) >= 4: self.tcpResponseLen, self.tcpData = Protocol.extractInt(self.tcpData) self.tcpReadState = self.STATE_TCP_READ_DATA self.handleTcpResponse() elif self.tcpReadState == self.STATE_TCP_READ_DATA: if len(self.tcpData) >= self.tcpResponseLen: # tcpResponseLen should be >= 4 if self.tcpResponseLen < 4: logdebug().error('Cannot handle TLV payload of less than 4 bytes') self.tcpData = self.tcpData[self.tcpResponseLen:] self.tcpResponseLen = 0 self.tcpReadState = self.STATE_TCP_READ_LEN self.handleTcpResponse() else: data = self.tcpData[:self.tcpResponseLen] self.tcpData = self.tcpData[self.tcpResponseLen:] seq = Protocol.unpackInt(data[0:4]) self.tcpResponseLen = 0 self.tcpReadState = self.STATE_TCP_READ_LEN self.dispatch(seq, data[4:]) self.handleTcpResponse()
def parseAuthResponse(self, data): if len(data) < 4: logdebug().error("Unknown auth response {}".format(repr(data))) return result, data = Protocol.extractInt(data) if result == 0: self.selectTimeout = 15 self.sigLoginSuccess.emit() # password incorrect, user incorrect #if result == 0x6 or result == 0x4: else: if self.tcpSock: self.tcpSock.close() self.tcpConnected = False if self.udpSock: self.udpSock.close() self.udpConnected = False self.sigLoginFailed.emit() self.sigStatusMessage.emit("Login failed {}".format(result))
def dispatch(self, seq, data): logdebug().info('Dispatch ' + Protocol.outOfBandCodeToString(seq) + ' ' + repr(data)) # out of band data if seq == Protocol.CHAT_DATA: self.parseChatResponse(data) elif seq == Protocol.PLAYER_STATE_CHANGE: self.parseStateChangesResponse(data) elif seq == Protocol.CHALLENGE_DECLINED: self.parseChallengeDeclinedResponse(data) elif seq == Protocol.CHALLENGE_RECEIVED: self.parseChallengeReceivedResponse(data) elif seq == Protocol.CHALLENGE_RETRACTED: self.parseChallengeCancelledResponse(data) elif seq == Protocol.JOINING_A_CHANNEL: self.parseJoinChannelResponse(data) elif seq == Protocol.SPECTATE_GRANTED: self.parseSpectateResponse(data) else: # in band response to our previous request self.dispatchInbandData(seq, data)
def sendAuth(self, username, password): self.username = username try: port = self.udpSock.getsockname()[1] except: port=6009 #raise # piggyback the OS and timezone onto the login request since there doesn't seem to be another convenient place to send it. authdata = Protocol.packTLV(username) + Protocol.packTLV(password) + Protocol.packInt(port) + \ Protocol.packInt(copyright.versionNum()) + \ Protocol.packInt(self.os) + \ Protocol.packTLV(str(self.utcoffset)) # There's a string conversion error here if packInt returns any #Protocol.packInt(self.utcoffset) # non-ascii bytes. Send utcoffset as a string for now. self.sendAndRemember(Protocol.AUTH, authdata)
def parseStateChangesResponse(self, data): count, data = Protocol.extractInt(data) while count > 0 and len(data) >= 4: state, p1, p2, playerinfo, data = self.__class__.extractStateChangesResponse(data) if state == PlayerStates.PLAYING: self.parsePlayerStartGameResponse(p1, p2, playerinfo) elif state == PlayerStates.AVAILABLE: self.parsePlayerAvailableResponse(p1, playerinfo) elif state == PlayerStates.AFK: self.parsePlayerAFKResponse(p1, playerinfo) elif state == PlayerStates.QUIT: self.parsePlayerLeftResponse(p1) else: logger().error( "Unknown state change payload state: {} {}".format(state, repr(data))) if state == PlayerStates.PLAYING: msg = p1 + ' ' + PlayerStates.codeToString(state) + ' ' + p2 else: msg = p1 + ' ' + PlayerStates.codeToString(state) logger().info(msg) count -= 1 if len(data) > 0: logger().error("stateChangesResponse, remaining data {}".format(repr(data)))
def sendJoinChannelRequest(self, channel=None): if channel: self.channel = channel Settings.setValue(Settings.SELECTED_CHANNEL, channel) if channel in self.channels: if channel != 'lobby': self.rom = self.channels[channel]['rom'] else: self.rom = '' else: logdebug().error("Invalid channel {}".format(channel)) if (int(self.channelport)!=int(self.channels[channel]['port'])): self.switchingServer=True self.channelport = int(self.channels[channel]['port']) Settings.setValue(Settings.PORT, self.channelport) self.tcpSock.close() self.sequence = 0x1 self.connectTcp() self.sendWelcome() self.sendAuth(self.username, self.password) if Settings.value(Settings.AWAY): self.sendToggleAFK(1) self.sendAndRemember(Protocol.JOIN_CHANNEL, Protocol.packTLV(self.channel))
def sendChat(self, line): if self.channel == 'unsupported' and self.unsupportedRom: line = '[' + self.unsupportedRom + '] ' + line line = line.encode('utf-8') self.sendAndRemember(Protocol.CHAT, Protocol.packTLV(line))
def sendToggleAFK(self, afk): if afk: val = 1 else: val = 0 self.sendAndRemember(Protocol.TOGGLE_AFK, Protocol.packInt(val))
def sendCancelChallenge(self, name=None): if (name is None and self.challenged) or (name and name == self.challenged): self.sendAndRemember(Protocol.CANCEL_CHALLENGE, Protocol.packTLV(self.challenged)) self.challenged = None
def sendAndRemember(self, command, data=''): logdebug().info('Sending {} seq {} {}'.format(Protocol.codeToString(command), self.sequence, repr(data))) self.tcpCommandsWaitingForResponse[self.sequence] = command self.sendtcp(struct.pack('!I', command) + data)
def sendAndForget(self, command, data=''): logdebug().info('Sending {} seq {} {}'.format(Protocol.codeToString(command), self.sequence, repr(data))) self.sendtcp(struct.pack('!I', command) + data)
def extractStateChangesResponse(data): if len(data) >= 4: code, data = Protocol.extractInt(data) p1, data = Protocol.extractTLV(data) if code == 0: p2 = '' return PlayerStates.QUIT, p1, p2, None, data elif code != 1: logdebug().error("Unknown player state change code {}".format(code)) state, data = Protocol.extractInt(data) p2, data = Protocol.extractTLV(data) if not p2: p2 = "null" ip, data = Protocol.extractTLV(data) # \xff\xff\xff\x9f # \x00\x00\x00& unknown1, data = Protocol.extractInt(data) unknown2, data = Protocol.extractInt(data) city, data = Protocol.extractTLV(data) cc, data = Protocol.extractTLV(data) if cc: cc = cc.lower() country, data = Protocol.extractTLV(data) # \x00\x00\x17y marker, data = Protocol.extractInt(data) playerinfo = dict( player=p1, ip=ip, city=city, cc=cc, country=country, ) return state, p1, p2, playerinfo, data
def sendSpectateRequest(self, name): isFbaPresent = self.checkInstallation() isRomPresent = self.checkRom() if not isRomPresent or not isFbaPresent: return self.sendAndRemember(Protocol.SPECTATE, Protocol.packTLV(name))
def parseListUsersResponse(self, data): self.resetPlayers() if not data: return status, data = Protocol.extractInt(data) status2, data = Protocol.extractInt(data) while len(data) > 8: p1, data = Protocol.extractTLV(data) # if len(data) <= 4: break state, data = Protocol.extractInt(data) p2, data = Protocol.extractTLV(data) ip, data = Protocol.extractTLV(data) unk1, data = Protocol.extractInt(data) unk2, data = Protocol.extractInt(data) city, data = Protocol.extractTLV(data) cc, data = Protocol.extractTLV(data) if cc: cc = cc.lower() country, data = Protocol.extractTLV(data) port, data = Protocol.extractInt(data) self.addUser( player=p1, ip=ip, port=port, city=city, cc=cc, country=country, ) if state == PlayerStates.AVAILABLE: self.available[p1] = True elif state == PlayerStates.AFK: self.awayfromkb[p1] = True elif state == PlayerStates.PLAYING: if not p2: p2 = 'null' self.playing[p1] = p2 self.sigPlayersLoaded.emit() if len(data) > 0: logdebug().error('List users - REMAINING DATA len {} {}'.format(len(data), repr(data)))
def sendDeclineChallenge(self, name): self.sendAndRemember(Protocol.DECLINE_CHALLENGE, Protocol.packTLV(name)) if name in self.challengers: self.challengers.remove(name)
def sendAndForget(self, command, data=''): logdebug().info('Sending {} seq {} {}'.format( Protocol.codeToString(command), self.sequence, repr(data))) self.sendtcp(struct.pack('!I', command) + data)
def extractStateChangesResponse(data): if len(data) >= 4: code, data = Protocol.extractInt(data) p1, data = Protocol.extractTLV(data) if code == 0: p2 = '' return PlayerStates.QUIT, p1, p2, None, data elif code != 1: logdebug().error( "Unknown player state change code {}".format(code)) state, data = Protocol.extractInt(data) p2, data = Protocol.extractTLV(data) if not p2: p2 = "null" ip, data = Protocol.extractTLV(data) # \xff\xff\xff\x9f # \x00\x00\x00& unknown1, data = Protocol.extractInt(data) unknown2, data = Protocol.extractInt(data) city, data = Protocol.extractTLV(data) cc, data = Protocol.extractTLV(data) if cc: cc = cc.lower() country, data = Protocol.extractTLV(data) # \x00\x00\x17y marker, data = Protocol.extractInt(data) playerinfo = dict( player=p1, ip=ip, city=city, cc=cc, country=country, spectators=0, ) return state, p1, p2, playerinfo, data
def parseListUsersResponse(self, data): self.resetPlayers() if not data: return status, data = Protocol.extractInt(data) status2, data = Protocol.extractInt(data) while len(data) > 8: p1, data = Protocol.extractTLV(data) # if len(data) <= 4: break state, data = Protocol.extractInt(data) p2, data = Protocol.extractTLV(data) ip, data = Protocol.extractTLV(data) unk1, data = Protocol.extractInt(data) unk2, data = Protocol.extractInt(data) city, data = Protocol.extractTLV(data) cc, data = Protocol.extractTLV(data) if cc: cc = cc.lower() country, data = Protocol.extractTLV(data) port, data = Protocol.extractInt(data) spectators, data = Protocol.extractInt(data) self.addUser( player=p1, ip=ip, port=port, city=city, cc=cc, country=country, spectators=spectators + 1, ) if state == PlayerStates.AVAILABLE: self.available[p1] = True elif state == PlayerStates.AFK: self.awayfromkb[p1] = True elif state == PlayerStates.PLAYING: if not p2: p2 = 'null' self.playing[p1] = p2 self.sigPlayersLoaded.emit() if len(data) > 0: logdebug().error('List users - REMAINING DATA len {} {}'.format( len(data), repr(data)))
def sendAndRemember(self, command, data=''): logdebug().info('Sending {} seq {} {}'.format( Protocol.codeToString(command), self.sequence, repr(data))) self.tcpCommandsWaitingForResponse[self.sequence] = command self.sendtcp(struct.pack('!I', command) + data)