Beispiel #1
0
def test_integration():
    service_added = Event()
    service_removed = Event()

    type_ = "_http._tcp.local."
    registration_name = "xxxyyy.%s" % type_

    def on_service_state_change(zeroconf, service_type, state_change, name):
        if name == registration_name:
            if state_change is ServiceStateChange.Added:
                service_added.set()
            elif state_change is ServiceStateChange.Removed:
                service_removed.set()

    zeroconf_browser = Zeroconf()
    browser = ServiceBrowser(zeroconf_browser, type_, [on_service_state_change])

    zeroconf_registrar = Zeroconf()
    desc = {'path': '/~paulsm/'}
    info = ServiceInfo(
        type_, registration_name,
        socket.inet_aton("10.0.1.2"), 80, 0, 0,
        desc, "ash-2.local.")
    zeroconf_registrar.register_service(info)

    try:
        service_added.wait(1)
        assert service_added.is_set()
        # Don't remove service, allow close() to cleanup

    finally:
        zeroconf_registrar.close()
        browser.cancel()
        zeroconf_browser.close()
def test_integration():
    service_added = Event()
    service_removed = Event()

    type_ = "_http._tcp.local."
    registration_name = "xxxyyy.%s" % type_

    class MyListener(object):

        def remove_service(self, zeroconf, type_, name):
            if name == registration_name:
                service_removed.set()

        def add_service(self, zeroconf, type_, name):
            if name == registration_name:
                service_added.set()

    zeroconf_browser = Zeroconf()
    listener = MyListener()
    browser = ServiceBrowser(zeroconf_browser, type_, listener)

    zeroconf_registrar = Zeroconf()
    desc = {'path': '/~paulsm/'}
    info = ServiceInfo(
        type_, registration_name,
        socket.inet_aton("10.0.1.2"), 80, 0, 0,
        desc, "ash-2.local.")
    zeroconf_registrar.register_service(info)

    try:
        service_added.wait(1)
        assert service_added.is_set()
        zeroconf_registrar.unregister_service(info)
        service_removed.wait(1)
        assert service_removed.is_set()
    finally:
        zeroconf_registrar.close()
        browser.cancel()
        zeroconf_browser.close()
Beispiel #3
0
def discover_chromecasts(max_devices=None, timeout=DISCOVER_TIMEOUT):
    """ Discover chromecasts on the network. """
    try:
        zconf = Zeroconf()
        listener = CastListener()
        browser = ServiceBrowser(zconf, "_googlecast._tcp.local.", listener)

        if max_devices is None:
            time.sleep(timeout)
            return listener.devices

        else:
            start = time.time()

            while (time.time() - start < timeout and
                   listener.count < max_devices):
                time.sleep(.1)

            return listener.devices
    finally:
        browser.cancel()
        zconf.close()
Beispiel #4
0
def discover_chromecasts(max_devices=None, timeout=DISCOVER_TIMEOUT):
    try:
        zconf = Zeroconf()
        listener = CastListener()
        browser = ServiceBrowser(zconf, "_googlecast._tcp.local.", listener)

        t = 0

        if max_devices is None:
            time.sleep(DISCOVER_TIMEOUT)
            return listener.devices

        else:
            while t < DISCOVER_TIMEOUT:
                time.sleep(.1)

                if listener.count >= max_devices:
                    return listener.devices

            return listener.devices
    finally:
        browser.cancel()
        zconf.close()
Beispiel #5
0

@app.route('/LED', methods=['GET'])
@auth.login_required
def get_color():
    if (LEDOK):
        com = request.args.get('command', '')
        if (com == ''):
            return "bad request"
        else:
            comarr = com.split('-')
            if (len(comarr) == 3):
                status = comarr[0]
                color = comarr[1]
                intensity = comarr[2]
                url = "http://pumpkin-pi.local:8081/LED?status=" + status + "&color=" + color + "&intensity=" + intensity
                r = req.get(url)
                return "Sending"

            else:
                return "bad request"
    else:
        return "Haven't found LED Pi"


if __name__ == '__main__':
    zeroconf = Zeroconf()
    listener = MyListener()
    browser = ServiceBrowser(zeroconf, "_http._tcp.local.", listener)
    app.run(debug=True, port="8081", host='0.0.0.0')
Beispiel #6
0
def discover_homekit_devices(max_seconds=10):
    """
    This method discovers all HomeKit Accessories. It browses for devices in the _hap._tcp.local. domain and checks if
    all required fields are set in the text record. It one field is missing, it will be excluded from the result list.

    :param max_seconds: the number of seconds we will wait for the devices to be discovered
    :return: a list of dicts containing all fields as described in table 5.7 page 69
    """
    zeroconf = Zeroconf()
    listener = CollectingListener()
    ServiceBrowser(zeroconf, '_hap._tcp.local.', listener)
    sleep(max_seconds)
    tmp = []
    for info in listener.get_data():
        # from Bonjour discovery
        d = {
            'name': info.name,
            'address': inet_ntoa(info.address),
            'port': info.port
        }

        props = info.properties

        # stuff taken from the Bonjour TXT record (see table 5-7 on page 69)
        conf_number = get_from_properties(props, b'c#', case_sensitive=False)
        if conf_number:
            d['c#'] = conf_number
        else:
            continue

        ff = get_from_properties(props, b'ff', case_sensitive=False)
        if ff:
            flags = int(ff)
        else:
            flags = 0
        d['ff'] = flags
#        d['flags'] = FeatureFlags[flags]

        id = get_from_properties(props, b'id', case_sensitive=False)
        if id:
            d['id'] = id

        md = get_from_properties(props, b'md', case_sensitive=False)
        if md:
            d['md'] = md
        else:
            continue

        pv = get_from_properties(props, b'pv', case_sensitive=False, default='1.0')
        if pv:
            d['pv'] = pv

        s = get_from_properties(props, b's#', case_sensitive=False)
        if s:
            d['s#'] = s

        sf = get_from_properties(props, b'sf', case_sensitive=False)
        if sf:
            d['sf'] = sf
        d['statusflags'] = IpStatusFlags[int(sf)]

        ci = get_from_properties(props, b'ci', case_sensitive=False)
        if ci:
            category = info.properties[b'ci'].decode()
            d['ci'] = category
            d['category'] = Categories[int(category)]

        # append device, it has all data
        tmp.append(d)

    zeroconf.close()
    return tmp
