Пример #1
0
def registre_mdns(port):
    LOCAL_HOST = "alexa.local"
    LOCAL_PORT = port
    BASE_URL = "http://" + LOCAL_HOST + ":" + str(LOCAL_PORT) + "/"

    def get_local_address():
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("www.amazon.com", 80))

        res = s.getsockname()[0]
        s.close()
        return res

    ip = get_local_address()
    print(f"Local IP is {ip}")

    desc = {
        'version': '0.1',
        'base_url': "http://{}:{}/".format(ip, str(LOCAL_PORT)),
        'path': '/'
    }
    info = ServiceInfo("_http._tcp.local.",
                       "Alexa Device._http._tcp.local.",
                       socket.inet_aton(ip), LOCAL_PORT, 0, 0,
                       desc, LOCAL_HOST + ".")

    zeroconf = Zeroconf()
    zeroconf.register_service(info)

    print(f"Local mDNS is started, domain is {LOCAL_HOST}")
    print(f"Local HTTP is {BASE_URL}")
Пример #2
0
class HomeKitServer(ThreadingMixIn, HTTPServer):
    def __init__(self, config_file, logger=sys.stderr):
        """
        Create a new server that acts like a homekit accessory.

        :param config_file: the file that contains the configuration data. Must be a string representing an absolute
        path to the file
        :param logger: this can be None to disable logging, sys.stderr to use the default behaviour of the python
        implementation or an instance of logging.Logger to use this.
        """
        if logger is None or logger == sys.stderr or isinstance(
                logger, logging.Logger):
            self.logger = logger
        else:
            raise Exception('Invalid logger given.')
        self.data = HomeKitServerData(config_file)
        self.data.increase_configuration_number()
        self.sessions = {}
        self.zeroconf = Zeroconf()
        self.mdns_type = '_hap._tcp.local.'
        self.mdns_name = self.data.name + '._hap._tcp.local.'

        self.accessories = Accessories()

        HTTPServer.__init__(self, (self.data.ip, self.data.port),
                            HomeKitRequestHandler)

    def publish_device(self):
        desc = {
            'md': 'My Lightbulb',  # model name of accessory
            'ci': Categories[
                'Lightbulb'],  # category identifier (page 254, 2 means bridge)
            'pv': '1.0',  # protocol version
            'c#': str(self.data.configuration_number),
            # configuration (consecutive number, 1 or greater, must be changed on every configuration change)
            'id': self.data.
            accessory_pairing_id_bytes,  # id MUST look like Mac Address
            'ff': '0',  # feature flags
            's#': '1',  # must be 1
            'sf':
            '1'  # status flag, lowest bit encodes pairing status, 1 means unpaired
        }
        if self.data.is_paired:
            desc['sf'] = '0'

        info = ServiceInfo(self.mdns_type, self.mdns_name,
                           socket.inet_aton(self.data.ip), self.data.port, 0,
                           0, desc, 'ash-2.local.')
        self.zeroconf.unregister_all_services()
        self.zeroconf.register_service(info)

    def unpublish_device(self):
        self.zeroconf.unregister_all_services()

    def shutdown(self):
        # tell all handlers to close the connection
        for session in self.sessions:
            self.sessions[session]['handler'].close_connection = True
        self.socket.close()
        HTTPServer.shutdown(self)
Пример #3
0
    def test_integration_with_subtype_and_listener(self):
        subtype_ = "_subtype._sub"
        type_ = "_type._tcp.local."
        name = "xxxyyy"
        # Note: discovery returns only DNS-SD type not subtype
        discovery_type = "%s.%s" % (subtype_, type_)
        registration_name = "%s.%s" % (name, type_)

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

        try:
            service_types = ZeroconfServiceTypes.find(interfaces=["127.0.0.1"],
                                                      timeout=0.5)
            assert discovery_type in service_types
            service_types = ZeroconfServiceTypes.find(zc=zeroconf_registrar,
                                                      timeout=0.5)
            assert discovery_type in service_types

        finally:
            zeroconf_registrar.close()
    def test_integration_with_subtype_and_listener(self):
        subtype_ = "_subtype._sub"
        type_ = "_type._tcp.local."
        name = "xxxyyy"
        # Note: discovery returns only DNS-SD type not subtype
        discovery_type = "%s.%s" % (subtype_, type_)
        registration_name = "%s.%s" % (name, type_)

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

        try:
            service_types = ZeroconfServiceTypes.find(
                interfaces=['127.0.0.1'], timeout=0.5)
            assert discovery_type in service_types
            service_types = ZeroconfServiceTypes.find(
                zc=zeroconf_registrar, timeout=0.5)
            assert discovery_type in service_types

        finally:
            zeroconf_registrar.close()
Пример #5
0
def register_mdns(receiver_name):
    addresses = []
    for ifen in ni.interfaces():
        ifenaddr = ni.ifaddresses(ifen)
        if ni.AF_INET in ifenaddr:
            addresses.append(
                socket.inet_pton(ni.AF_INET, ifenaddr[ni.AF_INET][0]["addr"]))
        if ni.AF_INET6 in ifenaddr:
            addresses.append(
                socket.inet_pton(
                    ni.AF_INET6,
                    ifenaddr[ni.AF_INET6][0]["addr"].split("%")[0]))

    info = ServiceInfo(
        "_airplay._tcp.local.",
        "%s._airplay._tcp.local." % receiver_name,
        # addresses=[socket.inet_aton("127.0.0.1")],
        addresses=addresses,
        port=7000,
        properties=mdns_props,
        server="%s.local." % receiver_name,
    )

    zeroconf = Zeroconf(ip_version=IPVersion.V4Only)
    zeroconf.register_service(info)
    print("mDNS service registered")
    return (zeroconf, info)
Пример #6
0
    def advertise(self):
        postfix = self.config['global']['service_prefix']
        self.port = int(self.config['global']['port'])
        #print(self.config['device']['hostname']+postfix)
        info = ServiceInfo(postfix, self.config['device']['hostname']+"."+postfix,
                       socket.inet_aton(self.ip), self.port, 0, 0,
                       {'info': self.config['device']['description']}, "hazc.local.")

        self.bindConnection()

        zeroconf = Zeroconf()
        zeroconf.register_service(info)


        try:
            while True:
#                 try:
                print("Ready")
                self.conn, self.addr = self.webcontrol.accept()
                self.listen()
                self.conn.close()
        except KeyboardInterrupt:
            pass
        finally:
            print()
            print("Unregistering...")
            zeroconf.unregister_service(info)
            zeroconf.close()

        try:
            print("Shutting down socket")
            self.webcontrol.shutdown(socket.SHUT_RDWR)
        except Exception as e:
            print(e)
Пример #7
0
def setup(hass, config):
    """Set up Zeroconf and make Home Assistant discoverable."""
    from zeroconf import Zeroconf, ServiceInfo

    zeroconf = Zeroconf()

    zeroconf_name = '{}.{}'.format(hass.config.location_name, ZEROCONF_TYPE)

    requires_api_password = hass.config.api.api_password is not None
    params = {
        'version': __version__,
        'base_url': hass.config.api.base_url,
        'requires_api_password': requires_api_password,
    }

    info = ServiceInfo(ZEROCONF_TYPE, zeroconf_name,
                       socket.inet_aton(hass.config.api.host),
                       hass.config.api.port, 0, 0, params)

    zeroconf.register_service(info)

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

    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zeroconf)

    return True
Пример #8
0
class Server:
    def __init__(self, name, address, port, description):
        self.zeroconf = Zeroconf()
        self.name = name
        self.description = description
        self.address = address
        self.port = port

        self.full_name = get_full_name(name)
        self.info = ServiceInfo(type_=TYPE,
                                name=self.full_name,
                                address=socket.inet_aton(self.address),
                                port=self.port,
                                weight=0,
                                priority=0,
                                properties=self.description)

    def register(self):
        logger.info("Broadcast server {} at {}:{}".format(
            self.full_name, self.address, self.port))
        self.zeroconf.register_service(self.info)

    def unregister(self):
        self.zeroconf.unregister_service(self.info)

    def close(self):
        self.zeroconf.close()
