Пример #1
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)
Пример #2
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
Пример #3
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")
Пример #4
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)
Пример #5
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()
Пример #6
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()
Пример #7
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()
        zeroconf_registrar.unregister_service(info)
        service_removed.wait(1)
        assert service_removed.is_set()
    finally:
        zeroconf_registrar.close()
        browser.cancel()
        zeroconf_browser.close()
Пример #8
0
class RegisterCar():
    def __init__(self):
        self.zeroconf = None
        self.info = None

    def register_car(self, name):
        my_ip_address = [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1] # Link: https://stackoverflow.com/questions/166506/finding-local-ip-addresses-using-pythons-stdlib

        if len(my_ip_address) > 0:
            logging.info("Service IP: " + my_ip_address[0])
            my_ip_address = socket.inet_aton(my_ip_address[0])
            
            desc = {'name': name}
            self.info = ServiceInfo("_http._tcp.local.",
                               name + " DrivingMatter._http._tcp.local.",
                               my_ip_address, 80, 0, 0, desc)

            self.zeroconf = Zeroconf()
            logging.info("Registration of a service, press Ctrl-C to exit...")
            self.zeroconf.register_service(self.info)
            return True
        else:
            logging.error("No network interface available, please connect to any network")
            #raise Exception("No network interface")
            return False

    def unregister_car(self):
        if self.zeroconf:
            self.zeroconf.unregister_service(self.info)
            self.zeroconf.close()    
            logging.info("Service unregistered successfully")
        else:
            logging.error("No Zeroconf established yet")
Пример #9
0
    def test_01(self):
        """Node can discover network registration service via mDNS"""

        test = Test("Node can discover network registration service via mDNS")

        self.registry.reset()

        default_gw_interface = netifaces.gateways()['default'][
            netifaces.AF_INET][1]
        default_ip = netifaces.ifaddresses(default_gw_interface)[
            netifaces.AF_INET][0]['addr']

        # TODO: Set api_ver to just the version under test. Later test support for parsing CSV string
        txt = {'api_ver': self.test_version, 'api_proto': 'http', 'pri': '0'}
        info = ServiceInfo("_nmos-registration._tcp.local.",
                           "NMOS Test Suite._nmos-registration._tcp.local.",
                           socket.inet_aton(default_ip), 5000, 0, 0, txt,
                           "nmos-test.local.")

        zeroconf = Zeroconf()
        zeroconf.register_service(info)

        while (
                time.time() - self.registry.last_time
        ) < 5:  # Ensure we allow 5 seconds to get at least one heartbeat
            time.sleep(1)

        zeroconf.unregister_service(info)
        zeroconf.close()

        if len(self.registry.get_data()) > 0:
            return test.PASS()

        return test.FAIL(
            "Node did not attempt to register with the advertised registry.")
Пример #10
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()
        zeroconf_registrar.unregister_service(info)
        service_removed.wait(1)
        assert service_removed.is_set()
    finally:
        zeroconf_registrar.close()
        browser.cancel()
        zeroconf_browser.close()
Пример #11
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()
Пример #12
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

            self.info = ServiceInfo(
                zeroconf_type,
                '{}:{}.{}'.format(hostname, args.port, zeroconf_type),
                address=socket.inet_aton(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()
Пример #13
0
def test_ptr_optimization():

    # 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, 80, 0, 0, desc, "ash-2.local.", addresses=[socket.inet_aton("10.0.1.2")]
    )

    # register
    zc.register_service(info)

    # Verify we won't respond for 1s with the same multicast
    query = r.DNSOutgoing(const._FLAGS_QR_QUERY)
    query.add_question(r.DNSQuestion(info.type, const._TYPE_PTR, const._CLASS_IN))
    unicast_out, multicast_out = zc.query_handler.response(
        [r.DNSIncoming(packet) for packet in query.packets()], None, const._MDNS_PORT
    )
    assert unicast_out is None
    assert multicast_out is None

    # Clear the cache to allow responding again
    _clear_cache(zc)

    # Verify we will now respond
    query = r.DNSOutgoing(const._FLAGS_QR_QUERY)
    query.add_question(r.DNSQuestion(info.type, const._TYPE_PTR, const._CLASS_IN))
    unicast_out, multicast_out = zc.query_handler.response(
        [r.DNSIncoming(packet) for packet in query.packets()], None, const._MDNS_PORT
    )
    assert multicast_out.id == query.id
    assert unicast_out is None
    assert multicast_out is not None
    has_srv = has_txt = has_a = False
    nbr_additionals = 0
    nbr_answers = len(multicast_out.answers)
    nbr_authorities = len(multicast_out.authorities)
    for answer in multicast_out.additionals:
        nbr_additionals += 1
        if answer.type == const._TYPE_SRV:
            has_srv = True
        elif answer.type == const._TYPE_TXT:
            has_txt = True
        elif answer.type == const._TYPE_A:
            has_a = True
    assert nbr_answers == 1 and nbr_additionals == 3 and nbr_authorities == 0
    assert has_srv and has_txt and has_a

    # unregister
    zc.unregister_service(info)
    zc.close()
Пример #14
0
class AirplayServer(HTTPServer):
    """
    Start an Airplay remote server on this device with a specific port.
    Available Events:
        - on_remote_command(AirplayCommand)
    """
    def __init__(self, dacp_id, active_remote, port=52485):
        super(AirplayServer, self).__init__(("", port), RequestHandler)

        self.dacp_id = dacp_id
        self.active_remote = active_remote

        self.on_remote_command = EventHook()

        hostname = socket.gethostname()
        local_ip = socket.gethostbyname(hostname)

        # setup the service information
        self.info = ServiceInfo(type_=AIRPLAY_ZEROCONF_SERVICE,
                                name="iTunes_Ctrl_{0}.{1}".format(
                                    dacp_id, AIRPLAY_ZEROCONF_SERVICE),
                                address=socket.inet_aton(local_ip),
                                port=port,
                                properties={},
                                server="{0}.local.".format(hostname))

        self._zeroconf = Zeroconf()

    def start(self):
        """
        Start the main http server and register the dacp service.
        :return: server thread
        """

        thread = Thread(target=self.serve_forever, daemon=True)
        thread.start()
        logger.debug("Started HTTP server on port: %s", self.info.port)

        # register a zeroconf dacp service
        self._zeroconf.register_service(self.info)
        logger.debug("Published service with info: %s", self.info)

        return thread

    def stop(self):
        """
        Close the current server.
        :return:
        """
        # unregister zero conf service
        self._zeroconf.unregister_service(self.info)
        self._zeroconf.close()
        logger.debug("Removed service with info: %s", self.info)

        # shutdown the http server
        self.shutdown()
        logger.debug("Stopped HTTP server on port: %s", self.info.port)
Пример #15
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))

            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()
