예제 #1
0
    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()
예제 #2
0
 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
예제 #3
0
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)
예제 #4
0
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)
예제 #5
0
    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
예제 #6
0
    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()
예제 #7
0
    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)
예제 #8
0
 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)