Пример #9
0
class DartsConnectBonjour():

    def stopBonjour(self):
        print("DartsConnectBonjour --> Unregistering...")
        self.zeroconf.unregister_service(self.info)
        self.zeroconf.close()

    def startBonjour(self):
        if len(sys.argv) > 1:
            assert sys.argv[1:] == ['--debug']
            self.logging.getLogger('zeroconf').setLevel(logging.DEBUG)

        #desc = {'path': '/~paulsm/'}

        self.info = ServiceInfo("_dartsconnect._tcp.local.",
                           "Dartboard._dartsconnect._tcp.local.",
                           socket.inet_aton(self.ip), self.port, 0, 0,
                           {}, None)

        self.zeroconf = Zeroconf()
        print("DartsConnectBonjour --> DartsConnect service registered")
        self.zeroconf.register_service(self.info)

    def __init__(self, ipAddr, port):
        self.ip = ipAddr
        self.port = port
Пример #10
0
    def test_integration_with_listener(self):

        type_ = "_test-srvc-type._tcp.local."
        name = "xxxyyy"
        registration_name = "%s.%s" % (name, type_)

        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_types = ZeroconfServiceTypes.find(interfaces=["127.0.0.1"],
                                                      timeout=0.5)
            assert type_ in service_types
            service_types = ZeroconfServiceTypes.find(zc=zeroconf_registrar,
                                                      timeout=0.5)
            assert type_ in service_types

        finally:
            zeroconf_registrar.close()
Пример #11
0
def register_service(ip, port, ssl=False, debug=False):
    global zeroconf, info

    if debug:
        logging.getLogger("zeroconf").setLevel(logging.DEBUG)
        logger.setLevel(logging.DEBUG)

    desc = {"path": "/check"}

    typ = "_espupdater-http._tcp.local."

    if ssl:
        typ = "_espupdater-https._tcp.local."

    #TODO: all_ips = addresses()
    #TODO: match against config["host"]
    all_ips = [ip]
    logger.info(f"IPs: {all_ips}")

    info = ServiceInfo(
        typ,
        "ESP Swarm Updater." + typ,
        addresses=[socket.inet_aton(ip) for ip in all_ips],
        port=port,
        properties=desc,
        server="ash-2.local.",
    )

    zeroconf = Zeroconf()
    logger.info("Registration of mDNS service")
    zeroconf.register_service(info)
Пример #12
0
    def test_discover_homekit_devices_missing_c(self):
        zeroconf = Zeroconf()
        desc = {
            'id': '00:00:01:00:00:03',
            'md': 'unittest',
            's#': '1',
            'ci': '5',
            'sf': '0'
        }
        info = ServiceInfo('_hap._tcp.local.',
                           'foo3._hap._tcp.local.',
                           addresses=[socket.inet_aton('127.0.0.1')],
                           port=1234,
                           properties=desc,
                           weight=0,
                           priority=0)
        zeroconf.unregister_all_services()
        zeroconf.register_service(info, allow_name_change=True)

        result = discover_homekit_devices()
        test_device = self.find_device(desc, result)

        zeroconf.unregister_all_services()

        self.assertIsNone(test_device)
Пример #13
0
class AdvertiseServer:
    def __init__(self):
        self._zeroconf = Zeroconf()
        self._addresses = [socket.inet_aton(_my_ip())]
        self._id2info = {}

    def register_device(self, id, device):
        info = ServiceInfo(type_="_repl._tcp.local.",
                           name=device.name + "." + "_repl._tcp.local.",
                           port=Config.get_attr('server_port', '34567'),
                           properties={
                               "uid": device.uid,
                               "name": device.name
                           },
                           addresses=self._addresses)
        self._id2info[id] = info
        self._zeroconf.register_service(info, allow_name_change=True)
        logger.debug(f"advertise {id}")

    def unregister_device(self, id):
        try:
            logger.debug(f"no longer advertise {id}")
            info = self._id2info[id]
            if info:
                self._zeroconf.unregister_service(info)
                del self._id2info[id]
        except AttributeError:
            pass
Пример #14
0
def setup(hass, config):
    """Set up Zeroconf and make Home Assistant discoverable."""
    from zeroconf import Zeroconf, ServiceInfo

    zeroconf = Zeroconf()

    zeroconf_name = "{}.{}".format(hass.config.location_name,
                                   ZEROCONF_TYPE)

    requires_api_password = (hass.config.api.api_password is not None)
    params = {"version": __version__, "base_url": hass.config.api.base_url,
              "requires_api_password": requires_api_password}

    info = ServiceInfo(ZEROCONF_TYPE, zeroconf_name,
                       socket.inet_aton(hass.config.api.host),
                       hass.config.api.port, 0, 0, params)

    zeroconf.register_service(info)

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

    hass.bus.listen_once(EVENT_BLUMATE_STOP, stop_zeroconf)

    return True
Пример #15
0
def setup(hass, config):
    """Set up Zeroconf and make Home Assistant discoverable."""
    from zeroconf import Zeroconf, ServiceInfo

    zeroconf = Zeroconf()

    zeroconf_name = '{}.{}'.format(hass.config.location_name, ZEROCONF_TYPE)

    requires_api_password = hass.config.api.api_password is not None
    params = {
        'version': __version__,
        'base_url': hass.config.api.base_url,
        'requires_api_password': requires_api_password,
    }

    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, host_ip_pton,
                       hass.http.server_port, 0, 0, params)

    zeroconf.register_service(info)

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

    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zeroconf)

    return True
Пример #16
0
def setup(hass, config):
    """Set up Zeroconf and make Home Assistant discoverable."""
    from zeroconf import Zeroconf, ServiceInfo

    zeroconf = Zeroconf()

    zeroconf_name = "{}.{}".format(hass.config.location_name, ZEROCONF_TYPE)

    requires_api_password = (hass.config.api.api_password is not None)
    params = {
        "version": __version__,
        "base_url": hass.config.api.base_url,
        "requires_api_password": requires_api_password
    }

    info = ServiceInfo(ZEROCONF_TYPE, zeroconf_name,
                       socket.inet_aton(hass.config.api.host),
                       hass.config.api.port, 0, 0, params)

    zeroconf.register_service(info)

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

    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zeroconf)

    return True
Пример #17
0
def register_service(code, addresses, port):
    r"""Registers an Airshare Multicast-DNS service based in the local network.

    Parameters
    ----------
    code : str
        Identifying code for the Airshare service.
    addresses : list
        List of local network IP Addresses for the service.
    port : int
        Port number for the Airshare service's server.

    Returns
    -------
    info : zeroconf.ServiceInfo
        Details of the Airshare service.
    """
    zeroconf = Zeroconf(ip_version=IPVersion.V4Only)
    service = "_airshare._http._tcp.local."
    info = ServiceInfo(service,
                       code + service,
                       addresses=addresses,
                       port=port,
                       server=code + ".local.")
    zeroconf.register_service(info)
    return info
Пример #18
0
    def test_register_and_lookup_type_by_uppercase_name(self):
        # instantiate a zeroconf instance
        zc = Zeroconf(interfaces=['127.0.0.1'])
        type_ = "_mylowertype._tcp.local."
        name = "Home"
        registration_name = "%s.%s" % (name, type_)

        info = ServiceInfo(
            type_,
            name=registration_name,
            server="random123.local.",
            addresses=[socket.inet_pton(socket.AF_INET, "1.2.3.4")],
            port=80,
            properties={"version": "1.0"},
        )
        zc.register_service(info)
        _clear_cache(zc)
        info = ServiceInfo(type_, registration_name)
        info.load_from_cache(zc)
        assert info.addresses == []

        out = r.DNSOutgoing(const._FLAGS_QR_QUERY)
        out.add_question(
            r.DNSQuestion(type_.upper(), const._TYPE_PTR, const._CLASS_IN))
        zc.send(out)
        time.sleep(0.5)
        info = ServiceInfo(type_, registration_name)
        info.load_from_cache(zc)
        assert info.addresses == [socket.inet_pton(socket.AF_INET, "1.2.3.4")]
        assert info.properties == {b"version": b"1.0"}
        zc.close()
Пример #19
0
def test_aaaa_query():
    """Test that queries for AAAA records work."""
    zc = Zeroconf(interfaces=['127.0.0.1'])
    type_ = "_knownservice._tcp.local."
    name = "knownname"
    registration_name = "%s.%s" % (name, type_)
    desc = {'path': '/~paulsm/'}
    server_name = "ash-2.local."
    ipv6_address = socket.inet_pton(socket.AF_INET6, "2001:db8::1")
    info = ServiceInfo(type_,
                       registration_name,
                       80,
                       0,
                       0,
                       desc,
                       server_name,
                       addresses=[ipv6_address])
    zc.register_service(info)

    _clear_cache(zc)
    generated = r.DNSOutgoing(const._FLAGS_QR_QUERY)
    question = r.DNSQuestion(server_name, const._TYPE_AAAA, const._CLASS_IN)
    generated.add_question(question)
    packets = generated.packets()
    _, multicast_out = zc.query_handler.response(r.DNSIncoming(packets[0]),
                                                 "1.2.3.4", const._MDNS_PORT)
    assert multicast_out.answers[0][0].address == ipv6_address
    # unregister
    zc.unregister_service(info)
    zc.close()
