BizHawkClient: Add support for server passwords (#2306)

This commit is contained in:
Bryce Wilson 2023-10-28 12:48:31 -07:00 committed by GitHub
parent e8a7200740
commit acfc71b8c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 53 additions and 10 deletions

View File

@ -5,6 +5,7 @@ checking or launching the client, otherwise it will probably cause circular impo
import asyncio import asyncio
import enum
import subprocess import subprocess
import traceback import traceback
from typing import Any, Dict, Optional from typing import Any, Dict, Optional
@ -21,6 +22,13 @@ from .client import BizHawkClient, AutoBizHawkClientRegister
EXPECTED_SCRIPT_VERSION = 1 EXPECTED_SCRIPT_VERSION = 1
class AuthStatus(enum.IntEnum):
NOT_AUTHENTICATED = 0
NEED_INFO = 1
PENDING = 2
AUTHENTICATED = 3
class BizHawkClientCommandProcessor(ClientCommandProcessor): class BizHawkClientCommandProcessor(ClientCommandProcessor):
def _cmd_bh(self): def _cmd_bh(self):
"""Shows the current status of the client's connection to BizHawk""" """Shows the current status of the client's connection to BizHawk"""
@ -35,6 +43,8 @@ class BizHawkClientCommandProcessor(ClientCommandProcessor):
class BizHawkClientContext(CommonContext): class BizHawkClientContext(CommonContext):
command_processor = BizHawkClientCommandProcessor command_processor = BizHawkClientCommandProcessor
auth_status: AuthStatus
password_requested: bool
client_handler: Optional[BizHawkClient] client_handler: Optional[BizHawkClient]
slot_data: Optional[Dict[str, Any]] = None slot_data: Optional[Dict[str, Any]] = None
rom_hash: Optional[str] = None rom_hash: Optional[str] = None
@ -45,6 +55,8 @@ class BizHawkClientContext(CommonContext):
def __init__(self, server_address: Optional[str], password: Optional[str]): def __init__(self, server_address: Optional[str], password: Optional[str]):
super().__init__(server_address, password) super().__init__(server_address, password)
self.auth_status = AuthStatus.NOT_AUTHENTICATED
self.password_requested = False
self.client_handler = None self.client_handler = None
self.bizhawk_ctx = BizHawkContext() self.bizhawk_ctx = BizHawkContext()
self.watcher_timeout = 0.5 self.watcher_timeout = 0.5
@ -61,10 +73,41 @@ class BizHawkClientContext(CommonContext):
def on_package(self, cmd, args): def on_package(self, cmd, args):
if cmd == "Connected": if cmd == "Connected":
self.slot_data = args.get("slot_data", None) self.slot_data = args.get("slot_data", None)
self.auth_status = AuthStatus.AUTHENTICATED
if self.client_handler is not None: if self.client_handler is not None:
self.client_handler.on_package(self, cmd, args) self.client_handler.on_package(self, cmd, args)
async def server_auth(self, password_requested: bool = False):
self.password_requested = password_requested
if self.bizhawk_ctx.connection_status != ConnectionStatus.CONNECTED:
logger.info("Awaiting connection to BizHawk before authenticating")
return
if self.client_handler is None:
return
# Ask handler to set auth
if self.auth is None:
self.auth_status = AuthStatus.NEED_INFO
await self.client_handler.set_auth(self)
# Handler didn't set auth, ask user for slot name
if self.auth is None:
await self.get_username()
if password_requested and not self.password:
self.auth_status = AuthStatus.NEED_INFO
await super(BizHawkClientContext, self).server_auth(password_requested)
await self.send_connect()
self.auth_status = AuthStatus.PENDING
async def disconnect(self, allow_autoreconnect: bool = False):
self.auth_status = AuthStatus.NOT_AUTHENTICATED
await super().disconnect(allow_autoreconnect)
async def _game_watcher(ctx: BizHawkClientContext): async def _game_watcher(ctx: BizHawkClientContext):
showed_connecting_message = False showed_connecting_message = False
@ -109,12 +152,13 @@ async def _game_watcher(ctx: BizHawkClientContext):
rom_hash = await get_hash(ctx.bizhawk_ctx) rom_hash = await get_hash(ctx.bizhawk_ctx)
if ctx.rom_hash is not None and ctx.rom_hash != rom_hash: if ctx.rom_hash is not None and ctx.rom_hash != rom_hash:
if ctx.server is not None: if ctx.server is not None and not ctx.server.socket.closed:
logger.info(f"ROM changed. Disconnecting from server.") logger.info(f"ROM changed. Disconnecting from server.")
await ctx.disconnect(True)
ctx.auth = None ctx.auth = None
ctx.username = None ctx.username = None
ctx.client_handler = None
await ctx.disconnect(False)
ctx.rom_hash = rom_hash ctx.rom_hash = rom_hash
if ctx.client_handler is None: if ctx.client_handler is None:
@ -136,15 +180,14 @@ async def _game_watcher(ctx: BizHawkClientContext):
except NotConnectedError: except NotConnectedError:
continue continue
# Get slot name and send `Connect` # Server auth
if ctx.server is not None and ctx.username is None: if ctx.server is not None and not ctx.server.socket.closed:
await ctx.client_handler.set_auth(ctx) if ctx.auth_status == AuthStatus.NOT_AUTHENTICATED:
Utils.async_start(ctx.server_auth(ctx.password_requested))
if ctx.auth is None: else:
await ctx.get_username() ctx.auth_status = AuthStatus.NOT_AUTHENTICATED
await ctx.send_connect()
# Call the handler's game watcher
await ctx.client_handler.game_watcher(ctx) await ctx.client_handler.game_watcher(ctx)