Пример #16
0
def mDNS():
	#zerconf info
	#logging.basicConfig(level=logging.DEBUG)
	#logging.getLogger('zeroconf').setLevel(logging.DEBUG)
	info = []
	zeroconf = Zeroconf(InterfaceChoice.All)
	output = subprocess.check_output('for /f "usebackq tokens=2 delims=:" %f in (`ipconfig ^| findstr /c:"IPv4 Address"`) do @echo off && echo%f',shell=True , stderr=subprocess.STDOUT,stdin=subprocess.PIPE).decode("utf-8")
	#F**K PYTHON
	output = output[:-1]
	i = 0
	infs = sorted(output.split('\n'))
	for ip in output.split('\n'):
		i += 1
		print(ip)
		info.append(ServiceInfo(
			"_coap._udp.local.",
			"hwmon" + str(i) + "._coap._udp.local.",
			addresses=[socket.inet_aton(ip)],
			port=5683,
			server="hwmon" + str(i) + ".local.",
			#host_ttl=0,
			#other_ttl=0,
		))
		zeroconf.register_service(info[-1])
	print("service started")
	while (stop_threads == False):
		output = subprocess.check_output('for /f "usebackq tokens=2 delims=:" %f in (`ipconfig ^| findstr /c:"IPv4 Address"`) do @echo off && echo%f',shell=True , stderr=subprocess.STDOUT,stdin=subprocess.PIPE).decode("utf-8")
		#F**K PYTHON TWICE
		output = output[:-1]
		i = 0
		if(sorted(output.split('\n')) != infs):
			for inf in info:
				try:
					zeroconf.unregister_service(inf)
				except :
					pass
			zeroconf.unregister_all_services()
			info.clear()
			print("new interface")
			for ip in output.split('\n'):
				i += 1
				print(ip)
				info.append(ServiceInfo(
					"_coap._udp.local.",
					"hwmon" + str(i) + "._coap._udp.local.",
					addresses=[socket.inet_aton(ip)],
					port=5683,
					server="hwmon" + str(i) + ".local.",
					#host_ttl=0,
					#other_ttl=0,
				))
				zeroconf.register_service(info[-1])
			infs = sorted(output.split('\n'))
		time.sleep(1)
	zeroconf.close()
Пример #17
0
def test_ptr_optimization():

    # 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
    has_srv = has_txt = has_a = False

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

        nbr_answers += len(out.answers)
        nbr_authorities += len(out.authorities)
        for answer in out.additionals:
            nbr_additionals += 1
            if answer.type == r._TYPE_SRV:
                has_srv = True
            elif answer.type == r._TYPE_TXT:
                has_txt = True
            elif answer.type == r._TYPE_A:
                has_a = True

        old_send(out, addr=addr, port=port)

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

    # register
    zc.register_service(info)
    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))
    zc.handle_query(r.DNSIncoming(query.packet()), r._MDNS_ADDR, r._MDNS_PORT)
    assert nbr_answers == 1 and nbr_additionals == 3 and nbr_authorities == 0
    assert has_srv and has_txt and has_a

    # unregister
    zc.unregister_service(info)
Пример #18
0
class YokeDrv:
    def __init__(self, daemon):
        self.daemon = daemon
        self.controller = None
        self.zeroconf = Zeroconf()
        self.trecv = time.time()
        self.irecv = 0

        log.debug("Registering zeroconf service...")
        # open udp socket on random available port
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF,
                             512)  # small buffer for low latency
        self.sock.bind((YokeDrv.get_ip_address(), 0))
        self.sock.settimeout(0)
        adr, port = self.sock.getsockname()
        # self.daemon.add_mainloop(self.mainloop)
        poller = self.daemon.get_poller()
        poller.register(self.sock.fileno(), poller.POLLIN, self.on_data_ready)

        # create zeroconf service
        stype = "_yoke._udp.local."
        netname = socket.gethostname() + "-sc-controller"
        fullname = netname + "." + stype
        self.info = ServiceInfo(stype, fullname, socket.inet_aton(adr), port,
                                0, 0, {}, fullname)
        self.zeroconf.register_service(self.info, ttl=10)
        log.info('To connect, select "%s" on your device.' % (netname, ))

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

    def on_exit(self, *a):
        self.daemon.get_poller().unregister(self.sock.fileno())
        if self.sock is not None:
            self.sock.close()
        if self.info is not None:
            self.zeroconf.unregister_service(self.info)
        log.debug("Unregistered zeroconf service.")

    def on_data_ready(self, *a):
        try:
            m, address = self.sock.recvfrom(128)
            if self.controller is None:
                self.controller = YokeController(self, address)
                self.daemon.add_controller(self.controller)
            self.controller.input(m)
        except Exception, e:
            log.exception(e)