Пример #20
0
    def test_integration_with_listener_v6_records(self):

        type_ = "_test-srvc-type._tcp.local."
        name = "xxxyyy"
        registration_name = "%s.%s" % (name, type_)
        addr = "2606:2800:220:1:248:1893:25c8:1946"  # example.com

        zeroconf_registrar = Zeroconf(interfaces=['127.0.0.1'])
        desc = {'path': '/~paulsm/'}
        info = ServiceInfo(
            type_,
            registration_name,
            80,
            0,
            0,
            desc,
            "ash-2.local.",
            addresses=[socket.inet_pton(socket.AF_INET6, addr)],
        )
        zeroconf_registrar.register_service(info)
        _clear_cache(zeroconf_registrar)
        try:
            service_types = ZeroconfServiceTypes.find(interfaces=['127.0.0.1'],
                                                      timeout=0.5)
            assert type_ in service_types
            _clear_cache(zeroconf_registrar)
            service_types = ZeroconfServiceTypes.find(zc=zeroconf_registrar,
                                                      timeout=0.5)
            assert type_ in service_types

        finally:
            zeroconf_registrar.close()
Пример #21
0
    def createServer(self):
        self.serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF,
                                     99999999)
        self.serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        print 'Socket created'

        # Bind socket to local host and port
        try:
            self.serverSocket.bind(("", self.PORT))
        except socket.error as msg:
            print 'Bind failed. Error: ' + str(msg[0]) + ' Message ' + msg[1]
            sys.exit()

        print 'Socket bind complete'

        # Start listening on socket
        self.serverSocket.listen(1)
        print 'Socket now listening'

        # Register service
        IP = socket.inet_aton(ifaddresses(self.INTERFACE)[2][0]['addr'])

        serviceType = "_naoqi._tcp.local."
        name = "Fake robot._naoqi._tcp.local."
        info = ServiceInfo(serviceType, name, IP, self.PORT, 0, 0, {})
        zeroconf = Zeroconf()
        print "Registration of service"
        zeroconf.register_service(info)
Пример #22
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(interfaces=['127.0.0.1'])
    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()
        # Don't remove service, allow close() to cleanup

    finally:
        zeroconf_registrar.close()
        browser.cancel()
        zeroconf_browser.close()
Пример #23
0
def run():
    try:
        zeroconf = Zeroconf(ip_version=IPVersion.All, interfaces=InterfaceChoice.All)
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("1.1.1.1", 80))
        ip = s.getsockname()[0]

        info = ServiceInfo(
            "_http._tcp.local.",
            "Member Matters Server._http._tcp.local.",
            addresses=[socket.inet_aton(ip)],
            properties={"ip": ip},
            port=80,
            server="membermatters.local.",
        )

        zeroconf.register_service(info)
    except:
        pass

    try:
        while True:
            time.sleep(0.1)
    except KeyboardInterrupt:
        pass
    finally:
        print("Unregistering...")
        zeroconf.unregister_service(info)
        zeroconf.close()
Пример #24
0
class ZeroconfService():
    def register(self, port: int):

        self._zeroconf = Zeroconf()

        hostname = socket.gethostname()

        host = socket.gethostbyname(hostname)

        desc = {
            'host': host,
            'port': str(port),
            'hostname': hostname,
        }

        self._info = ServiceInfo(
            "_mpv-http-router._tcp.local.",
            "MPV HTTP Router._mpv-http-router._tcp.local.",
            socket.inet_aton(host), port, 0, 0, desc)

        self._zeroconf.register_service(self._info)

        self._registered = True

        logger.info(
            "MPV HTTP Router has been registered in the network on %s:%s",
            hostname, port)

    def unregister(self):
        if self._zeroconf is None:
            return
        self._zeroconf.unregister_service(self._info)
        self._zeroconf.close()
        self._registered = False
        logger.info("MPV HTTP Router has been unregistered")
Пример #25
0
    def test_integration_with_listener_ipv6(self):

        type_ = "_test-srvc-type._tcp.local."
        name = "xxxyyy"
        registration_name = "%s.%s" % (name, type_)

        zeroconf_registrar = Zeroconf(ip_version=r.IPVersion.V6Only)
        desc = {'path': '/~paulsm/'}
        info = ServiceInfo(
            type_,
            registration_name,
            80,
            0,
            0,
            desc,
            "ash-2.local.",
            addresses=[socket.inet_aton("10.0.1.2")],
        )
        zeroconf_registrar.register_service(info)
        _clear_cache(zeroconf_registrar)
        try:
            service_types = ZeroconfServiceTypes.find(
                ip_version=r.IPVersion.V6Only, timeout=0.5)
            assert type_ in service_types
            _clear_cache(zeroconf_registrar)
            service_types = ZeroconfServiceTypes.find(zc=zeroconf_registrar,
                                                      timeout=0.5)
            assert type_ in service_types

        finally:
            zeroconf_registrar.close()
Пример #26
0
 def __init__(self, sname, stype, port, txt):
     host_name = socket.gethostname()
     host = self.get_ip()
     service_name = "{}.{}".format(sname, stype)
     desc_txt = 'FogLAMP Service'
     if isinstance(txt, list):
         try:
             desc_txt = txt[0]
         except:
             pass
     desc = {'description': desc_txt}
     """ Create a service description.
             type_: fully qualified service type name
             name: fully qualified service name
             address: IP address as unsigned short, network byte order
             port: port that the service runs on
             weight: weight of the service
             priority: priority of the service
             properties: dictionary of properties (or a string holding the
                         bytes for the text field)
             server: fully qualified name for service host (defaults to name)
             host_ttl: ttl used for A/SRV records
             other_ttl: ttl used for PTR/TXT records"""
     info = ServiceInfo(stype,
                        service_name,
                        socket.inet_aton(host),
                        port,
                        properties=desc,
                        server="{}.local.".format(host_name))
     zeroconf = Zeroconf()
     # Refresh zeroconf cache
     browser = ServiceBrowser(zeroconf,
                              stype,
                              handlers=[self.on_service_state_change])
     zeroconf.register_service(info, allow_name_change=True)
Пример #27
0
class Advertise:
    def __init__(self, name, device_type):
        self.zeroconf = Zeroconf()
        self.name = name
        self.device_type = device_type

    def get_hostname_port(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(("", 0))
        hostname = socket.gethostname()
        port = s.getsockname()[1]
        s.close()
        return hostname, port

    def start(self):
        hostname, port = self.get_hostname_port()
        self.port = port
        desc = {
            'service': 'RF Bridge',
            'version': '0.0.1',
            'name': self.name,
            'device_type': self.device_type
        }
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("8.8.8.8", 80))
        ip_addr = s.getsockname()[0]
        s.close()
        info = ServiceInfo("_rfbridge._tcp.local.",
                           hostname + "._rfbridge._tcp.local.",
                           socket.inet_aton(ip_addr), port, 0, 0, desc,
                           hostname + ".local.")
        self.zeroconf.register_service(info)
Пример #28
0
def setup(hass, config):
    """Set up Zeroconf and make Home Assistant discoverable."""
    from zeroconf import Zeroconf, ServiceInfo

    zeroconf = Zeroconf()

    zeroconf_name = '{}.{}'.format(hass.config.location_name, ZEROCONF_TYPE)

    requires_api_password = hass.config.api.api_password is not None
    params = {
        'version': __version__,
        'base_url': hass.config.api.base_url,
        'requires_api_password': requires_api_password,
    }

    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, host_ip_pton,
                       hass.http.server_port, 0, 0, params)

    zeroconf.register_service(info)

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

    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zeroconf)

    return True
