Beispiel #1
0
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))
Beispiel #2
0
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')
Beispiel #3
0
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))
Beispiel #4
0
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')
Beispiel #5
0
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))