Beispiel #7
0
def setup(hass, config):
    """Set up Zeroconf and make Home Assistant discoverable."""
    zeroconf = Zeroconf()
    zeroconf_name = f"{hass.config.location_name}.{ZEROCONF_TYPE}"

    params = {
        "version": __version__,
        "base_url": hass.config.api.base_url,
        # always needs authentication
        "requires_api_password": True,
    }

    host_ip = util.get_local_ip()

    try:
        host_ip_pton = socket.inet_pton(socket.AF_INET, host_ip)
    except socket.error:
        host_ip_pton = socket.inet_pton(socket.AF_INET6, host_ip)

    info = ServiceInfo(
        ZEROCONF_TYPE,
        zeroconf_name,
        None,
        addresses=[host_ip_pton],
        port=hass.http.server_port,
        properties=params,
    )

    def zeroconf_hass_start(_event):
        """Expose Home Assistant on zeroconf when it starts.

        Wait till started or otherwise HTTP is not up and running.
        """
        _LOGGER.info("Starting Zeroconf broadcast")
        zeroconf.register_service(info)

    hass.bus.listen_once(EVENT_HOMEASSISTANT_START, zeroconf_hass_start)

    def service_update(zeroconf, service_type, name, state_change):
        """Service state changed."""
        if state_change != ServiceStateChange.Added:
            return

        service_info = zeroconf.get_service_info(service_type, name)
        info = info_from_service(service_info)
        _LOGGER.debug("Discovered new device %s %s", name, info)

        # If we can handle it as a HomeKit discovery, we do that here.
        if service_type == HOMEKIT_TYPE and handle_homekit(hass, info):
            return

        for domain in ZEROCONF[service_type]:
            hass.add_job(
                hass.config_entries.flow.async_init(domain,
                                                    context={"source": DOMAIN},
                                                    data=info))

    for service in ZEROCONF:
        ServiceBrowser(zeroconf, service, handlers=[service_update])

    if HOMEKIT_TYPE not in ZEROCONF:
        ServiceBrowser(zeroconf, HOMEKIT_TYPE, handlers=[service_update])

    def stop_zeroconf(_):
        """Stop Zeroconf."""
        zeroconf.unregister_service(info)
        zeroconf.close()

    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zeroconf)

    return True