Пример #29
0
class mDNS(object):
    def __init__(self, port, mdns_desc, mdns_addr):
        try:
            ni.ifaddresses('wlan0')
            self.ip = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr']
        except ValueError:
            self.ip = socket.gethostbyname(socket.gethostname())

        self.port = port
        desc = {
            'version': '0.1',
            'base_url': "http://{}:{}/".format(self.ip, str(self.port)),
            'path': '/'
        }

        self.info = ServiceInfo("_http._tcp.local.",
                                "{}._http._tcp.local.".format(mdns_desc),
                                socket.inet_aton(self.ip), self.port, 0, 0,
                                desc, "{}.".format(mdns_addr))

        self.zeroconf = Zeroconf()

    def register(self):
        self.zeroconf.register_service(self.info)

    def unregister(self):
        self.zeroconf.unregister_service(self.info)
Пример #30
0
    def test_name_conflicts(self):
        # instantiate a zeroconf instance
        zc = Zeroconf(interfaces=['127.0.0.1'])
        type_ = "_homeassistant._tcp.local."
        name = "Home"
        registration_name = "%s.%s" % (name, type_)

        info = ServiceInfo(
            type_,
            name=registration_name,
            server="random123.local.",
            addresses=[socket.inet_pton(socket.AF_INET, "1.2.3.4")],
            port=80,
            properties={"version": "1.0"},
        )
        zc.register_service(info)

        conflicting_info = ServiceInfo(
            type_,
            name=registration_name,
            server="random456.local.",
            addresses=[socket.inet_pton(socket.AF_INET, "4.5.6.7")],
            port=80,
            properties={"version": "1.0"},
        )
        with pytest.raises(r.NonUniqueNameException):
            zc.register_service(conflicting_info)
        zc.close()
Пример #31
0
class WGZeroconf(ClassLogger):
    def __init__(self, ifname: str, wg_iface: WGInterface):
        self._setLoggerName(ifname)
        self.ifname = ifname
        self.ifindex: int = IPRoute().link_lookup(ifname=ifname)[0]
        self.wg_iface = wg_iface
        self.addresses = self.get_addrs()
        self.zeroconf = Zeroconf([addr.compressed for addr in self.addresses])
        self.listener = WGServiceListener(self)
        self.browser = ServiceBrowser(self.zeroconf, WG_TYPE, self.listener)

        digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
        digest.update(MACHINE_ID.encode('utf-8'))
        digest.update(ifname.encode('utf-8'))
        self.hostname = digest.finalize()[:16].hex()

        self.service: WGServiceInfo = WGServiceInfo.new(
            self.hostname,
            addresses=[addr.packed for addr in self.addresses],
            hostname=HOSTNAME,
            config=wg_iface.config,
        )
        self.zeroconf.register_service(self.service)

    def get_addrs(
        self,
    ) -> List[TAddress]:
        with IPRoute() as ip:
            return [
                ipaddress.ip_address(addr.get_attr('IFA_ADDRESS'))
                for addr in ip.get_addr(label=self.ifname)
            ]

    def close(self) -> None:
        self.zeroconf.close()
Пример #32
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()
Пример #33
0
def broadcast_zeroconf(frigate_id):
    zeroconf = Zeroconf(interfaces=InterfaceChoice.Default,
                        ip_version=IPVersion.V4Only)

    host_ip = get_local_ip()

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

    info = ServiceInfo(
        ZEROCONF_TYPE,
        name=f"{frigate_id}.{ZEROCONF_TYPE}",
        addresses=[host_ip_pton],
        port=5000,
    )

    logger.info("Starting Zeroconf broadcast")
    try:
        zeroconf.register_service(info)
    except NonUniqueNameException:
        logger.error(
            "Frigate instance with identical name present in the local network"
        )
    return zeroconf
Пример #34
0
    def __init__(self):
        """
        """
        self.hostname = socket.gethostname()
        self.address = socket.gethostbyname(self.hostname + "." + self.__net_suffix)
        self.port = PORT
        self.uid = "virtual_sensor_%s" % MAC_ADDRESS

        try:
            serviceInfo = ServiceInfo("_sensor._tcp.%s." % self.__net_suffix,
                            self.uid + "._sensor._tcp.%s." % self.__net_suffix,
                            addresses = [socket.inet_aton(self.address)],
                            port = PORT,
                            properties = {
                                'version': '0.0.1',
                                'id_page': '/id',
                                'settings' : '/set'
                            } )
        except:
            serviceInfo = ServiceInfo("_sensor._tcp.%s." % self.__net_suffix,
                            self.uid + "._sensor._tcp.%s." % self.__net_suffix,
                            address = socket.inet_aton(self.address),
                            port = PORT,
                            properties = {
                                'version': '0.0.1',
                                'id_page': '/id',
                                'settings' : '/set'
                            } )
            

                
        zeroconf = Zeroconf()
        zeroconf.register_service(serviceInfo)
Пример #35
0
class DiscoveryServerService:
    _SERVICE_TYPE = '_http._tcp.local.'
    _SERVICE_NAME = 'sound-system-server._http._tcp.local.'

    def __init__(self, host, port):
        self._host = host
        self._port = port
        self._zeroconf = None
        self._info = None
        self._registered = False

    def start(self):
        if not self._registered:
            self._zeroconf = Zeroconf()
            self._start_service()

    def stop(self):
        if self._registered:
            self._zeroconf.unregister_all_services()
            self._zeroconf = None
            self._registered = False

    def _start_service(self):
        self._info = ServiceInfo(self._SERVICE_TYPE, self._SERVICE_NAME,
                                 socket.inet_aton(self._host), self._port, 0,
                                 0, {})
        logging.debug('Registered zeroconf service %s host %s:%d',
                      self._SERVICE_NAME, self._host, self._port)
        self._zeroconf.register_service(self._info)
        self._registered = True
Пример #36
0
def setup(hass, config):
    """Set up Zeroconf and make Home Assistant discoverable."""
    from zeroconf import Zeroconf, ServiceInfo

    zeroconf = Zeroconf()

    zeroconf_name = '{}.{}'.format(uuid_util.get_mac_address(), ZEROCONF_TYPE)

    dev_uuid = uuid_util.get_uuid(hass.config.config_dir)
    params = {
        'version': CUR_VERSION,
        'uuid': dev_uuid
    }

    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, host_ip_pton,
                       hass.http.server_port, 0, 0, params)

    zeroconf.register_service(info)

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

    hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zeroconf)

    return True
Пример #37
0
class GlancesAutoDiscoverClient(object):

    """Implementation of the zeroconf protocol (client side for the Glances server)."""

    def __init__(self, hostname, args=None):
        if zeroconf_tag:
            zeroconf_bind_address = args.bind_address
            try:
                self.zeroconf = Zeroconf()
            except socket.error as e:
                logger.error("Cannot start zeroconf: {}".format(e))

            # XXX *BSDs: Segmentation fault (core dumped)
            # -- https://bitbucket.org/al45tair/netifaces/issues/15
            if not BSD:
                try:
                    # -B @ overwrite the dynamic IPv4 choice
                    if zeroconf_bind_address == '0.0.0.0':
                        zeroconf_bind_address = self.find_active_ip_address()
                except KeyError:
                    # Issue #528 (no network interface available)
                    pass

            # Check IP v4/v6
            address_family = socket.getaddrinfo(zeroconf_bind_address, args.port)[0][0]

            # Start the zeroconf service
            self.info = ServiceInfo(
                zeroconf_type, '{}:{}.{}'.format(hostname, args.port, zeroconf_type),
                address=socket.inet_pton(address_family, zeroconf_bind_address),
                port=args.port, weight=0, priority=0, properties={}, server=hostname)
            try:
                self.zeroconf.register_service(self.info)
            except socket.error as e:
                logger.error("Error while announcing Glances server: {}".format(e))
            else:
                print("Announce the Glances server on the LAN (using {} IP address)".format(zeroconf_bind_address))
        else:
            logger.error("Cannot announce Glances server on the network: zeroconf library not found.")

    @staticmethod
    def find_active_ip_address():
        """Try to find the active IP addresses."""
        import netifaces
        # Interface of the default gateway
        gateway_itf = netifaces.gateways()['default'][netifaces.AF_INET][1]
        # IP address for the interface
        return netifaces.ifaddresses(gateway_itf)[netifaces.AF_INET][0]['addr']

    def close(self):
        if zeroconf_tag:
            self.zeroconf.unregister_service(self.info)
            self.zeroconf.close()
