fix: patch pymumble protocol version and harden mumble connections

- Update reported protocol version from 1.2.4 to 1.5.0 so modern
  Murmur servers treat PyMumble as a compatible client
- Fix OS string to report actual platform instead of "PyMumble 1.6.1"
  (was shown as [Invalid] by Murmur)
- Raise pymumble reconnect retry interval to 15s to prevent autoban
  when running multiple bots from the same IP
- Enable TCP keepalive on control socket (10s idle) to prevent NAT
  gateways from dropping long-lived connections

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
user
2026-02-22 22:28:57 +01:00
parent 40c6bf8c53
commit 8b504364a9
2 changed files with 42 additions and 1 deletions

View File

@@ -2,6 +2,7 @@
1. pymumble: ssl.wrap_socket was removed in 3.13
2. opuslib: ctypes.util.find_library fails on musl-based distros
3. pymumble: protocol version 1.2.4 is rejected by modern servers
"""
import pathlib
@@ -65,5 +66,29 @@ new_init = """\
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))
src = src.replace(old_init, new_init)
print("pymumble reconnect socket patch applied")
p.write_text(src)
# -- pymumble: report modern protocol version --
# PyMumble 1.6.1 reports protocol version 1.2.4, which modern Murmur
# (1.5.x) treats as an invalid/legacy client. Update to 1.5.0 so the
# server enables full feature set and stops sending warnings.
p = pathlib.Path(f"{site}/pymumble_py3/constants.py")
src = p.read_text()
old_ver = "PYMUMBLE_PROTOCOL_VERSION = (1, 2, 4)"
new_ver = "PYMUMBLE_PROTOCOL_VERSION = (1, 5, 0)"
assert old_ver in src, "pymumble version patch target not found"
src = src.replace(old_ver, new_ver)
old_os = 'PYMUMBLE_OS_STRING = "PyMumble %s" % PYMUMBLE_VERSION'
new_os = 'PYMUMBLE_OS_STRING = platform.system()'
assert old_os in src, "pymumble OS string patch target not found"
src = src.replace(old_os, new_os)
p.write_text(src)
print("pymumble version patch applied (1.5.0, native OS string)")

View File

@@ -218,11 +218,27 @@ class MumbleBot:
self._on_sound_received,
)
self._mumble.set_receive_sound(self._receive_sound)
# Raise retry interval so 2+ bots on the same IP don't trip
# the server's autoban (default: 10 attempts / 120s).
import pymumble_py3.mumble as _pm
if getattr(_pm, "PYMUMBLE_CONNECTION_RETRY_INTERVAL", 0) < 15:
_pm.PYMUMBLE_CONNECTION_RETRY_INTERVAL = 15
self._mumble.start()
self._mumble.is_ready()
def _on_connected(self) -> None:
"""Callback from pymumble thread: connection established."""
# Enable TCP keepalive on the control socket to prevent NAT
# gateways from dropping the mapping during idle periods.
try:
import socket as _sock
raw = self._mumble.control_socket
raw.setsockopt(_sock.SOL_SOCKET, _sock.SO_KEEPALIVE, 1)
raw.setsockopt(_sock.IPPROTO_TCP, _sock.TCP_KEEPIDLE, 10)
raw.setsockopt(_sock.IPPROTO_TCP, _sock.TCP_KEEPINTVL, 5)
raw.setsockopt(_sock.IPPROTO_TCP, _sock.TCP_KEEPCNT, 3)
except Exception:
pass
self._connect_count += 1
kind = "reconnected" if self._connect_count > 1 else "connected"
session = getattr(self._mumble.users, "myself_session", "?")