Пример #19
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()
Пример #20
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)
Пример #21
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)
def main():
    logging.basicConfig(level=logging.DEBUG)

    parser = argparse.ArgumentParser()
    parser.add_argument('--debug', action='store_true')
    parser.add_argument("--name", dest="name", default=None,
                        help="mdns service name")
    version_group = parser.add_mutually_exclusive_group()
    version_group.add_argument('--v6', action='store_true')
    version_group.add_argument('--v6-only', action='store_true')
    args = parser.parse_args()

    if args.debug:
        logging.getLogger('zeroconf').setLevel(logging.DEBUG)
    if args.v6:
        ip_version = IPVersion.All
    elif args.v6_only:
        ip_version = IPVersion.V6Only
    else:
        ip_version = IPVersion.V4Only

    properties = {'who': 'codelab'}  # 详细信息

    name = args.name if args.name else uuid.uuid4().hex[:8]

    service_type = "_http._tcp.local."
    service_name = f"{name}._http._tcp.local."
    server = f"{name}.local." 
    port = 12358
    info = ServiceInfo(
        service_type,
        service_name,
        addresses=[socket.inet_aton(get_local_ip())],
        port=port,
        properties=properties,
        server=server,
    )
    print(info)
    zeroconf = Zeroconf(ip_version=ip_version)
    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()
Пример #23
0
    def __start_advertising(self):
        self.service = ServiceInfo("{}._tcp.local.".format(self.type),
                                   "{}.{}._tcp.local.".format(self.name, self.type),
                                   socket.inet_aton(self.address), self.port, 0, 0,
                                   self.properties, "{}.local.".format(self.server))

        zeroconf = Zeroconf()
        zeroconf.register_service(self.service)

        while self.alive:
            time.sleep(.1)

        zeroconf.unregister_service(self.service)
        zeroconf.close()
Пример #24
0
def mDNS():
    #zerconf info
    infomqtt = ServiceInfo(
        "_mqtt._tcp.local.",
        "hwmon._mqtt._tcp.local.",
        addresses=[
            socket.inet_aton(socket.gethostbyname(socket.gethostname()))
        ],
        port=1883,
        server="hwmon.local.",
    )
    infocoap = ServiceInfo(
        "_coap._udp.local.",
        "hwmon._coap._udp.local.",
        addresses=[
            socket.inet_aton(socket.gethostbyname(socket.gethostname()))
        ],
        port=5683,
        server="hwmon.local.",
    )
    zeroconf = Zeroconf(ip_version=IPVersion.All)
    while (stop_threads == False):
        try:
            zeroconf.unregister_service(infomqtt)
            zeroconf.unregister_service(infocoap)
            zeroconf.close()
            zeroconf.close()
            zeroconf = Zeroconf(ip_version=IPVersion.All)
            infomqtt.addresses = [
                socket.inet_aton(socket.gethostbyname(socket.gethostname()))
            ]
            infocoap.addresses = [
                socket.inet_aton(socket.gethostbyname(socket.gethostname()))
            ]
            zeroconf.register_service(infomqtt)
            zeroconf.register_service(infocoap)
        except:
            pass
        while (infocoap.addresses == [
                socket.inet_aton(socket.gethostbyname(socket.gethostname()))
        ] and stop_threads == False):
            try:
                client.publish("display/hwmon", json.dumps(data))
                time.sleep(0.2)
            except:
                pass
    zeroconf.unregister_service(infomqtt)
    zeroconf.unregister_service(infocoap)
    zeroconf.close()
Пример #25
0
class MDNSServer:
    """Announce accessory on the network via mDNS / DNS-SD

    To debug service: avahi-browse -r -k _hap._tcp
    """

    # TODO: restart / reload zeroconf on config change
    def __init__(self, config: Config) -> None:
        self.zeroconf = Zeroconf()
        self.hap_service: ServiceInfo = None
        self.config = config

    def update_service(self):
        self.hap_service = ServiceInfo(
            type_=self.config.service_type,
            name=f'{self.config.model_name}.{self.config.service_type}',
            address=inet_aton(self.config.server_ip),
            port=self.config.server_port,
            properties={
                'c#': str(self.config.configuration_number),
                'ff':
                '0',  # feature flag: enable HAP pairing  # TODO: disable pairing once paired
                'id': self.config.device_id,
                'md': self.config.model_name,
                'pv': '1.0',  # protocol version
                's#':
                '1',  # current state number, this must have a value of '1'
                'sf': str(StatusFlag.not_paired.value),  # pylint: disable=no-member
                'ci': str(AccessoryCategory.bridge.value
                          ),  # accessory category identifier
            },
        )

    def start(self):
        """Start announcing accessory on the network"""
        self.update_service()
        self.zeroconf.register_service(self.hap_service)

    def restart(self):
        self.stop()
        self.update_service()
        self.start()

    def stop(self):
        self.zeroconf.unregister_service(self.hap_service)

    def close(self):
        self.zeroconf.close()
Пример #26
0
class RegisterCar():
    def __init__(self):
        logging.info("RegisterCar.__init__()")
        self.zeroconf = None
        self.info = None

    def register_car(self, name, port=8000):
        logging.info("RegisterCar.register_car()")

        my_ip_address = None
        while not my_ip_address:
            try:
                s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                s.connect(("8.8.8.8", 80))
                my_ip_address = s.getsockname()[0]
                s.close()
            except Exception:
                sleep(1)
                my_ip_address = None

        if len(my_ip_address) > 0:
            logging.info("Service IP: " + my_ip_address)
            my_ip_address = socket.inet_aton(my_ip_address)

            desc = {'name': name}
            self.info = ServiceInfo("_http._tcp.local.",
                                    name + " DrivingMatter._http._tcp.local.",
                                    my_ip_address, port, 0, 0, desc)

            self.zeroconf = Zeroconf()
            logging.info("Registration of a service, press Ctrl-C to exit...")
            self.zeroconf.register_service(self.info)

            return True
        else:
            logging.error(
                "No network interface available, please connect to any network"
            )
            #raise Exception("No network interface")
            return False

    def unregister_car(self):
        if self.zeroconf:
            self.zeroconf.unregister_service(self.info)
            self.zeroconf.close()
            logging.info("Service unregistered successfully")
        else:
            logging.error("No Zeroconf established yet")