Пример #38
0
class ZeroconfService(AbstractZeroconfService):
    """
    :class:`ZeroconfService` uses `python zeroconf`_

    .. _python zeroconf: https://pypi.org/project/zeroconf/

    Install::

    .. code-block:: bash

        pip install zeroconf
    """

    def __init__(self, name, port):
        super(ZeroconfService, self).__init__(name, port)

        self._zeroconf = None
        self._infos = []

    @classmethod
    def has_support(cls):
        return support

    def start(self):
        self._zeroconf = Zeroconf()
        for index, ip in enumerate(self.ips):
            info = self._gerenate_service_info(index, ip)
            self._infos.append(info)

            self._zeroconf.register_service(info)
            self._log('Zeroconf {} - Registered service: name={}, regtype={}, domain={}', self.__class__.__name__,
                      self.name, self.type, 'local.')
            self._log('         Network: {}', ip)

    def _gerenate_service_info(self, index, ip):
        name = '{}-{}.{}.local.'.format(self.name.lower(), index, self.type, '.local.')

        return ServiceInfo(
            self.type + '.local.',
            name,
            socket.inet_aton(ip),
            self.port,
            0,
            0,
            {}
        )

    def close(self):
        for info in self._infos:
            self._zeroconf.unregister_service(info)
def createService():

    zeroconf = Zeroconf()
    # Look up info's __init__ in python-zeroconf's documentation #
    info = ServiceInfo("_http._tcp.local.", "Takiyaki._http._tcp.local.", socket.inet_aton(socket.gethostbyname(socket.gethostname())), 8080,0,0,socket.gethostname() + ".local.")
    # Server is supported but not compulsory, set server as inputted name #
    print "Registered Service [" + info.name + "]"
    zeroconf.register_service(info)

    try:
        while True: sleep(0.1)
    except KeyboardInterrupt:
        zeroconf.unregister_service(info)
        print("Unregistered")
        zeroconf.close()
    print("Service registered")
    zeroconf.close()
Пример #40
0
class GlancesAutoDiscoverClient(object):

    """Implementation of the zeroconf protocol (client side for the Glances server)."""

    def __init__(self, hostname, args=None):
        if zeroconf_tag:
            zeroconf_bind_address = args.bind_address
            try:
                self.zeroconf = Zeroconf()
            except socket.error as e:
                logger.error("Cannot start zeroconf: {0}".format(e))

            try:
                # -B @ overwrite the dynamic IPv4 choice
                if zeroconf_bind_address == '0.0.0.0':
                    zeroconf_bind_address = self.find_active_ip_address()
            except KeyError:
                # Issue #528 (no network interface available)
                pass

            print("Announce the Glances server on the LAN (using {0} IP address)".format(zeroconf_bind_address))
            self.info = ServiceInfo(
                zeroconf_type, '{0}:{1}.{2}'.format(hostname, args.port, zeroconf_type),
                address=socket.inet_aton(zeroconf_bind_address), port=args.port,
                weight=0, priority=0, properties={}, server=hostname)
            self.zeroconf.register_service(self.info)
        else:
            logger.error("Cannot announce Glances server on the network: zeroconf library not found.")

    @staticmethod
    def find_active_ip_address():
        """Try to find the active IP addresses."""
        if not 'freebsd' in sys.platform:
            import netifaces
            # Interface of the default gateway
            gateway_itf = netifaces.gateways()['default'][netifaces.AF_INET][1]
            # IP address for the interface
            return netifaces.ifaddresses(gateway_itf)[netifaces.AF_INET][0]['addr']
        else:
            raise KeyError, 'On FreeBSD, this would segfault'

    def close(self):
        if zeroconf_tag:
            self.zeroconf.unregister_service(self.info)
            self.zeroconf.close()
class GlancesAutoDiscoverClient(object):

    """Implementation of the zeroconf protocol (client side for the Glances server)."""

    def __init__(self, hostname, args=None):
        if zeroconf_tag:
            zeroconf_bind_address = args.bind_address
            try:
                self.zeroconf = Zeroconf()
            except socket.error as e:
                logger.error("Cannot start zeroconf: {0}".format(e))

            if netifaces_tag:
                # -B @ overwrite the dynamic IPv4 choice
                if zeroconf_bind_address == '0.0.0.0':
                    zeroconf_bind_address = self.find_active_ip_address()
            else:
                logger.error("Couldn't find the active IP address: netifaces library not found.")

            logger.info("Announce the Glances server on the LAN (using {0} IP address)".format(zeroconf_bind_address))
            print("Announce the Glances server on the LAN (using {0} IP address)".format(zeroconf_bind_address))

            self.info = ServiceInfo(
                zeroconf_type, '{0}:{1}.{2}'.format(hostname, args.port, zeroconf_type),
                address=socket.inet_aton(zeroconf_bind_address), port=args.port,
                weight=0, priority=0, properties={}, server=hostname)
            self.zeroconf.register_service(self.info)
        else:
            logger.error("Cannot announce Glances server on the network: zeroconf library not found.")

    def find_active_ip_address(self):
        """Try to find the active IP addresses."""
        try:
            # Interface of the default gateway
            gateway_itf = netifaces.gateways()['default'][netifaces.AF_INET][1]
            # IP address for the interface
            return netifaces.ifaddresses(gateway_itf)[netifaces.AF_INET][0]['addr']
        except Exception:
            return None

    def close(self):
        if zeroconf_tag:
            self.zeroconf.unregister_service(self.info)
            self.zeroconf.close()
Пример #42
0
class Advertisement(object):
    def __init__(self, ip=None):
        """
        :ip: if string `ip` given, register on given IP
             (if None: default route's IP).
        """
        self.zeroconf = Zeroconf()
        self.info = build_service_info(ip=ip or main_ip())

    def register(self):
        """Registers the service on the network.
        """
        self.zeroconf.register_service(self.info)
        log.debug("Registered {} on {}:{}".format(self.info.name,
                                                   self.ip,
                                                   self.info.port))

    def unregister(self):
        """Unregisters the service.
        """
        self.zeroconf.unregister_service(self.info)
        log.debug("Unregistered touchoscbridge.")

    def update(self, ip=None):
        """Re-register the the service on the network.

        :ip: if string `ip` is given, use given IP when registering.
        """
        self.unregister()
        self.info = build_service_info(ip=ip or main_ip())
        self.register()

    def close(self):
        """Free resources.
        Advertisement.unregister() should be called before closing.
        """
        self.zeroconf.close()

    def get_ip(self):
        """:return: the service's IP as a string.
        """
        return socket.inet_ntoa(self.info.address)

    ip = property(get_ip)
Пример #43
0
class ServiceDiscoveryServer:

    def __init__(self, port):
        inet = netifaces.AF_INET
        hostname = socket.gethostname()
        def_gw = netifaces.gateways()['default'][inet][1]
        addr = netifaces.ifaddresses(def_gw)[inet][0]['addr']
        addr = socket.inet_aton(addr)
        self.zeroconf = Zeroconf()
        self.info = ServiceInfo(
            SRV_TYPE, srv_fqname(), addr, port, 0, 0,
            {}, '{}.local.'.format(hostname)
        )

    def start(self):
        self.zeroconf.register_service(self.info)

    def stop(self):
        self.zeroconf.unregister_service(self.info)
        self.zeroconf.close()
Пример #44
0
    def test_integration_with_listener(self):

        type_ = "_test-srvc-type._tcp.local."
        name = "xxxyyy"
        registration_name = "%s.%s" % (name, type_)

        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_types = ZeroconfServiceTypes.find(interfaces=['127.0.0.1'], timeout=0.5)
            assert type_ in service_types
            service_types = ZeroconfServiceTypes.find(zc=zeroconf_registrar, timeout=0.5)
            assert type_ in service_types

        finally:
            zeroconf_registrar.close()
Пример #45
0
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()
Пример #46
0
    def bootstrap(self):
        try:
            zeroconf = Zeroconf(interfaces=[ self.bootstrap_ip ])
            self._log.debug('Zeroconf instantiated.')
        except:
            self._log.error('Error instantiating zeroconf instance on interface: {0} with IP: {1}'.format(self.iface, self.bootstrap_ip))
            raise

        try:
            zeroconf.register_service(self.service_discovery_def)
            discovery_browser = ServiceBrowser(zeroconf, self.service_discovery_type, handlers=[ self._election_handler ])
            leader_browser = ServiceBrowser(zeroconf, self.service_leader_type, handlers=[ self._election_handler ])
        except:
            self._log.error('Error encountered with registered zeroconf services or browser.')
            raise

        while True:
            sleep(.1)
            if self._discovery_peer_count <= 0:
                log.debug('All peers unregistered from discovery service.')
                break

        if self.election_id == self._leader_id:
            zeroconf.unregister_service(self.service_leader_def)
            self._log.debug('Leader service unregistered.')

        sleep(1)
        try:
            zeroconf.close()
        except:
            self._log.error('Error encountered closing zerconf instance.')
            raise

        self._log.debug('Zerconf instance close.')

        if self.election_id == self._leader_id:
            bootstrap_command = [ self.action ] + self.get_peer_addresses(self._peers)
            self._log.info('Leader performing bootstrap action: {}'.format(' '.join(bootstrap_command)))
            Popen(bootstrap_command)
