diff --git a/copyparty/__main__.py b/copyparty/__main__.py index 456cf0ed..bd53ef60 100755 --- a/copyparty/__main__.py +++ b/copyparty/__main__.py @@ -614,7 +614,7 @@ def run_argparse( ap2.add_argument("-mcr", metavar="SEC", type=int, default=60, help="md-editor mod-chk rate") ap2.add_argument("--urlform", metavar="MODE", type=u, default="print,get", help="how to handle url-form POSTs; see --help-urlform") ap2.add_argument("--wintitle", metavar="TXT", type=u, default="cpp @ $pub", help="window title, for example [\033[32m$ip-10.1.2.\033[0m] or [\033[32m$ip-]") - ap2.add_argument("--name", metavar="TXT", type=str, default=srvname, help="server name (displayed topleft in browser and in mDNS)") + ap2.add_argument("--name", metavar="TXT", type=u, default=srvname, help="server name (displayed topleft in browser and in mDNS)") ap2.add_argument("--license", action="store_true", help="show licenses and exit") ap2.add_argument("--version", action="store_true", help="show versions and exit") @@ -665,26 +665,32 @@ def run_argparse( ap2 = ap.add_argument_group("Zeroconf options") ap2.add_argument("-z", action="store_true", help="enable all zeroconf backends (mdns, ssdp)") + ap2.add_argument("--z-on", metavar="NICS/NETS", type=u, default="", help="enable zeroconf ONLY on the comma-separated list of subnets and/or interface names\n └─example: \033[32meth0, wlo1, virhost0, 192.168.123.0/24, fd00:fda::/96\033[0m") + ap2.add_argument("--z-off", metavar="NICS/NETS", type=u, default="", help="disable zeroconf on the comma-separated list of subnets and/or interface names") ap2.add_argument("-zv", action="store_true", help="verbose all zeroconf backends") ap2.add_argument("--mc-hop", metavar="SEC", type=int, default=0, help="rejoin multicast groups every SEC seconds (workaround for some switches/routers which cause mDNS to suddenly stop working after some time); try [\033[32m300\033[0m] or [\033[32m180\033[0m]") ap2 = ap.add_argument_group("Zeroconf-mDNS options:") ap2.add_argument("--zm", action="store_true", help="announce the enabled protocols over mDNS (multicast DNS-SD) -- compatible with KDE, gnome, macOS, ...") + ap2.add_argument("--zm-on", metavar="NICS/NETS", type=u, default="", help="enable zeroconf ONLY on the comma-separated list of subnets and/or interface names") + ap2.add_argument("--zm-off", metavar="NICS/NETS", type=u, default="", help="disable zeroconf on the comma-separated list of subnets and/or interface names") ap2.add_argument("--zm4", action="store_true", help="IPv4 only -- try this if some clients can't connect") ap2.add_argument("--zm6", action="store_true", help="IPv6 only") ap2.add_argument("--zmv", action="store_true", help="verbose mdns") ap2.add_argument("--zmvv", action="store_true", help="verboser mdns") - ap2.add_argument("--zms", metavar="dhf", type=str, default="", help="list of services to announce -- d=webdav h=http f=ftp s=smb -- lowercase=plaintext uppercase=TLS -- default: all enabled services except http/https (\033[32mDdfs\033[0m if \033[33m--ftp\033[0m and \033[33m--smb\033[0m is set)") - ap2.add_argument("--zm-ld", metavar="PATH", type=str, default="", help="link a specific folder for webdav shares") - ap2.add_argument("--zm-lh", metavar="PATH", type=str, default="", help="link a specific folder for http shares") - ap2.add_argument("--zm-lf", metavar="PATH", type=str, default="", help="link a specific folder for ftp shares") - ap2.add_argument("--zm-ls", metavar="PATH", type=str, default="", help="link a specific folder for smb shares") + ap2.add_argument("--zms", metavar="dhf", type=u, default="", help="list of services to announce -- d=webdav h=http f=ftp s=smb -- lowercase=plaintext uppercase=TLS -- default: all enabled services except http/https (\033[32mDdfs\033[0m if \033[33m--ftp\033[0m and \033[33m--smb\033[0m is set)") + ap2.add_argument("--zm-ld", metavar="PATH", type=u, default="", help="link a specific folder for webdav shares") + ap2.add_argument("--zm-lh", metavar="PATH", type=u, default="", help="link a specific folder for http shares") + ap2.add_argument("--zm-lf", metavar="PATH", type=u, default="", help="link a specific folder for ftp shares") + ap2.add_argument("--zm-ls", metavar="PATH", type=u, default="", help="link a specific folder for smb shares") ap2.add_argument("--zm-mnic", action="store_true", help="merge NICs which share subnets; assume that same subnet means same network") ap2.add_argument("--zm-msub", action="store_true", help="merge subnets on each NIC -- always enabled for ipv6 -- reduces network load, but gnome-gvfs clients may stop working") ap2.add_argument("--zm-noneg", action="store_true", help="disable NSEC replies -- try this if some clients don't see copyparty") ap2 = ap.add_argument_group("Zeroconf-SSDP options:") ap2.add_argument("--zs", action="store_true", help="announce the enabled protocols over SSDP -- compatible with Windows") + ap2.add_argument("--zs-on", metavar="NICS/NETS", type=u, default="", help="enable zeroconf ONLY on the comma-separated list of subnets and/or interface names") + ap2.add_argument("--zs-off", metavar="NICS/NETS", type=u, default="", help="disable zeroconf on the comma-separated list of subnets and/or interface names") ap2.add_argument("--zsv", action="store_true", help="verbose SSDP") ap2.add_argument("--zsl", metavar="PATH", type=u, default="", help="location to include in the url (or a complete external URL), for example [\033[32mpriv/?pw=hunter2\033[0m] or [\033[32mpriv/?pw=hunter2\033[0m]") ap2.add_argument("--zsid", metavar="UUID", type=u, default=uuid.uuid4().urn[4:], help="USN (device identifier) to announce") diff --git a/copyparty/mdns.py b/copyparty/mdns.py index 15b50c28..fcd2e7f5 100644 --- a/copyparty/mdns.py +++ b/copyparty/mdns.py @@ -60,9 +60,12 @@ class MDNS_Sck(MC_Sck): class MDNS(MCast): def __init__(self, hub: "SvcHub") -> None: - grp4 = "" if hub.args.zm6 else MDNS4 - grp6 = "" if hub.args.zm4 else MDNS6 - super(MDNS, self).__init__(hub, MDNS_Sck, grp4, grp6, 5353, hub.args.zmv) + al = hub.args + grp4 = "" if al.zm6 else MDNS4 + grp6 = "" if al.zm4 else MDNS6 + super(MDNS, self).__init__( + hub, MDNS_Sck, al.zm_on, al.zm_off, grp4, grp6, 5353, hub.args.zmv + ) self.srv: dict[socket.socket, MDNS_Sck] = {} self.ttl = 300 diff --git a/copyparty/multicast.py b/copyparty/multicast.py index f61a211b..46fc9d20 100644 --- a/copyparty/multicast.py +++ b/copyparty/multicast.py @@ -54,6 +54,8 @@ class MCast(object): self, hub: "SvcHub", Srv: type[MC_Sck], + on: list[str], + off: list[str], mc_grp_4: str, mc_grp_6: str, port: int, @@ -65,6 +67,8 @@ class MCast(object): self.args = hub.args self.asrv = hub.asrv self.log_func = hub.log + self.on = on + self.off = off self.grp4 = mc_grp_4 self.grp6 = mc_grp_6 self.port = port @@ -84,26 +88,37 @@ class MCast(object): def create_servers(self) -> list[str]: bound: list[str] = [] + netdevs = self.hub.tcpsrv.netdevs ips = [x[0] for x in self.hub.tcpsrv.bound] if "::" in ips: ips = [x for x in ips if x != "::"] + list( - [x.split("/")[0] for x in self.hub.tcpsrv.netdevs if ":" in x] + [x.split("/")[0] for x in netdevs if ":" in x] ) ips.append("0.0.0.0") if "0.0.0.0" in ips: ips = [x for x in ips if x != "0.0.0.0"] + list( - [x.split("/")[0] for x in self.hub.tcpsrv.netdevs if ":" not in x] + [x.split("/")[0] for x in netdevs if ":" not in x] ) ips = [x for x in ips if x not in ("::1", "127.0.0.1")] # ip -> ip/prefix - ips = [ - [x for x in self.hub.tcpsrv.netdevs if x.startswith(y + "/")][0] - for y in ips - ] + ips = [[x for x in netdevs if x.startswith(y + "/")][0] for y in ips] + + on = self.on[:] + off = self.off[:] + for lst in (on, off): + for av in list(lst): + for sk, sv in netdevs.items(): + if av == sv.split(",")[0] and sk not in lst: + lst.append(sk) + + if on: + ips = [x for x in ips if x in on] + elif off: + ips = [x for x in ips if x not in off] if not self.grp4: ips = [x for x in ips if ":" in x] @@ -124,7 +139,7 @@ class MCast(object): v6 = ":" in ip netdev = "?" try: - netdev = self.hub.tcpsrv.netdevs[ip].split(",")[0] + netdev = netdevs[ip].split(",")[0] idx = socket.if_nametoindex(netdev) except: idx = socket.INADDR_ANY @@ -145,7 +160,7 @@ class MCast(object): # add a/aaaa records for the other nic IPs other_ips: set[str] = set() if v6 and netdev not in ("?", ""): - for oip, onic in self.hub.tcpsrv.netdevs.items(): + for oip, onic in netdevs.items(): if ( onic.split(",")[0] == netdev and oip in all_selected diff --git a/copyparty/ssdp.py b/copyparty/ssdp.py index 0fa7511f..3f536c07 100644 --- a/copyparty/ssdp.py +++ b/copyparty/ssdp.py @@ -88,8 +88,11 @@ class SSDPd(MCast): """communicates with ssdp clients over multicast""" def __init__(self, hub: "SvcHub") -> None: - vinit = hub.args.zsv and not hub.args.zmv - super(SSDPd, self).__init__(hub, SSDP_Sck, GRP, "", 1900, vinit) + al = hub.args + vinit = al.zsv and not al.zmv + super(SSDPd, self).__init__( + hub, SSDP_Sck, al.zs_on, al.zs_off, GRP, "", 1900, vinit + ) self.srv: dict[socket.socket, SSDP_Sck] = {} self.rxc = CachedSet(0.7) self.txc = CachedSet(5) # win10: every 3 sec diff --git a/copyparty/svchub.py b/copyparty/svchub.py index 13defa0e..3eaadeae 100644 --- a/copyparty/svchub.py +++ b/copyparty/svchub.py @@ -289,12 +289,22 @@ class SvcHub(object): Daemon(self.sd_notify, "sd-notify") def _process_config(self) -> bool: - if self.args.loris1 == "no": - self.args.loris1 = "0,0" + al = self.args + if al.loris1 == "no": + al.loris1 = "0,0" - i1, i2 = self.args.loris1.split(",") - self.args.loris1w = int(i1) - self.args.loris1b = int(i2) + i1, i2 = al.loris1.split(",") + al.loris1w = int(i1) + al.loris1b = int(i2) + + al.zm_on = al.zm_on or al.z_on + al.zs_on = al.zs_on or al.z_on + al.zm_off = al.zm_off or al.z_off + al.zs_off = al.zs_off or al.z_off + for n in ("zm_on", "zm_off", "zs_on", "zs_off"): + vs = getattr(al, n).replace(" ", ",").split(",") + vs = [x for x in vs if x] + setattr(al, n, vs) return True