Two issues causing ~2min reconnect cycles: 1. pymumble captures threading.current_thread() as parent_thread at init. Since we construct it in a run_in_executor thread, the parent dies after _connect_sync returns, triggering pymumble's loop exit. Fix: point parent_thread at threading.main_thread(). 2. pymumble's init_connection() drops the control_socket reference without closing it. The lingering TCP connection makes Murmur kick the new session with "connected from another device". Fix: patch init_connection to close the old socket before reconnecting.
70 lines
2.5 KiB
Python
70 lines
2.5 KiB
Python
"""Patch pymumble deps for Python 3.13+ / musl (Alpine).
|
|
|
|
1. pymumble: ssl.wrap_socket was removed in 3.13
|
|
2. opuslib: ctypes.util.find_library fails on musl-based distros
|
|
"""
|
|
|
|
import pathlib
|
|
import sysconfig
|
|
|
|
site = sysconfig.get_path("purelib")
|
|
|
|
# -- pymumble: replace ssl.wrap_socket with SSLContext --
|
|
p = pathlib.Path(f"{site}/pymumble_py3/mumble.py")
|
|
src = p.read_text()
|
|
|
|
old = """\
|
|
try:
|
|
self.control_socket = ssl.wrap_socket(std_sock, certfile=self.certfile, keyfile=self.keyfile, ssl_version=ssl.PROTOCOL_TLS)
|
|
except AttributeError:
|
|
self.control_socket = ssl.wrap_socket(std_sock, certfile=self.certfile, keyfile=self.keyfile, ssl_version=ssl.PROTOCOL_TLSv1)
|
|
try:"""
|
|
|
|
new = """\
|
|
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
|
ctx.check_hostname = False
|
|
ctx.verify_mode = ssl.CERT_NONE
|
|
if self.certfile:
|
|
ctx.load_cert_chain(certfile=self.certfile, keyfile=self.keyfile)
|
|
self.control_socket = ctx.wrap_socket(std_sock, server_hostname=self.host)
|
|
try:"""
|
|
|
|
assert old in src, "pymumble ssl patch target not found"
|
|
p.write_text(src.replace(old, new))
|
|
print("pymumble ssl patch applied")
|
|
|
|
# -- opuslib: find_library fails on musl, use direct CDLL fallback --
|
|
p = pathlib.Path(f"{site}/opuslib/api/__init__.py")
|
|
src = p.read_text()
|
|
|
|
old_opus = "lib_location = find_library('opus')"
|
|
new_opus = "lib_location = find_library('opus') or 'libopus.so.0'"
|
|
|
|
assert old_opus in src, "opuslib find_library patch target not found"
|
|
p.write_text(src.replace(old_opus, new_opus))
|
|
print("opuslib musl patch applied")
|
|
|
|
# -- pymumble: close old socket before reconnecting --
|
|
# init_connection() drops control_socket reference without closing it.
|
|
# The lingering TCP connection causes Murmur to kick the new session
|
|
# with "You connected to the server from another device".
|
|
p = pathlib.Path(f"{site}/pymumble_py3/mumble.py")
|
|
src = p.read_text()
|
|
|
|
old_init = """\
|
|
self.connected = PYMUMBLE_CONN_STATE_NOT_CONNECTED
|
|
self.control_socket = None"""
|
|
|
|
new_init = """\
|
|
self.connected = PYMUMBLE_CONN_STATE_NOT_CONNECTED
|
|
if getattr(self, 'control_socket', None) is not None:
|
|
try:
|
|
self.control_socket.close()
|
|
except Exception:
|
|
pass
|
|
self.control_socket = None"""
|
|
|
|
assert old_init in src, "pymumble init_connection socket patch target not found"
|
|
p.write_text(src.replace(old_init, new_init))
|
|
print("pymumble reconnect socket patch applied")
|