Пример #47
0
class ZstStage(ZstNode):

    def __init__(self, stageName="stage", port=6000):
        ZstNode.__init__(self, stageName)
        self.zeroconf = Zeroconf()

        address = "tcp://*:" + str(port)
        self.reply.socket.bind(address)

        desc = {'name': self.name}
        addr = socket.gethostbyname(socket.gethostname())
        servicename = "ShowtimeStage"
        self.stageServiceInfo = ServiceInfo("_zeromq._tcp.local.",
           servicename + "._zeromq._tcp.local.",
           socket.inet_aton(addr), port, 0, 0,
           desc)
        self.zeroconf.register_service(self.stageServiceInfo)
        print("Stage active on address " + str(self.reply.socket.getsockopt(zmq.LAST_ENDPOINT)))
        
    def close(self):
        self.zeroconf.unregister_service(self.stageServiceInfo)
        self.zeroconf.close()
        ZstNode.close(self)
Пример #48
0
class Zeroconf(object):
    """ A simple class to publish a network service using zeroconf. """

    def __init__(self, name, port, **kwargs):
        self.zconf = None
        stype = kwargs.get('stype', "_http._tcp.local.")

        full_name = name
        if not name.endswith('.'):
            full_name += '.' + stype

        props = {'txtvers': '1',
                 'iTSh Version': '131073', #'196609'
                 'Machine Name': name,
                 'Password': '******'}

        self.svc_info = ServiceInfo(stype,
                                    full_name,
                                    find_local_ipaddress(),
                                    port,
                                    0,
                                    0,
                                    props)

    def publish(self):
        """ Publish the service to the network. """
        if self.zconf is None:
            self.zconf = ZeroC()
            self.zconf.register_service(self.svc_info)

    def unpublish(self):
        """ Tell the network we're closed :-) """
        if self.zconf is not None:
            self.zconf.unregister_service(self.svc_info)
            self.zconf.close()
            self.zconf = None
Пример #49
0
 local_ip = get_ip()
 
 print 'Webserver listening on {}:{} ...'.format(local_ip, WEBPORT)
 print 'Webservice listening on {}:{} ...'.format(local_ip, WSPORT)
 
 serviceinfo = ServiceInfo(
     '_http._tcp.local.', 
     SERVICENAME+'._http._tcp.local.', 
     socket.inet_aton(local_ip), 
     WEBPORT,
     0,
     0,
     {"desc":SERVICENAME},
     "mute.local."
     )
 serviceconf.register_service(serviceinfo)
 
 log.startLogging(sys.stdout)
 
 # factory = WebSocketServerFactory(u"ws://127.0.0.1:9000")
 factory = WebSocketServerFactory()
 factory.protocol = MuteServerProtocol
 # factory.setProtocolOptions(maxConnections=2)
  
 signal.signal(signal.SIGINT, customHandler)
 
 reactor.listenTCP(WSPORT, factory)
 
 webdir = File("../CLIENT")
 webdir.putChild('wsport.js', WSPortJs())
 web = Site(webdir)
Пример #50
0
class Server:
    def run(self):
        self.find_plasma_trim()
        self.register_service()
        self.run_web_server()
        self.write_plasma_trim_changes()
    
    def find_plasma_trim(self):
        plasmas = plasmatrim.find()
        self.plasma = plasmas[0]
    
    def register_service(self):
        ip_address = socket.gethostbyname(socket.gethostname())
        type = "_radiance._tcp.local."
        hostname = socket.gethostname()
        split_index = hostname.find(".local")
        if split_index > 0:
            hostname = hostname[:split_index]
        name = str("%s.%s") % (hostname, type)
        self.service = ServiceInfo(type, name, socket.inet_aton(ip_address), 8080, 0, 0, name)
        
        self.zeroconf = Zeroconf()
        self.zeroconf.register_service(self.service)
    
    def run_web_server(self):
        self.render = web.template.render('templates/')
        
        urls = (
            '/', 'Home',
            '/api/color', 'API_Color',
            '/api/brightness', 'API_Brightness'
        )
        self.app = web.application(urls, globals())
        self.app.add_processor(web.loadhook(self.load_plasma_trim))
        self.app.add_processor(web.loadhook(self.load_renderer))
        self.app.add_processor(web.loadhook(self.load_main_thread_queue))
        
        self.web_server_thread = Thread(None, self.app.run)
        self.web_server_thread.start()
    
    def write_plasma_trim_changes(self):
        signal.signal(signal.SIGINT, self.handle_ctrl_c)
        self.callback_queue = Queue.Queue()
        while True:
            try:
                callback = self.callback_queue.get(False)
            except Queue.Empty:
                continue
            callback()
    
    def load_plasma_trim(self):
        web.ctx['plasma'] = self.plasma
    
    def load_renderer(self):
        web.ctx['render'] = self.render
    
    def load_main_thread_queue(self):
        web.ctx['callback_queue'] = self.callback_queue
    
    def handle_ctrl_c(self, signal, frame):
        print "Exiting"
        os._exit(0)
    def test_ttl(self):

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

        # service definition
        type_ = "_test-srvc-type._tcp.local."
        name = "xxxyyy"
        registration_name = "%s.%s" % (name, type_)

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

        # 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
        nbr_answers = [0, None]
        nbr_additionals = [0, None]
        nbr_authorities = [0, None]

        def send(out, addr=r._MDNS_ADDR, port=r._MDNS_PORT):
            """Sends an outgoing packet."""
            for answer, time_ in out.answers:
                nbr_answers[0] += 1
                assert answer.ttl == expected_ttl
            for answer in out.additionals:
                nbr_additionals[0] += 1
                assert answer.ttl == expected_ttl
            for answer in out.authorities:
                nbr_authorities[0] += 1
                assert answer.ttl == expected_ttl
            old_send(out, addr=addr, port=port)

        # monkey patch the zeroconf send
        zc.send = send

        # register service with default TTL
        expected_ttl = r._DNS_TTL
        zc.register_service(info)
        assert nbr_answers[0] == 12 and nbr_additionals[0] == 0 and nbr_authorities[0] == 3
        nbr_answers[0] = nbr_additionals[0] = nbr_authorities[0] = 0

        # query
        query = r.DNSOutgoing(r._FLAGS_QR_QUERY | r._FLAGS_AA)
        query.add_question(r.DNSQuestion(info.type, r._TYPE_PTR, r._CLASS_IN))
        query.add_question(r.DNSQuestion(info.name, r._TYPE_SRV, r._CLASS_IN))
        query.add_question(r.DNSQuestion(info.name, r._TYPE_TXT, r._CLASS_IN))
        query.add_question(r.DNSQuestion(info.server, r._TYPE_A, r._CLASS_IN))
        zc.handle_query(query, r._MDNS_ADDR, r._MDNS_PORT)
        assert nbr_answers[0] == 4 and nbr_additionals[0] == 1 and nbr_authorities[0] == 0
        nbr_answers[0] = nbr_additionals[0] = nbr_authorities[0] = 0

        # unregister
        expected_ttl = 0
        zc.unregister_service(info)
        assert nbr_answers[0] == 12 and nbr_additionals[0] == 0 and nbr_authorities[0] == 0
        nbr_answers[0] = nbr_additionals[0] = nbr_authorities[0] = 0

        # register service with custom TTL
        expected_ttl = r._DNS_TTL * 2
        assert expected_ttl != r._DNS_TTL
        zc.register_service(info, ttl=expected_ttl)
        assert nbr_answers[0] == 12 and nbr_additionals[0] == 0 and nbr_authorities[0] == 3
        nbr_answers[0] = nbr_additionals[0] = nbr_authorities[0] = 0

        # query
        query = r.DNSOutgoing(r._FLAGS_QR_QUERY | r._FLAGS_AA)
        query.add_question(r.DNSQuestion(info.type, r._TYPE_PTR, r._CLASS_IN))
        query.add_question(r.DNSQuestion(info.name, r._TYPE_SRV, r._CLASS_IN))
        query.add_question(r.DNSQuestion(info.name, r._TYPE_TXT, r._CLASS_IN))
        query.add_question(r.DNSQuestion(info.server, r._TYPE_A, r._CLASS_IN))
        zc.handle_query(query, r._MDNS_ADDR, r._MDNS_PORT)
        assert nbr_answers[0] == 4 and nbr_additionals[0] == 1 and nbr_authorities[0] == 0
        nbr_answers[0] = nbr_additionals[0] = nbr_authorities[0] = 0

        # unregister
        expected_ttl = 0
        zc.unregister_service(info)
        assert nbr_answers[0] == 12 and nbr_additionals[0] == 0 and nbr_authorities[0] == 0
        nbr_answers[0] = nbr_additionals[0] = nbr_authorities[0] = 0
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()
Пример #53
0
Файл: put.py Проект: mchafu/zget
def put(
    filename,
    output=None,
    interface=None,
    address=None,
    port=None,
    reporthook=None,
    timeout=None,
):
    """Send a file using the zget protocol.

    Parameters
    ----------
    filename : string
        The filename to be transferred
    output : string
        The alias to share on the network. Optional. If empty, the input
        filename will be used.
    interface : string
        The network interface to use. Optional.
    address : string
        The network address to use. Optional.
    port : int
        The network port to use. Optional.
    reporthook : callable
        A hook that will be called during transfer. Handy for watching the
        transfer. See :code:`urllib.urlretrieve` for callback parameters.
        Optional.
    timeout : int
        Seconds to wait until process is aborted. A running transfer is not
        aborted even when timeout was hit. Optional.

    Raises
    -------
    TimeoutException
        When a timeout occurred.

    """
    if port is None:
        port = utils.config().getint('DEFAULT', 'port')

    if interface is None:
        interface = utils.config().get('DEFAULT', 'interface')

    if not 0 <= port <= 65535:
        raise ValueError(_("Port %d exceeds allowed range") % port)

    basename = os.path.basename(filename)

    filehashes = []
    filehashes.append(hashlib.sha1(basename.encode('utf-8')).hexdigest())
    if output is not None:
        filehashes.append(hashlib.sha1(output.encode('utf-8')).hexdigest())

    if interface is None:
        interface = utils.default_interface()

    if address is None:
        address = utils.ip_addr(interface)

    server = StateHTTPServer((address, port), FileHandler)
    server.timeout = timeout
    server.filename = filename
    server.allowed_basenames.append(basename)
    if output is not None:
        server.allowed_basenames.append(output)
    server.reporthook = reporthook

    port = server.server_port

    utils.logger.debug(
        _("Using interface %s") % interface
    )

    utils.logger.debug(
        _("Listening on %(a)s:%(p)d \n"
          "you may change address using --address and "
          "port using --port") % {'a': address, 'p': port}
    )

    zeroconf = Zeroconf()

    infos = []
    for filehash in filehashes:
        utils.logger.debug(
            _("Broadcasting as %s._zget._http._tcp.local.") % filehash
        )
        infos.append(ServiceInfo(
            "_zget._http._tcp.local.",
            "%s._zget._http._tcp.local." % filehash,
            socket.inet_aton(address), port, 0, 0,
            {'path': None}
        ))

    try:
        for info in infos:
            zeroconf.register_service(info)
        server.handle_request()
    except KeyboardInterrupt:
        pass

    server.socket.close()
    for info in infos:
        zeroconf.unregister_service(info)
    zeroconf.close()

    if timeout is not None and not server.downloaded:
        raise utils.TimeoutException()
    else:
        utils.logger.info(_("Done."))