Пример #27
0
def test_unicast_response():
    """Ensure we send a unicast response when the source port is not the MDNS port."""
    # 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,
                       80,
                       0,
                       0,
                       desc,
                       "ash-2.local.",
                       addresses=[socket.inet_aton("10.0.1.2")])
    # register
    zc.register_service(info)
    _clear_cache(zc)

    # query
    query = r.DNSOutgoing(const._FLAGS_QR_QUERY | const._FLAGS_AA)
    query.add_question(
        r.DNSQuestion(info.type, const._TYPE_PTR, const._CLASS_IN))
    unicast_out, multicast_out = zc.query_handler.response(
        r.DNSIncoming(query.packets()[0]), "1.2.3.4", 1234)
    for out in (unicast_out, multicast_out):
        assert out.id == query.id
        has_srv = has_txt = has_a = False
        nbr_additionals = 0
        nbr_answers = len(out.answers)
        nbr_authorities = len(out.authorities)
        for answer in out.additionals:
            nbr_additionals += 1
            if answer.type == const._TYPE_SRV:
                has_srv = True
            elif answer.type == const._TYPE_TXT:
                has_txt = True
            elif answer.type == const._TYPE_A:
                has_a = True
        assert nbr_answers == 1 and nbr_additionals == 3 and nbr_authorities == 0
        assert has_srv and has_txt and has_a

    # unregister
    zc.unregister_service(info)
    zc.close()
Пример #28
0
class HSMZeroConfSetup(object):
    def __init__(self, ip_addr, serial, firmware_version, sd_version):
        self.zeroconf = None
        self.registered = False

        caps = ""

        try:
            with open("/etc/diamond-hsm/caps", "rt") as fp:
                for line in fp:
                    caps = "%s %s" % (caps, line.strip("\r\n"))
        except:
            pass

        desc = {
            'serial': serial,
            'host': 'dks-hsm',
            'type': 'Diamond HSM Prototype',
            'firmware': firmware_version,
            'sd': sd_version,
            'IP': ip_addr,
            'caps': caps
        }

        self.service_info = ServiceInfo("_dks-hsm-cty._tcp.local.",
                                        "%s._dks-hsm-cty._tcp.local." % serial,
                                        socket.inet_aton(ip_addr), 8081, 0, 0,
                                        desc, "dkey.local.")

        atexit.register(self.unregister_service)

    def register_service(self):
        if (not self.registered):
            print "zeroconf registered"
            self.zeroconf = Zeroconf()
            self.zeroconf.register_service(self.service_info)

            self.registered = True

    def unregister_service(self):
        if (self.registered):
            print "zeroconf unregistered"
            self.zeroconf.unregister_service(self.service_info)
            self.zeroconf.close()
            self.zeroconf = None

            self.registered = False
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()
Пример #30
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 default_route_interface())

    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 default_route_interface())
        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)
Пример #31
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()
Пример #32
0
 def start(self):
     """
     Start the service
     """
     http_info = ServiceInfo('_http._tcp.local.', 'OpenLP._http._tcp.local.',
                             address=self.address, port=self.http_port, properties={})
     ws_info = ServiceInfo('_ws._tcp.local.', 'OpenLP._ws._tcp.local.',
                           address=self.address, port=self.ws_port, properties={})
     zc = Zeroconf()
     zc.register_service(http_info)
     zc.register_service(ws_info)
     self._can_run = True
     while self.can_run():
         sleep(0.1)
     zc.unregister_service(http_info)
     zc.unregister_service(ws_info)
     zc.close()
     self.quit.emit()
Пример #33
0
class Discovery:
    def __init__(self,
                 zeroconf_name="",
                 address="127.0.0.1",
                 port=None,
                 model_name="",
                 uuid="",
                 device_name=""):
        service_type = "._googlecast._tcp.local."
        service_name = zeroconf_name + service_type
        address_bytes = socket.inet_aton(address)

        self._zeroconf = None
        self._service = ServiceInfo(service_type,
                                    service_name,
                                    address_bytes,
                                    port,
                                    properties={
                                        "md": model_name,
                                        "id": uuid,
                                        "fn": device_name,
                                    })

    def run(self):
        if self._zeroconf is not None:
            return

        logger.info("starting discovery")

        try:
            self._zeroconf = Zeroconf()
            self._zeroconf.register_service(self._service)
        except KeyboardInterrupt:
            pass

    def stop(self):
        if self._zeroconf is None:
            return

        logger.info("stopping discovery")

        self._zeroconf.unregister_service(self._service)
        self._zeroconf.close()
        self._zeroconf = None
Пример #34
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)
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()
Пример #36
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)
Пример #37
0
class BonjourService:
    ip_version = IPVersion.V4Only

    def __init__(self, host, type, domain, port, ips):
        self.info = ServiceInfo(type + domain,
                                host + '.' + type + domain,
                                addresses=[socket.inet_aton(ip) for ip in ips],
                                port=port,
                                properties={'path': '/~paulsm/'},
                                server=host + '.' + domain)

        self.zeroconf = Zeroconf(ip_version=self.ip_version)

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

    def close(self):
        self.zeroconf.unregister_service(self.info)
        self.zeroconf.close()
Пример #38
0
    def __start_advertising(self):
        self.service = ServiceInfo("{}._tcp.local.".format(self.type),
                                   "{}.{}._tcp.local.".format(
                                       self.name, self.type),
                                   port=self.port,
                                   weight=0,
                                   priority=0,
                                   properties=self.properties,
                                   server="{}.local.".format(self.server),
                                   addresses=[socket.inet_aton(self.address)])

        zeroconf = Zeroconf()
        zeroconf.register_service(self.service)

        while self.alive:
            time.sleep(.5)

        zeroconf.unregister_service(self.service)
        zeroconf.close()
