aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorterminaldweller <thabogre@gmail.com>2023-03-11 06:40:58 +0000
committerterminaldweller <thabogre@gmail.com>2023-03-11 06:40:58 +0000
commit013c71605185653f735b6a7e6fe622becc03e0fa (patch)
tree65fa452f049078b402cce315e4426130c2858c91
parentfixed the quit bug where we were waiting on cancelled asyncio tasks (diff)
downloadtunneltop-013c71605185653f735b6a7e6fe622becc03e0fa.tar.gz
tunneltop-013c71605185653f735b6a7e6fe622becc03e0fa.zip
we now revive the scheduler if it dies. added a new option to determine which tunnels to auto_start
-rw-r--r--README.md2
-rw-r--r--pyproject.toml7
-rwxr-xr-xtunneltop/tunneltop.py58
3 files changed, 29 insertions, 38 deletions
diff --git a/README.md b/README.md
index 168d2dc..c44b92b 100644
--- a/README.md
+++ b/README.md
@@ -46,6 +46,7 @@ test_command = 'curl -s -o /dev/null -s -w "%{http_code}" -k -I -4 --socks5 sock
test_command_result = "200"
test_interval = 300
test_timeout = 10
+auto_start = false
[tunnel.socks5_3]
address = "127.0.0.1"
@@ -55,6 +56,7 @@ test_command = 'curl -s -o /dev/null -s -w "%{http_code}" -k -I -4 --socks5 sock
test_command_result = "200"
test_interval = 300
test_timeout = 10
+auto_start = true
```
The tunnel names must be unique.</br>
diff --git a/pyproject.toml b/pyproject.toml
index ad57e70..44270e7 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "tunneltop"
-version = "0.3.6"
+version = "0.4.0"
description = "A top-like tunnel manager"
authors = ["terminaldweller <devi@terminaldweller.com>"]
license = "GPL-3.0"
@@ -27,3 +27,8 @@ python = "^3.11"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
+
+[tool.ruff]
+profile = "black"
+target-version = "py311"
+unfixable = ["B", "SIM", "TRY", "RUF"]
diff --git a/tunneltop/tunneltop.py b/tunneltop/tunneltop.py
index 984f6c9..f9e734b 100755
--- a/tunneltop/tunneltop.py
+++ b/tunneltop/tunneltop.py
@@ -105,9 +105,7 @@ def ffs(
if header_list is not None:
if numbered:
numbers_f.extend(range(1, len(args[-1]) + 1))
- max_column_width.append(
- max(len(repr(number)) for number in numbers_f)
- )
+ max_column_width.append(max(len(repr(number)) for number in numbers_f))
header_list.insert(0, "idx")
index = range(0, len(header_list))
@@ -116,10 +114,7 @@ def ffs(
for i in index:
dummy.append(
- greenie
- + bold
- + header_list[i].ljust(max_column_width[i])
- + endc
+ greenie + bold + header_list[i].ljust(max_column_width[i]) + endc
)
lines.append("".join(dummy))
dummy.clear()
@@ -127,9 +122,7 @@ def ffs(
index2 = range(0, len(args[-1]))
for i in index2:
if numbered:
- dummy.append(
- goo + bold + repr(i).ljust(max_column_width[0]) + endc
- )
+ dummy.append(goo + bold + repr(i).ljust(max_column_width[0]) + endc)
for arg, width in zip(args, max_column_width[1:]):
dummy.append(blueblue + (arg[i]).ljust(width) + endc)
else:
@@ -205,19 +198,15 @@ def render(
class TunnelManager:
"""The tunnel top class"""
- def __init__(self):
+ def __init__(self) -> None:
self.stdscr = curses.initscr()
self.argparser = Argparser()
self.colos: typing.Dict[str, int] = {}
- self.data_cols: typing.Dict[
- str, typing.Dict[str, str]
- ] = self.read_conf()
+ self.data_cols: typing.Dict[str, typing.Dict[str, str]] = self.read_conf()
self.tunnel_tasks: typing.List[asyncio.Task] = []
self.tunnel_test_tasks: typing.Dict[str, asyncio.Task] = {}
self.scheduler_task: asyncio.Task
- self.scheduler_table: typing.Dict[
- str, int
- ] = self.init_scheduler_table()
+ self.scheduler_table: typing.Dict[str, int] = self.init_scheduler_table()
# we use this when its time to quit. this will prevent any
# new tasks from being scheduled
self.are_we_dying: bool = False
@@ -231,12 +220,8 @@ class TunnelManager:
)
curses.init_pair(2, self.colos["active_fg"], self.colos["active_bg"])
curses.init_pair(3, self.colos["active_bg"], self.colos["active_fg"])
- curses.init_pair(
- 4, self.colos["disabled_fg"], self.colos["disabled_bg"]
- )
- curses.init_pair(
- 5, self.colos["disabled_bg"], self.colos["disabled_fg"]
- )
+ curses.init_pair(4, self.colos["disabled_fg"], self.colos["disabled_bg"])
+ curses.init_pair(5, self.colos["disabled_bg"], self.colos["disabled_fg"])
curses.init_pair(6, self.colos["unknown_fg"], self.colos["unknown_bg"])
curses.init_pair(7, self.colos["unknown_bg"], self.colos["unknown_fg"])
curses.init_pair(8, self.colos["timeout_fg"], self.colos["timeout_bg"])
@@ -291,9 +276,7 @@ class TunnelManager:
def read_conf(self) -> typing.Dict[str, typing.Dict[str, str]]:
"""Read the config file"""
data_cols: typing.Dict[str, typing.Dict[str, str]] = {}
- with open(
- os.path.expanduser(self.argparser.args.config), "rb"
- ) as conf_file:
+ with open(os.path.expanduser(self.argparser.args.config), "rb") as conf_file:
data = tomllib.load(conf_file)
for key, value in data.items():
if key == "tunnel":
@@ -305,14 +288,13 @@ class TunnelManager:
"command": tunnel_value["command"],
"status": "UNKWN",
"test_command": tunnel_value["test_command"],
- "test_command_result": tunnel_value[
- "test_command_result"
- ],
+ "test_command_result": tunnel_value["test_command_result"],
"test_interval": tunnel_value["test_interval"],
"test_timeout": tunnel_value["test_timeout"],
"stdout": "n/a",
"stderr": "n/a",
"disabled": "",
+ "auto_start": tunnel_value["auto_start"],
}
elif key == "color":
for color_key, color_value in value.items():
@@ -372,6 +354,9 @@ class TunnelManager:
"""run all the tunnels in the background as separate subprocesses"""
tasks: typing.List[asyncio.Task] = []
for _, value in self.data_cols.items():
+ if value["auto_start"] is False:
+ self.data_cols[value["name"]]["disabled"] = "manual"
+ continue
tasks.append(
asyncio.create_task(
self.run_subprocess(value["command"]), name=value["name"]
@@ -389,9 +374,7 @@ class TunnelManager:
for k, value in data_cols_new.items():
if k not in self.data_cols:
self.tunnel_tasks.append(
- asyncio.create_task(
- self.run_subprocess(value["command"]), name=k
- )
+ asyncio.create_task(self.run_subprocess(value["command"]), name=k)
)
await asyncio.sleep(0)
self.data_cols[k] = copy.deepcopy(value)
@@ -400,8 +383,7 @@ class TunnelManager:
if (
self.data_cols[k]["command"] != data_cols_new[k]["command"]
or self.data_cols[k]["port"] != data_cols_new[k]["port"]
- or self.data_cols[k]["address"]
- != data_cols_new[k]["address"]
+ or self.data_cols[k]["address"] != data_cols_new[k]["address"]
):
for task in self.tunnel_tasks:
if task.get_name() == k:
@@ -567,9 +549,7 @@ class TunnelManager:
await asyncio.sleep(0)
self.tunnel_test_tasks[key] = test_task
if value > 0:
- self.scheduler_table[key] = (
- self.scheduler_table[key] - 1
- )
+ self.scheduler_table[key] = self.scheduler_table[key] - 1
if value <= 0:
self.write_log("revitalizing test for " + key + "\n")
self.scheduler_table[key] = int(
@@ -604,6 +584,10 @@ class TunnelManager:
)
while True:
+ if self.scheduler_task.cancelled() or self.scheduler_task.done():
+ self.scheduler_task = asyncio.create_task(
+ self.scheduler(), name="scheduler"
+ )
self.stdscr.clear()
render(self.data_cols, self.tunnel_tasks, self.stdscr, sel)
char = self.stdscr.getch()