Initial support for multiple clients and cross-client play

This commit is contained in:
Ben
2019-08-06 22:55:11 +01:00
parent fedf855f74
commit 4fa0f4dfe0
7 changed files with 98 additions and 23 deletions

View File

@@ -3,6 +3,7 @@ import enum
import itertools
import importlib
import sys
import config
from types import FunctionType
from houdini.converters import _listener, _ArgumentDeserializer, get_converter, do_conversion, _ConverterContext
@@ -51,7 +52,7 @@ class Priority(enum.Enum):
class _Listener(_ArgumentDeserializer):
__slots__ = ['priority', 'packet', 'overrides', 'before', 'after']
__slots__ = ['priority', 'packet', 'overrides', 'before', 'after', 'client_type']
def __init__(self, packet, callback, **kwargs):
super().__init__(packet.id, callback, **kwargs)
@@ -60,6 +61,7 @@ class _Listener(_ArgumentDeserializer):
self.priority = kwargs.get('priority', Priority.Low)
self.before = kwargs.get('before')
self.after = kwargs.get('after')
self.client_type = kwargs.get('client')
self.overrides = kwargs.get('overrides', [])

View File

@@ -1,6 +1,6 @@
import config
from houdini import handlers
from houdini import handlers, ClientType
from houdini.handlers import XMLPacket
from houdini.converters import VersionChkConverter
@@ -10,7 +10,15 @@ from houdini.data.buddy import BuddyList
@handlers.handler(XMLPacket('verChk'))
@handlers.allow_once
async def handle_version_check(p, version: VersionChkConverter):
if not version == 153:
if config.client['MultiClientSupport']:
if config.client['LegacyVersionChk'] == version:
p.client_type = ClientType.Legacy
elif config.client['VanillaVersionChk'] == version:
p.client_type = ClientType.Vanilla
elif config.client['DefaultVersionChk'] == version:
p.client_type = config.client['DefaultClientType']
if p.client_type is None:
await p.send_xml({'body': {'action': 'apiKO', 'r': '0'}})
await p.close()
else:
@@ -20,7 +28,7 @@ async def handle_version_check(p, version: VersionChkConverter):
@handlers.handler(XMLPacket('rndK'))
@handlers.allow_once
async def handle_random_key(p, data):
await p.send_xml({'body': {'action': 'rndK', 'r': '-1'}, 'k': 'houdini'})
await p.send_xml({'body': {'action': 'rndK', 'r': '-1'}, 'k': config.client['AuthStaticKey']})
async def get_server_presence(p, pid):

View File

@@ -1,4 +1,4 @@
from houdini import handlers
from houdini import handlers, ClientType
from houdini.handlers import XMLPacket, login
from houdini.handlers.login import get_server_presence
from houdini.converters import Credentials
@@ -27,7 +27,7 @@ async def handle_login(p, credentials: Credentials):
data = await Penguin.query.where(Penguin.username == username).gino.first()
if data is None:
p.logger.info('{} failed to login: penguin does not exist')
p.logger.info('{} failed to login: penguin does not exist'.format(username))
return await p.send_error_and_disconnect(100)
password_correct = await loop.run_in_executor(None, bcrypt.checkpw,
@@ -84,16 +84,19 @@ async def handle_login(p, credentials: Credentials):
confirmation_hash = Crypto.hash(os.urandom(24))
tr = p.server.redis.multi_exec()
tr.setex('{}.lkey'.format(data.id), p.server.server_config['KeyTTL'], login_key)
tr.setex('{}.ckey'.format(data.id), p.server.server_config['KeyTTL'], confirmation_hash)
tr.setex('{}.lkey'.format(data.username), p.server.server_config['KeyTTL'], login_key)
tr.setex('{}.ckey'.format(data.username), p.server.server_config['KeyTTL'], confirmation_hash)
await tr.execute()
world_populations, buddy_presence = await get_server_presence(p, data.id)
raw_login_data = '|'.join([str(data.id), str(data.id), data.username, login_key, str(data.approval),
str(data.rejection)])
await p.send_xt('l', raw_login_data, confirmation_hash, '', world_populations, buddy_presence,
data.email)
if p.client_type == ClientType.Vanilla:
raw_login_data = '|'.join([str(data.id), str(data.id), data.username, login_key, str(data.approval),
str(data.rejection)])
await p.send_xt('l', raw_login_data, confirmation_hash, '', world_populations, buddy_presence,
data.email)
else:
await p.send_xt('l', data.id, login_key, world_populations, buddy_presence)
handle_version_check = login.handle_version_check
handle_random_key = login.handle_random_key

View File

@@ -1,8 +1,11 @@
from houdini import handlers
import config
from houdini import handlers, ClientType
from houdini.handlers import XMLPacket, login
from houdini.converters import WorldCredentials
from houdini.converters import WorldCredentials, Credentials
from houdini.data.penguin import Penguin
from houdini.data.moderator import Ban
from houdini.crypto import Crypto
from datetime import datetime
@@ -10,20 +13,26 @@ handle_version_check = login.handle_version_check
handle_random_key = login.handle_random_key
@handlers.handler(XMLPacket('login'))
@handlers.handler(XMLPacket('login'), client=ClientType.Vanilla)
@handlers.allow_once
@handlers.depends_on_packet(XMLPacket('verChk'), XMLPacket('rndK'))
async def handle_login(p, credentials: WorldCredentials):
tr = p.server.redis.multi_exec()
tr.get('{}.lkey'.format(credentials.id))
tr.get('{}.ckey'.format(credentials.id))
tr.delete('{}.lkey'.format(credentials.id), '{}.ckey'.format(credentials.id))
tr.get('{}.lkey'.format(credentials.username))
tr.get('{}.ckey'.format(credentials.username))
tr.delete('{}.lkey'.format(credentials.username), '{}.ckey'.format(credentials.username))
login_key, confirmation_hash, _ = await tr.execute()
if login_key is None or confirmation_hash is None:
return await p.close()
if login_key.decode() != credentials.login_key or confirmation_hash.decode() != credentials.confirmation_hash:
login_key = login_key.decode()
login_hash = Crypto.encrypt_password(login_key + config.client['AuthStaticKey']) + login_key
if credentials.client_key != login_hash:
return await p.close()
if login_key != credentials.login_key or confirmation_hash.decode() != credentials.confirmation_hash:
return await p.close()
data = await Penguin.get(credentials.id)
@@ -47,5 +56,5 @@ async def handle_login(p, credentials: WorldCredentials):
p.logger.info('{} logged in successfully'.format(data.username))
p.data = data
p.login_key = credentials.login_key
p.login_key = login_key
await p.send_xt('l')