mirror of
https://github.com/onyx-and-iris/vban-cmd-python.git
synced 2026-03-12 04:59:09 +00:00
separate ping from pong
this separates concerns and allows the pong_timeout to strictly handle timeouts for pongs. patch bump
This commit is contained in:
parent
2dd52a7258
commit
3d01321be3
@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "vban-cmd"
|
||||
version = "2.9.5"
|
||||
version = "2.9.6"
|
||||
description = "Python interface for the VBAN RT Packet Service (Sendtext)"
|
||||
authors = [{ name = "Onyx and Iris", email = "code@onyxandiris.online" }]
|
||||
license = { text = "MIT" }
|
||||
|
||||
@ -21,8 +21,8 @@ def ratelimit(func):
|
||||
return wrapper
|
||||
|
||||
|
||||
def ping_timeout(func):
|
||||
"""ping_timeout decorator for {VbanCmd}._ping, to handle timeout logic and socket management."""
|
||||
def pong_timeout(func):
|
||||
"""pong_timeout decorator for {VbanCmd}._handle_pong, to handle timeout logic and socket management."""
|
||||
|
||||
def wrapper(self, timeout: float = None):
|
||||
if timeout is None:
|
||||
@ -32,25 +32,14 @@ def ping_timeout(func):
|
||||
self.sock.settimeout(0.5)
|
||||
|
||||
try:
|
||||
func(self)
|
||||
|
||||
start_time = time.time()
|
||||
response_count = 0
|
||||
|
||||
while time.time() - start_time < timeout:
|
||||
try:
|
||||
data, addr = self.sock.recvfrom(2048)
|
||||
response_count += 1
|
||||
|
||||
self.logger.debug(
|
||||
f'Received packet #{response_count} from {addr}: {len(data)} bytes'
|
||||
)
|
||||
self.logger.debug(
|
||||
f'Response header: {data[: min(32, len(data))].hex()}'
|
||||
)
|
||||
|
||||
result = func(self, data, addr)
|
||||
if result is True:
|
||||
if func(self):
|
||||
return
|
||||
|
||||
except socket.timeout:
|
||||
|
||||
@ -17,7 +17,7 @@ from .packet.headers import (
|
||||
)
|
||||
from .packet.ping0 import VbanPing0Payload, VbanServerType
|
||||
from .subject import Subject
|
||||
from .util import bump_framecounter, deep_merge, ping_timeout, ratelimit
|
||||
from .util import bump_framecounter, deep_merge, pong_timeout, ratelimit
|
||||
from .worker import Producer, Subscriber, Updater
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -59,7 +59,6 @@ class VbanCmd(abc.ABC):
|
||||
@abc.abstractmethod
|
||||
def __str__(self):
|
||||
"""Ensure subclasses override str magic method"""
|
||||
pass
|
||||
|
||||
def _conn_from_toml(self) -> dict:
|
||||
try:
|
||||
@ -97,6 +96,7 @@ class VbanCmd(abc.ABC):
|
||||
If the server is detected as Matrix, RT listeners will be disabled for compatibility.
|
||||
"""
|
||||
self._ping()
|
||||
self._handle_pong()
|
||||
|
||||
if not self.disable_rt_listeners:
|
||||
self.event.info()
|
||||
@ -138,30 +138,27 @@ class VbanCmd(abc.ABC):
|
||||
self._framecounter = bump_framecounter(self._framecounter)
|
||||
return current
|
||||
|
||||
@ping_timeout
|
||||
def _ping(self, data=None, addr=None) -> bool:
|
||||
"""Handles the PING/PONG handshake with the VBAN server, including timeout logic and server type detection.
|
||||
def _ping(self):
|
||||
"""Initiates the PING/PONG handshake with the VBAN server."""
|
||||
ping_packet = VbanPing0Payload.create_packet(self._get_next_framecounter())
|
||||
|
||||
If data and addr are None, it sends a PING packet. If a PONG response is received, it returns True.
|
||||
try:
|
||||
self.sock.sendto(ping_packet, (socket.gethostbyname(self.host), self.port))
|
||||
self.logger.debug(f'PING sent to {self.host}:{self.port}')
|
||||
|
||||
If a non-PONG packet is received, it logs the packet details and continues waiting until timeout"""
|
||||
if data is None and addr is None:
|
||||
ping_packet = VbanPing0Payload.create_packet(self._get_next_framecounter())
|
||||
except socket.gaierror as e:
|
||||
raise VBANCMDConnectionError(
|
||||
f'Unable to resolve hostname {self.host}'
|
||||
) from e
|
||||
except Exception as e:
|
||||
raise VBANCMDConnectionError(f'PING failed: {e}') from e
|
||||
|
||||
try:
|
||||
self.sock.sendto(
|
||||
ping_packet, (socket.gethostbyname(self.host), self.port)
|
||||
)
|
||||
self.logger.debug(f'PING sent to {self.host}:{self.port}')
|
||||
@pong_timeout
|
||||
def _handle_pong(self) -> bool:
|
||||
"""Handles incoming packets during the PING/PONG handshake, looking for a valid PONG response to confirm connectivity and detect server type.
|
||||
|
||||
except socket.gaierror as e:
|
||||
raise VBANCMDConnectionError(
|
||||
f'Unable to resolve hostname {self.host}'
|
||||
) from e
|
||||
except Exception as e:
|
||||
raise VBANCMDConnectionError(f'PING failed: {e}') from e
|
||||
|
||||
return False
|
||||
Returns True if a valid PONG is received, False otherwise."""
|
||||
data, addr = self.sock.recvfrom(2048)
|
||||
|
||||
if VbanPongHeader.is_pong_response(data):
|
||||
self.logger.debug(f'PONG received from {addr}, connectivity confirmed')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user