Пример #39
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()
Пример #40
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()
Пример #41
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)
Пример #42
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)
Пример #43
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
Пример #44
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
Пример #45
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()
Пример #46
0
class LightService(service.Service):
    step_sizes = [0.01, 0.05, 0.1, 0.5, 1, 5, 10, 30, 60]

    def __init__(self, counter=None, loop=None, device = AdaDevice(serial=DummySerialDevice()), step_time_index=2, current_value="default",
                 avail_progs=None, avail_filters = {}, default_filters=[], default_prog=None, lambent_port=8680,
                 discovery_name="", remote_device_managed=False, xbar_component=None, xbar_runner_kwargs=None, **kwargs):
        self.current_value = current_value
        self.step_time_index = step_time_index
        self.available_progs = avail_progs
        self.remote_device_managed = remote_device_managed

        if not device:
            self.device = device
        else:
            self.device = device

        if default_prog:
            if default_prog in self.available_progs.keys():
                prog = self.available_progs.get(default_prog)
                # self.change_program(prog, default_prog)
                prog_kwargs = prog['kwargs']
                prog_kwargs['device'] = self.device
                prog_kwargs.update(GLOBAL_KWARGS)
                counter = prog['class'](**prog_kwargs)
                self.current_value = default_prog
            else:
                sys.stderr.write("SELECTED (%s) NOT IN (%s)" % (default_prog, ",".join(i for i in self.available_progs)))

        if not counter:
            self.counter = WaitingCounter(5)
        else:
            self.counter = counter

        self.service_avail_filters = avail_filters
        self.service_enabled_filters = collections.OrderedDict()
        for filter in default_filters:
            try:
                self.service_enabled_filters[uuid.uuid4().hex[0:4].upper()] = [filter,self.service_avail_filters[filter]()]
            except:
                sys.stderr.write("LAMBENT FILTER DIDN'T EXIST '" + filter + "', SKIPPING\n")

        # these next 2 lines for testing
        # self.service_enabled_filters[uuid.uuid4().hex[0:4].upper()] = ['GRB',self.service_avail_filters['GRB']()]
        # self.service_enabled_filters[uuid.uuid4().hex[0:4].upper()] = ['GRB',self.service_avail_filters['GRB']()]

        self.counter.filters = self.get_filters()

        if not loop:
            self.loop = task.LoopingCall(self.counter.step)
            self.loop.start(self.step_time)
        else:
            self.loop = loop


        self.update_filters()
        self.disc_name = discovery_name
        self.announce(discovery_name, port=lambent_port)

        if xbar_runner_kwargs:
            self.xbar_session = None
            self.xbar_component = xbar_component
            self.xbar_runner_kwargs = xbar_runner_kwargs
            self.xbar_init()


    @inlineCallbacks
    def _init_xbar(self):
        if self.xbar_session is None:
            self.xbar_session = yield self.start_crossbar()
            self.xbar_session.name = self.disc_name.lower()

    @inlineCallbacks
    def start_crossbar(self):
        running_deferred = Deferred()
        extra = dict(running=running_deferred)
        self.xbar_runner_kwargs['extra'] = extra

        xbar_runner = ApplicationRunner(**self.xbar_runner_kwargs)
        xbar_runner.run(self.xbar_component, start_reactor=False, auto_reconnect=True)
        session = yield running_deferred
        returnValue(session)

    # @inlineCallbacks
    def xbar_change_program(self, program):
        # this should be improved and normalized later to not repat code but for now it works
        if program not in self.available_progs.keys():
            return json.dumps(
                    {
                        "status": "ERROR_NON_EXISTENT_PROGRAM_PARAMETER",
                        "value": program
                    }
                )
        else:
            prog = self.available_progs.get(program, None)
            self.change_program(prog, program)
            return json.dumps(
                {
                    "status": "SUCCESS_CHANGED_PROGRAM",
                    "value": program
                }
            )

    @inlineCallbacks
    def xbar_init(self):
        yield self._init_xbar()
        yield self.xbar_hello()
        yield self.xbar_register_methods()

    @inlineCallbacks
    def xbar_register_methods(self):
        xbar_method = "us.thingcosm.aethers.lambent.%(name)s.program" % {"name":self.disc_name.lower()}
        # print("qqq")
        # print(xbar_method)
        self.xbar_method = xbar_method
        yield self.xbar_session.register(self.xbar_change_program, xbar_method)

        # Continuous Lookup And Data Publishing
        yield self.xbar_session.subscribe(self.xbar_info_ui, "us.thingcosm.aethers.continuous")
        yield self.xbar_session.publish("us.thingcosm.aethers.continuous", options=PublishOptions(exclude_me=False))
        # yield self.xbar_session.publish("us.thingcosm.aethers.continuous", 0)

    @inlineCallbacks
    def xbar_hello(self):
        yield self.xbar_session.publish("us.thingcosm.aethers.lambent.updates.program", server_name=self.disc_name, server_program=self.current_value)

    @inlineCallbacks
    def xbar_update_speed(self):
        yield self.xbar_session.publish("us.thingcosm.aethers.lambent.updates.speed", server_name=self.disc_name, server_value=self.step_time)

    @inlineCallbacks
    def xbar_info_ui_items(self):
        progs_grp = {}
        for k,v in self.available_progs.iteritems():
            key = deepcopy(k)
            grp = v.get("grouping", "NONE")

            if grp in progs_grp:
                progs_grp[grp].append(key)
            else:
                progs_grp[grp] = [key]

        loader = txtemplate.Jinja2TemplateLoader(TEMPLATE_DIR)
        template = loader.load("xbar_ui.jinja2")
        context={"programs":progs_grp, "method":self.xbar_method}
        rendered = yield template.render(**context)
        print(rendered)
        returnValue(rendered)
        # return {"a":"B"}

    @inlineCallbacks
    def xbar_info_ui(self, *args, **kwargs):
        """ When the frontend looks for us, populate it"""
        body = yield self.xbar_info_ui_items()
        yield self.xbar_session.publish("us.thingcosm.aethers.continuous.ui", cls="lambent", name=self.disc_name.lower(), body=body)
        # yield self.xbar_session.publish("us.thingcosm.aethers.continuous.ui", cls="lambent", name=self.disc_name.upper(), body=body)

    @property
    def step_time(self):
        return self.step_sizes[self.step_time_index]

    def getCntr(self):
        return self.counter

    def setCntr(self, cntr):
        self.counter = cntr

    def setLoop(self, loop):
        self.loop = loop

    def setLoopInterval(self, value):
        self.step_time = value
        self.loop.stop()
        self.loop.start(self.step_time)

    # blendy bits
    def bigblender(self, upper, lower, count=64):
        blend = [int(lower + x*(upper-lower)/count) for x in range(count)]
        return blend

    def do_all_filters(self, value):
        for f in self.get_filters():
            value = f.do_filter(value)

        return value

    def change_program(self, prog, val):
        self.current_value = val

        # # stop the existing one
        if hasattr(self, "loop"):
            loop_old = self.loop
            try:
                loop_old.stop()
            except AssertionError:
                pass
                print "too quick slick"


        # # setup
        self.program_class = prog['class']
        self.program_args = prog.get('kwargs', {})
        self.program_args['device'] = self.device
        self.program_args.update(GLOBAL_KWARGS)

        initiated_prog = self.program_class(**self.program_args)
        # doing it here, prevents that flicker
        initiated_prog.filters = self.get_filters()

        ##
        # # Transitions
        if self.counter and hasattr(self.counter, "leds") and hasattr(initiated_prog, "leds"):
        # if self.transition:
            if self.counter.transitions_list:
                leds_nowflat = self.counter.transitions_list.pop(0)
            else:
                leds_now = [i.read_rgb() for i in self.counter.leds]
                leds_filtered = [self.do_all_filters(i) for i in leds_now]
                leds_nowflat = list(itertools.chain(*leds_filtered))


            leds_l8r = [k.read_rgb() for k in initiated_prog.leds]
            leds_l8r_filt = [self.do_all_filters(i) for i in leds_l8r]
            leds_l8rflat = list(itertools.chain(*leds_l8r_filt))

            place_to_hold_stuff =  [list() for i in xrange(128)]

            for j,l in zip(leds_nowflat, leds_l8rflat):
                blendvals = self.bigblender(l,j,count=128)
                for v,p in zip(blendvals, place_to_hold_stuff):
                    p.append(v)

            # for l in place_to_hold_stuff:
            #     self.device.write(l)
        else:
            place_to_hold_stuff = []

        if place_to_hold_stuff and remote_device_managed != False:
            """
            This is a stupid quick implementation of taking far fewer steps,
            its not particularly perfect, but its Good Enough
            """
            len_pl = len(place_to_hold_stuff)

            if remote_device_managed == 0: # no fade
                place_to_hold_stuff = []

            elif remote_device_managed == 1: # half as many
                place_to_hold_stuff = place_to_hold_stuff[::2]

            elif remote_device_managed == 2: # 1/4 as many
                last = place_to_hold_stuff[-1]
                place_to_hold_stuff = place_to_hold_stuff[::4]
                if place_to_hold_stuff[-1] != last:
                    place_to_hold_stuff.append(last)

            elif remote_device_managed == 3:
                last = place_to_hold_stuff[-1]
                place_to_hold_stuff = place_to_hold_stuff[::10]
                if place_to_hold_stuff[-1] != last:
                    place_to_hold_stuff.append(last)

            elif remote_device_managed == 4:
                pass

            elif remote_device_managed == 5 and len_pl > 3: # single intermediate
                start = place_to_hold_stuff[0]
                end = place_to_hold_stuff[-1]
                middle = len_pl/2

                place_to_hold_stuff=[start, place_to_hold_stuff[middle], end]

            elif remote_device_managed == 6 and len_pl > 5:
                start = place_to_hold_stuff[0]
                end = place_to_hold_stuff[-1]
                mid_1 = len_pl / 4 * 1  # 25%ish
                mid_2 = len_pl / 4 * 2  # 50%ish
                mid_3 = len_pl / 4 * 3  # 75%ish

                place_to_hold_stuff = [start, place_to_hold_stuff[mid_1], place_to_hold_stuff[mid_2],
                                       place_to_hold_stuff[mid_3], end]

            elif remote_device_managed == 7 and len_pl > 7:
                start = place_to_hold_stuff[0]
                end = place_to_hold_stuff[-1]
                mid_1 = len_pl / 6 * 1  # 16%ish
                mid_2 = len_pl / 6 * 2  # 32%ish
                mid_3 = len_pl / 6 * 3  # 48%ish
                mid_4 = len_pl / 6 * 4  # 64%ish
                mid_5 = len_pl / 6 * 5  # 80%ish
                place_to_hold_stuff = [start, place_to_hold_stuff[mid_1], place_to_hold_stuff[mid_2],
                                       place_to_hold_stuff[mid_3], place_to_hold_stuff[mid_4],
                                       place_to_hold_stuff[mid_5], end]

            else: # fallback
                place_to_hold_stuff = []
            pass

        initiated_prog.transitions_list = place_to_hold_stuff
        loop_new = task.LoopingCall(initiated_prog.step)
        loop_new.start(self.step_time)
        self.setLoop(loop_new)
        self.setCntr(initiated_prog)
        self.update_filters()
        self.xbar_hello()

    def get_filters(self):
        filters = [f[1] for f in self.service_enabled_filters.values()]
        return filters

    def update_filters(self):
        self.counter.filters = self.get_filters()

    def loop_set(self):
        self.loop.stop()
        self.loop.start(self.step_time)
        self.xbar_update_speed()

    def loop_slower(self):
        max_index = len(self.step_sizes) - 1
        if self.step_time_index >= max_index:
            return self.step_time, False
        else:
            self.step_time_index += 1
            self.loop_set()
            return self.step_time, True
        # return 0,True

    def loop_faster(self):
        if self.step_time_index <= 0:
            return self.step_time, False
        else:
            self.step_time_index -= 1
            self.loop_set()
            return self.step_time, True

    def set_time_index(self, value):
        self.step_time_index = value
        self.loop_set()

    def getLightFactory(self):
        f = protocol.ServerFactory()
        f.protocol = TelnetLightProtocol
        f.counter = self.counter
        f.loop = self.loop
        f.device = self.device

        f.setLoop = self.setLoop
        f.setCntr = self.setCntr
        f.change_program = self.change_program
        return f

    def getLightResource(self):
        r = LightHTMLTree(self)
        r.putChild("", r)

        st = LightStatus(self)
        r.putChild("status", st)

        si = LightInfo(self)
        r.putChild("info", si)

        pl = LightProgramList(self)
        r.putChild("progs", pl)

        plg = LightProgramListGrouped(self)
        r.putChild("progs_grp", plg)

        se = LightProgramSetter(self)
        r.putChild("set", se)

        ass = static.File('assets')
        r.putChild("assets", ass)

        filt_enabled = LightProgramEnabledFilterList(self)
        r.putChild("filt_en", filt_enabled)

        filt_list = LightProgramFilterList(self)
        r.putChild("filt_ls", filt_list)

        filt_delete = LightProgramRMFilter(self)
        r.putChild("filt_rm", filt_delete)

        filt_add = LightProgramAddFilter(self)
        r.putChild("filt_add", filt_add)

        sp_faster = LightSpeedFaster(self)
        r.putChild("sp_up", sp_faster)

        sp_slower = LightSpeedSlower(self)
        r.putChild("sp_dn", sp_slower)

        sp_list = LightSpeedOptions(self)
        r.putChild("sp_ls", sp_list)

        sp_set = LightSpeedSet(self)
        r.putChild("sp_set", sp_set)

        return r

    def announce(self, discovery_name, port=8680):
        self.zeroconf = Zeroconf()

        self.zconfigs = []
        for i in netifaces.interfaces():
            if i.startswith("lo"):
                # remove loopback from announce
                continue
            if i.startswith("veth"):
                # remove docker interface from announce
                continue

            addrs = netifaces.ifaddresses(i)
            if addrs.keys() == [17]:
                continue
            print addrs
            for a in addrs[netifaces.AF_INET]:
                print a
                info_desc = {'path': '/progs_grp/', 'name': discovery_name, "port":port}
                config = ServiceInfo("_aether._tcp.local.",
                               "%s_%s_%s_lambent._aether._tcp.local." % (socket.gethostname(),i, port),
                               socket.inet_aton(a['addr']), port, 0, 0,
                               info_desc)
                try:
                    self.zeroconf.register_service(config)
                    self.zconfigs.append(config)
                except:
                    print("Service %s failed to register" % config)

    def stopService(self):
        for c in self.zconfigs:
            self.zeroconf.unregister_service(c)
        self.zeroconf.close()