Beispiel #8
0
            ServiceInfo(
                type='_sciabc._tcp.local.',
                name='SupercomputerInABriefcase on tom-xps._sciabc._tcp.local.',
                address=b'\n\xb7\xcd\xb6',
                port=34343,
                weight=0,
                priority=0,
                server='tom-xps.local.',
                properties={}
            )
        """
        info = zeroconf.get_service_info(type, name)
        print("Service %s added, service info: %s" % (name, info))
        ip = ipaddress.ip_address(info.address)
        append_ip_to_nodes_file(str(ip))


if __name__ == '__main__':
    zeroconf = Zeroconf()
    listener = MyListener()
    browser = ServiceBrowser(zeroconf, "_sciabc._tcp.local.", listener)

    reset_nodes_file()

    try:
        input("Press Ctrl-C to exit...\n\n")
    except KeyboardInterrupt:
        print('Exiting.')
    finally:
        zeroconf.close()
 def start(self):
     # Use self as the listener class because I have add_service and remove_service methods
     self.browser = ServiceBrowser(self._zeroconf, self._service_type, self)
import sys
from zeroconf import ServiceBrowser, Zeroconf

class MyListener:

    def remove_service(self, zeroconf, type, name):
        print("Service %s removed" % (name,))

    def add_service(self, zeroconf, type, name):
        info = zeroconf.get_service_info(type, name)
        print("Service %s added, service info: %s" % (name, info))

try:
    arg = sys.argv[1]
except IndexError:
    raise SystemExit("Usage: {sys.argv[0]} <service to browse>")

zeroconf = Zeroconf()
listener = MyListener()
browser = ServiceBrowser(zeroconf, arg, listener)
try:
    input("Press enter to exit...\n\n")
finally:
    zeroconf.close()
def test_integration():
    service_added = Event()
    service_removed = Event()
    unexpected_ttl = Event()
    got_query = Event()

    type_ = "_http._tcp.local."
    registration_name = "xxxyyy.%s" % type_

    def on_service_state_change(zeroconf, service_type, state_change, name):
        if name == registration_name:
            if state_change is ServiceStateChange.Added:
                service_added.set()
            elif state_change is ServiceStateChange.Removed:
                service_removed.set()

    zeroconf_browser = Zeroconf(interfaces=['127.0.0.1'])

    # we are going to monkey patch the zeroconf send to check packet sizes
    old_send = zeroconf_browser.send

    time_offset = 0

    def current_time_millis():
        """Current system time in milliseconds"""
        return time.time() * 1000 + time_offset * 1000

    expected_ttl = r._DNS_TTL

    # needs to be a list so that we can modify it in our phony send
    nbr_queries = [0, None]

    def send(out, addr=r._MDNS_ADDR, port=r._MDNS_PORT):
        """Sends an outgoing packet."""
        pout = r.DNSIncoming(out.packet())

        for answer in pout.answers:
            nbr_queries[0] += 1
            if not answer.ttl > expected_ttl / 2:
                unexpected_ttl.set()

        got_query.set()
        old_send(out, addr=addr, port=port)

    # monkey patch the zeroconf send
    zeroconf_browser.send = send

    # monkey patch the zeroconf current_time_millis
    r.current_time_millis = current_time_millis

    service_added = Event()
    service_removed = Event()

    browser = ServiceBrowser(zeroconf_browser, type_,
                             [on_service_state_change])

    zeroconf_registrar = Zeroconf(interfaces=['127.0.0.1'])
    desc = {'path': '/~paulsm/'}
    info = ServiceInfo(type_, registration_name, socket.inet_aton("10.0.1.2"),
                       80, 0, 0, desc, "ash-2.local.")
    zeroconf_registrar.register_service(info)

    try:
        service_added.wait(1)
        assert service_added.is_set()

        sleep_count = 0
        while nbr_queries[0] < 50:
            time_offset += expected_ttl / 4
            zeroconf_browser.notify_all()
            sleep_count += 1
            got_query.wait(1)
            got_query.clear()
        assert not unexpected_ttl.is_set()

        # Don't remove service, allow close() to cleanup

    finally:
        zeroconf_registrar.close()
        browser.cancel()
        zeroconf_browser.close()
Beispiel #12
0
 def find_servers(self, timeout=AUTO_DISCOVERY_WAIT):
     log.info('searching for game servers')
     service_browser = ServiceBrowser(Zeroconf(), '%s.local.' % AUTO_DISCOVERY_TYPE, self)
     service_browser.join(timeout=timeout)
     return self.servers
Beispiel #13
0
class ZeroConfClient:

    # The discovery protocol name for Ultimaker printers.
    ZERO_CONF_NAME = u"_ultimaker._tcp.local."

    # Signals emitted when new services were discovered or removed on the network.
    addedNetworkCluster = Signal()
    removedNetworkCluster = Signal()

    def __init__(self) -> None:
        self._zero_conf = None  # type: Optional[Zeroconf]
        self._zero_conf_browser = None  # type: Optional[ServiceBrowser]
        self._service_changed_request_queue = None  # type: Optional[Queue]
        self._service_changed_request_event = None  # type: Optional[Event]
        self._service_changed_request_thread = None  # type: Optional[Thread]

    ## The ZeroConf service changed requests are handled in a separate thread so we don't block the UI.
    #  We can also re-schedule the requests when they fail to get detailed service info.
    #  Any new or re-reschedule requests will be appended to the request queue and the thread will process them.
    def start(self) -> None:
        self._service_changed_request_queue = Queue()
        self._service_changed_request_event = Event()
        self._service_changed_request_thread = Thread(
            target=self._handleOnServiceChangedRequests, daemon=True)
        self._service_changed_request_thread.start()
        self._zero_conf = Zeroconf()
        self._zero_conf_browser = ServiceBrowser(self._zero_conf,
                                                 self.ZERO_CONF_NAME,
                                                 [self._queueService])

    # Cleanup ZeroConf resources.
    def stop(self) -> None:
        if self._zero_conf is not None:
            self._zero_conf.close()
            self._zero_conf = None
        if self._zero_conf_browser is not None:
            self._zero_conf_browser.cancel()
            self._zero_conf_browser = None

    ## Handles a change is discovered network services.
    def _queueService(self, zeroconf: Zeroconf, service_type, name: str,
                      state_change: ServiceStateChange) -> None:
        item = (zeroconf, service_type, name, state_change)
        if not self._service_changed_request_queue or not self._service_changed_request_event:
            return
        self._service_changed_request_queue.put(item)
        self._service_changed_request_event.set()

    ## Callback for when a ZeroConf service has changes.
    def _handleOnServiceChangedRequests(self) -> None:
        if not self._service_changed_request_queue or not self._service_changed_request_event:
            return

        while True:
            # Wait for the event to be set
            self._service_changed_request_event.wait(timeout=5.0)

            # Stop if the application is shutting down
            if CuraApplication.getInstance().isShuttingDown():
                return

            self._service_changed_request_event.clear()

            # Handle all pending requests
            reschedule_requests = [
            ]  # A list of requests that have failed so later they will get re-scheduled
            while not self._service_changed_request_queue.empty():
                request = self._service_changed_request_queue.get()
                zeroconf, service_type, name, state_change = request
                try:
                    result = self._onServiceChanged(zeroconf, service_type,
                                                    name, state_change)
                    if not result:
                        reschedule_requests.append(request)
                except Exception:
                    Logger.logException(
                        "e",
                        "Failed to get service info for [%s] [%s], the request will be rescheduled",
                        service_type, name)
                    reschedule_requests.append(request)

            # Re-schedule the failed requests if any
            if reschedule_requests:
                for request in reschedule_requests:
                    self._service_changed_request_queue.put(request)

    ##  Handler for zeroConf detection.
    #   Return True or False indicating if the process succeeded.
    #   Note that this function can take over 3 seconds to complete. Be careful calling it from the main thread.
    def _onServiceChanged(self, zero_conf: Zeroconf, service_type: str,
                          name: str, state_change: ServiceStateChange) -> bool:
        if state_change == ServiceStateChange.Added:
            return self._onServiceAdded(zero_conf, service_type, name)
        elif state_change == ServiceStateChange.Removed:
            return self._onServiceRemoved(name)
        return True

    ## Handler for when a ZeroConf service was added.
    def _onServiceAdded(self, zero_conf: Zeroconf, service_type: str,
                        name: str) -> bool:
        # First try getting info from zero-conf cache
        info = ServiceInfo(service_type, name, properties={})
        for record in zero_conf.cache.entries_with_name(name.lower()):
            info.update_record(zero_conf, time(), record)

        for record in zero_conf.cache.entries_with_name(info.server):
            info.update_record(zero_conf, time(), record)
            if info.address:
                break

        # Request more data if info is not complete
        if not info.address:
            info = zero_conf.get_service_info(service_type, name)

        if info:
            type_of_device = info.properties.get(b"type", None)
            if type_of_device:
                if type_of_device == b"printer":
                    address = '.'.join(map(lambda n: str(n), info.address))
                    self.addedNetworkCluster.emit(str(name), address,
                                                  info.properties)
                else:
                    Logger.log(
                        "w",
                        "The type of the found device is '%s', not 'printer'."
                        % type_of_device)
        else:
            Logger.log("w", "Could not get information about %s" % name)
            return False

        return True

    ## Handler for when a ZeroConf service was removed.
    def _onServiceRemoved(self, name: str) -> bool:
        Logger.log("d", "ZeroConf service removed: %s" % name)
        self.removedNetworkCluster.emit(str(name))
        return True
    def test_lots_of_names(self):

        # instantiate a zeroconf instance
        zc = Zeroconf(interfaces=['127.0.0.1'])

        # create a bunch of servers
        type_ = "_my-service._tcp.local."
        name = 'a wonderful service'
        server_count = 300
        self.generate_many_hosts(zc, type_, name, server_count)

        # verify that name changing works
        self.verify_name_change(zc, type_, name, server_count)

        # we are going to monkey patch the zeroconf send to check packet sizes
        old_send = zc.send

        # needs to be a list so that we can modify it in our phony send
        longest_packet = [0, None]

        def send(out, addr=r._MDNS_ADDR, port=r._MDNS_PORT):
            """Sends an outgoing packet."""
            packet = out.packet()
            if longest_packet[0] < len(packet):
                longest_packet[0] = len(packet)
                longest_packet[1] = out
            old_send(out, addr=addr, port=port)

        # monkey patch the zeroconf send
        zc.send = send

        # dummy service callback
        def on_service_state_change(zeroconf, service_type, state_change,
                                    name):
            pass

        # start a browser
        browser = ServiceBrowser(zc, type_, [on_service_state_change])

        # wait until the browse request packet has maxed out in size
        sleep_count = 0
        while sleep_count < 100 and \
                longest_packet[0] < r._MAX_MSG_ABSOLUTE - 100:
            sleep_count += 1
            time.sleep(0.1)

        browser.cancel()
        time.sleep(0.5)

        import zeroconf
        zeroconf.log.debug('sleep_count %d, sized %d', sleep_count,
                           longest_packet[0])

        # now the browser has sent at least one request, verify the size
        assert longest_packet[0] <= r._MAX_MSG_ABSOLUTE
        assert longest_packet[0] >= r._MAX_MSG_ABSOLUTE - 100

        # mock zeroconf's logger warning() and debug()
        from unittest.mock import patch
        patch_warn = patch('zeroconf.log.warning')
        patch_debug = patch('zeroconf.log.debug')
        mocked_log_warn = patch_warn.start()
        mocked_log_debug = patch_debug.start()

        # now that we have a long packet in our possession, let's verify the
        # exception handling.
        out = longest_packet[1]
        out.data.append(b'\0' * 1000)

        # mock the zeroconf logger and check for the correct logging backoff
        call_counts = mocked_log_warn.call_count, mocked_log_debug.call_count
        # try to send an oversized packet
        zc.send(out)
        assert mocked_log_warn.call_count == call_counts[0] + 1
        assert mocked_log_debug.call_count == call_counts[0]
        zc.send(out)
        assert mocked_log_warn.call_count == call_counts[0] + 1
        assert mocked_log_debug.call_count == call_counts[0] + 1

        # force a receive of an oversized packet
        packet = out.packet()
        s = zc._respond_sockets[0]

        # mock the zeroconf logger and check for the correct logging backoff
        call_counts = mocked_log_warn.call_count, mocked_log_debug.call_count
        # force receive on oversized packet
        s.sendto(packet, 0, (r._MDNS_ADDR, r._MDNS_PORT))
        s.sendto(packet, 0, (r._MDNS_ADDR, r._MDNS_PORT))
        time.sleep(2.0)
        zeroconf.log.debug('warn %d debug %d was %s',
                           mocked_log_warn.call_count,
                           mocked_log_debug.call_count, call_counts)
        assert mocked_log_debug.call_count > call_counts[0]

        # close our zeroconf which will close the sockets
        zc.close()

        # pop the big chunk off the end of the data and send on a closed socket
        out.data.pop()
        zc._GLOBAL_DONE = False

        # mock the zeroconf logger and check for the correct logging backoff
        call_counts = mocked_log_warn.call_count, mocked_log_debug.call_count
        # send on a closed socket (force a socket error)
        zc.send(out)
        zeroconf.log.debug('warn %d debug %d was %s',
                           mocked_log_warn.call_count,
                           mocked_log_debug.call_count, call_counts)
        assert mocked_log_warn.call_count > call_counts[0]
        assert mocked_log_debug.call_count > call_counts[0]
        zc.send(out)
        zeroconf.log.debug('warn %d debug %d was %s',
                           mocked_log_warn.call_count,
                           mocked_log_debug.call_count, call_counts)
        assert mocked_log_debug.call_count > call_counts[0] + 2

        mocked_log_warn.stop()
        mocked_log_debug.stop()
Beispiel #15
0
from OSCServer import ClientHandler, ClientScanner, ClientBasedOSCUDPServer
from OSCClient import OSCClient

from config import *

# StudioLive object
sl = StudioLive1602(debug=True, local=False)
sl.connect(args.slip)
sl.start()
#while(not sl.loaded):
time.sleep(2)

# Client handler object
client_handler = ClientHandler(OSCClient, sl, 8080)

# OSC UDP Server
server = ClientBasedOSCUDPServer((args.oscip, args.oscport), client_handler)
server_thread = threading.Thread(target=server.serve_forever)
server_thread.start()
print("Serving OSC UDP server on {}".format(server.server_address))

# Zeroconf server & client
zeroconf_service = "_osc._udp.local."
zeroconf = Zeroconf([args.oscip])
print("OSCServer" + zeroconf_service)
zeroconf.register_service(
    ServiceInfo(zeroconf_service, "OSCServer" + "." + zeroconf_service,
                socket.inet_aton(args.oscip), args.oscport, 0, 0, {}))
browser = ServiceBrowser(zeroconf, zeroconf_service,
                         ClientScanner(client_handler))
Beispiel #16
0
    def listen(self, add_device: Callable):
        self._add_device = add_device

        zeroconf = Zeroconf()
        ServiceBrowser(zeroconf, '_yandexio._tcp.local.', listener=self)
Beispiel #17
0
 def start(self):
     self.browser = ServiceBrowser(self.zeroconf, utils.TYPE, handlers=[self.handler])
Beispiel #18
0
    def mdns_query(self,
                   dst='ff02::fb',
                   service='_meshcop._udp.local',
                   addrs_blacklist=[]):
        print('mdns_query %s %s %s' % (dst, service, addrs_blacklist))

        # For BBR-TC-03 or DH test cases just send a query
        if dst == 'ff02::fb' and not addrs_blacklist:
            self.bash('dig -p 5353 @%s %s ptr' % (dst, service))
            return

        # For MATN-TC-17 and MATN-TC-18 use Zeroconf to get the BBR address and border agent port
        from zeroconf import ServiceBrowser, ServiceStateChange, Zeroconf, DNSAddress, DNSService, DNSText

        def on_service_state_change(zeroconf, service_type, name,
                                    state_change):
            if state_change is ServiceStateChange.Added:
                zeroconf.get_service_info(service_type, name)

        class BorderAgent(object):
            alias = None
            server_name = None
            link_local_addr = None
            port = None
            thread_status = None

            def __init__(self, alias):
                self.alias = alias

            def __repr__(self):
                return '%s # [%s]:%s TIS=%s' % (self.alias,
                                                self.link_local_addr,
                                                self.port, self.thread_status)

        def parse_cache(cache):
            border_agents = []

            # Find all border routers
            for ptr in cache['_meshcop._udp.local.']:
                border_agents.append(BorderAgent(ptr.alias))

            # Find server name, port and Thread Interface status for each border router
            for ba in border_agents:
                for record in cache[ba.alias.lower()]:
                    if isinstance(record, DNSService):
                        ba.server_name = record.server
                        ba.port = record.port
                    elif isinstance(record, DNSText):
                        text = bytearray(record.text)
                        sb = text.split(b'sb=')[1][0:4]
                        ba.thread_status = (sb[3] & 0x18) >> 3

            # Find link local address for each border router
            for ba in border_agents:
                for record in cache[ba.server_name]:
                    if isinstance(record, DNSAddress):
                        addr = ipaddress.ip_address(record.address)
                        if isinstance(
                                addr,
                                ipaddress.IPv6Address) and addr.is_link_local:
                            ba.link_local_addr = str(addr)
                            break

            return border_agents

        # Browse border agents
        zeroconf = Zeroconf()
        ServiceBrowser(zeroconf,
                       "_meshcop._udp.local.",
                       handlers=[on_service_state_change])
        time.sleep(2)
        cache = zeroconf.cache.cache
        zeroconf.close()

        # Find an active border agent not in the blacklist
        border_agents = parse_cache(cache)
        for ba in border_agents:
            if ba.thread_status == 2 and ba.link_local_addr not in addrs_blacklist:
                return ('%s%%eth0' % ba.link_local_addr, ba.port)

        raise Exception('No active Border Agents found')
Beispiel #19
0
            print("  Address: %s:%d" % (socket.inet_ntoa(info.address), info.port))
            print("  Weight: %d, priority: %d" % (info.weight, info.priority))
            print("  Server: %s" % (info.server,))
            if info.properties:
                print("  Properties are:")
                for key, value in info.properties.items():
                    print("    %s: %s" % (key, value))
            else:
                print("  No properties")
        else:
            print("  No info")
        print('\n')

if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)
    if len(sys.argv) > 1:
        assert sys.argv[1:] == ['--debug']
        logging.getLogger('zeroconf').setLevel(logging.DEBUG)

    zeroconf = Zeroconf()
    print("\nBrowsing services, press Ctrl-C to exit...\n")
    browser = ServiceBrowser(zeroconf, "_http._tcp.local.", handlers=[on_service_state_change])
    browser.start()
    try:
        while True:
            sleep(0.1)
    except KeyboardInterrupt:
        pass
    finally:
        zeroconf.close()
Beispiel #20
0
 def start(self, handlerer: Callable, zeroconf: Zeroconf):
     self.add_handlerer = handlerer
     self.browser = ServiceBrowser(zeroconf,
                                   '_yandexio._tcp.local.',
                                   handlers=[self._zeroconf_handler])
def test_backoff():
    got_query = Event()

    type_ = "_http._tcp.local."
    zeroconf_browser = Zeroconf(interfaces=['127.0.0.1'])

    # we are going to monkey patch the zeroconf send to check query transmission
    old_send = zeroconf_browser.send

    time_offset = 0.0
    start_time = time.time() * 1000
    initial_query_interval = r._BROWSER_TIME / 1000

    def current_time_millis():
        """Current system time in milliseconds"""
        return start_time + time_offset * 1000

    def send(out, addr=r._MDNS_ADDR, port=r._MDNS_PORT):
        """Sends an outgoing packet."""
        got_query.set()
        old_send(out, addr=addr, port=port)

    # monkey patch the zeroconf send
    setattr(zeroconf_browser, "send", send)

    # monkey patch the zeroconf current_time_millis
    r.current_time_millis = current_time_millis

    # monkey patch the backoff limit to prevent test running forever
    r._BROWSER_BACKOFF_LIMIT = 10  # seconds

    # dummy service callback
    def on_service_state_change(zeroconf, service_type, state_change, name):
        pass

    browser = ServiceBrowser(zeroconf_browser, type_, [on_service_state_change])

    try:
        # Test that queries are sent at increasing intervals
        sleep_count = 0
        next_query_interval = 0.0
        expected_query_time = 0.0
        while True:
            zeroconf_browser.notify_all()
            sleep_count += 1
            got_query.wait(0.1)
            if time_offset == expected_query_time:
                assert got_query.is_set()
                got_query.clear()
                if next_query_interval == r._BROWSER_BACKOFF_LIMIT:
                    # Only need to test up to the point where we've seen a query
                    # after the backoff limit has been hit
                    break
                elif next_query_interval == 0:
                    next_query_interval = initial_query_interval
                    expected_query_time = initial_query_interval
                else:
                    next_query_interval = min(2 * next_query_interval, r._BROWSER_BACKOFF_LIMIT)
                    expected_query_time += next_query_interval
            else:
                assert not got_query.is_set()
            time_offset += initial_query_interval

    finally:
        browser.cancel()
        zeroconf_browser.close()
def test_integration():
    service_added = Event()
    service_removed = Event()
    unexpected_ttl = Event()
    got_query = Event()

    type_ = "_http._tcp.local."
    registration_name = "xxxyyy.%s" % type_

    def on_service_state_change(zeroconf, service_type, state_change, name):
        if name == registration_name:
            if state_change is ServiceStateChange.Added:
                service_added.set()
            elif state_change is ServiceStateChange.Removed:
                service_removed.set()

    zeroconf_browser = Zeroconf(interfaces=['127.0.0.1'])

    # we are going to monkey patch the zeroconf send to check packet sizes
    old_send = zeroconf_browser.send

    time_offset = 0

    def current_time_millis():
        """Current system time in milliseconds"""
        return time.time() * 1000 + time_offset * 1000

    expected_ttl = r._DNS_TTL

    # needs to be a list so that we can modify it in our phony send
    nbr_queries = [0, None]

    def send(out, addr=r._MDNS_ADDR, port=r._MDNS_PORT):
        """Sends an outgoing packet."""
        pout = r.DNSIncoming(out.packet())

        for answer in pout.answers:
            nbr_queries[0] += 1
            if not answer.ttl > expected_ttl / 2:
                unexpected_ttl.set()

        got_query.set()
        old_send(out, addr=addr, port=port)

    # monkey patch the zeroconf send
    zeroconf_browser.send = send

    # monkey patch the zeroconf current_time_millis
    r.current_time_millis = current_time_millis

    service_added = Event()
    service_removed = Event()

    browser = ServiceBrowser(zeroconf_browser, type_, [on_service_state_change])

    zeroconf_registrar = Zeroconf(interfaces=['127.0.0.1'])
    desc = {'path': '/~paulsm/'}
    info = ServiceInfo(
        type_, registration_name,
        socket.inet_aton("10.0.1.2"), 80, 0, 0,
        desc, "ash-2.local.")
    zeroconf_registrar.register_service(info)

    try:
        service_added.wait(1)
        assert service_added.is_set()

        sleep_count = 0
        while nbr_queries[0] < 50:
            time_offset += expected_ttl / 4
            zeroconf_browser.notify_all()
            sleep_count += 1
            got_query.wait(1)
            got_query.clear()
        assert not unexpected_ttl.is_set()

        # Don't remove service, allow close() to cleanup

    finally:
        zeroconf_registrar.close()
        browser.cancel()
        zeroconf_browser.close()
Beispiel #23
0
def main():
    IP = requests.get('http://ip.42.pl/raw').text
    print(IP)
    user = os.environ['USER']

    connections = []
    opponents = dict()
    TIMEOUT = 0.001
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    HOST = ''
    PORT = 9876
    sock.bind((HOST, PORT))
    sock.listen(8)
    sock.settimeout(TIMEOUT)

    class ZListener(object):
        def remove_service(self, zeroconf, tpe, name):
            print("Service %s removed" % (name, ))

        def add_service(self, zeroconf, tpe, name):
            info = zeroconf.get_service_info(tpe, name)
            print("Service %s added, service info: %s" % (name, info))
            address = socket.inet_ntoa(info.address)
            port = info.port
            print(address)
            print(port)
            if address == IP:
                return
            mutex.acquire()
            n_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            n_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            n_sock.connect((address, port))
            n_sock.settimeout(TIMEOUT)
            found = False
            for c in connections:
                if c.getpeername()[0] == address:
                    found = True
            if not found:
                print("ADDING CONNECTION ZCONF")
                connections.append(n_sock)
            mutex.release()

    desc = {'path': '/stuff/'}
    zeroconf = Zeroconf()
    listener = ZListener()
    browser = ServiceBrowser(zeroconf, "_hackathonator._tcp.local.", listener)
    info = ServiceInfo("_hackathonator._tcp.local.",
                       user + "._hackathonator._tcp.local.",
                       socket.inet_aton(IP), 9876, 0, 0, desc, "ash-2.local.")
    zeroconf.register_service(info)

    pygame.init()
    width = 1200
    height = 720
    win = pygame.display.set_mode((width, height))
    pygame.display.set_caption('Hackathonator')

    sprites = dict()
    sprites['l_hand'] = HandSprite(yellow, (width // 2 - 140, height), 20)
    sprites['r_hand'] = HandSprite(yellow, (width // 2 + 140, height), 20)

    my_clock = pygame.time.Clock()

    string = ''
    wrong_string = ''
    font = pygame.font.Font('RobotoMono-Medium.ttf', 14)
    code_line = 'I may be slow but watch me go'
    code_index = 0
    line_height = 40
    finished_lines = []
    mods = [304, 303, 13, 301]

    time_limit = 60
    clock = pygame.time.Clock()
    ticks = 0
    other_lost = False
    other_score = 0

    try:
        while time_limit > 0:
            # Event handling and game logic
            ticks += clock.tick()
            if ticks > 1000:
                time_limit -= 1
                ticks = 0
            events = pygame.event.get()
            for event in events:
                if event.type == pygame.QUIT:
                    pygame.quit()
                elif event.type == pygame.KEYDOWN:
                    if event.key != pygame.K_BACKSPACE:
                        hand = random.randint(0, 1)
                        if hand == 0:
                            sprites['l_hand'].move()
                        else:
                            sprites['r_hand'].move()

                        if code_index < len(code_line):
                            if (event.unicode == code_line[code_index]
                                    and len(string) == len(wrong_string)
                                ) or event.key == pygame.K_LALT:
                                string += event.unicode
                                wrong_string += event.unicode
                                code_index += 1
                                if code_index == len(
                                        code_line
                                ) or event.key == pygame.K_LALT:
                                    time_limit += 5
                                    finished_lines.append(
                                        (code_line, len(finished_lines) + 1))
                                    code_line = code_lines[random.randint(
                                        0,
                                        len(code_lines) - 1)]
                                    string = ''
                                    wrong_string = ''
                                    code_index = 0
                                    reply_str = user + ',' + str(
                                        len(finished_lines))
                                    print(connections)
                                    for conn in connections:
                                        conn.sendall(
                                            bytearray(reply_str, 'utf-8'))
                            else:
                                if event.key not in mods and len(
                                        string) == len(wrong_string):
                                    if code_line[code_index] == ' ':
                                        wrong_string += '_'
                                    else:
                                        wrong_string += code_line[code_index]
                                    code_index += 1
                    else:
                        if (code_index > 0):
                            if len(string) == len(wrong_string):
                                string = string[:-1]
                            wrong_string = wrong_string[:-1]
                            code_index -= 1
                            sprites['r_hand'].move()

            for sprite_name, sprite in sprites.items():
                sprite.update()

            # Networking
            mutex.acquire()
            try:
                conn, addr = sock.accept()
                conn.settimeout(TIMEOUT)
                found = False
                for c in connections:
                    print(addr)
                    print(c.getpeername()[0])
                    if c.getpeername()[0] == addr[0]:
                        found = True
                        print('REMOVING CONNECTION')
                        connections.remove(c)
                        break
                print("ADDING CONNECTION SERVER")
                connections.append(conn)
                print(connections)
            except socket.timeout:
                try:
                    new_conns = []
                    for conn in connections:
                        msg = conn.recv(256)
                        if msg is not None and msg != b'':
                            msg = str(msg).strip('b').strip('\'')
                            if ',' in msg:
                                sender, s_line = msg.split(',')
                                opponents[sender] = s_line
                                other_score = int(s_line)
                            else:
                                other_lost = True
                                game_over_line = msg
                            print(msg)
                            new_conns.append(conn)
                        else:
                            print('Closing')
                            conn.close()
                    connections = new_conns
                except socket.timeout:
                    pass
            mutex.release()

            # Rendering
            win.fill((0, 0, 0))
            screen_bezel = pygame.draw.rect(win, white,
                                            (30, 10, width - 60, height - 70))
            screen = pygame.draw.rect(win, gray,
                                      (50, 30, width - 100, height - 110))
            camera = pygame.draw.circle(win, black, (width // 2, 20), 5)
            head = pygame.draw.circle(win, yellow, (width // 2, height), 100)

            if code_index != len(code_line):
                cursor = font.render(code_line[code_index], 1, black, white)

            code = font.render(code_line, 1, white)
            wrong_text = font.render(wrong_string, 1, white, red)
            text = font.render(string, 1, orange, gray)
            l_num = font.render(str(len(finished_lines) + 1) + '.', 1, white)
            time = font.render("Time Left: " + str(time_limit), 1, white)
            if other_lost:
                other_lost_line = font.render(game_over_line, 1, white, black)
                if len(finished_lines) > 0:
                    your_score = finished_lines[-1][1]
                else:
                    your_score = 0
                if other_score > your_score:
                    end_msg = font.render("You lost", 1, white, black)
                else:
                    end_msg = font.render("You won!", 1, white, black)

            line_h = line_height
            for line in finished_lines[-38:]:
                f_line = font.render(line[0], 1, orange)
                win.blit(f_line,
                         (55 + font.size(str(line[1]) + '. ')[0], line_h))
                l_number = font.render(str(line[1]) + '. ', 1, white)
                win.blit(l_number, (55, line_h))
                line_h = min(line_h + 15, 625)

            start_line_x = font.size(str(len(finished_lines) + 1) + '. ')[0]
            win.blit(code, (55 + start_line_x, line_h))
            win.blit(cursor,
                     (55 + start_line_x + (font.size(string)[0]), line_h))
            win.blit(wrong_text, (55 + start_line_x, line_h))
            win.blit(text, (55 + start_line_x, line_h))
            win.blit(l_num, (55, line_h))
            win.blit(time, (width - 200, height - 20))

            if other_lost:
                win.blit(other_lost_line,
                         ((width // 2) -
                          (font.size(game_over_line)[0] // 2), height // 2))
                win.blit(end_msg,
                         ((width // 2) -
                          (font.size("You won!")[0] // 2), height // 2 + 20))

            head = pygame.draw.circle(win, yellow, (width // 2, height), 100)
            for sprite_name, sprite in sprites.items():
                sprite.draw(win)

            sorted_opps = sorted(opponents.items(),
                                 key=operator.itemgetter(1),
                                 reverse=True)
            if len(sorted_opps) != 0:
                opp = sorted_opps[0]
                opponent = font.render(opp[0] + ": " + opp[1], 1, white)
                win.blit(opponent, (55, height - 20))

            pygame.display.flip()
            my_clock.tick(240)

            if other_lost:
                break

        if not other_lost:
            for conn in connections:
                conn.sendall(bytearray(user + " ran out of time", 'utf-8'))

        while True and not other_lost:
            events = pygame.event.get()
            for event in events:
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:
                        pygame.quit()
                        sock.close()
                        zeroconf.unregister_service(info)
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sock.close()
                    zeroconf.unregister_service(info)
            if len(finished_lines) > 0:
                your_score = finished_lines[-1][1]
            else:
                your_score = 0
            if other_score > your_score:
                end_msg = font.render("You lost", 1, white, black)
            else:
                end_msg = font.render("You won!", 1, white, black)
            game_over = font.render("Game Over", 1, white, black)
            win.blit(game_over,
                     (width // 2 -
                      (font.size("Game Over")[0] // 2), height // 2))
            win.blit(end_msg,
                     (width // 2 -
                      (font.size("You won!")[0] // 2), height // 2 + 20))
            pygame.display.flip()
            my_clock.tick(240)

        while True and other_lost:
            events = pygame.event.get()
            for event in events:
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:
                        break
                        pygame.quit()
                        sock.close()
                        zeroconf.unregister_service(info)
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sock.close()
                    zeroconf.unregister_service(info)
            win.blit(other_lost_line,
                     (width // 2 -
                      (font.size(game_over_line)[0] // 2), height // 2))
            win.blit(end_msg,
                     ((width // 2) -
                      (font.size("You won!")[0] // 2), height // 2 + 20))
            pygame.display.flip()
            my_clock.tick(240)

    except pygame.error:
        pass
Beispiel #24
0
class EWeLinkLocal:
    _devices: dict = None
    _handlers = None
    browser = None

    # cut temperature for sync to cloud API
    sync_temperature = False

    def __init__(self, session: ClientSession):
        self.session = session
        self.loop = asyncio.get_event_loop()

    @property
    def started(self) -> bool:
        return self.browser is not None

    def start(self, handlers: List[Callable], devices: dict, zeroconf):
        self._handlers = handlers
        self._devices = devices
        self.browser = ServiceBrowser(zeroconf,
                                      '_ewelink._tcp.local.',
                                      handlers=[self._zeroconf_handler])
        # for beautiful logs
        self.browser.name = 'Sonoff_LAN'

    def stop(self, *args):
        self.browser.cancel()
        self.browser.zc.close()

    def _zeroconf_handler(self, zeroconf: Zeroconf, service_type: str,
                          name: str, state_change: ServiceStateChange):
        if state_change == ServiceStateChange.Removed:
            _LOGGER.debug(f"Zeroconf Removed: {name}")
            # TTL of record 5 minutes
            deviceid = name[8:18]
            # _LOGGER.debug(f"{deviceid} <= Local2 | Zeroconf Removed Event")
            # check if device added
            if 'handlers' in self._devices[deviceid]:
                coro = self.check_offline(deviceid)
                self.loop.create_task(coro)
            return

        info = zeroconf.get_service_info(service_type, name)
        properties = {
            k.decode(): v.decode() if isinstance(v, bytes) else v
            for k, v in info.properties.items()
        }

        deviceid = properties['id']
        device = self._devices.setdefault(deviceid, {})

        log = f"{deviceid} <= Local{state_change.value}"

        if properties.get('encrypt'):
            devicekey = device.get('devicekey')
            if devicekey == 'skip':
                return
            if not devicekey:
                _LOGGER.info(f"{log} | No devicekey for device")
                # skip device next time
                device['devicekey'] = 'skip'
                return

            data = decrypt(properties, devicekey)
            # Fix Sonoff RF Bridge sintax bug
            if data and data.startswith(b'{"rf'):
                data = data.replace(b'"="', b'":"')
        else:
            data = ''.join([
                properties[f'data{i}'] for i in range(1, 4, 1)
                if f'data{i}' in properties
            ])

        state = json.loads(data)
        seq = properties.get('seq')

        _LOGGER.debug(f"{log} | {state} | {seq}")

        # TH bug in local mode https://github.com/AlexxIT/SonoffLAN/issues/110
        if state.get('temperature') == 0 and state.get('humidity') == 0:
            del state['temperature'], state['humidity']

        elif 'temperature' in state and self.sync_temperature:
            # cloud API send only one decimal (not round)
            state['temperature'] = int(state['temperature'] * 10) / 10.0

        if properties['type'] == 'fan_light':
            state = ifan03to02(state)
            device['uiid'] = 'fan_light'

        host = str(ipaddress.ip_address(info.addresses[0]))
        # update every time device host change (alsow first time)
        if device.get('host') != host:
            # state connection for attrs update
            state['local'] = 'online'
            # device host for local connection
            device['host'] = host
            # update or set device init state
            if 'params' in device:
                device['params'].update(state)
            else:
                device['params'] = state
                # set uiid with: strip, plug, light, rf
                device['uiid'] = properties['type']

        for handler in self._handlers:
            handler(deviceid, state, seq)

    async def check_offline(self, deviceid: str):
        """Try to get response from device after received Zeroconf Removed."""
        log = f"{deviceid} => Local4"
        device = self._devices[deviceid]
        if device.get('check_offline') or device['host'] is None:
            _LOGGER.debug(f"{log} | Skip parallel checks")
            return

        device['check_offline'] = True
        sequence = str(int(time.time() * 1000))

        for t in range(20, 61, 20):
            _LOGGER.debug(f"{log} | Check offline with timeout {t}s")

            t0 = time.time()

            conn = await self.send(deviceid, {'cmd': 'info'}, sequence, t)
            if conn == 'online':
                device['check_offline'] = False
                _LOGGER.debug(f"{log} | Welcome back!")
                return

            if t < 60 and conn != 'timeout':
                # sometimes need to wait more
                await asyncio.sleep(t - time.time() + t0)

        _LOGGER.debug(f"{log} | Device offline")

        device['check_offline'] = False
        device['host'] = None

        for handler in self._handlers:
            handler(deviceid, {'local': 'offline'}, None)

    async def send(self, deviceid: str, data: dict, sequence: str, timeout=5):
        device: dict = self._devices[deviceid]

        if '_query' in data:
            data = {'cmd': 'signal_strength'} \
                if data['_query'] is None else \
                {'sledonline': data['_query']}

        if device['uiid'] == 'fan_light' and 'switches' in data:
            data = ifan02to03(data)

        # cmd for D1 and RF Bridge 433
        command = data.get('cmd') or next(iter(data))

        payload = {
            'sequence': sequence,
            'deviceid': deviceid,
            'selfApikey': '123',
            'data': data
        }

        if 'devicekey' in device:
            payload = encrypt(payload, device['devicekey'])

        log = f"{deviceid} => Local4 | {data}"

        try:
            r = await self.session.post(
                f"http://{device['host']}:8081/zeroconf/{command}",
                json=payload,
                headers=LOCAL_HEADERS,
                timeout=timeout)
            resp = await r.json()
            err = resp['error']
            # no problem with any response from device for info command
            if err == 0 or command == 'info':
                _LOGGER.debug(f"{log} <= {resp}")
                return 'online'
            else:
                _LOGGER.warning(f"{log} <= {resp}")
                return f"E#{err}"

        except asyncio.TimeoutError:
            _LOGGER.debug(f"{log} !! Timeout {timeout}")
            return 'timeout'
        except ClientOSError as e:
            _LOGGER.debug(f"{log} !! {e.args}")
            return 'E#COS'
        except:
            _LOGGER.exception(log)
            return 'E#???'
                )
                print(
                    "Attempting to connect to Tally Arbiter server: {}:{} (UUID {}, server version {})"
                    .format(info.server, str(info.port), server_uuid,
                            server_version))
                sio.connect("http://" + info.server + ":" + str(info.port))
                sio.wait()
            except socketio.exceptions.ConnectionError:
                time.sleep(15)


try:
    if "useMDNS" in config["DEFAULT"] and config["DEFAULT"]["useMDNS"]:
        zeroconf = Zeroconf()
        listener = TallyArbiterServerListener()
        browser = ServiceBrowser(zeroconf, "_tally-arbiter._tcp.local.",
                                 listener)
        while True:
            time.sleep(0.1)
    else:
        while 1:
            try:
                print(
                    "Tally Arbiter Blink1 Listener Running. Press CTRL-C to exit."
                )
                print("Attempting to connect to Tally Arbiter server: {}:{}".
                      format(config["DEFAULT"]["host"],
                             str(config["DEFAULT"]["port"])))
                sio.connect("http://" + config["DEFAULT"]["host"] + ":" +
                            str(config["DEFAULT"]["port"]))
                sio.wait()
            except socketio.exceptions.ConnectionError:
    def test_lots_of_names(self):

        # instantiate a zeroconf instance
        zc = Zeroconf(interfaces=['127.0.0.1'])

        # create a bunch of servers
        type_ = "_my-service._tcp.local."
        name = 'a wonderful service'
        server_count = 300
        self.generate_many_hosts(zc, type_, name, server_count)

        # verify that name changing works
        self.verify_name_change(zc, type_, name, server_count)

        # we are going to monkey patch the zeroconf send to check packet sizes
        old_send = zc.send

        longest_packet_len = 0
        longest_packet = None  # type: Optional[r.DNSOutgoing]

        def send(out, addr=r._MDNS_ADDR, port=r._MDNS_PORT):
            """Sends an outgoing packet."""
            packet = out.packet()
            nonlocal longest_packet_len, longest_packet
            if longest_packet_len < len(packet):
                longest_packet_len = len(packet)
                longest_packet = out
            old_send(out, addr=addr, port=port)

        # monkey patch the zeroconf send
        setattr(zc, "send", send)

        # dummy service callback
        def on_service_state_change(zeroconf, service_type, state_change, name):
            pass

        # start a browser
        browser = ServiceBrowser(zc, type_, [on_service_state_change])

        # wait until the browse request packet has maxed out in size
        sleep_count = 0
        while sleep_count < 100 and longest_packet_len < r._MAX_MSG_ABSOLUTE - 100:
            sleep_count += 1
            time.sleep(0.1)

        browser.cancel()
        time.sleep(0.5)

        import zeroconf

        zeroconf.log.debug('sleep_count %d, sized %d', sleep_count, longest_packet_len)

        # now the browser has sent at least one request, verify the size
        assert longest_packet_len <= r._MAX_MSG_ABSOLUTE
        assert longest_packet_len >= r._MAX_MSG_ABSOLUTE - 100

        # mock zeroconf's logger warning() and debug()
        from unittest.mock import patch

        patch_warn = patch('zeroconf.log.warning')
        patch_debug = patch('zeroconf.log.debug')
        mocked_log_warn = patch_warn.start()
        mocked_log_debug = patch_debug.start()

        # now that we have a long packet in our possession, let's verify the
        # exception handling.
        out = longest_packet
        assert out is not None
        out.data.append(b'\0' * 1000)

        # mock the zeroconf logger and check for the correct logging backoff
        call_counts = mocked_log_warn.call_count, mocked_log_debug.call_count
        # try to send an oversized packet
        zc.send(out)
        assert mocked_log_warn.call_count == call_counts[0] + 1
        assert mocked_log_debug.call_count == call_counts[0]
        zc.send(out)
        assert mocked_log_warn.call_count == call_counts[0] + 1
        assert mocked_log_debug.call_count == call_counts[0] + 1

        # force a receive of an oversized packet
        packet = out.packet()
        s = zc._respond_sockets[0]

        # mock the zeroconf logger and check for the correct logging backoff
        call_counts = mocked_log_warn.call_count, mocked_log_debug.call_count
        # force receive on oversized packet
        s.sendto(packet, 0, (r._MDNS_ADDR, r._MDNS_PORT))
        s.sendto(packet, 0, (r._MDNS_ADDR, r._MDNS_PORT))
        time.sleep(2.0)
        zeroconf.log.debug(
            'warn %d debug %d was %s', mocked_log_warn.call_count, mocked_log_debug.call_count, call_counts
        )
        assert mocked_log_debug.call_count > call_counts[0]

        # close our zeroconf which will close the sockets
        zc.close()

        # pop the big chunk off the end of the data and send on a closed socket
        out.data.pop()
        zc._GLOBAL_DONE = False

        # mock the zeroconf logger and check for the correct logging backoff
        call_counts = mocked_log_warn.call_count, mocked_log_debug.call_count
        # send on a closed socket (force a socket error)
        zc.send(out)
        zeroconf.log.debug(
            'warn %d debug %d was %s', mocked_log_warn.call_count, mocked_log_debug.call_count, call_counts
        )
        assert mocked_log_warn.call_count > call_counts[0]
        assert mocked_log_debug.call_count > call_counts[0]
        zc.send(out)
        zeroconf.log.debug(
            'warn %d debug %d was %s', mocked_log_warn.call_count, mocked_log_debug.call_count, call_counts
        )
        assert mocked_log_debug.call_count > call_counts[0] + 2

        mocked_log_warn.stop()
        mocked_log_debug.stop()
Beispiel #27
0
                                   (dest.ip, dest.port))
                sleep(0.01)


class ZeroConfListener:
    def __init__(self):
        self.streamer = SensorStreamThread()
        self.streamer.start()

    def remove_service(self, zeroconf, type, name):
        info = zeroconf.get_service_info(type, name)
        print("Service %s removed, $s" % (name, info))
        self.streamer.rm_destination(Dest(ip=info.addresses[0],
                                          port=info.port))

    def add_service(self, zeroconf, type, name):
        info = zeroconf.get_service_info(type, name)
        print("Sensor sink %s added, service info: %s" % (name, info))
        self.streamer.add_destination(
            Dest(ip=socket.inet_ntoa(info.addresses[0]), port=info.port))


zeroconf = Zeroconf()
listener = ZeroConfListener()
browser = ServiceBrowser(zeroconf, "_sensor._udp.local.", listener)

try:
    input("Press enter to exit...\n\n")
finally:
    zeroconf.close()
def test_integration():
    service_added = Event()
    service_removed = Event()
    unexpected_ttl = Event()
    got_query = Event()

    type_ = "_http._tcp.local."
    registration_name = "xxxyyy.%s" % type_

    def on_service_state_change(zeroconf, service_type, state_change, name):
        if name == registration_name:
            if state_change is ServiceStateChange.Added:
                service_added.set()
            elif state_change is ServiceStateChange.Removed:
                service_removed.set()

    zeroconf_browser = Zeroconf(interfaces=['127.0.0.1'])

    # we are going to monkey patch the zeroconf send to check packet sizes
    old_send = zeroconf_browser.send

    time_offset = 0.0

    def current_time_millis():
        """Current system time in milliseconds"""
        return time.time() * 1000 + time_offset * 1000

    expected_ttl = r._DNS_HOST_TTL

    nbr_answers = 0

    def send(out, addr=r._MDNS_ADDR, port=r._MDNS_PORT):
        """Sends an outgoing packet."""
        pout = r.DNSIncoming(out.packet())
        nonlocal nbr_answers
        for answer in pout.answers:
            nbr_answers += 1
            if not answer.ttl > expected_ttl / 2:
                unexpected_ttl.set()

        got_query.set()
        old_send(out, addr=addr, port=port)

    # monkey patch the zeroconf send
    setattr(zeroconf_browser, "send", send)

    # monkey patch the zeroconf current_time_millis
    r.current_time_millis = current_time_millis

    # monkey patch the backoff limit to ensure we always get one query every 1/4 of the DNS TTL
    r._BROWSER_BACKOFF_LIMIT = int(expected_ttl / 4)

    service_added = Event()
    service_removed = Event()

    browser = ServiceBrowser(zeroconf_browser, type_, [on_service_state_change])

    zeroconf_registrar = Zeroconf(interfaces=['127.0.0.1'])
    desc = {'path': '/~paulsm/'}
    info = ServiceInfo(type_, registration_name, socket.inet_aton("10.0.1.2"), 80, 0, 0, desc, "ash-2.local.")
    zeroconf_registrar.register_service(info)

    try:
        service_added.wait(1)
        assert service_added.is_set()

        # Test that we receive queries containing answers only if the remaining TTL
        # is greater than half the original TTL
        sleep_count = 0
        test_iterations = 50
        while nbr_answers < test_iterations:
            # Increase simulated time shift by 1/4 of the TTL in seconds
            time_offset += expected_ttl / 4
            zeroconf_browser.notify_all()
            sleep_count += 1
            got_query.wait(0.1)
            got_query.clear()
            # Prevent the test running indefinitely in an error condition
            assert sleep_count < test_iterations * 4
        assert not unexpected_ttl.is_set()

        # Don't remove service, allow close() to cleanup

    finally:
        zeroconf_registrar.close()
        service_removed.wait(1)
        assert service_removed.is_set()
        browser.cancel()
        zeroconf_browser.close()
Beispiel #29
0
    if info is None:
      self._lock.acquire()
      self._pending.append((type, name))
      self._lock.release()
    else:
      print "Found IoThing at %s" % (inet_ntoa(info.address),)

  def update(self):
    self._lock.acquire()
    unresolved = list()
    for type, name in self._pending:
      info = zeroconf.get_service_info(type, name)
      if info is None:
        unresolved.append((type, name))
      else:
        print "Found IoThing at %s" % (inet_ntoa(info.address),)
    self._pending = unresolved
    self._lock.release()

if __name__ == "__main__":
  # Set up the listener
  zeroconf = Zeroconf()
  listener = IoThingListener()
  browser = ServiceBrowser(zeroconf, "_iothing._tcp.local.", listener)
  try:
    while True:
      listener.update()
      sleep(0.5)
  finally:
    zeroconf.close()
Beispiel #30
0
 def listen(self, add_device: Callable):
     from homeassistant.components.zeroconf import Zeroconf
     self._add_device = add_device
     self._zeroconf = Zeroconf()
     ServiceBrowser(self._zeroconf, '_yandexio._tcp.local.', listener=self)
Beispiel #31
0
 def resolve(self, type, timeout=10):
     browser = ServiceBrowser(self.zeroconf, type, self)
     self.discover_complete.wait(timeout)
     if not self.discover_complete.is_set(): return None
     # else
     return [self.ip_address, self.port]