Skip to content

Commit 320cb16

Browse files
authored
Improve SSH/telnet CLIs (#40)
* Only expose tuning arguments to SSH clients * Add graceful shutdown to ssh server * Add pdbpp as a dev dependency * Bump blessed to allow for EOF handling * simplify cleanup in ssh_app_session * Add graceful shutdown to telnet server * Add --users-directory arguments to server CLIs
1 parent 1287f8f commit 320cb16

9 files changed

Lines changed: 261 additions & 93 deletions

File tree

gambaterm/console.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,22 +115,15 @@ def add_console_arguments(cls, parser: argparse.ArgumentParser) -> None:
115115
action="store_true",
116116
help="Force the emulator to treat the rom as a GB file",
117117
)
118-
parser.add_argument(
119-
"--save-directory",
120-
"--sd",
121-
type=Path,
122-
default=None,
123-
help="Path to the save directory",
124-
)
125118

126119
@classmethod
127120
def pop_console_arguments(
128121
cls, namespace: argparse.Namespace
129122
) -> Callable[[], Console]:
130123
romfile: Path = namespace.romfile
131124
input_file: Path | None = namespace.input_file
125+
save_directory: Path | None = namespace.save_directory
132126
force_gameboy: bool = namespace.__dict__.pop("force_gameboy")
133-
save_directory: Path | None = namespace.__dict__.pop("save_directory")
134127
# Save directory defaults to the rom file directory (unless we read the input from a file)
135128
if input_file is None and save_directory is None:
136129
save_directory = romfile.parent

gambaterm/keyboard_input.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,7 @@ def __init__(
125125
self._pop_keystrokes = pop_keystrokes
126126

127127
def pop_keystrokes(self) -> list[Keystroke]:
128-
if self._pop_keystrokes is not None:
129-
return self._pop_keystrokes()
130-
return super().pop_keystrokes()
128+
return self._pop_keystrokes()
131129

132130

133131
def is_kitty_keyboard_protocol_supported(

gambaterm/main.py

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,34 @@ class AppConfig:
2929
speed: float
3030
skip_inputs: int
3131
cpr_sync: bool
32+
save_directory: Path | None
33+
34+
35+
@dataclass
36+
class LocalAppConfig(AppConfig):
3237
enable_controller: bool
3338
write_input: Path | None
3439

3540

3641
def add_base_arguments(parser: argparse.ArgumentParser) -> None:
3742
parser.add_argument("romfile", metavar="ROM", type=Path, help="Path to a rom file")
43+
44+
45+
def add_input_file_arguments(parser: argparse.ArgumentParser) -> None:
3846
parser.add_argument(
3947
"--input-file", "-i", type=Path, default=None, help="Path to a bizhawk BK2 file"
4048
)
49+
parser.add_argument(
50+
"--skip-inputs",
51+
"--si",
52+
type=int,
53+
default=188,
54+
help="Number of frame inputs to skip in order to compensate "
55+
"for the lack of BIOS (default is 188)",
56+
)
4157

4258

43-
def add_optional_arguments(parser: argparse.ArgumentParser) -> None:
59+
def add_tuning_arguments(parser: argparse.ArgumentParser) -> None:
4460
parser.add_argument(
4561
"--color-mode",
4662
"-c",
@@ -73,20 +89,18 @@ def add_optional_arguments(parser: argparse.ArgumentParser) -> None:
7389
default=1.0,
7490
help="Control the execution speed (default is 1.0)",
7591
)
76-
parser.add_argument(
77-
"--skip-inputs",
78-
"--si",
79-
type=int,
80-
default=188,
81-
help="Number of frame inputs to skip in order to compensate "
82-
"for the lack of BIOS (default is 188)",
83-
)
8492
parser.add_argument(
8593
"--cpr-sync",
8694
"--cs",
8795
action="store_true",
8896
help="Use CPR synchronization to prevent video buffering",
8997
)
98+
99+
100+
def add_local_only_arguments(parser: argparse.ArgumentParser) -> None:
101+
parser.add_argument(
102+
"--disable-audio", "--da", action="store_true", help="Disable audio entirely"
103+
)
90104
parser.add_argument(
91105
"--enable-controller",
92106
"--ec",
@@ -99,6 +113,13 @@ def add_optional_arguments(parser: argparse.ArgumentParser) -> None:
99113
type=Path,
100114
help="Record inputs into a file",
101115
)
116+
parser.add_argument(
117+
"--save-directory",
118+
"--sd",
119+
type=Path,
120+
default=None,
121+
help="Path to the save directory (default to the ROM directory)",
122+
)
102123

103124

104125
def main(
@@ -110,17 +131,16 @@ def main(
110131
prog="gambaterm", description="Gambatte terminal front-end"
111132
)
112133
add_base_arguments(parser)
113-
add_optional_arguments(parser)
134+
add_input_file_arguments(parser)
135+
add_tuning_arguments(parser)
136+
add_local_only_arguments(parser)
114137
console_cls.add_console_arguments(parser)
115-
parser.add_argument(
116-
"--disable-audio", "--da", action="store_true", help="Disable audio entirely"
117-
)
118138

119139
# Parse arguments
120140
namespace = parser.parse_args(parser_args)
121141
disable_audio: bool = namespace.__dict__.pop("disable_audio")
122142
console_callback = console_cls.pop_console_arguments(namespace)
123-
args = AppConfig(**vars(namespace))
143+
args = LocalAppConfig(**vars(namespace))
124144

125145
# Check that the ROM file exists
126146
if not args.romfile.exists():

gambaterm/remote_terminal.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from __future__ import annotations
66

77
import codecs
8+
import hashlib
89
import contextlib
910
from typing import IO, Generator
1011

@@ -84,3 +85,14 @@ def _height_and_width(self) -> WINSZ:
8485
def update_size(self, rows: int, columns: int) -> None:
8586
self._rows = rows
8687
self._columns = columns
88+
89+
90+
def user_directory_name(username: str | None) -> str:
91+
"""Hash the username into a safe directory name.
92+
93+
:param username: telnet/ssh-negotiated username, or ``None``
94+
:returns: hex digest suitable for use as a directory name
95+
"""
96+
if username is None:
97+
return "_anonymous"
98+
return hashlib.sha256(username.encode("utf-8")).hexdigest()[:16]

0 commit comments

Comments
 (0)