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]
|
[project]
|
||||||
name = "vban-cmd"
|
name = "vban-cmd"
|
||||||
version = "2.9.5"
|
version = "2.9.6"
|
||||||
description = "Python interface for the VBAN RT Packet Service (Sendtext)"
|
description = "Python interface for the VBAN RT Packet Service (Sendtext)"
|
||||||
authors = [{ name = "Onyx and Iris", email = "code@onyxandiris.online" }]
|
authors = [{ name = "Onyx and Iris", email = "code@onyxandiris.online" }]
|
||||||
license = { text = "MIT" }
|
license = { text = "MIT" }
|
||||||
|
|||||||
@ -21,8 +21,8 @@ def ratelimit(func):
|
|||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
def ping_timeout(func):
|
def pong_timeout(func):
|
||||||
"""ping_timeout decorator for {VbanCmd}._ping, to handle timeout logic and socket management."""
|
"""pong_timeout decorator for {VbanCmd}._handle_pong, to handle timeout logic and socket management."""
|
||||||
|
|
||||||
def wrapper(self, timeout: float = None):
|
def wrapper(self, timeout: float = None):
|
||||||
if timeout is None:
|
if timeout is None:
|
||||||
@ -32,25 +32,14 @@ def ping_timeout(func):
|
|||||||
self.sock.settimeout(0.5)
|
self.sock.settimeout(0.5)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
func(self)
|
|
||||||
|
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
response_count = 0
|
response_count = 0
|
||||||
|
|
||||||
while time.time() - start_time < timeout:
|
while time.time() - start_time < timeout:
|
||||||
try:
|
try:
|
||||||
data, addr = self.sock.recvfrom(2048)
|
|
||||||
response_count += 1
|
response_count += 1
|
||||||
|
|
||||||
self.logger.debug(
|
if func(self):
|
||||||
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:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
except socket.timeout:
|
except socket.timeout:
|
||||||
|
|||||||
@ -17,7 +17,7 @@ from .packet.headers import (
|
|||||||
)
|
)
|
||||||
from .packet.ping0 import VbanPing0Payload, VbanServerType
|
from .packet.ping0 import VbanPing0Payload, VbanServerType
|
||||||
from .subject import Subject
|
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
|
from .worker import Producer, Subscriber, Updater
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -59,7 +59,6 @@ class VbanCmd(abc.ABC):
|
|||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"""Ensure subclasses override str magic method"""
|
"""Ensure subclasses override str magic method"""
|
||||||
pass
|
|
||||||
|
|
||||||
def _conn_from_toml(self) -> dict:
|
def _conn_from_toml(self) -> dict:
|
||||||
try:
|
try:
|
||||||
@ -97,6 +96,7 @@ class VbanCmd(abc.ABC):
|
|||||||
If the server is detected as Matrix, RT listeners will be disabled for compatibility.
|
If the server is detected as Matrix, RT listeners will be disabled for compatibility.
|
||||||
"""
|
"""
|
||||||
self._ping()
|
self._ping()
|
||||||
|
self._handle_pong()
|
||||||
|
|
||||||
if not self.disable_rt_listeners:
|
if not self.disable_rt_listeners:
|
||||||
self.event.info()
|
self.event.info()
|
||||||
@ -138,30 +138,27 @@ class VbanCmd(abc.ABC):
|
|||||||
self._framecounter = bump_framecounter(self._framecounter)
|
self._framecounter = bump_framecounter(self._framecounter)
|
||||||
return current
|
return current
|
||||||
|
|
||||||
@ping_timeout
|
def _ping(self):
|
||||||
def _ping(self, data=None, addr=None) -> bool:
|
"""Initiates the PING/PONG handshake with the VBAN server."""
|
||||||
"""Handles the PING/PONG handshake with the VBAN server, including timeout logic and server type detection.
|
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"""
|
except socket.gaierror as e:
|
||||||
if data is None and addr is None:
|
raise VBANCMDConnectionError(
|
||||||
ping_packet = VbanPing0Payload.create_packet(self._get_next_framecounter())
|
f'Unable to resolve hostname {self.host}'
|
||||||
|
) from e
|
||||||
|
except Exception as e:
|
||||||
|
raise VBANCMDConnectionError(f'PING failed: {e}') from e
|
||||||
|
|
||||||
try:
|
@pong_timeout
|
||||||
self.sock.sendto(
|
def _handle_pong(self) -> bool:
|
||||||
ping_packet, (socket.gethostbyname(self.host), self.port)
|
"""Handles incoming packets during the PING/PONG handshake, looking for a valid PONG response to confirm connectivity and detect server type.
|
||||||
)
|
|
||||||
self.logger.debug(f'PING sent to {self.host}:{self.port}')
|
|
||||||
|
|
||||||
except socket.gaierror as e:
|
Returns True if a valid PONG is received, False otherwise."""
|
||||||
raise VBANCMDConnectionError(
|
data, addr = self.sock.recvfrom(2048)
|
||||||
f'Unable to resolve hostname {self.host}'
|
|
||||||
) from e
|
|
||||||
except Exception as e:
|
|
||||||
raise VBANCMDConnectionError(f'PING failed: {e}') from e
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
if VbanPongHeader.is_pong_response(data):
|
if VbanPongHeader.is_pong_response(data):
|
||||||
self.logger.debug(f'PONG received from {addr}, connectivity confirmed')
|
self.logger.debug(f'PONG received from {addr}, connectivity confirmed')
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user