Пример #54
0
    logging.basicConfig(level=logging.DEBUG)
    if len(sys.argv) > 1:
        assert sys.argv[1:] == ['--debug']
        logging.getLogger('zeroconf').setLevel(logging.DEBUG)

    # Test a few module features, including service registration, service
    # query (for Zoe), and service unregistration.
    print("Multicast DNS Service Discovery for Python, version %s" % (__version__,))
    r = Zeroconf()
    print("1. Testing registration of a service...")
    desc = {'version': '0.10', 'a': 'test value', 'b': 'another value'}
    info = ServiceInfo("_http._tcp.local.",
                       "My Service Name._http._tcp.local.",
                       socket.inet_aton("127.0.0.1"), 1234, 0, 0, desc)
    print("   Registering service...")
    r.register_service(info)
    print("   Registration done.")
    print("2. Testing query of service information...")
    print("   Getting ZOE service: %s" % (
        r.get_service_info("_http._tcp.local.", "ZOE._http._tcp.local.")))
    print("   Query done.")
    print("3. Testing query of own service...")
    queried_info = r.get_service_info("_http._tcp.local.", "My Service Name._http._tcp.local.")
    assert queried_info
    print("   Getting self: %s" % (queried_info,))
    print("   Query done.")
    print("4. Testing unregister of service information...")
    r.unregister_service(info)
    print("   Unregister done.")
    r.close()
Пример #55
0
    def test_integration_with_listener_class(self):

        service_added = Event()
        service_removed = Event()
        service_updated = Event()

        subtype_name = "My special Subtype"
        type_ = "_http._tcp.local."
        subtype = subtype_name + "._sub." + type_
        name = "xxxyyyæøå"
        registration_name = "%s.%s" % (name, subtype)

        class MyListener(r.ServiceListener):
            def add_service(self, zeroconf, type, name):
                zeroconf.get_service_info(type, name)
                service_added.set()

            def remove_service(self, zeroconf, type, name):
                service_removed.set()

        class MySubListener(r.ServiceListener):
            def add_service(self, zeroconf, type, name):
                pass

            def remove_service(self, zeroconf, type, name):
                pass

            def update_service(self, zeroconf, type, name):
                service_updated.set()

        listener = MyListener()
        zeroconf_browser = Zeroconf(interfaces=['127.0.0.1'])
        zeroconf_browser.add_service_listener(subtype, listener)

        properties = dict(
            prop_none=None,
            prop_string=b'a_prop',
            prop_float=1.0,
            prop_blank=b'a blanked string',
            prop_true=1,
            prop_false=0,
        )

        zeroconf_registrar = Zeroconf(interfaces=['127.0.0.1'])
        desc = {'path': '/~paulsm/'}  # type: r.ServicePropertiesType
        desc.update(properties)
        info_service = ServiceInfo(
            subtype, registration_name, socket.inet_aton("10.0.1.2"), 80, 0, 0, desc, "ash-2.local."
        )
        zeroconf_registrar.register_service(info_service)

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

            # short pause to allow multicast timers to expire
            time.sleep(3)

            # clear the answer cache to force query
            for record in zeroconf_browser.cache.entries():
                zeroconf_browser.cache.remove(record)

            # get service info without answer cache
            info = zeroconf_browser.get_service_info(type_, registration_name)
            assert info is not None
            assert info.properties[b'prop_none'] is False
            assert info.properties[b'prop_string'] == properties['prop_string']
            assert info.properties[b'prop_float'] is False
            assert info.properties[b'prop_blank'] == properties['prop_blank']
            assert info.properties[b'prop_true'] is True
            assert info.properties[b'prop_false'] is False

            info = zeroconf_browser.get_service_info(subtype, registration_name)
            assert info is not None
            assert info.properties[b'prop_none'] is False

            # Begin material test addition
            sublistener = MySubListener()
            zeroconf_browser.add_service_listener(registration_name, sublistener)
            properties['prop_blank'] = b'an updated string'
            desc.update(properties)
            info_service = ServiceInfo(
                subtype, registration_name, socket.inet_aton("10.0.1.2"), 80, 0, 0, desc, "ash-2.local."
            )
            zeroconf_registrar.update_service(info_service)
            service_updated.wait(1)
            assert service_updated.is_set()

            info = zeroconf_browser.get_service_info(type_, registration_name)
            assert info is not None
            assert info.properties[b'prop_blank'] == properties['prop_blank']
            # End material test addition

            zeroconf_registrar.unregister_service(info_service)
            service_removed.wait(1)
            assert service_removed.is_set()

        finally:
            zeroconf_registrar.close()
            zeroconf_browser.remove_service_listener(listener)
            zeroconf_browser.close()
