def dnssd_search(stype='_http._tcp'): dnssd = zeroconf.search(name=None, type=stype, domain="local") for key in dnssd: inst_type = key[1] # <Instance> must be a single DNS label, any dots should be escaped before concatenating # all portions of a Service Instance Name, according to DNS-SD (RFC6763). # A workaround is necessary for buggy software that does not adhere to the rules: inst_name = re.sub(r'(?<!\\)\.', r'\.', key[0]) inst_fullname = dns.name.from_text(inst_name + '.' + inst_type).to_text(omit_final_dot=True) try: inst_hostname_rev_rr = dns.resolver.query(dns.reversename.from_address(dnssd[key]['address']), 'PTR') except DNSException, e: continue dnssd[key]['hostname_rev'] = [i.to_text(relativize=False) for i in inst_hostname_rev_rr] inst_port = dnssd[key]['port'] inst_txt_rdata_rev = re.split(r'(?<=")\s+(?=")', dnssd[key]['txt'])[::-1] if not len(dnssd[key]['hostname_rev']) > 0: continue print "%-100s %-3s %-30s" % (inst_type, 'PTR', inst_fullname) for h in dnssd[key]['hostname_rev']: # replace hostname.local with reverse-resolved fqdn in TXT rdata inst_txt_rdata_rev_host = [ re.sub(r'%s\.?' % dnssd[key]['hostname'], r'%s' % h.rstrip('.'), blob) for blob in inst_txt_rdata_rev ] inst_txt_rdata_rev_host = ' '.join(inst_txt_rdata_rev_host) print "%-100s %-3s %2d %2d %-5s %-50s" % (inst_fullname, 'SRV', 0, 0, inst_port, h) if (dnssd[key]['txt'] != ''): print "%-100s %-3s %s" % (inst_fullname, 'TXT', inst_txt_rdata_rev_host)
def zeroconf_search_multi(name=None, types=[None], domains=['local'], sed_pattern=None, sed_repl=None, sed_service=[None]): import zeroconf default_subtypes = { '_ipp._tcp': ['_universal._sub._ipp._tcp', '_cups._sub._ipp._tcp'], '_ipps._tcp': ['_universal._sub._ipps._tcp', '_cups._sub._ipps._tcp'], '_http._tcp': ['_printer._sub._http._tcp'] } types = set(types) domains = set(domains) # special handling for subtypes: they are not queried through _services # enumeration and we can not tell them apart in responses from the # corresponding master service) subtypes_all = { type for type in types if isinstance(type, basestring) and len(re.split(r'(?<!\\)\.', type)) > 3 and re.split(r'(?<!\\)\.', type)[-3] == '_sub' } types -= subtypes_all # enumerate for well known sub-types if the master is requested for k in default_subtypes: if k in types: subtypes_all.update(default_subtypes[k]) # but also enumerate the master if a sub-type is requested else: types |= {k for i in default_subtypes[k] if i in subtypes_all} filter_types = set() stype = None if len(types) > 1: filter_types = types elif types: stype = types.pop() results_all = {} for domain in domains: results = zeroconf.search(name=name, type=stype, domain=domain) subtypes = subtypes_all # add default subtypes to subtypes to be enumerated if the master is # found in results for subt_key in default_subtypes: if subt_key in [res_key[1] for res_key in results.keys()]: subtypes.update(default_subtypes[subt_key]) # enumerate for each subtype individually for subtype in subtypes: for (key, val) in zeroconf.search(name=name, type=subtype, domain=domain).items(): subtype = re.sub(r'._sub.%s' % key[1], '', subtype) # record in results for master type, add subtype if key in results and \ {k: results[key][k] for k in results[key] if k != 'subtypes'} == val: if 'subtypes' in results[key]: results[key]['subtypes'].append(subtype) else: results[key]['subtypes'] = [subtype] # no record in results for master type, add record and subtype else: results.update({key: val}) results[key]['subtypes'] = [subtype] results_all.update(results) if filter_types: for key in results_all.keys(): _, svc_, _ = key if not svc_ in filter_types and \ not svc_ in subtypes: del results_all[key] for key in results_all.keys(): name_, svc_, dom_ = key displayname = name_ if sed_pattern is not None and sed_repl is not None: if sed_service != [None] and svc_ in sed_service: # newname = re.sub(r'^(.+)( @ cups)', r'AirPrint: \g<1>', # name_) displayname = re.sub(r'%s' % sed_pattern, r'%s' % sed_repl, name_) results_all[(displayname, svc_, dom_, name_)] = results_all[key] del results_all[key] return results_all # if len(results) > 0 else None
import zeroconf import json import sys svc_list = [] hostname = {} services = zeroconf.search(domain="local") if len(services) is 0: print "No device found" sys.exit(0) for host in services.items(): if str(host[1]['hostname']) not in hostname: data = {} extra = {} port = [] serv_type = [] data['hostname'] = str(host[1]['hostname']) data['name'] = str(host[0][0]) data['address'] = str(host[1]['address']) extra['type'] = str(host[0][1]) extra['port'] = str(host[1]['port']) data['extra'] = extra hostname[str(host[1]['hostname'])] = data else: extra = hostname[str(host[1]['hostname'])]['extra'] extra['type'] += ", " + str(host[0][1]) extra['port'] += ", " + str(host[1]['port']) hostname[str(host[1]['hostname'])]['extra'] = extra
def __iter__(self): for name, type, domain in zeroconf.search(type="_rc._tcp"): yield (name, get(name))
def __init__(self, name): service_info = zeroconf.search(name, "_rc._tcp").items()[0][1] self.socket = context.socket(zmq.REQ) self.socket.connect("tcp://{address}:{port}".format(**service_info))
def zeroconf_search_multi(name=None, types=[None], domains=['local'], sed_pattern=None, sed_repl=None, sed_service=[None]): import zeroconf default_subtypes = {'_ipp._tcp': ['_universal._sub._ipp._tcp', '_cups._sub._ipp._tcp'], '_ipps._tcp': ['_universal._sub._ipps._tcp', '_cups._sub._ipps._tcp'], '_http._tcp': ['_printer._sub._http._tcp'] } types = set(types) domains = set(domains) # special handling for subtypes: they are not queried through _services # enumeration and we can not tell them apart in responses from the # corresponding master service) subtypes_all = {type for type in types if isinstance(type, basestring) and len(re.split(r'(?<!\\)\.', type)) > 3 and re.split(r'(?<!\\)\.', type)[-3] == '_sub'} types -= subtypes_all # enumerate for well known sub-types if the master is requested for k in default_subtypes: if k in types: subtypes_all.update(default_subtypes[k]) # but also enumerate the master if a sub-type is requested else: types |= {k for i in default_subtypes[k] if i in subtypes_all} filter_types = set() stype = None if len(types) > 1: filter_types = types elif types: stype = types.pop() results_all = {} for domain in domains: results = zeroconf.search(name=name, type=stype, domain=domain) subtypes = subtypes_all # add default subtypes to subtypes to be enumerated if the master is # found in results for subt_key in default_subtypes: if subt_key in [res_key[1] for res_key in results.keys()]: subtypes.update(default_subtypes[subt_key]) # enumerate for each subtype individually for subtype in subtypes: for (key, val) in zeroconf.search(name=name, type=subtype, domain=domain).items(): subtype = re.sub(r'._sub.%s' % key[1], '', subtype) # record in results for master type, add subtype if key in results and \ {k: results[key][k] for k in results[key] if k != 'subtypes'} == val: if 'subtypes' in results[key]: results[key]['subtypes'].append(subtype) else: results[key]['subtypes'] = [subtype] # no record in results for master type, add record and subtype else: results.update({key: val}) results[key]['subtypes'] = [subtype] results_all.update(results) if filter_types: for key in results_all.keys(): _, svc_, _ = key if not svc_ in filter_types and \ not svc_ in subtypes: del results_all[key] for key in results_all.keys(): name_, svc_, dom_ = key displayname = name_ if sed_pattern is not None and sed_repl is not None: if sed_service != [None] and svc_ in sed_service: # newname = re.sub(r'^(.+)( @ cups)', r'AirPrint: \g<1>', # name_) displayname = re.sub(r'%s' % sed_pattern, r'%s' % sed_repl, name_) results_all[(displayname, svc_, dom_, name_)] = results_all[key] del results_all[key] return results_all # if len(results) > 0 else None