class URLMarcos(object): __MACROS_PREFIX = '$' def __init__(self): super(URLMarcos, self).__init__() self.__macros = {'LANGUAGE_CODE': 'getLanguageCode', 'AREA_ID': 'getAreaID', 'ENCODED_LOGIN': '******', 'QUOTED_LOGIN': '******', 'TARGET_URL': 'getTargetURL', 'DB_ID': 'getDatabaseID', 'WGNI_TOKEN': 'getWgniToken'} patterns = [] for macro in self.__macros.iterkeys(): patterns.append('\\%(macro)s\\(.*\\)|\\%(macro)s' % {'macro': self._getUserMacrosName(macro)}) self.__filter = re.compile('|'.join(patterns)) self.__argsFilter = re.compile('\\$(\\w*)(\\((.*)\\))?') self.__targetURL = '' self.__tokenRqs = TokenRequester(TOKEN_TYPE.WGNI, cache=False) def clear(self): self.__tokenRqs.clear() self.__macros.clear() self.__argsFilter = None self.__filter = None return def hasMarcos(self, url): return len(self.__filter.findall(url)) > 0 @async @process def parse(self, url, callback): yield lambda callback: callback(True) for macros in self.__filter.findall(url): macroName, _, args = self.__argsFilter.match(macros).groups() replacement = yield self._replace(macroName, args) url = url.replace(macros, replacement) callback(url) @async def getLanguageCode(self, args, callback): code = getClientLanguage() callback(code.replace('_', '-')) @async def getAreaID(self, args, callback): areaID = connectionManager.areaID if areaID: result = str(areaID) else: result = 'errorArea' callback(result) @async def getEncodedLogin(self, args, callback): login = connectionManager.loginName if login: result = login else: result = 'errorLogin' callback(base64.b64encode(result)) @async def getQuotedLogin(self, args, callback): login = connectionManager.lastLoginName if login: result = quote_plus(login) else: result = '' callback(result) @async def getDatabaseID(self, args, callback): dbID = connectionManager.databaseID if dbID: result = str(dbID) else: result = 'errorID' callback(result) @async def getTargetURL(self, args, callback): if args: result = args else: result = self.__targetURL if result: result = quote_plus(result) callback(result) @async def getWgniToken(self, args, callback): def _cbWrapper(response): if response and response.isValid(): callback(str(response.getToken())) else: callback('') if not self.__tokenRqs.isInProcess(): self.__tokenRqs.request(timeout=10.0)(_cbWrapper) else: _cbWrapper(response=None) return def setTargetURL(self, targetURL): self.__targetURL = targetURL @async @process def _replace(self, macros, args, callback): yield lambda callback: callback(True) result = '' if macros in self.__macros: result = yield getattr(self, self.__macros[macros])(args) else: LOG_ERROR('URL marcos is not found', macros) callback(result) def _getUserMacrosName(self, macros): return '%s%s' % (self.__MACROS_PREFIX, str(macros))
class ConnectionHandler(ClientEventsHandler): def __init__(self): super(ConnectionHandler, self).__init__() self.__tokenRequester = TokenRequester(TOKEN_TYPE.XMPPCS, ChatTokenResponse, False) self.__reconnectCallbackID = None self.__reqTokenCallbackID = None self.__connectionsInfo = ConnectionsInfo() self.__reqTokenBackOff = backoff.ExpBackoff(self.__tokenRequester.getReqCoolDown(), _BACK_OFF_MAX_DELAY, _BACK_OFF_MODIFIER, _BACK_OFF_EXP_RANDOM_FACTOR) return def connect(self): if self.__reconnectCallbackID is None: self.__connectionsInfo.init() self.__doConnect() else: g_logOutput.debug(CLIENT_LOG_AREA.CONNECTION, 'Connection already is processing') return def disconnect(self): client = self.client() if client: g_logOutput.debug(CLIENT_LOG_AREA.CONNECTION, 'Sends request to disconnect and removes all listeners') client.disconnect() self.clear() def clear(self): self.__connectionsInfo.clear() self.__reqTokenBackOff.reset() self.__cancelReconnectCallback() self.__cancelReqTokenCallback() self.__tokenRequester.clear() g_settings.server.XMPP.clear() def isInGameServer(self): return connectionManager.isConnected() def registerHandlers(self): client = self.client() client.registerHandler(GLOOX_EVENT.CONNECTED, self.__handleConnect) client.registerHandler(GLOOX_EVENT.LOGIN, self.__handleLogin) client.registerHandler(GLOOX_EVENT.DISCONNECTED, self.__handleDisconnect) def unregisterHandlers(self): client = self.client() client.unregisterHandler(GLOOX_EVENT.CONNECTED, self.__handleConnect) client.unregisterHandler(GLOOX_EVENT.LOGIN, self.__handleLogin) client.unregisterHandler(GLOOX_EVENT.DISCONNECTED, self.__handleDisconnect) def __doConnect(self): client = self.client() if not client.isDisconnected(): g_logOutput.warning(CLIENT_LOG_AREA.CONNECTION, 'Client already is connected(ing)', client.getConnectionAddress(), client.getConnectionState()) return jid = self.__connectionsInfo.getPlayerFullJID() if jid: cType, host, port = self.__connectionsInfo.getNextConnection() g_logOutput.debug(CLIENT_LOG_AREA.CONNECTION, 'Connect to XMPP sever', jid, host, port) if cType == CONNECTION_IMPL_TYPE.TCP: client.connect(str(jid), host, port) elif cType == CONNECTION_IMPL_TYPE.BOSH: client.connectBosh(str(jid), host, port, '/bosh/') else: g_logOutput.error(CLIENT_LOG_AREA.CONNECTION, 'This type of connection is not supported', cType) else: g_logOutput.error(CLIENT_LOG_AREA.CONNECTION, 'JID is empty') def __doNextConnect(self): self.__reconnectCallbackID = None self.__doConnect() return @process def __doLogin(self): client = self.client() if not client.isConnecting(): g_logOutput.warning(CLIENT_LOG_AREA.LOGIN, 'Client is not connecting', client.getConnectionAddress(), client.getConnectionState()) yield lambda callback: callback(None) return g_logOutput.debug(CLIENT_LOG_AREA.TOKEN, 'Sends request to SPA') response = yield self.__tokenRequester.request() g_logOutput.debug(CLIENT_LOG_AREA.TOKEN, 'Response is received from SPA', response) if not response: g_logOutput.error(CLIENT_LOG_AREA.TOKEN, 'Received chat token is empty') return if response.isValid(): if response.getDatabaseID() == getPlayerDatabaseID(): g_logOutput.debug(CLIENT_LOG_AREA.LOGIN, 'Login to XMPP sever') client.login(response.getCredential()) else: g_logOutput.error(CLIENT_LOG_AREA.LOGIN, "Player's database ID mismatch", getPlayerDatabaseID()) else: g_logOutput.warning(CLIENT_LOG_AREA.TOKEN, 'Received chat token is not valid', response) self.__handleTokenError() def __doNextLogin(self): self.__reqTokenCallbackID = None self.__doLogin() return def __cancelReconnectCallback(self): if self.__reconnectCallbackID is not None: BigWorld.cancelCallback(self.__reconnectCallbackID) self.__reconnectCallbackID = None return def __cancelReqTokenCallback(self): if self.__reqTokenCallbackID is not None: BigWorld.cancelCallback(self.__reqTokenCallbackID) self.__reqTokenCallbackID = None return def __invokeConnectFailedEvent(self, tries): host, port = self.__connectionsInfo.getLastAddress() g_messengerEvents.onPluginConnectFailed(PROTO_TYPE.XMPP, (host, port), tries) def __handleConnect(self): g_logOutput.debug(CLIENT_LOG_AREA.CONNECTION, 'Client is connected') self.__cancelReconnectCallback() self.__reqTokenBackOff.reset() self.__doLogin() def __handleLogin(self): g_logOutput.debug(CLIENT_LOG_AREA.LOGIN, 'Client is login') self.__connectionsInfo.clear() self.__reqTokenBackOff.reset() g_messengerEvents.onPluginConnected(PROTO_TYPE.XMPP) def __handleDisconnect(self, reason, description): g_messengerEvents.onPluginDisconnected(PROTO_TYPE.XMPP) client = self.client() if not client: return g_logOutput.debug(CLIENT_LOG_AREA.CONNECTION, 'Client is disconnected') self.__cancelReconnectCallback() self.__cancelReqTokenCallback() if reason == DISCONNECT_REASON.AUTHENTICATION: self.__tokenRequester.clear() if self.isInGameServer() and reason != DISCONNECT_REASON.BY_REQUEST: delay = self.__connectionsInfo.getNextDelay() self.__reconnectCallbackID = BigWorld.callback(delay, self.__doNextConnect) g_logOutput.debug(CLIENT_LOG_AREA.CONNECTION, 'Will try to reconnect after {0} seconds'.format(delay), description) host, port = self.__connectionsInfo.getLastAddress() tries = self.__connectionsInfo.getTries() self.__invokeConnectFailedEvent(tries) sendEventToServer(XMPP_EVENT_LOG.DISCONNECT, host, port, reason, description, tries) def __handleTokenError(self): client = self.client() if not client: return tries = self.__reqTokenBackOff.getTries() if tries < _MAX_REQ_TOKEN_TRIES: delay = self.__reqTokenBackOff.next() self.__reqTokenCallbackID = BigWorld.callback(delay, self.__doNextLogin) g_logOutput.debug(CLIENT_LOG_AREA.TOKEN, 'Will try to request token after {0} seconds'.format(delay)) self.__invokeConnectFailedEvent(tries) else: self.client().disconnect() self.__handleDisconnect(DISCONNECT_REASON.OTHER_ERROR, 'Received chat token is not valid')
class URLMarcos(object): __MACROS_PREFIX = '$' def __init__(self): super(URLMarcos, self).__init__() self.__macros = { 'LANGUAGE_CODE': 'getLanguageCode', 'AREA_ID': 'getAreaID', 'ENCODED_LOGIN': '******', 'QUOTED_LOGIN': '******', 'TARGET_URL': 'getTargetURL', 'DB_ID': 'getDatabaseID', 'WGNI_TOKEN': 'getWgniToken' } patterns = [] for macro in self.__macros.iterkeys(): patterns.append('\\%(macro)s\\(.*\\)|\\%(macro)s' % {'macro': self._getUserMacrosName(macro)}) self.__filter = re.compile('|'.join(patterns)) self.__argsFilter = re.compile('\\$(\\w*)(\\((.*)\\))?') self.__targetURL = '' self.__tokenRqs = TokenRequester(TOKEN_TYPE.WGNI, cache=False) def clear(self): self.__tokenRqs.clear() self.__macros.clear() self.__argsFilter = None self.__filter = None def hasMarcos(self, url): return len(self.__filter.findall(url)) > 0 @async @process def parse(self, url, callback): yield lambda callback: callback(True) for macros in self.__filter.findall(url): macroName, _, args = self.__argsFilter.match(macros).groups() replacement = yield self._replace(macroName, args) url = url.replace(macros, replacement) callback(url) @async def getLanguageCode(self, args, callback): code = getClientLanguage() callback(code.replace('_', '-')) @async def getAreaID(self, args, callback): areaID = connectionManager.areaID if areaID: result = str(areaID) else: result = 'errorArea' callback(result) @async def getEncodedLogin(self, args, callback): login = connectionManager.loginName if login: result = login else: result = 'errorLogin' callback(base64.b64encode(result)) @async def getQuotedLogin(self, args, callback): login = connectionManager.lastLoginName if login: result = quote_plus(login) else: result = '' callback(result) @async def getDatabaseID(self, args, callback): dbID = connectionManager.databaseID if dbID: result = str(dbID) else: result = 'errorID' callback(result) @async def getTargetURL(self, args, callback): if args: result = args else: result = self.__targetURL if result: result = quote_plus(result) callback(result) @async def getWgniToken(self, args, callback): def _cbWrapper(response): if response and response.isValid(): callback(str(response.getToken())) else: callback('') if not self.__tokenRqs.isInProcess(): self.__tokenRqs.request(timeout=10.0)(_cbWrapper) else: _cbWrapper(response=None) def setTargetURL(self, targetURL): self.__targetURL = targetURL @async @process def _replace(self, macros, args, callback): yield lambda callback: callback(True) result = '' if macros in self.__macros: result = yield getattr(self, self.__macros[macros])(args) else: LOG_ERROR('URL marcos is not found', macros) callback(result) def _getUserMacrosName(self, macros): return '%s%s' % (self.__MACROS_PREFIX, str(macros))
class ConnectionHandler(ClientEventsHandler): connectionMgr = dependency.descriptor(IConnectionManager) def __init__(self): super(ConnectionHandler, self).__init__() self.__tokenRequester = TokenRequester(TOKEN_TYPE.XMPPCS, ChatTokenResponse, False) self.__reconnectCallbackID = None self.__reqTokenCallbackID = None self.__connectionsInfo = ConnectionsInfo() self.__reqTokenBackOff = backoff.ExpBackoff( self.__tokenRequester.getReqCoolDown(), _BACK_OFF_MAX_DELAY, _BACK_OFF_MODIFIER, _BACK_OFF_EXP_RANDOM_FACTOR) return def connect(self): if self.__reconnectCallbackID is None: self.__connectionsInfo.init() self.__doConnect() else: g_logOutput.debug(CLIENT_LOG_AREA.CONNECTION, 'Connection already is processing') return def disconnect(self): client = self.client() if client: g_logOutput.debug( CLIENT_LOG_AREA.CONNECTION, 'Sends request to disconnect and removes all listeners') client.disconnect() self.clear() def clear(self): self.__connectionsInfo.clear() self.__reqTokenBackOff.reset() self.__cancelReconnectCallback() self.__cancelReqTokenCallback() self.__tokenRequester.clear() g_settings.server.XMPP.clear() def isInGameServer(self): return self.connectionMgr.isConnected() def registerHandlers(self): client = self.client() client.registerHandler(GLOOX_EVENT.CONNECTED, self.__handleConnect) client.registerHandler(GLOOX_EVENT.LOGIN, self.__handleLogin) client.registerHandler(GLOOX_EVENT.DISCONNECTED, self.__handleDisconnect) def unregisterHandlers(self): client = self.client() client.unregisterHandler(GLOOX_EVENT.CONNECTED, self.__handleConnect) client.unregisterHandler(GLOOX_EVENT.LOGIN, self.__handleLogin) client.unregisterHandler(GLOOX_EVENT.DISCONNECTED, self.__handleDisconnect) def __doConnect(self): client = self.client() if not client.isDisconnected(): g_logOutput.warning(CLIENT_LOG_AREA.CONNECTION, 'Client already is connected(ing)', client.getConnectionAddress(), client.getConnectionState()) return jid = self.__connectionsInfo.getPlayerFullJID() if jid: cType, host, port = self.__connectionsInfo.getNextConnection() g_logOutput.debug(CLIENT_LOG_AREA.CONNECTION, 'Connect to XMPP sever', jid, host, port) if cType == CONNECTION_IMPL_TYPE.TCP: client.connect(str(jid), host, port) elif cType == CONNECTION_IMPL_TYPE.BOSH: client.connectBosh(str(jid), host, port, '/bosh/') else: g_logOutput.error(CLIENT_LOG_AREA.CONNECTION, 'This type of connection is not supported', cType) else: g_logOutput.error(CLIENT_LOG_AREA.CONNECTION, 'JID is empty') def __doNextConnect(self): self.__reconnectCallbackID = None self.__doConnect() return @process def __doLogin(self): client = self.client() if not client.isConnecting(): g_logOutput.warning(CLIENT_LOG_AREA.LOGIN, 'Client is not connecting', client.getConnectionAddress(), client.getConnectionState()) yield lambda callback: callback(None) return g_logOutput.debug(CLIENT_LOG_AREA.TOKEN, 'Sends request to SPA') response = yield self.__tokenRequester.request() g_logOutput.debug(CLIENT_LOG_AREA.TOKEN, 'Response is received from SPA', response) if not response: g_logOutput.error(CLIENT_LOG_AREA.TOKEN, 'Received chat token is empty') return if response.isValid(): if response.getDatabaseID() == getPlayerDatabaseID(): g_logOutput.debug(CLIENT_LOG_AREA.LOGIN, 'Login to XMPP sever') client.login(response.getCredential()) else: g_logOutput.error(CLIENT_LOG_AREA.LOGIN, "Player's database ID mismatch", getPlayerDatabaseID()) else: g_logOutput.warning(CLIENT_LOG_AREA.TOKEN, 'Received chat token is not valid', response) self.__handleTokenError() def __doNextLogin(self): self.__reqTokenCallbackID = None self.__doLogin() return def __cancelReconnectCallback(self): if self.__reconnectCallbackID is not None: BigWorld.cancelCallback(self.__reconnectCallbackID) self.__reconnectCallbackID = None return def __cancelReqTokenCallback(self): if self.__reqTokenCallbackID is not None: BigWorld.cancelCallback(self.__reqTokenCallbackID) self.__reqTokenCallbackID = None return def __invokeConnectFailedEvent(self, tries): host, port = self.__connectionsInfo.getLastAddress() g_messengerEvents.onPluginConnectFailed(PROTO_TYPE.XMPP, (host, port), tries) def __handleConnect(self): g_logOutput.debug(CLIENT_LOG_AREA.CONNECTION, 'Client is connected') self.__cancelReconnectCallback() self.__reqTokenBackOff.reset() self.__doLogin() def __handleLogin(self): g_logOutput.debug(CLIENT_LOG_AREA.LOGIN, 'Client is login') self.__connectionsInfo.clear() self.__reqTokenBackOff.reset() g_messengerEvents.onPluginConnected(PROTO_TYPE.XMPP) def __handleDisconnect(self, reason, description): g_messengerEvents.onPluginDisconnected(PROTO_TYPE.XMPP) client = self.client() if not client: return g_logOutput.debug(CLIENT_LOG_AREA.CONNECTION, 'Client is disconnected') self.__cancelReconnectCallback() self.__cancelReqTokenCallback() if reason == DISCONNECT_REASON.AUTHENTICATION: self.__tokenRequester.clear() if self.isInGameServer() and reason != DISCONNECT_REASON.BY_REQUEST: delay = self.__connectionsInfo.getNextDelay() self.__reconnectCallbackID = BigWorld.callback( delay, self.__doNextConnect) g_logOutput.debug( CLIENT_LOG_AREA.CONNECTION, 'Will try to reconnect after {0} seconds'.format(delay), description) host, port = self.__connectionsInfo.getLastAddress() tries = self.__connectionsInfo.getTries() self.__invokeConnectFailedEvent(tries) sendEventToServer(XMPP_EVENT_LOG.DISCONNECT, host, port, reason, description, tries) def __handleTokenError(self): client = self.client() if not client: return tries = self.__reqTokenBackOff.getTries() if tries < _MAX_REQ_TOKEN_TRIES: delay = self.__reqTokenBackOff.next() self.__reqTokenCallbackID = BigWorld.callback( delay, self.__doNextLogin) g_logOutput.debug( CLIENT_LOG_AREA.TOKEN, 'Will try to request token after {0} seconds'.format(delay)) self.__invokeConnectFailedEvent(tries) else: self.client().disconnect() self.__handleDisconnect(DISCONNECT_REASON.OTHER_ERROR, 'Received chat token is not valid')
class URLMarcos(object): __MACROS_PREFIX = '$' def __init__(self): super(URLMarcos, self).__init__() self.__macros = {'LANGUAGE_CODE': 'getLanguageCode', 'AREA_ID': 'getAreaID', 'ENCODED_LOGIN': '******', 'QUOTED_LOGIN': '******', 'TARGET_URL': 'getTargetURL', 'DB_ID': 'getDatabaseID', 'WGNI_TOKEN': 'getWgniToken'} pattern = ('\\%s(' + reduce(lambda x, y: x + '|' + y, self.__macros.iterkeys()) + ')') % self.__MACROS_PREFIX self.__filter = re.compile(pattern) self.__targetURL = '' self.__tokenRqs = TokenRequester(TOKEN_TYPE.WGNI, cache=False) def clear(self): self.__tokenRqs.clear() self.__macros.clear() self.__filter = None return def hasMarcos(self, url): return len(self.__filter.findall(url)) > 0 @async @process def parse(self, url, callback): yield lambda callback: callback(True) for macros in self.__filter.findall(url): replacement = yield self._replace(macros) url = url.replace(self._getUserMacrosName(macros), replacement) callback(url) @async def getLanguageCode(self, callback): code = getClientLanguage() callback(code.replace('_', '-')) @async def getAreaID(self, callback): areaID = connectionManager.areaID if areaID: result = str(areaID) else: result = 'errorArea' callback(result) @async def getEncodedLogin(self, callback): login = connectionManager.loginName if login: result = login else: result = 'errorLogin' callback(base64.b64encode(result)) @async def getQuotedLogin(self, callback): login = connectionManager.lastLoginName if login: result = quote_plus(login) else: result = '' callback(result) @async def getDatabaseID(self, callback): dbID = connectionManager.databaseID if dbID: result = str(dbID) else: result = 'errorID' callback(result) @async def getTargetURL(self, callback): result = self.__targetURL if self.__targetURL: result = quote_plus(self.__targetURL) callback(result) @async def getWgniToken(self, callback): def _cbWrapper(response): if response and response.isValid(): callback(str(response.getToken())) else: callback('') self.__tokenRqs.request()(_cbWrapper) def setTargetURL(self, targetURL): self.__targetURL = targetURL @async @process def _replace(self, macros, callback): yield lambda callback: callback(True) result = '' if macros in self.__macros: result = yield getattr(self, self.__macros[macros])() else: LOG_ERROR('URL marcos is not found', macros) callback(result) def _getUserMacrosName(self, macros): return '%s%s' % (self.__MACROS_PREFIX, str(macros))