Пример #56
0
    def test_integration_with_listener_class(self):

        service_added = Event()
        service_removed = Event()

        type_ = "_http._tcp.local."
        name = "xxxyyy"
        registration_name = "%s.%s" % (name, type_)

        class MyListener(object):
            def add_service(self, zeroconf, type, name):
                zeroconf.get_service_info(type, name)
                service_added.set()

            def remove_service(self, zeroconf, type, name):
                service_removed.set()

        zeroconf_browser = Zeroconf()
        zeroconf_browser.add_service_listener(type_, MyListener())

        properties = dict(
            prop_none=None,
            prop_string=b'a_prop',
            prop_float=1.0,
            prop_blank=b'a blanked string',
            prop_true=1,
            prop_false=0,
        )

        zeroconf_registrar = Zeroconf()
        desc = {'path': '/~paulsm/'}
        desc.update(properties)
        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()

            # short pause to allow multicast timers to expire
            time.sleep(2)

            # clear the answer cache to force query
            for record in zeroconf_browser.cache.entries():
                zeroconf_browser.cache.remove(record)

            # get service info without answer cache
            info = zeroconf_browser.get_service_info(type_, registration_name)

            assert info.properties[b'prop_none'] is False
            assert info.properties[b'prop_string'] == properties['prop_string']
            assert info.properties[b'prop_float'] is False
            assert info.properties[b'prop_blank'] == properties['prop_blank']
            assert info.properties[b'prop_true'] is True
            assert info.properties[b'prop_false'] is False

            zeroconf_registrar.unregister_service(info)
            service_removed.wait(1)
            assert service_removed.is_set()
        finally:
            zeroconf_registrar.close()
            zeroconf_browser.close()
Пример #57
0
    def test_ttl(self):

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

        # service definition
        type_ = "_test-srvc-type._tcp.local."
        name = "xxxyyy"
        registration_name = "%s.%s" % (name, type_)

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

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

        nbr_answers = nbr_additionals = nbr_authorities = 0

        def get_ttl(record_type):
            if expected_ttl is not None:
                return expected_ttl
            elif record_type in [r._TYPE_A, r._TYPE_SRV]:
                return r._DNS_HOST_TTL
            else:
                return r._DNS_OTHER_TTL

        def send(out, addr=r._MDNS_ADDR, port=r._MDNS_PORT):
            """Sends an outgoing packet."""
            nonlocal nbr_answers, nbr_additionals, nbr_authorities

            for answer, time_ in out.answers:
                nbr_answers += 1
                assert answer.ttl == get_ttl(answer.type)
            for answer in out.additionals:
                nbr_additionals += 1
                assert answer.ttl == get_ttl(answer.type)
            for answer in out.authorities:
                nbr_authorities += 1
                assert answer.ttl == get_ttl(answer.type)
            old_send(out, addr=addr, port=port)

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

        # register service with default TTL
        expected_ttl = None
        zc.register_service(info)
        assert nbr_answers == 12 and nbr_additionals == 0 and nbr_authorities == 3
        nbr_answers = nbr_additionals = nbr_authorities = 0

        # query
        query = r.DNSOutgoing(r._FLAGS_QR_QUERY | r._FLAGS_AA)
        query.add_question(r.DNSQuestion(info.type, r._TYPE_PTR, r._CLASS_IN))
        query.add_question(r.DNSQuestion(info.name, r._TYPE_SRV, r._CLASS_IN))
        query.add_question(r.DNSQuestion(info.name, r._TYPE_TXT, r._CLASS_IN))
        query.add_question(r.DNSQuestion(info.server, r._TYPE_A, r._CLASS_IN))
        zc.handle_query(r.DNSIncoming(query.packet()), r._MDNS_ADDR, r._MDNS_PORT)
        assert nbr_answers == 4 and nbr_additionals == 1 and nbr_authorities == 0
        nbr_answers = nbr_additionals = nbr_authorities = 0

        # unregister
        expected_ttl = 0
        zc.unregister_service(info)
        assert nbr_answers == 12 and nbr_additionals == 0 and nbr_authorities == 0
        nbr_answers = nbr_additionals = nbr_authorities = 0

        # register service with custom TTL
        expected_ttl = r._DNS_HOST_TTL * 2
        assert expected_ttl != r._DNS_HOST_TTL
        zc.register_service(info, ttl=expected_ttl)
        assert nbr_answers == 12 and nbr_additionals == 0 and nbr_authorities == 3
        nbr_answers = nbr_additionals = nbr_authorities = 0

        # query
        query = r.DNSOutgoing(r._FLAGS_QR_QUERY | r._FLAGS_AA)
        query.add_question(r.DNSQuestion(info.type, r._TYPE_PTR, r._CLASS_IN))
        query.add_question(r.DNSQuestion(info.name, r._TYPE_SRV, r._CLASS_IN))
        query.add_question(r.DNSQuestion(info.name, r._TYPE_TXT, r._CLASS_IN))
        query.add_question(r.DNSQuestion(info.server, r._TYPE_A, r._CLASS_IN))
        zc.handle_query(r.DNSIncoming(query.packet()), r._MDNS_ADDR, r._MDNS_PORT)
        assert nbr_answers == 4 and nbr_additionals == 1 and nbr_authorities == 0
        nbr_answers = nbr_additionals = nbr_authorities = 0

        # unregister
        expected_ttl = 0
        zc.unregister_service(info)
        assert nbr_answers == 12 and nbr_additionals == 0 and nbr_authorities == 0
        nbr_answers = nbr_additionals = nbr_authorities = 0
Пример #58
0
import logging
import socket
import sys
from time import sleep

from zeroconf import ServiceInfo, Zeroconf

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

    desc = {'version': '0.1'}
    info = ServiceInfo("_http._tcp.local.",
                       "pispotify._http._tcp.local.",
                       socket.inet_aton("192.168.0.17"), 80, 0, 0, desc) #use the right ip
    
    zeroconf = Zeroconf()
    print("Registration of a service, press Ctrl-C to exit...")
    zeroconf.register_service(info)
    try:
        while True:
            sleep(0.1)
    except KeyboardInterrupt:
        pass
    finally:
        print("Unregistering...")
        zeroconf.unregister_service(info)
        zeroconf.close()
Пример #59
0
class VoicePlayZeroConf(object):
    """
    Very basic mDNS/Zeroconf check/registration
    """
    def __init__(self):
        self.zeroconf = None
        self.known_servers = []
        self.info = None
        self.threads = None
        self.exit = False

    @staticmethod
    def get_ip_address():
        """
        Get my IP
        """
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("8.8.8.8", 80))
        return s.getsockname()[0]

    def service_info(self, hostname):
        """
        Prepare service information for (my) hostname
        """
        port = int(Config.cfg_data().get('webapp_port'))
        info = ServiceInfo("_http._tcp.local.",
                           "{0!s}._http._tcp.local.".format(hostname),
                           socket.inet_aton(self.get_ip_address()), port, 0, 0,
                           {'path': '/'}, "{0!s}.local.".format(hostname))
        return info

    def on_service_state_change(self, zeroconf, service_type, name, state_change):
        """
        Service state change callback
        """
        if state_change is ServiceStateChange.Added:
            info = zeroconf.get_service_info(service_type, name)
            if info and not info.server in self.known_servers:
                self.known_servers.append(info.server)

    def get_others(self):
        """
        Wait for other services to make themselves visible
        """
        zeroconf = Zeroconf()
        _ = ServiceBrowser(zeroconf, "_http._tcp.local.", handlers=[self.on_service_state_change])
        for _ in range(1, 10 + 1):
            time.sleep(1)
        zeroconf.close()
        return self.known_servers

    def run(self):
        """
        Actual Zeroconf runner
        """
        # has to be here, otherwise quick start/stop will not provide self.zeroconf descriptor
        self.zeroconf = Zeroconf()
        servers = self.get_others()
        hostname = __title__.lower()
        if '{0!s}.local'.format(hostname) in servers:
            hostname = '{0!s}-{1!s}'.format(__title__.lower(), str(uuid.uuid4()))
        self.info = self.service_info(hostname)
        self.zeroconf.register_service(self.info)
        while not self.exit:
            try:
                time.sleep(0.1)
            except Exception as _:
                break

    def unregister(self):
        """
        Unregister (remove) service from local network
        """
        if self.info:
            self.zeroconf.unregister_service(self.info)
        self.zeroconf.close()

    def start(self):
        """
        Start Zeroconf inside thread
        """
        self.threads = ThreadGroup()
        self.threads.targets = [self.run]
        self.threads.start_all()

    def stop(self):
        """
        Stop and unregister Zeroconf service
        """
        self.exit = True
        self.unregister()
        if self.threads:
            self.threads.stop_all()
Пример #60
0
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()