def _browse_callback(self, _sdref, flags, interface, error_code, service_name, regtype, reply_domain): log.debug('Found service %s in domain %s on %i(type: %s).', service_name, reply_domain, interface, regtype) if not self.connected: return if error_code != kDNSServiceErr_NoError: log.debug('Error in browse_callback: %s', str(error_code)) return if not flags & kDNSServiceFlagsAdd: self._remove_service_callback(service_name) return try: # asynchronous resolving resolve_sdref = None resolve_sdref = DNSServiceResolve(0, interface, service_name, regtype, reply_domain, self._service_resolved_callback) while not self._resolved: ready = select.select([resolve_sdref], [], [], resolve_timeout) if resolve_sdref not in ready[0]: log.info('Resolve timed out') break DNSServiceProcessResult(resolve_sdref) else: self._resolved.pop() except BonjourError as error: log.info('Error when resolving DNS: %s', error) finally: if resolve_sdref: resolve_sdref.close()
def browse_loop(self): try: ready = select.select([self._browse_sdref], [], [], 0) if self._browse_sdref in ready[0]: DNSServiceProcessResult(self._browse_sdref) except BonjourError as error: if error.errorCode == kDNSServiceErr_ServiceNotRunning: log.info('Service not running') return False log.error('Error while browsing for services. %s', error) return True
def fetch_bonjour(_service, alias='Bonjour', timeout=0.1): cache = path.join(alfred.work(volatile=True), 'bonjour.1.json') if path.isfile(cache) and (time() - path.getmtime(cache) < 60): return (json.load(open(cache, 'r')), alias) results = set() try: from pybonjour import DNSServiceBrowse, DNSServiceProcessResult from select import select bj_callback = lambda s, f, i, e, n, t, d: results.add('%s.%s' % ( n.lower(), d[:-1])) bj_browser = DNSServiceBrowse(regtype=_service, callBack=bj_callback) select([bj_browser], [], [], timeout) DNSServiceProcessResult(bj_browser) bj_browser.close() except ImportError: pass json.dump(list(results), open(cache, 'w')) return (results, alias)
def fetch_bonjour(_service='_ssh._tcp', alias='Bonjour', timeout=0.1): if int(os.getenv('alfredssh_bonjour', 1)) != 1: return (alias, ()) cache = cache_file('bonjour.1.json') if os.path.isfile(cache) and (time() - os.path.getmtime(cache) < 60): return (alias, json.load(open(cache, 'r'))) results = set() try: from pybonjour import DNSServiceBrowse, DNSServiceProcessResult from select import select bj_callback = lambda s, f, i, e, n, t, d: results.add('{}.{}'.format(n.lower(), d[:-1])) bj_browser = DNSServiceBrowse(regtype=_service, callBack=bj_callback) select([bj_browser], [], [], timeout) DNSServiceProcessResult(bj_browser) bj_browser.close() except ImportError: pass json.dump(list(results), open(cache, 'w')) return (alias, results)
def resolve_all(self): if not self.connected: return False # for now put here as this is synchronous if not self.browse_loop(): return False # Monitor TXT Records with DNSServiceQueryRecord because # its more efficient (see pybonjour documentation) for val in self._contacts.values(): bare_name = val[Constant.RESOLVED_INFO][0][Constant.BARE_NAME] try: query_sdref = None query_sdref = \ DNSServiceQueryRecord( interfaceIndex=kDNSServiceInterfaceIndexAny, fullname=bare_name, rrtype=kDNSServiceType_TXT, callBack=self._query_txt_callback) while not self._queried: ready = select.select([query_sdref], [], [], resolve_timeout) if query_sdref not in ready[0]: log.info('Query record timed out') break DNSServiceProcessResult(query_sdref) else: self._queried.pop() except BonjourError as error: if error.errorCode == kDNSServiceErr_ServiceNotRunning: log.info('Service not running') return False log.error('Error in query for TXT records. %s', error) finally: if query_sdref: query_sdref.close() return True
def _create_service(self): txt = {} # remove empty keys for key, val in self.txt.items(): if val: txt[key] = val txt['port.p2pj'] = self.port txt['version'] = 1 txt['txtvers'] = 1 # replace gajim's show messages with compatible ones if 'status' in self.txt: txt['status'] = self._replace_show(self.txt['status']) else: txt['status'] = 'avail' self.txt = txt try: self._service_sdref = DNSServiceRegister( flags=kDNSServiceFlagsNoAutoRename, name=self.name, regtype=self.stype, port=self.port, txtRecord=TXTRecord(self.txt, strict=True), callBack=self.service_added_callback) log.info('Publishing service %s of type %s', self.name, self.stype) ready = select.select([self._service_sdref], [], []) if self._service_sdref in ready[0]: DNSServiceProcessResult(self._service_sdref) except BonjourError as error: if error.errorCode == kDNSServiceErr_ServiceNotRunning: log.info('Service not running') else: self._error_cb(_('Error while adding service. %s') % error) self.disconnect()
def _service_resolved_callback(self, _sdref, _flags, interface, error_code, fullname, hosttarget, port, txt_record): if error_code != kDNSServiceErr_NoError: log.error('Error in service_resolved_callback: %s', str(error_code)) return self._resolved_hosts[hosttarget] = (fullname, port, txt_record) try: getaddrinfo_sdref = \ DNSServiceGetAddrInfo( interfaceIndex=interface, hostname=hosttarget, callBack=self._getaddrinfo_callback) while not self._queried: ready = select.select([getaddrinfo_sdref], [], [], resolve_timeout) if getaddrinfo_sdref not in ready[0]: log.warning('GetAddrInfo timed out') break DNSServiceProcessResult(getaddrinfo_sdref) else: self._queried.pop() except BonjourError as error: if error.error_code == kDNSServiceErr_ServiceNotRunning: log.info('Service not running') else: self._error_cb(_('Error while adding service. %s') % error) finally: if getaddrinfo_sdref: getaddrinfo_sdref.close() self._resolved.append(True)
def wait_on_event(self, sdRef, event): while not event.isSet(): ready = select.select([sdRef], [], [], self.timeout) self.assertTrue(sdRef in ready[0], 'operation timed out') DNSServiceProcessResult(sdRef)