Пример #47
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."))
Пример #48
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()
Пример #49
0
class UbiquitousService(service.Service):

    def __init__(self, devices, discovery_name, port, update_freq=5.0):
        self.devices = devices
        self.update_freq = update_freq

        # start the update loop
        self.loop = task.LoopingCall(self.devices_update)
        self.loop.start(self.update_freq)
        self.announce(discovery_name, port)

    def devices_update(self):
        [d.update_port_status() for d in self.devices]

    def device_as_prg_grp(self, d):
        return d._as_prg_grp()

    def devices_as_prg_grp(self):
        return {d.name: self.device_as_prg_grp(d) for d in self.devices}

    def all_programs(self):
        # l = []
        # [l.extend(d._as_prg_list()) for d in self.devices]
        # print [d._as_prg_list() for d in self.devices]
        l = {}
        for d in self.devices:
            ps = d._as_prg_list()
            for p in ps:
                l[p] = d

        print l
        return l

    def announce(self, discovery_name, port):
        self.zeroconf = Zeroconf()
        self.zconfigs = []
        for i in netifaces.interfaces():
            if i.startswith("lo"):
                # remove loopback from announce
                continue
            if i.startswith("veth"):
                # remove docker interface from announce
                continue

            addrs = netifaces.ifaddresses(i)
            if addrs.keys() == [17]:
                continue
            print addrs
            for a in addrs[netifaces.AF_INET]:
                print a
                info_desc = {'path': '/progs_grp/', 'name': discovery_name}
                config = ServiceInfo("_aether._tcp.local.",
                               "%s_%s_%s_ubiquitous._aether._tcp.local." % (socket.gethostname(),i, port),
                               socket.inet_aton(a['addr']), port, 0, 0,
                               info_desc)# , "aether-autodisc-0.local.")

                self.zeroconf.register_service(config)
                self.zconfigs.append(config)

    def stopService(self):
        for c in self.zconfigs:
            self.zeroconf.unregister_service(c)
        self.zeroconf.close()

    def getResources(self):
        r = resource.Resource()
        r.putChild("", r)

        se = ProgramSetter(self)
        r.putChild("set", se)

        pl = ProgramList(self)
        r.putChild("progs", pl)

        plg = ProgramListGrouped(self)
        r.putChild("progs_grp", plg)

        st = ServiceStatus(self)
        r.putChild("status", st)

        return r
Пример #50
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()
Пример #51
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()
Пример #52
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()
    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
Пример #54
0
class CentralServer:
	_server_name = "CentralServer"
	_vhost = "/bottle"
	_exchange = "pebble"
	_routing_key = "central"
		
	def _get_service_name(self):
		return CentralServer._server_name + "._http._tcp.local."
		
	def _get_service_ip(self):
		wlanIfaceAddrs = netifaces.ifaddresses('wlan0')
		ethIfaceAddrs = netifaces.ifaddresses('eth0')

		if netifaces.AF_INET in ethIfaceAddrs and "addr" in ethIfaceAddrs[netifaces.AF_INET][0]:
			return ethIfaceAddrs[netifaces.AF_INET][0]["addr"], "eth0"
		elif netifaces.AF_INET in wlanIfaceAddrs and "addr" in wlanIfaceAddrs[netifaces.AF_INET][0]:
			return wlanIfaceAddrs[netifaces.AF_INET][0]["addr"], "wlan0"
		else:
			return None, None
		
	def __init__(self, listen_pin):
		GPIO.setwarnings(False)
		GPIO.setmode(GPIO.BOARD)
		GPIO.setup(listen_pin, GPIO.IN)
		self._pin = listen_pin
		
		self._log_fmt = logging.Formatter(fmt="%(asctime)s [%(levelname)-8s] %(message)s", datefmt="%b %d %H:%M:%S")
		self._log = logging.getLogger()
		self._log.setLevel(logging.INFO)
		
		streamHandler = logging.StreamHandler()
		streamHandler.setLevel(logging.DEBUG)
		streamHandler.setFormatter(self._log_fmt)
		self._log.addHandler(streamHandler)
		
		self._display = DisplayRunner.DisplayRunner()
		self._display.set_mode(0)
		self._display.start()
			
		self._new_connections = []
		self._accept_responses = threading.Event()
		self._responses = []
		
		self._conn = pika.BlockingConnection(pika.ConnectionParameters(host="localhost", virtual_host=self._vhost))	
		self._chan = self._conn.channel()
		
		queueResult = self._chan.queue_declare(auto_delete=True)
		if queueResult is None:
			self._log.error("Could not create connect queue")
			raise RuntimeError("Error configuring RabbitMQ")
		else:
			self._log.info("Created queue \'%s\'" % (queueResult.method.queue,))
			self._log.info("Using exchange \'%s/%s\'" % (self._vhost, self._exchange,))
			self._chan.exchange_declare(exchange=self._exchange, type="topic", auto_delete=True)
			self._chan.queue_bind(exchange=self._exchange, queue=queueResult.method.queue, routing_key=self._routing_key)
			
		self._queue_name = queueResult.method.queue
		
		server_ip, ifaceName = self._get_service_ip()
		if server_ip is None:
			self._log.error("Could not determine server IP")
			raise RuntimeError("Error finding server IP")
		else:
			self._log.info("Broadcasting service %s with IP %s (%s)" % (self._get_service_name(), server_ip, ifaceName))
		
		# Configure zeroconf to broadcast this service
		self._zeroconf = Zeroconf()
		self._zeroconf_info = ServiceInfo("_http._tcp.local.",
			self._get_service_name(),
			socket.inet_aton(server_ip),
			5672, 0, 0,
			{"exchange_name": self._exchange, "routing_key": self._routing_key, "virtual_host": self._vhost},
			None)
		
		try:
			self._zeroconf.register_service(self._zeroconf_info)
		except Zeroconf.NonUniqueNameException:
			self._log.warn("Service with name \'%s\' already broadcasting on this network!" % (self._get_service_name(),))
		
	def start(self):
		state = "IDLE_INIT"
		startTime = None
		msg = None
		try:
			while True:
				if state == "IDLE_INIT":
					self._display.set_message("NEED A TABLE?")
					self._display.set_mode(2)
					state = "IDLE"
				elif state == "IDLE":
					# If new nodes join the network, display them on the screen
					if len(self._new_connections) > 0:
						# Display / log newly connected nodes, if present
						pass
					# Otherwise if the user presses the button, ping the network and wait
					elif GPIO.input(self._pin):
						self._accept_responses.set()
						self.ping()
						
						self._display.set_mode(0)
						time.sleep(0.5)
						self._display.set_message("SEARCHING...")
						self._display.set_mode(2)
						
						startTime = time.time()
						state = "WAIT_FOR_RESPONSE"
				elif state == "WAIT_FOR_RESPONSE":
					timeElapsed = math.floor(time.time() - startTime)
					msg = self._chan.basic_get(queue=self._queue_name, no_ack=True)
					# If nodes respond, pick a node from the list of responses and display it
					self._log.info(str(msg))
					if msg[0] is not None:
						self._log.info("RESPONSES RECEIVED %s" % str(msg[2]))
						
						self._display.set_mode(0)
						time.sleep(0.5)
						self._display.set_message("TABLE %s IS FREE" % str(msg[2]))
						self._display.set_mode(2)
						
						startTime = time.time()
						state = "DISPLAY_RESULT"
					# Or if 30 seconds pass then all tables are probably full
					elif timeElapsed > 45:
						self._log.info("REQUEST TIMED OUT")
						self._display.set_mode(0)
						time.sleep(0.5)
						self._display.set_message("SORRY, COULDN'T FIND ANYTING!")
						self._display.set_mode(2)
						
						startTime = time.time()
						self._accept_responses.clear()
						state = "DISPLAY_TIMEOUT"
					# ... Or if the user presses the button, cancel the request
					elif GPIO.input(self._pin):
						self._log.info("REQUEST CANCELLED")
						self._display.set_mode(0)
						time.sleep(0.5)
						self._display.set_message("REQUEST CANCELLED")
						self._display.set_mode(2)
						
						startTime = time.time()
						self._accept_responses.clear()
						state = "REQ_CANCEL"
				elif state == "DISPLAY_RESULT":
					if time.time() > (startTime + 30):
						self._display.set_mode(0)
						time.sleep(0.5)
						self._display.set_message("NEED A TABLE?")
						self._display.set_mode(2)
						
						state = "IDLE"
				elif state == "DISPLAY_TIMEOUT":
					if time.time() > (startTime + 10):
						self._display.set_mode(0)
						time.sleep(0.5)
						self._display.set_message("NEED A TABLE?")
						self._display.set_mode(2)
						
						state = "IDLE"
				elif state == "REQ_CANCEL":
					# Display cancelled message
					if time.time() > (startTime + 5):
						self._display.set_mode(0)
						time.sleep(0.5)
						self._display.set_message("NEED A TABLE?")
						self._display.set_mode(2)
						
						state = "IDLE"
				else:
					state = "IDLE_INIT"
				time.sleep(0.5)
		except KeyboardInterrupt:
			pass
		finally:
			self._display.set_mode(0)
			self._chan.stop_consuming()
			self._log.info("Shutting down server...")
			self._log.info("Closing connection with RabbitMQ")
			if self._conn is not None:
				self._conn.close()
			
			self._log.info("Unregistering server")
			self._zeroconf.unregister_service(self._zeroconf_info)
			self._zeroconf.close()
		
			self._log.info("Shutdown complete!")
		
	def ping(self):
		self._responses = []
		self._log.info("Pinging network...")
		tempConn = pika.BlockingConnection(pika.ConnectionParameters(host='localhost', virtual_host=self._vhost))
		tempChan = tempConn.channel()
		tempChan.basic_publish(exchange=self._exchange, routing_key="node", body="")
		tempConn.close()
		
	def _consume(self, ch, method, properties, body):
		print "MSG: %s" % body