actually impl --mc-hop (and improve --zm-spam)

This commit is contained in:
ed 2023-08-20 21:27:28 +00:00
parent b28bfe64c0
commit 7673beef72
2 changed files with 47 additions and 21 deletions

View File

@ -295,7 +295,9 @@ class MDNS(MCast):
while self.running: while self.running:
timeout = ( timeout = (
0.02 + random.random() * 0.07 0.02 + random.random() * 0.07
if self.probing or self.q or self.defend or self.unsolicited if self.probing or self.q or self.defend
else max(0.05, self.unsolicited[0] - time.time())
if self.unsolicited
else (last_hop + ihop if ihop else 180) else (last_hop + ihop if ihop else 180)
) )
rdy = select.select(self.srv, [], [], timeout) rdy = select.select(self.srv, [], [], timeout)
@ -514,7 +516,8 @@ class MDNS(MCast):
tx.add(srv) tx.add(srv)
if not self.unsolicited and self.args.zm_spam: if not self.unsolicited and self.args.zm_spam:
self.unsolicited.append(time.time() + self.args.zm_spam) zf = time.time() + self.args.zm_spam + random.random() * 0.07
self.unsolicited.append(zf)
for srv, deadline in list(self.defend.items()): for srv, deadline in list(self.defend.items()):
if now < deadline: if now < deadline:

View File

@ -15,7 +15,7 @@ from ipaddress import (
) )
from .__init__ import MACOS, TYPE_CHECKING from .__init__ import MACOS, TYPE_CHECKING
from .util import Netdev, find_prefix, min_ex, spack from .util import Daemon, Netdev, find_prefix, min_ex, spack
if TYPE_CHECKING: if TYPE_CHECKING:
from .svchub import SvcHub from .svchub import SvcHub
@ -228,6 +228,7 @@ class MCast(object):
for srv in self.srv.values(): for srv in self.srv.values():
assert srv.ip in self.sips assert srv.ip in self.sips
Daemon(self.hopper, "mc-hop")
return bound return bound
def setup_socket(self, srv: MC_Sck) -> None: def setup_socket(self, srv: MC_Sck) -> None:
@ -299,33 +300,55 @@ class MCast(object):
t = "failed to set IPv4 TTL/LOOP; announcements may not survive multiple switches/routers" t = "failed to set IPv4 TTL/LOOP; announcements may not survive multiple switches/routers"
self.log(t, 3) self.log(t, 3)
self.hop(srv) if self.hop(srv, False):
self.log("igmp was already joined?? chilling for a sec", 3)
time.sleep(1.2)
self.hop(srv, True)
self.b4.sort(reverse=True) self.b4.sort(reverse=True)
self.b6.sort(reverse=True) self.b6.sort(reverse=True)
def hop(self, srv: MC_Sck) -> None: def hop(self, srv: MC_Sck, on: bool) -> bool:
"""rejoin to keepalive on routers/switches without igmp-snooping""" """rejoin to keepalive on routers/switches without igmp-snooping"""
sck = srv.sck sck = srv.sck
req = srv.mreq req = srv.mreq
if ":" in srv.ip: if ":" in srv.ip:
try: if not on:
sck.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_LEAVE_GROUP, req) try:
# linux does leaves/joins twice with 0.2~1.05s spacing sck.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_LEAVE_GROUP, req)
time.sleep(1.2) return True
except: except:
pass return False
else:
sck.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, req) sck.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, req)
else: else:
try: if not on:
sck.setsockopt(socket.IPPROTO_IP, socket.IP_DROP_MEMBERSHIP, req) try:
time.sleep(1.2) sck.setsockopt(socket.IPPROTO_IP, socket.IP_DROP_MEMBERSHIP, req)
except: return True
pass except:
return False
else:
# t = "joining {} from ip {} idx {} with mreq {}"
# self.log(t.format(srv.grp, srv.ip, srv.idx, repr(srv.mreq)), 6)
sck.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, req)
# t = "joining {} from ip {} idx {} with mreq {}" return True
# self.log(t.format(srv.grp, srv.ip, srv.idx, repr(srv.mreq)), 6)
sck.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, req) def hopper(self):
while self.args.mc_hop and self.running:
time.sleep(self.args.mc_hop)
if not self.running:
return
for srv in self.srv.values():
self.hop(srv, False)
# linux does leaves/joins twice with 0.2~1.05s spacing
time.sleep(1.2)
for srv in self.srv.values():
self.hop(srv, True)
def map_client(self, cip: str) -> Optional[MC_Sck]: def map_client(self, cip: str) -> Optional[MC_Sck]:
try: try: