A pure python implementation of multicast DNS service discovery

Overview

python-zeroconf

Documentation.

This is fork of pyzeroconf, Multicast DNS Service Discovery for Python, originally by Paul Scott-Murphy (https://github.com/paulsm/pyzeroconf), modified by William McBrine (https://github.com/wmcbrine/pyzeroconf).

The original William McBrine's fork note:

This fork is used in all of my TiVo-related projects: HME for Python
(and therefore HME/VLC), Network Remote, Remote Proxy, and pyTivo.
Before this, I was tracking the changes for zeroconf.py in three
separate repos. I figured I should have an authoritative source.

Although I make changes based on my experience with TiVos, I expect that
they're generally applicable. This version also includes patches found
on the now-defunct (?) Launchpad repo of pyzeroconf, and elsewhere
around the net -- not always well-documented, sorry.

Compatible with:

  • Bonjour
  • Avahi

Compared to some other Zeroconf/Bonjour/Avahi Python packages, python-zeroconf:

  • isn't tied to Bonjour or Avahi
  • doesn't use D-Bus
  • doesn't force you to use particular event loop or Twisted (asyncio is used under the hood but not required)
  • is pip-installable
  • has PyPI distribution

Python compatibility

  • CPython 3.6+
  • PyPy3 7.2+

Versioning

This project's versions follow the following pattern: MAJOR.MINOR.PATCH.

  • MAJOR version has been 0 so far
  • MINOR version is incremented on backward incompatible changes
  • PATCH version is incremented on backward compatible changes

Status

This project is actively maintained.

Traffic Reduction

Before version 0.32, most traffic reduction techniques described in https://datatracker.ietf.org/doc/html/rfc6762#section-7 where not implemented which could lead to excessive network traffic. It is highly recommended that version 0.32 or later is used if this is a concern.

IPv6 support

IPv6 support is relatively new and currently limited, specifically:

  • InterfaceChoice.All is an alias for InterfaceChoice.Default on non-POSIX systems.
  • Dual-stack IPv6 sockets are used, which may not be supported everywhere (some BSD variants do not have them).
  • Listening on localhost (::1) does not work. Help with understanding why is appreciated.

How to get python-zeroconf?

The easiest way to install python-zeroconf is using pip:

pip install zeroconf

How do I use it?

Here's an example of browsing for a service:

from zeroconf import ServiceBrowser, Zeroconf


class MyListener:

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

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


zeroconf = Zeroconf()
listener = MyListener()
browser = ServiceBrowser(zeroconf, "_http._tcp.local.", listener)
try:
    input("Press enter to exit...\n\n")
finally:
    zeroconf.close()

Note

Discovery and service registration use all available network interfaces by default. If you want to customize that you need to specify interfaces argument when constructing Zeroconf object (see the code for details).

If you don't know the name of the service you need to browse for, try:

from zeroconf import ZeroconfServiceTypes
print('\n'.join(ZeroconfServiceTypes.find()))

See examples directory for more.

Changelog

0.37.0

Technically backwards incompatible:

  • Adding a listener that does not inherit from RecordUpdateListener now logs an error (#1034) @bdraco

  • The NotRunningException exception is now thrown when Zeroconf is not running (#1033) @bdraco

    Before this change the consumer would get a timeout or an EventLoopBlocked exception when calling ServiceInfo.*request when the instance had already been shutdown or had failed to startup.

  • The EventLoopBlocked exception is now thrown when a coroutine times out (#1032) @bdraco

    Previously concurrent.futures.TimeoutError would have been raised instead. This is never expected to happen during normal operation.

0.36.13

  • Unavailable interfaces are now skipped during socket bind (#1028) @bdraco

  • Downgraded incoming corrupt packet logging to debug (#1029) @bdraco

    Warning about network traffic we have no control over is confusing to users as they think there is something wrong with zeroconf

0.36.12

  • Prevented service lookups from deadlocking if time abruptly moves backwards (#1006) @bdraco

    The typical reason time moves backwards is via an ntp update

0.36.11

No functional changes from 0.36.10. This release corrects an error in the README.rst file that prevented the build from uploading to PyPI

0.36.10

  • scope_id is now stripped from IPv6 addresses if given (#1020) @StevenLooman

    cpython 3.9 allows a suffix %scope_id in IPv6Address. This caused an error with the existing code if it was not stripped

  • Optimized decoding labels from incoming packets (#1019) @bdraco

0.36.9

  • Ensure ServiceInfo orders newest addresses first (#1012) @bdraco

    This change effectively restored the behavior before 1s cache flush expire behavior described in rfc6762 section 10.2 was added for callers that rely on this.

0.36.8

  • Fixed ServiceBrowser infinite loop when zeroconf is closed before it is canceled (#1008) @bdraco

0.36.7

  • Improved performance of responding to queries (#994) (#996) (#997) @bdraco
  • Improved log message when receiving an invalid or corrupt packet (#998) @bdraco

0.36.6

  • Improved performance of sending outgoing packets (#990) @bdraco

0.36.5

  • Reduced memory usage for incoming and outgoing packets (#987) @bdraco

0.36.4

  • Improved performance of constructing outgoing packets (#978) (#979) @bdraco
  • Deferred parsing of incoming packets when it can be avoided (#983) @bdraco

0.36.3

  • Improved performance of parsing incoming packets (#975) @bdraco

0.36.2

0.36.1

  • Skip goodbye packets for addresses when there is another service registered with the same name (#968) @bdraco

    If a ServiceInfo that used the same server name as another ServiceInfo was unregistered, goodbye packets would be sent for the addresses and would cause the other service to be seen as offline.

  • Fixed equality and hash for dns records with the unique bit (#969) @bdraco

    These records should have the same hash and equality since the unique bit (cache flush bit) is not considered when adding or removing the records from the cache.

0.36.0

Technically backwards incompatible:

  • Fill incomplete IPv6 tuples to avoid WinError on windows (#965) @lokesh2019

    Fixed #932

0.35.1

  • Only reschedule types if the send next time changes (#958) @bdraco

    When the PTR response was seen again, the timer was being canceled and rescheduled even if the timer was for the same time. While this did not cause any breakage, it is quite inefficient.

  • Cache DNS record and question hashes (#960) @bdraco

    The hash was being recalculated every time the object was being used in a set or dict. Since the hashes are effectively immutable, we only calculate them once now.

0.35.0

  • Reduced chance of accidental synchronization of ServiceInfo requests (#955) @bdraco
  • Sort aggregated responses to increase chance of name compression (#954) @bdraco

Technically backwards incompatible:

  • Send unicast replies on the same socket the query was received (#952) @bdraco

    When replying to a QU question, we do not know if the sending host is reachable from all of the sending sockets. We now avoid this problem by replying via the receiving socket. This was the existing behavior when InterfaceChoice.Default is set.

    This change extends the unicast relay behavior to used with InterfaceChoice.Default to apply when InterfaceChoice.All or interfaces are explicitly passed when instantiating a Zeroconf instance.

    Fixes #951

0.34.3

  • Fix sending immediate multicast responses (#949) @bdraco

0.34.2

  • Coalesce aggregated multicast answers (#945) @bdraco

    When the random delay is shorter than the last scheduled response, answers are now added to the same outgoing time group.

    This reduces traffic when we already know we will be sending a group of answers inside the random delay window described in datatracker.ietf.org/doc/html/rfc6762#section-6.3

  • Ensure ServiceInfo requests can be answered inside the default timeout with network protection (#946) @bdraco

    Adjust the time windows to ensure responses that have triggered the protection against against excessive packet flooding due to software bugs or malicious attack described in RFC6762 section 6 can respond in under 1350ms to ensure ServiceInfo can ask two questions within the default timeout of 3000ms

0.34.1

  • Ensure multicast aggregation sends responses within 620ms (#942) @bdraco

    Responses that trigger the protection against against excessive packet flooding due to software bugs or malicious attack described in RFC6762 section 6 could cause the multicast aggregation response to be delayed longer than 620ms (The maximum random delay of 120ms and 500ms additional for aggregation).

    Only responses that trigger the protection are delayed longer than 620ms

0.34.0

  • Implemented Multicast Response Aggregation (#940) @bdraco

    Responses are now aggregated when possible per rules in RFC6762 section 6.4

    Responses that trigger the protection against against excessive packet flooding due to software bugs or malicious attack described in RFC6762 section 6 are delayed instead of discarding as it was causing responders that implement Passive Observation Of Failures (POOF) to evict the records.

    Probe responses are now always sent immediately as there were cases where they would fail to be answered in time to defend a name.

0.33.4

  • Ensure zeroconf can be loaded when the system disables IPv6 (#933) @che0

0.33.3

  • Added support for forward dns compression pointers (#934) @bdraco
  • Provide sockname when logging a protocol error (#935) @bdraco

0.33.2

  • Handle duplicate goodbye answers in the same packet (#928) @bdraco

    Solves an exception being thrown when we tried to remove the known answer from the cache when the second goodbye answer in the same packet was processed

    Fixed #926

  • Skip ipv6 interfaces that return ENODEV (#930) @bdraco

0.33.1

  • Version number change only with less restrictive directory permissions

    Fixed #923

0.33.0

This release eliminates all threading locks as all non-threadsafe operations now happen in the event loop.

  • Let connection_lost close the underlying socket (#918) @bdraco

    The socket was closed during shutdown before asyncio's connection_lost handler had a chance to close it which resulted in a traceback on windows.

    Fixed #917

Technically backwards incompatible:

  • Removed duplicate unregister_all_services code (#910) @bdraco

    Calling Zeroconf.close from same asyncio event loop zeroconf is running in will now skip unregister_all_services and log a warning as this a blocking operation and is not async safe and never has been.

    Use AsyncZeroconf instead, or for legacy code call async_unregister_all_services before Zeroconf.close

0.32.1

  • Increased timeout in ServiceInfo.request to handle loaded systems (#895) @bdraco

    It can take a few seconds for a loaded system to run the async_request coroutine when the event loop is busy, or the system is CPU bound (example being Home Assistant startup). We now add an additional _LOADED_SYSTEM_TIMEOUT (10s) to the run_coroutine_threadsafe calls to ensure the coroutine has the total amount of time to run up to its internal timeout (default of 3000ms).

    Ten seconds is a bit large of a timeout; however, it is only used in cases where we wrap other timeouts. We now expect the only instance the run_coroutine_threadsafe result timeout will happen in a production circumstance is when someone is running a ServiceInfo.request() in a thread and another thread calls Zeroconf.close() at just the right moment that the future is never completed unless the system is so loaded that it is nearly unresponsive.

    The timeout for run_coroutine_threadsafe is the maximum time a thread can cleanly shut down when zeroconf is closed out in another thread, which should always be longer than the underlying thread operation.

0.32.0

This release offers 100% line and branch coverage.

  • Made ServiceInfo first question QU (#852) @bdraco

    We want an immediate response when requesting with ServiceInfo by asking a QU question; most responders will not delay the response and respond right away to our question. This also improves compatibility with split networks as we may not have been able to see the response otherwise. If the responder has not multicast the record recently, it may still choose to do so in addition to responding via unicast

    Reduces traffic when there are multiple zeroconf instances running on the network running ServiceBrowsers

    If we don't get an answer on the first try, we ask a QM question in the event, we can't receive a unicast response for some reason

    This change puts ServiceInfo inline with ServiceBrowser which also asks the first question as QU since ServiceInfo is commonly called from ServiceBrowser callbacks

  • Limited duplicate packet suppression to 1s intervals (#841) @bdraco

    Only suppress duplicate packets that happen within the same second. Legitimate queriers will retry the question if they are suppressed. The limit was reduced to one second to be in line with rfc6762

  • Made multipacket known answer suppression per interface (#836) @bdraco

    The suppression was happening per instance of Zeroconf instead of per interface. Since the same network can be seen on multiple interfaces (usually and wifi and ethernet), this would confuse the multi-packet known answer supression since it was not expecting to get the same data more than once

  • New ServiceBrowsers now request QU in the first outgoing when unspecified (#812) @bdraco

    https://datatracker.ietf.org/doc/html/rfc6762#section-5.4 When we start a ServiceBrowser and zeroconf has just started up, the known answer list will be small. By asking a QU question first, it is likely that we have a large known answer list by the time we ask the QM question a second later (current default which is likely too low but would be a breaking change to increase). This reduces the amount of traffic on the network, and has the secondary advantage that most responders will answer a QU question without the typical delay answering QM questions.

  • IPv6 link-local addresses are now qualified with scope_id (#343) @ibygrave

    When a service is advertised on an IPv6 address where the scope is link local, i.e. fe80::/64 (see RFC 4007) the resolved IPv6 address must be extended with the scope_id that identifies through the "%" symbol the local interface to be used when routing to that address. A new API parsed_scoped_addresses() is provided to return qualified addresses to avoid breaking compatibility on the existing parsed_addresses().

  • Network adapters that are disconnected are now skipped (#327) @ZLJasonG

  • Fixed listeners missing initial packets if Engine starts too quickly (#387) @bdraco

    When manually creating a zeroconf.Engine object, it is no longer started automatically. It must manually be started by calling .start() on the created object.

    The Engine thread is now started after all the listeners have been added to avoid a race condition where packets could be missed at startup.

  • Fixed answering matching PTR queries with the ANY query (#618) @bdraco

  • Fixed lookup of uppercase names in the registry (#597) @bdraco

    If the ServiceInfo was registered with an uppercase name and the query was for a lowercase name, it would not be found and vice-versa.

  • Fixed unicast responses from any source port (#598) @bdraco

    Unicast responses were only being sent if the source port was 53, this prevented responses when testing with dig:

    dig -p 5353 @224.0.0.251 media-12.local

    The above query will now see a response

  • Fixed queries for AAAA records not being answered (#616) @bdraco

  • Removed second level caching from ServiceBrowsers (#737) @bdraco

    The ServiceBrowser had its own cache of the last time it saw a service that was reimplementing the DNSCache and presenting a source of truth problem that lead to unexpected queries when the two disagreed.

  • Fixed server cache not being case-insensitive (#731) @bdraco

    If the server name had uppercase chars and any of the matching records were lowercase, and the server would not be found

  • Fixed cache handling of records with different TTLs (#729) @bdraco

    There should only be one unique record in the cache at a time as having multiple unique records will different TTLs in the cache can result in unexpected behavior since some functions returned all matching records and some fetched from the right side of the list to return the newest record. Instead we now store the records in a dict to ensure that the newest record always replaces the same unique record, and we never have a source of truth problem determining the TTL of a record from the cache.

  • Fixed ServiceInfo with multiple A records (#725) @bdraco

    If there were multiple A records for the host, ServiceInfo would always return the last one that was in the incoming packet, which was usually not the one that was wanted.

  • Fixed stale unique records expiring too quickly (#706) @bdraco

    Records now expire 1s in the future instead of instant removal.

    tools.ietf.org/html/rfc6762#section-10.2 Queriers receiving a Multicast DNS response with a TTL of zero SHOULD NOT immediately delete the record from the cache, but instead record a TTL of 1 and then delete the record one second later. In the case of multiple Multicast DNS responders on the network described in Section 6.6 above, if one of the responders shuts down and incorrectly sends goodbye packets for its records, it gives the other cooperating responders one second to send out their own response to "rescue" the records before they expire and are deleted.

  • Fixed exception when unregistering a service multiple times (#679) @bdraco

  • Added an AsyncZeroconfServiceTypes to mirror ZeroconfServiceTypes to zeroconf.asyncio (#658) @bdraco

  • Fixed interface_index_to_ip6_address not skiping ipv4 adapters (#651) @bdraco

  • Added async_unregister_all_services to AsyncZeroconf (#649) @bdraco

  • Fixed services not being removed from the registry when calling unregister_all_services (#644) @bdraco

    There was a race condition where a query could be answered for a service in the registry, while goodbye packets which could result in a fresh record being broadcast after the goodbye if a query came in at just the right time. To avoid this, we now remove the services from the registry right after we generate the goodbye packet

  • Fixed zeroconf exception on load when the system disables IPv6 (#624) @bdraco

  • Fixed the QU bit missing from for probe queries (#609) @bdraco

    The bit should be set per datatracker.ietf.org/doc/html/rfc6762#section-8.1

  • Fixed the TC bit missing for query packets where the known answers span multiple packets (#494) @bdraco

  • Fixed packets not being properly separated when exceeding maximum size (#498) @bdraco

    Ensure that questions that exceed the max packet size are moved to the next packet. This fixes DNSQuestions being sent in multiple packets in violation of: datatracker.ietf.org/doc/html/rfc6762#section-7.2

    Ensure only one resource record is sent when a record exceeds _MAX_MSG_TYPICAL datatracker.ietf.org/doc/html/rfc6762#section-17

  • Fixed PTR questions asked in uppercase not being answered (#465) @bdraco

  • Added Support for context managers in Zeroconf and AsyncZeroconf (#284) @shenek

  • Implemented an AsyncServiceBrowser to compliment the sync ServiceBrowser (#429) @bdraco

  • Added async_get_service_info to AsyncZeroconf and async_request to AsyncServiceInfo (#408) @bdraco

  • Implemented allowing passing in a sync Zeroconf instance to AsyncZeroconf (#406) @bdraco

  • Fixed IPv6 setup under MacOS when binding to "" (#392) @bdraco

  • Fixed ZeroconfServiceTypes.find not always cancels the ServiceBrowser (#389) @bdraco

    There was a short window where the ServiceBrowser thread could be left running after Zeroconf is closed because the .join() was never waited for when a new Zeroconf object was created

  • Fixed duplicate packets triggering duplicate updates (#376) @bdraco

    If TXT or SRV records update was already processed and then received again, it was possible for a second update to be called back in the ServiceBrowser

  • Fixed ServiceStateChange.Updated event happening for IPs that already existed (#375) @bdraco

  • Fixed RFC6762 Section 10.2 paragraph 2 compliance (#374) @bdraco

  • Reduced length of ServiceBrowser thread name with many types (#373) @bdraco

  • Fixed empty answers being added in ServiceInfo.request (#367) @bdraco

  • Fixed ServiceInfo not populating all AAAA records (#366) @bdraco

    Use get_all_by_details to ensure all records are loaded into addresses.

    Only load A/AAAA records from the cache once in load_from_cache if there is a SRV record present

    Move duplicate code that checked if the ServiceInfo was complete into its own function

  • Fixed a case where the cache list can change during iteration (#363) @bdraco

  • Return task objects created by AsyncZeroconf (#360) @nocarryr

Traffic Reduction:

  • Added support for handling QU questions (#621) @bdraco

    Implements RFC 6762 sec 5.4: Questions Requesting Unicast Responses datatracker.ietf.org/doc/html/rfc6762#section-5.4

  • Implemented protect the network against excessive packet flooding (#619) @bdraco

  • Additionals are now suppressed when they are already in the answers section (#617) @bdraco

  • Additionals are no longer included when the answer is suppressed by known-answer suppression (#614) @bdraco

  • Implemented multi-packet known answer supression (#687) @bdraco

    Implements datatracker.ietf.org/doc/html/rfc6762#section-7.2

  • Implemented efficient bucketing of queries with known answers (#698) @bdraco

  • Implemented duplicate question suppression (#770) @bdraco

    http://datatracker.ietf.org/doc/html/rfc6762#section-7.3

Technically backwards incompatible:

  • Update internal version check to match docs (3.6+) (#491) @bdraco

    Python version earlier then 3.6 were likely broken with zeroconf already, however, the version is now explicitly checked.

  • Update python compatibility as PyPy3 7.2 is required (#523) @bdraco

Backwards incompatible:

  • Drop oversize packets before processing them (#826) @bdraco

    Oversized packets can quickly overwhelm the system and deny service to legitimate queriers. In practice, this is usually due to broken mDNS implementations rather than malicious actors.

  • Guard against excessive ServiceBrowser queries from PTR records significantly lowerthan recommended (#824) @bdraco

    We now enforce a minimum TTL for PTR records to avoid ServiceBrowsers generating excessive queries refresh queries. Apple uses a 15s minimum TTL, however, we do not have the same level of rate limit and safeguards, so we use 1/4 of the recommended value.

  • RecordUpdateListener now uses async_update_records instead of update_record (#419, #726) @bdraco

    This allows the listener to receive all the records that have been updated in a single transaction such as a packet or cache expiry.

    update_record has been deprecated in favor of async_update_records A compatibility shim exists to ensure classes that use RecordUpdateListener as a base class continue to have update_record called, however, they should be updated as soon as possible.

    A new method async_update_records_complete is now called on each listener when all listeners have completed processing updates and the cache has been updated. This allows ServiceBrowsers to delay calling handlers until they are sure the cache has been updated as its a common pattern to call for ServiceInfo when a ServiceBrowser handler fires.

    The async_ prefix was chosen to make it clear that these functions run in the eventloop and should never do blocking I/O. Before 0.32+ these functions ran in a select() loop and should not have been doing any blocking I/O, but it was not clear to implementors that I/O would block the loop.

  • Pass both the new and old records to async_update_records (#792) @bdraco

    Pass the old_record (cached) as the value and the new_record (wire) to async_update_records instead of forcing each consumer to check the cache since we will always have the old_record when generating the async_update_records call. This avoids the overhead of multiple cache lookups for each listener.

0.31.0

  • Separated cache loading from I/O in ServiceInfo and fixed cache lookup (#356), thanks to J. Nick Koston.

    The ServiceInfo class gained a load_from_cache() method to only fetch information from Zeroconf cache (if it exists) with no IO performed. Additionally this should reduce IO in cases where cache lookups were previously incorrectly failing.

0.30.0

  • Some nice refactoring work including removal of the Reaper thread, thanks to J. Nick Koston.
  • Fixed a Windows-specific The requested address is not valid in its context regression, thanks to Timothee β€˜TTimo’ Besset and J. Nick Koston.
  • Provided an asyncio-compatible service registration layer (in the zeroconf.asyncio module), thanks to J. Nick Koston.

0.29.0

  • A single socket is used for listening on responding when InterfaceChoice.Default is chosen. Thanks to J. Nick Koston.

Backwards incompatible:

  • Dropped Python 3.5 support

0.28.8

  • Fixed the packet generation when multiple packets are necessary, previously invalid packets were generated sometimes. Patch thanks to J. Nick Koston.

0.28.7

  • Fixed the IPv6 address rendering in the browser example, thanks to Alexey Vazhnov.
  • Fixed a crash happening when a service is added or removed during handle_response and improved exception handling, thanks to J. Nick Koston.

0.28.6

  • Loosened service name validation when receiving from the network this lets us handle some real world devices previously causing errors, thanks to J. Nick Koston.

0.28.5

  • Enabled ignoring duplicated messages which decreases CPU usage, thanks to J. Nick Koston.
  • Fixed spurious AttributeError: module 'unittest' has no attribute 'mock' in tests.

0.28.4

  • Improved cache reaper performance significantly, thanks to J. Nick Koston.
  • Added ServiceListener to __all__ as it's part of the public API, thanks to Justin Nesselrotte.

0.28.3

  • Reduced a time an internal lock is held which should eliminate deadlocks in high-traffic networks, thanks to J. Nick Koston.

0.28.2

  • Stopped asking questions we already have answers for in cache, thanks to Paul Daumlechner.
  • Removed initial delay before querying for service info, thanks to Erik Montnemery.

0.28.1

  • Fixed a resource leak connected to using ServiceBrowser with multiple types, thanks to J. Nick Koston.

0.28.0

  • Improved Windows support when using socket errno checks, thanks to Sandy Patterson.
  • Added support for passing text addresses to ServiceInfo.
  • Improved logging (includes fixing an incorrect logging call)
  • Improved Windows compatibility by using Adapter.index from ifaddr, thanks to PhilippSelenium.
  • Improved Windows compatibility by stopping using socket.if_nameindex.
  • Fixed an OS X edge case which should also eliminate a memory leak, thanks to Emil Styrke.

Technically backwards incompatible:

  • ifaddr 0.1.7 or newer is required now.

0.27.1

  • Improved the logging situation (includes fixing a false-positive "packets() made no progress adding records", thanks to Greg Badros)

0.27.0

  • Large multi-resource responses are now split into separate packets which fixes a bad mdns-repeater/ChromeCast Audio interaction ending with ChromeCast Audio crash (and possibly some others) and improves RFC 6762 compliance, thanks to Greg Badros
  • Added a warning presented when the listener passed to ServiceBrowser lacks update_service() callback
  • Added support for finding all services available in the browser example, thanks to Perry Kunder

Backwards incompatible:

  • Removed previously deprecated ServiceInfo address constructor parameter and property

0.26.3

  • Improved readability of logged incoming data, thanks to Erik Montnemery
  • Threads are given unique names now to aid debugging, thanks to Erik Montnemery
  • Fixed a regression where get_service_info() called within a listener add_service method would deadlock, timeout and incorrectly return None, fix thanks to Erik Montnemery, but Matt Saxon and Hmmbob were also involved in debugging it.

0.26.2

  • Added support for multiple types to ServiceBrowser, thanks to J. Nick Koston
  • Fixed a race condition where a listener gets a message before the lock is created, thanks to J. Nick Koston

0.26.1

  • Fixed a performance regression introduced in 0.26.0, thanks to J. Nick Koston (this is close in spirit to an optimization made in 0.24.5 by the same author)

0.26.0

  • Fixed a regression where service update listener wasn't called on IP address change (it's called on SRV/A/AAAA record changes now), thanks to Matt Saxon

Technically backwards incompatible:

  • Service update hook is no longer called on service addition (service added hook is still called), this is related to the fix above

0.25.1

  • Eliminated 5s hangup when calling Zeroconf.close(), thanks to Erik Montnemery

0.25.0

  • Reverted uniqueness assertions when browsing, they caused a regression

Backwards incompatible:

  • Rationalized handling of TXT records. Non-bytes values are converted to str and encoded to bytes using UTF-8 now, None values mean value-less attributes. When receiving TXT records no decoding is performed now, keys are always bytes and values are either bytes or None in value-less attributes.

0.24.5

  • Fixed issues with shared records being used where they shouldn't be (TXT, SRV, A records are unique now), thanks to Matt Saxon
  • Stopped unnecessarily excluding host-only interfaces from InterfaceChoice.all as they don't forbid multicast, thanks to Andreas Oberritter
  • Fixed repr() of IPv6 DNSAddress, thanks to Aldo Hoeben
  • Removed duplicate update messages sent to listeners, thanks to Matt Saxon
  • Added support for cooperating responders, thanks to Matt Saxon
  • Optimized handle_response cache check, thanks to J. Nick Koston
  • Fixed memory leak in DNSCache, thanks to J. Nick Koston

0.24.4

  • Fixed resetting TTL in DNSRecord.reset_ttl(), thanks to Matt Saxon
  • Improved various DNS class' string representations, thanks to Jay Hogg

0.24.3

  • Fixed import-time "TypeError: 'ellipsis' object is not iterable." on CPython 3.5.2

0.24.2

  • Added support for AWDL interface on macOS (needed and used by the opendrop project but should be useful in general), thanks to Milan Stute
  • Added missing type hints

0.24.1

  • Applied some significant performance optimizations, thanks to Jaime van Kessel for the patch and to Ghostkeeper for performance measurements
  • Fixed flushing outdated cache entries when incoming record is unique, thanks to Michael Hu
  • Fixed handling updates of TXT records (they'd not get recorded previously), thanks to Michael Hu

0.24.0

  • Added IPv6 support, thanks to Dmitry Tantsur
  • Added additional recommended records to PTR responses, thanks to Scott Mertz
  • Added handling of ENOTCONN being raised during shutdown when using Eventlet, thanks to TamΓ‘s Nepusz
  • Included the py.typed marker in the package so that type checkers know to use type hints from the source code, thanks to Dmitry Tantsur

0.23.0

  • Added support for MyListener call getting updates to service TXT records, thanks to Matt Saxon
  • Added support for multiple addresses when publishing a service, getting/setting single address has become deprecated. Change thanks to Dmitry Tantsur

Backwards incompatible:

  • Dropped Python 3.4 support

0.22.0

  • A lot of maintenance work (tooling, typing coverage and improvements, spelling) done, thanks to Ville SkyttΓ€
  • Provided saner defaults in ServiceInfo's constructor, thanks to Jorge Miranda
  • Fixed service removal packets not being sent on shutdown, thanks to Andrew Bonney
  • Added a way to define TTL-s through ServiceInfo contructor parameters, thanks to Andrew Bonney

Technically backwards incompatible:

  • Adjusted query intervals to match RFC 6762, thanks to Andrew Bonney
  • Made default TTL-s match RFC 6762, thanks to Andrew Bonney

0.21.3

  • This time really allowed incoming service names to contain underscores (patch released as part of 0.21.0 was defective)

0.21.2

  • Fixed import-time typing-related TypeError when older typing version is used

0.21.1

  • Fixed installation on Python 3.4 (we use typing now but there was no explicit dependency on it)

0.21.0

  • Added an error message when importing the package using unsupported Python version
  • Fixed TTL handling for published service
  • Implemented unicast support
  • Fixed WSL (Windows Subsystem for Linux) compatibility
  • Fixed occasional UnboundLocalError issue
  • Fixed UTF-8 multibyte name compression
  • Switched from netifaces to ifaddr (pure Python)
  • Allowed incoming service names to contain underscores

0.20.0

  • Dropped support for Python 2 (this includes PyPy) and 3.3
  • Fixed some class' equality operators
  • ServiceBrowser entries are being refreshed when 'stale' now
  • Cache returns new records first now instead of last

0.19.1

  • Allowed installation with netifaces >= 0.10.6 (a bug that was concerning us got fixed)

0.19.0

0.18.0

  • Dropped Python 2.6 support
  • Improved error handling inside code executed when Zeroconf object is being closed

0.17.7

  • Better Handling of DNS Incoming Packets parsing exceptions
  • Many exceptions will now log a warning the first time they are seen
  • Catch and log sendto() errors
  • Fix/Implement duplicate name change
  • Fix overly strict name validation introduced in 0.17.6
  • Greatly improve handling of oversized packets including:
    • Implement name compression per RFC1035
    • Limit size of generated packets to 9000 bytes as per RFC6762
    • Better handle over sized incoming packets
  • Increased test coverage to 95%

0.17.6

  • Many improvements to address race conditions and exceptions during ZC() startup and shutdown, thanks to: morpav, veawor, justingiorgi, herczy, stephenrauch
  • Added more test coverage: strahlex, stephenrauch
  • Stephen Rauch contributed:
    • Speed up browser startup
    • Add ZeroconfServiceTypes() query class to discover all advertised service types
    • Add full validation for service names, types and subtypes
    • Fix for subtype browsing
    • Fix DNSHInfo support

0.17.5

  • Fixed OpenBSD compatibility, thanks to Alessio Sergi
  • Fixed race condition on ServiceBrowser startup, thanks to gbiddison
  • Fixed installation on some Python 3 systems, thanks to Per SandstrΓΆm
  • Fixed "size change during iteration" bug on Python 3, thanks to gbiddison

0.17.4

  • Fixed support for Linux kernel versions < 3.9 (thanks to Giovanni Harting and Luckydonald, GitHub pull request #26)

0.17.3

  • Fixed DNSText repr on Python 3 (it'd crash when the text was longer than 10 bytes), thanks to Paulus Schoutsen for the patch, GitHub pull request #24

0.17.2

  • Fixed installation on Python 3.4.3+ (was failing because of enum34 dependency which fails to install on 3.4.3+, changed to depend on enum-compat instead; thanks to Michael Brennan for the original patch, GitHub pull request #22)

0.17.1

  • Fixed EADDRNOTAVAIL when attempting to use dummy network interfaces on Windows, thanks to daid

0.17.0

  • Added some Python dependencies so it's not zero-dependencies anymore
  • Improved exception handling (it'll be quieter now)
  • Messages are listened to and sent using all available network interfaces by default (configurable); thanks to Marcus MΓΌller
  • Started using logging more freely
  • Fixed a bug with binary strings as property values being converted to False (https://github.com/jstasiak/python-zeroconf/pull/10); thanks to Dr. Seuss
  • Added new ServiceBrowser event handler interface (see the examples)
  • PyPy3 now officially supported
  • Fixed ServiceInfo repr on Python 3, thanks to Yordan Miladinov

0.16.0

  • Set up Python logging and started using it
  • Cleaned up code style (includes migrating from camel case to snake case)

0.15.1

  • Fixed handling closed socket (GitHub #4)

0.15

  • Forked by Jakub Stasiak
  • Made Python 3 compatible
  • Added setup script, made installable by pip and uploaded to PyPI
  • Set up Travis build
  • Reformatted the code and moved files around
  • Stopped catching BaseException in several places, that could hide errors
  • Marked threads as daemonic, they won't keep application alive now

0.14

  • Fix for SOL_IP undefined on some systems - thanks Mike Erdely.
  • Cleaned up examples.
  • Lowercased module name.

0.13

  • Various minor changes; see git for details.
  • No longer compatible with Python 2.2. Only tested with 2.5-2.7.
  • Fork by William McBrine.

0.12

  • allow selection of binding interface
  • typo fix - Thanks A. M. Kuchlingi
  • removed all use of word 'Rendezvous' - this is an API change

0.11

  • correction to comments for addListener method
  • support for new record types seen from OS X - IPv6 address - hostinfo
  • ignore unknown DNS record types
  • fixes to name decoding
  • works alongside other processes using port 5353 (e.g. on Mac OS X)
  • tested against Mac OS X 10.3.2's mDNSResponder
  • corrections to removal of list entries for service browser

0.10

  • Jonathon Paisley contributed these corrections:
    • always multicast replies, even when query is unicast
    • correct a pointer encoding problem
    • can now write records in any order
    • traceback shown on failure
    • better TXT record parsing
    • server is now separate from name
    • can cancel a service browser
  • modified some unit tests to accommodate these changes

0.09

  • remove all records on service unregistration
  • fix DOS security problem with readName

0.08

  • changed licensing to LGPL

0.07

  • faster shutdown on engine
  • pointer encoding of outgoing names
  • ServiceBrowser now works
  • new unit tests

0.06

  • small improvements with unit tests
  • added defined exception types
  • new style objects
  • fixed hostname/interface problem
  • fixed socket timeout problem
  • fixed add_service_listener() typo bug
  • using select() for socket reads
  • tested on Debian unstable with Python 2.2.2

0.05

  • ensure case insensitivty on domain names
  • support for unicast DNS queries

0.04

  • added some unit tests
  • added __ne__ adjuncts where required
  • ensure names end in '.local.'
  • timeout on receiving socket for clean shutdown

License

LGPL, see COPYING file for details.

Comments
  • Zeroconf.get_service_info seems broken in 0.26.0

    Zeroconf.get_service_info seems broken in 0.26.0

    Several Home Assistant users have reported that cast devices can't be discovered correctly after a recent upgrade which bumps zeroconf from 0.25.1 to 0.26.1: https://github.com/home-assistant/core/issues/35922

    According to some testing, the problem appeared in 0.26.0, which adds jstasiak/python-zeroconf#239

    It seems that the problem is that Zeroconf.get_service_info doesn't return anything useful in 0.26.0+, from the logs it seems that Zeroconf keeps sending queries but does not get or does not accept answers.

    Debug logs here: https://github.com/home-assistant/core/issues/35922#issuecomment-633261933

    For context, this is the code in pychromecast which calls Zeroconf.get_service_info, look for the add_service and service prints in the logs:

        def add_service(self, zconf, typ, name):
            """ Add a service to the collection. """
            service = None
            tries = 0
            _LOGGER.debug("add_service %s, %s", typ, name)
            while service is None and tries < 4:
                try:
                    service = zconf.get_service_info(typ, name)
                except IOError:
                    # If the zeroconf fails to receive the necessary data we abort
                    # adding the service
                    break
                tries += 1
    
            if not service:
                _LOGGER.debug("add_service failed to add %s, %s", typ, name)
                return
    

    @mattsaxon, any idea?

    opened by emontnemery 33
  • Ensure the name cache is rolled back when the packet reaches maximum size

    Ensure the name cache is rolled back when the packet reaches maximum size

    Fixes #308

    If the packet was too large, it would be rolled back at the end of write_record. We need to remove the names that were added to the name cache (self.names) as well to avoid a case were we would create a pointer to a name that was rolled back.

    The size of the packet was incorrect at the end after the inserts because insert_short would increase self.size even though it was already accounted before. To resolve this insert_short_at_start was added which does not increase self.size. This did not cause an actual bug, however it sure made debugging this problem far more difficult.

    Additionally the size now inserted and then replaced when the actual size is known because it made debugging quite difficult since the size did not previously agree with the data.

    opened by bdraco 29
  • Some sockets are opened but never read. UDP socket buffer memory usage increases

    Some sockets are opened but never read. UDP socket buffer memory usage increases

    In the Zeroconf class init, some sockets: https://github.com/jstasiak/python-zeroconf/blob/c7876108150cd251786db4ab52dadd1b2283d262/zeroconf.py#L1810

    are created in both the unicast and multicast case.

    But here: https://github.com/jstasiak/python-zeroconf/blob/c7876108150cd251786db4ab52dadd1b2283d262/zeroconf.py#L1858-L1862 in case of multicast, the _respond_sockets are never read.

    This causes some problem with the Recv queue of UDP, because the OS (in my case Ubuntu) keeps all the packets in memory waiting for the socket to read them, but this never happens and the memory keeps growing "forever"!

    This is my output of sudo ss -nlpu:

    State     Recv-Q     Send-Q                                Local Address:Port            Peer Address:Port                                                     
    UNCONN    156416     0                                           0.0.0.0:5353                 0.0.0.0:*         users:(("python",pid=10571,fd=54))             
    

    To solve: I tried running these two lines https://github.com/jstasiak/python-zeroconf/blob/c7876108150cd251786db4ab52dadd1b2283d262/zeroconf.py#L1861-L1862 even in the case of multicast. The problem is "solved".

    I'm sure that is not the right solution and may actually be logically wrong doing that for this case. I'm not an expert, but maybe there is a way to actually tell the OS that those sockets are not interested in listening for packets.

    opened by nicoladefranceschi 24
  • Sample code causes Windows OSError #10038

    Sample code causes Windows OSError #10038

    Code from the README:

    from zeroconf import ServiceBrowser, Zeroconf
    
    class MyListener:
    
        def remove_service(self, zeroconf, type, name):
            print("Service %s removed" % (name,))
    
        def add_service(self, zeroconf, type, name):
            info = zeroconf.get_service_info(type, name)
            print("Service %s added, service info: %s" % (name, info))
    
    zeroconf = Zeroconf()
    listener = MyListener()
    browser = ServiceBrowser(zeroconf, "_http._tcp.local.", listener)
    
    try:
        input("Press enter to exit...\n\n")
    finally:
        zeroconf.close()
    

    Causes this error on Windows:

    Exception in callback _ProactorBasePipeTransport._call_connection_lost(None)
    handle: <Handle _ProactorBasePipeTransport._call_connection_lost(None)>
    Traceback (most recent call last):
      File "C:\Program Files\Python39\lib\asyncio\events.py", line 80, in _run
        self._context.run(self._callback, *self._args)
      File "C:\Program Files\Python39\lib\asyncio\proactor_events.py", line 162, in _call_connection_lost
        self._sock.shutdown(socket.SHUT_RDWR)
    OSError: [WinError 10038] An operation was attempted on something that is not a socket
    Exception in callback _ProactorBasePipeTransport._call_connection_lost(None)
    handle: <Handle _ProactorBasePipeTransport._call_connection_lost(None)>
    Traceback (most recent call last):
      File "C:\Program Files\Python39\lib\asyncio\events.py", line 80, in _run
        self._context.run(self._callback, *self._args)
      File "C:\Program Files\Python39\lib\asyncio\proactor_events.py", line 162, in _call_connection_lost
        self._sock.shutdown(socket.SHUT_RDWR)
    OSError: [WinError 10038] An operation was attempted on something that is not a socket
    Exception in callback _ProactorBasePipeTransport._call_connection_lost(None)
    handle: <Handle _ProactorBasePipeTransport._call_connection_lost(None)>
    Traceback (most recent call last):
      File "C:\Program Files\Python39\lib\asyncio\events.py", line 80, in _run
        self._context.run(self._callback, *self._args)
      File "C:\Program Files\Python39\lib\asyncio\proactor_events.py", line 162, in _call_connection_lost
        self._sock.shutdown(socket.SHUT_RDWR)
    OSError: [WinError 10038] An operation was attempted on something that is not a socket
    

    On Python 3.9.3.

    Is there a way to shut down this library cleanly?

    opened by ahrbe1 22
  • ServiceBrowser Exception in OSX if browser generates long packets

    ServiceBrowser Exception in OSX if browser generates long packets

    My network has ~135 devices in the type category I am trying to browse.

    On OSX 10.11 (El Capitan) hosts, ServiceBrowser generates the following exception regularly because it appears to generate a very large (~11kb) single datagram by accumulating 'add_answer_at_time' responses and sending them all out as one event. I don't have specialist knowledge of the OS to know if this is exceeding some UDP size limit.

    This error does not occur on Ubuntu 14.04 hosts.

    I have another type category that contains ~75 devices and the exception never occurs while browsing that group (maximum packet length there is ~4305 bytes).

    Normal single response packets are ~75 bytes.

    Traceback (most recent call last):
      File "/Users/gbiddison/source/browser_test.py", line 100, in run
        super().run()
      File "//anaconda/envs/py34/lib/python3.4/site-packages/zeroconf.py", line 1060, in run
        self.zc.send(out)
      File "//anaconda/envs/py34/lib/python3.4/site-packages/zeroconf.py", line 1670, in send
        bytes_sent = s.sendto(packet, 0, (addr, port))
    OSError: [Errno 40] Message too long
    

    This prevents the browser from producing complete results .

    In proof-of-concept code, I have eliminated this exception by grouping the responses by a threshold count value and will post the PR when I've cleaned it up.

    bug 
    opened by gbiddison 21
  • Zeroconf.get_service_info returns None

    Zeroconf.get_service_info returns None

    I have a velux KLF200 and trying to indentify its IP by it's mdns name. However using your example code does find the name of the device, but get_service_info always runs into timout.

    I aready increased the timeout to 60000, but still I only return None due to timeout. The strange thing is, when using in parallel Bonjour browser get_service_info immediately returns correct information.

    opened by pawlizio 20
  • _ServiceBrowserBase._async_send_ready_queries_schedule_next() blocking?

    _ServiceBrowserBase._async_send_ready_queries_schedule_next() blocking?

    From time to time I get the following message with asyncio debug on:

    2021-10-07 21:05:22,047 - WARNING  - asyncio: Executing <TimerHandle when=1265.868092168 _ServiceBrowserBase._async_send_ready_queries_schedule_next() created at /home/dominikkarall/.local/lib/python3.7/site-packages/zeroconf/_services/browser.py:488> took 0.247 seconds
    2021-10-07 21:05:22,262 - WARNING  - asyncio: Executing <TimerHandle when=1266.114710128 _ServiceBrowserBase._async_send_ready_queries_schedule_next() created at /home/dominikkarall/.local/lib/python3.7/site-packages/zeroconf/_services/browser.py:488> took 0.137 seconds
    

    Could it be that there is some blocking code within that function?

    opened by fhempy 19
  • Use a single socket for InterfaceChoice.Default

    Use a single socket for InterfaceChoice.Default

    Fixes #330

    When using multiple sockets with multi-cast, the outgoing socket's responses could be read back on the incoming socket, which leads to duplicate processing and could fill up the incoming buffer before it could be processed.

    This behavior manifested with error similar to OSError: [Errno 105] No buffer space available

    By using a single socket with InterfaceChoice.Default we avoid this case.

    opened by bdraco 18
  • Avoid processing duplicate packets

    Avoid processing duplicate packets

    When watching packet captures, I noticed that zeroconf was processing incoming data 3x on a my Home Assistant OS install because there are three interfaces.

    We can skip processing duplicate packets in order to reduce the overhead of decoding data we have already processed.

    strace -p 231 -f -s 4096 -e trace=recvfrom

    [pid   267] recvfrom(7, "\224\7\0\0\0\1\0\0\0\0\0\0\17_home-assistant\4_tcp\5local\0\0\f\0\1", 8966, 0, {sa_family=AF_INET, sin_port=htons(5353), sin_addr=inet_addr("172.30.32.3")}, [16]) = 44
    [pid   267] recvfrom(7, "\224\7\0\0\0\1\0\0\0\0\0\0\17_home-assistant\4_tcp\5local\0\0\f\0\1", 8966, 0, {sa_family=AF_INET, sin_port=htons(5353), sin_addr=inet_addr("192.168.213.154")}, [16]) = 44
    [pid   267] recvfrom(9, "\224\7\0\0\0\1\0\0\0\0\0\0\17_home-assistant\4_tcp\5local\0\0\f\0\1", 8966, 0, {sa_family=AF_INET, sin_port=htons(5353), sin_addr=inet_addr("172.30.32.3")}, [16]) = 44
    

    Top 10 Before

      0.00%   0.00%    2.01s     2.01s   handle_read (zeroconf/__init__.py:1379)
      0.00%   0.00%    1.48s     1.48s   read_utf (zeroconf/__init__.py:838)
      0.00%   0.00%    1.27s     2.75s   read_name (zeroconf/__init__.py:854)
      0.00%   0.00%   0.570s    0.570s   unpack (zeroconf/__init__.py:738)
      0.00%   0.00%   0.420s    0.420s   read_name (zeroconf/__init__.py:848)
      0.00%   0.00%   0.410s    0.410s   do_execute (sqlalchemy/engine/default.py:593)
      0.00%   0.00%   0.390s    0.520s   __eq__ (zeroconf/__init__.py:607)
      0.00%   0.00%   0.390s    0.390s   read_name (zeroconf/__init__.py:859)
      0.00%   0.00%   0.360s    0.360s   get_expiration_time (zeroconf/__init__.py:494)
      0.00%   0.00%   0.330s    0.330s   write (asyncio/selector_events.py:908)
    

    Top 10 After

      3.00%   3.00%    2.01s     2.01s   handle_read (zeroconf/__init__.py:1379)
      0.00%   0.00%    1.30s     1.30s   create_connection (urllib3/util/connection.py:74)
      0.00%   0.00%    1.25s     1.25s   get_subscription (pysonos/events_base.py:765)
      0.00%   0.00%    1.05s     1.05s   __init__ (socket.py:231)
      2.00%   2.00%    1.02s     1.02s   read_utf (zeroconf/__init__.py:838)
      0.00%   0.00%   0.950s    0.950s   do_commit (sqlalchemy/engine/default.py:546)
      0.00%   0.00%   0.940s    0.940s   subscribe (pysonos/events_base.py:476)
      0.00%   0.00%   0.880s    0.880s   readinto (socket.py:669)
      0.00%   0.00%   0.850s    0.850s   getaddrinfo (socket.py:918)
      0.00%   2.00%   0.780s     1.81s   read_name (zeroconf/__init__.py:854)
    
    opened by bdraco 17
  • Multi service browsers of the same type create excessive queries

    Multi service browsers of the same type create excessive queries

    If we are already browsing for a type we should suppress additional question generation. We need to call soon thread safe coordination when adding and removing a service browser

    traffic-reduction 
    opened by bdraco 16
  • Loosen validation to ensure get_service_info can handle production devices

    Loosen validation to ensure get_service_info can handle production devices

    Validation of names was too strict and rejected devices that are otherwise functional. A partial list of devices that unexpectedly triggered a BadTypeInNameException:

    Bose Soundtouch Yeelights Rachio Sprinklers iDevices

    Fixes: https://github.com/home-assistant/core/issues/39116, https://github.com/home-assistant/core/issues/38914, https://github.com/home-assistant/core/issues/33085, https://github.com/home-assistant/core/issues/31262, https://github.com/home-assistant/core/issues/41355

    opened by bdraco 15
  • Unexpected multicast response

    Unexpected multicast response

    I have a setup with C++ client and Python service using zeroconf==0.37.0 (python3.6). My C++ client's probing for service on all interfaces and every request is marked as Unicast response. Maybe I am missing something, but why is Python service responding to multicast address 224.0.0.251 and only one response actually goes to interface address (192.168.56.1)? image

    I'd expect also no multicast response in this case. Thank you for clarification

    opened by polakovicp 1
  • Supertype query discards subtype in result

    Supertype query discards subtype in result

    If a device is advertising a service of type "_blah._http._tcp.local.", but I've set ServiceBrowser to filter for its supertype "_http._tcp.local.", then in

        def add_service(self, zc: Zeroconf, type_: str, name: str) -> None:
            info = zc.get_service_info(type_, name)
    

    the type_, and info.type, are both the supertype "_http._tcp.local.", rather than the actual type of the service. IMO, the actual type ought to be accessible. A key point seems to be here: https://github.com/jstasiak/python-zeroconf/blob/7430ce1c462be0dd210712b4f7b3675efd3a6963/zeroconf/_services/browser.py#L355 wherein the actual type is split into a list of it and its supertypes, I guess? Probably then there's something that filters the resulting events, and only the one keyed to the supertype succeeds.

    Desired result: get_service_info ought to include the actual type of the service, and possibly type_ in add_service et al. ought to be the actual type, too, though I'm less convinced of that.

    opened by Erhannis 0
  • ServiceBrowser handler argument overwrites zeroconf name

    ServiceBrowser handler argument overwrites zeroconf name

    In the default pattern

    import zeroconf
    
    instance = zeroconf.Zeroconf()
    browser = zeroconf.ServiceBrowser(
        instance,
        ['_osc._udp.local.'],
        handlers=[handler]
    )
    
    def handler(zeroconf, service_type, name, state_change):
        # I cannot use zeroconf.ServiceStateChange.Added here, because zeroconf is not the import but the argument
        pass
    

    we have the problem that handler() is receiving a named argument zeroconf that overloads import zeroconf and that we cannot change. If I defined

    def handler(zc, service_type, name, state_change):
        if state_change is zeroconf.ServiceStateChange.Added:
            print(name)
    

    I would receive

    TypeError: handler() got an unexpected keyword argument 'zeroconf'
    

    To avoid it I would have to alias the import, which is a bit ugly:

    import zeroconf as imported_zeroconf
    
    def handler(zeroconf, service_type, name, state_change):
        if state_change is imported_zeroconf.ServiceStateChange.Added:
            print(name)
    

    It would be nice if the arguments were to be passed in as positional arguments, or named differently, so that the names didn't clash.

    opened by nils-werner 0
  • Published service undiscoverable due to NSEC

    Published service undiscoverable due to NSEC

    There is a problem when trying to discover a service published by python-zeroconf with https://github.com/grandcat/zeroconf/ See also: https://github.com/grandcat/zeroconf/issues/34 Leaving out the NSEC block in python-zeroconf, e.g. not sending it at all, makes the discovery work with the golang side

    opened by bbusse 1
  • 0.38.6: sphinx warnings `reference target not found`

    0.38.6: sphinx warnings `reference target not found`

    On building my packages I'm using sphinx-build command with -n switch which shows warmings about missing references. These are not critical issues. Here is the output with warnings:

    + /usr/bin/sphinx-build -n -T -b man docs build/sphinx/man
    Running Sphinx v4.5.0
    making output directory... done
    WARNING: html_static_path entry '_static' does not exist
    loading intersphinx inventory from http://docs.python.org/objects.inv...
    intersphinx inventory has moved: http://docs.python.org/objects.inv -> https://docs.python.org/3/objects.inv
    building [mo]: targets for 0 po files that are out of date
    building [man]: all manpages
    updating environment: [new config] 2 added, 0 changed, 0 removed
    reading sources... [100%] index
    looking for now-outdated files... none found
    pickling environment... done
    checking consistency... done
    writing... python-zeroconf.3 { api } /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_updates.py:docstring of zeroconf.RecordUpdate.new:: WARNING: py:class reference target not found: zeroconf._dns.DNSRecord
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_updates.py:docstring of zeroconf.RecordUpdate.old:: WARNING: py:class reference target not found: zeroconf._dns.DNSRecord
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_updates.py:docstring of zeroconf._updates.RecordUpdateListener.update_record:: WARNING: py:class reference target not found: zeroconf._dns.DNSRecord
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_services/browser.py:docstring of zeroconf._services.browser.ServiceBrowser:: WARNING: py:class reference target not found: zeroconf._services.ServiceListener
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_services/browser.py:docstring of zeroconf._services.browser.ServiceBrowser:: WARNING: py:class reference target not found: zeroconf._services.ServiceListener
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_services/browser.py:docstring of zeroconf._services.browser.ServiceBrowser:1: WARNING: py:class reference target not found: zeroconf._services.browser._ServiceBrowserBase
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_services/info.py:docstring of zeroconf._services.info.ServiceInfo.dns_addresses:: WARNING: py:class reference target not found: zeroconf._dns.DNSAddress
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_services/info.py:docstring of zeroconf._services.info.ServiceInfo.dns_pointer:: WARNING: py:class reference target not found: zeroconf._dns.DNSPointer
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_services/info.py:docstring of zeroconf._services.info.ServiceInfo.dns_service:: WARNING: py:class reference target not found: zeroconf._dns.DNSService
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_services/info.py:docstring of zeroconf._services.info.ServiceInfo.dns_text:: WARNING: py:class reference target not found: zeroconf._dns.DNSText
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_services/info.py:docstring of zeroconf._services.info.ServiceInfo.generate_request_query:: WARNING: py:class reference target not found: zeroconf._protocol.outgoing.DNSOutgoing
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_services/info.py:docstring of zeroconf._services.info.ServiceInfo.update_record:: WARNING: py:class reference target not found: zeroconf._dns.DNSRecord
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_core.py:docstring of zeroconf._core.Zeroconf:1: WARNING: py:class reference target not found: zeroconf._logger.QuietLogger
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_core.py:docstring of zeroconf._core.Zeroconf.add_listener:: WARNING: py:class reference target not found: zeroconf._dns.DNSQuestion
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_core.py:docstring of zeroconf._core.Zeroconf.add_listener:: WARNING: py:class reference target not found: zeroconf._dns.DNSQuestion
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_core.py:docstring of zeroconf._core.Zeroconf.add_service_listener:: WARNING: py:class reference target not found: zeroconf._services.ServiceListener
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_core.py:docstring of zeroconf._core.Zeroconf.async_add_listener:: WARNING: py:class reference target not found: zeroconf._dns.DNSQuestion
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_core.py:docstring of zeroconf._core.Zeroconf.async_add_listener:: WARNING: py:class reference target not found: zeroconf._dns.DNSQuestion
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_core.py:docstring of zeroconf._core.Zeroconf.async_send:: WARNING: py:class reference target not found: zeroconf._protocol.outgoing.DNSOutgoing
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_core.py:docstring of zeroconf._core.Zeroconf.async_send:: WARNING: py:class reference target not found: asyncio.transports.DatagramTransport
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_core.py:docstring of zeroconf._core.Zeroconf.generate_service_broadcast:: WARNING: py:class reference target not found: zeroconf._protocol.outgoing.DNSOutgoing
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_core.py:docstring of zeroconf._core.Zeroconf.generate_service_query:: WARNING: py:class reference target not found: zeroconf._protocol.outgoing.DNSOutgoing
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_core.py:docstring of zeroconf._core.Zeroconf.generate_unregister_all_services:: WARNING: py:class reference target not found: zeroconf._protocol.outgoing.DNSOutgoing
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_core.py:docstring of zeroconf._core.Zeroconf.handle_assembled_query:: WARNING: py:class reference target not found: zeroconf._protocol.incoming.DNSIncoming
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_core.py:docstring of zeroconf._core.Zeroconf.handle_assembled_query:: WARNING: py:class reference target not found: asyncio.transports.DatagramTransport
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_core.py:docstring of zeroconf._core.Zeroconf.handle_response:: WARNING: py:class reference target not found: zeroconf._protocol.incoming.DNSIncoming
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_core.py:docstring of zeroconf._core.Zeroconf.remove_service_listener:: WARNING: py:class reference target not found: zeroconf._services.ServiceListener
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_core.py:docstring of zeroconf._core.Zeroconf.send:: WARNING: py:class reference target not found: zeroconf._protocol.outgoing.DNSOutgoing
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_core.py:docstring of zeroconf._core.Zeroconf.send:: WARNING: py:class reference target not found: asyncio.transports.DatagramTransport
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/_services/types.py:docstring of zeroconf._services.types.ZeroconfServiceTypes:1: WARNING: py:class reference target not found: zeroconf._services.ServiceListener
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/asyncio.py:docstring of zeroconf.asyncio.AsyncServiceBrowser:: WARNING: py:class reference target not found: zeroconf._services.ServiceListener
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/asyncio.py:docstring of zeroconf.asyncio.AsyncServiceBrowser:: WARNING: py:class reference target not found: zeroconf._services.ServiceListener
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/asyncio.py:docstring of zeroconf.asyncio.AsyncServiceBrowser:1: WARNING: py:class reference target not found: zeroconf._services.browser._ServiceBrowserBase
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/asyncio.py:docstring of zeroconf.asyncio.AsyncZeroconf.async_add_service_listener:: WARNING: py:class reference target not found: zeroconf._services.ServiceListener
    /home/tkloczko/rpmbuild/BUILD/python-zeroconf-0.38.6/zeroconf/asyncio.py:docstring of zeroconf.asyncio.AsyncZeroconf.async_remove_service_listener:: WARNING: py:class reference target not found: zeroconf._services.ServiceListener
    done
    build succeeded, 36 warnings.
    
    opened by kloczek 1
  • Lowest TTL

    Lowest TTL

    I'm trying to use zeroconf service discovery to register and discover some python services I have. In my POCs, as long as I unregister the services, it gets recognized again whenever I start it up. My main problem and concern right now are that sometimes my devices loses power supply being uncleanly shutdown and thus don't unregister the services in it. So that leads me to a question: How do I avoid having those stuck services on my service discovery? Is there some way to clear the entries that are not working anymore, so that when a new service is registered with the same info, I get notified? For example, I could ping my service, and if it didn't respond I would remove it from zeroconf "database". Is there a method for that? Couldn't find one!

    opened by andreguilhon 0
Releases(0.47.1)
Owner
Jakub Stasiak
Jakub Stasiak
A great python/java dynamic DNS service for NameSilo, with log, email reminder...

English NameSilo DDNS is a DDNS service for NameSilo domain names for home broadband , it can automatically detect IP changes in home broadband

云牧青 77 Dec 28, 2022
JF⚑can - Super fast port scanning & service discovery using Masscan and Nmap. Scan large networks with Masscan and use Nmap's scripting abilities to discover information about services. Generate report.

Description Killing features Perform a large-scale scans using Nmap! Allows you to use Masscan to scan targets and execute Nmap on detected ports with

null 377 Jan 3, 2023
DNSStager is an open-source project based on Python used to hide and transfer your payload using DNS.

What is DNSStager? DNSStager is an open-source project based on Python used to hide and transfer your payload using DNS. DNSStager will create a malic

Askar 547 Dec 20, 2022
πŸ₯‘ A Python ARP and DNS Spoofer CLI and INTERFACE πŸ₯“

NEXTGEN SPOOFER ?? A Python ARP and DNS Spoofer CLI and INTERFACE ?? CLI -> advanced pentesters INTERFACE -> beginners SetUp Make sure you installed P

null 9 Dec 25, 2022
Build custom OSINT tools and APIs (Ping, Traceroute, Scans, Archives, DNS, Scrape, Whois, Metadata & built-in database for more info) with this python package

Build custom OSINT tools and APIs with this python package - It includes different OSINT modules (Ping, Traceroute, Scans, Archives, DNS, Scrape, Whoi

QeeqBox 52 Jan 6, 2023
Way find out if DNS is down or your instance

DNS-PING Way to find out if DNS is down or your instance Problem: At times it happens that DNS provider services of a website URL is down and so to re

Giten Mitra 4 Nov 18, 2022
ExtDNS synchronizes labeled records in docker-compose with DNS providers.

ExtDNS for docker-compose ExtDNS synchronizes labeled records in docker-compose with DNS providers. Inspired by External DNS, ExtDNS makes resources d

DNTSK 6 Dec 24, 2022
mitm6 is a pentesting tool that exploits the default configuration of Windows to take over the default DNS server.

mitm6 is a pentesting tool that exploits the default configuration of Windows to take over the default DNS server.

Fox-IT 1.3k Jan 5, 2023
Script and library to wait for a DNS authority server to get its configuration.

DNSWait dnswait is a small script to wait for the "propagation" of a namserver configuration. Installing It's as easy as: python -m pip install dnswai

Julien Palard 14 Jan 17, 2022
Makes dynamically updating your Cloudflare DNS records a bit easier β©πŸ‘πŸ˜Ž

Easy Dynamic Cloudflare DNS Updater Makes dynamically updating your Cloudflare DNS records a bit easier ⏩ ?? ?? If using it as a 'Dynamic DNS' client,

Zac Koch 3 Dec 19, 2021
Octodns-cloudflare - Cloudflare DNS provider for octoDNS

CloudflareProvider provider for octoDNS An octoDNS provider that targets Cloudfl

octoDNS 6 May 28, 2022
Tool for ROS 2 IP Discovery + System Monitoring

Monitor the status of computers on a network using the DDS function of ROS2.

Ar-Ray 33 Apr 3, 2022
A pure-Python KSUID implementation

Svix - Webhooks as a service Svix-KSUID This library is inspired by Segment's KSUID implementation: https://github.com/segmentio/ksuid What is a ksuid

Svix 83 Dec 16, 2022
Pywbem - A WBEM client and related utilities, written in pure Python.

Pywbem - A WBEM client and related utilities, written in pure Python Overview Pywbem is a WBEM client and WBEM indication listener and provides relate

PyWBEM Projects 39 Dec 22, 2022
Modern Denial-of-service ToolKit for python

?? Impulse Modern Denial-of-service ToolKit ?? Main window ?? Methods: Method Target Description SMS PHONE Sends a massive amount of SMS messages and

null 1 Nov 29, 2021
Very simple and tiny file sharing service written in python

Simple File sharing tool Sharing client usage (You will need to use python3 for linux) main.py --send -f file/path Optionnal flags : pwd : set a passw

null 2 Jul 26, 2022
Public HTTPS access to Home Assistant with Dataplicity service

Custom component for public HTTPS access to Home Assistant with Dataplicity service. Should work on any Linux PC or ARM, not only Raspberry as Dataplicity service said. Don't work on Windows.

Alex X 70 Oct 3, 2022
Bark Toolkit is a toolkit wich provides Denial-of-service attacks, SMS attacks and more.

Bark Toolkit About Bark Toolkit Bark Toolkit is a set of tools that provides denial of service attacks. Bark Toolkit includes SMS attack tool, HTTP

null 13 Jan 4, 2023
Client library for relay - a service for relaying server side messages to the client side browsers via websockets.

Client library for relay - a service for relaying server side messages to the client side browsers via websockets.

getme 1 Nov 10, 2021