FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

First stab at supporting listening on IPv6 interfaces · python-zeroconf/python-zeroconf@3d5787b · GitHub

Commit 3d5787b

Browse files
authored andcommitted
First stab at supporting listening on IPv6 interfaces
This change adds basic support for listening on IPv6 interfaces. Some limitations exist for non-POSIX platforms, pending fixes in Python and in the ifaddr library. Also dual V4-V6 sockets may not work on all BSD platforms. As a result, V4-only is used by default. Unfortunately, Travis does not seem to support IPv6, so the tests are disabled on it, which also leads to coverage decrease.
1 parent 7bd0436 commit 3d5787b

7 files changed

Lines changed: 349 additions & 78 deletions

File tree

‎.travis.yml‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ install:
1313
- if [[ "${TRAVIS_PYTHON_VERSION}" != "pypy"* ]] ; then pip install mypy ; fi
1414
- if [[ "${TRAVIS_PYTHON_VERSION}" != *"3.5"* ]] ; then pip install black ; fi
1515
script:
16-
- make ci
16+
# no IPv6 support in Travis :(
17+
- make TEST_ARGS='-a "!IPv6"' ci
1718
after_success:
1819
- coveralls

‎Makefile‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
MAX_LINE_LENGTH=110
33
PYTHON_IMPLEMENTATION:=$(shell python -c "import sys;import platform;sys.stdout.write(platform.python_implementation())")
44
PYTHON_VERSION:=$(shell python -c "import sys;sys.stdout.write('%d.%d' % sys.version_info[:2])")
5+
TEST_ARGS=
56

67
LINT_TARGETS:=flake8
78

@@ -39,10 +40,10 @@ mypy:
3940
mypy examples/*.py test_zeroconf.py zeroconf.py
4041

4142
test:
42-
nosetests -v
43+
nosetests -v $(TEST_ARGS)
4344

4445
test_coverage:
45-
nosetests -v --with-coverage --cover-package=zeroconf
46+
nosetests -v --with-coverage --cover-package=zeroconf $(TEST_ARGS)
4647

4748
autopep8:
4849
autopep8 --max-line-length=$(MAX_LINE_LENGTH) -i examples *.py

‎README.rst‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,18 @@ Status
6161
There are some people using this package. I don't actively use it and as such
6262
any help I can offer with regard to any issues is very limited.
6363

64+
IPv6 support
65+
------------
66+
67+
IPv6 support is relatively new and currently limited, specifically:
68+
* `InterfaceChoice.All` is an alias for `InterfaceChoice.Default` on non-POSIX
69+
systems.
70+
* On Windows specific interfaces can only be requested as interface indexes,
71+
not as IP addresses.
72+
* Dual-stack IPv6 sockets are used, which may not be supported everywhere (some
73+
BSD variants do not have them).
74+
* Listening on localhost (`::1`) does not work. Help with understanding why is
75+
appreciated.
6476

6577
How to get python-zeroconf?
6678
===========================

‎examples/browser.py‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
""" Example of browsing for a service (in this case, HTTP) """
44

5+
import argparse
56
import logging
67
import socket
7-
import sys
88
from time import sleep
99
from typing import cast
1010

11-
from zeroconf import ServiceBrowser, ServiceStateChange, Zeroconf
11+
from zeroconf import IpVersion, ServiceBrowser, ServiceStateChange, Zeroconf
1212

1313

1414
def on_service_state_change(
@@ -36,11 +36,24 @@ def on_service_state_change(
3636

3737
if __name__ == '__main__':
3838
logging.basicConfig(level=logging.DEBUG)
39-
if len(sys.argv) > 1:
40-
assert sys.argv[1:] == ['--debug']
39+
40+
parser = argparse.ArgumentParser()
41+
parser.add_argument('--debug', action='store_true')
42+
version_group = parser.add_mutually_exclusive_group()
43+
version_group.add_argument('--v6', action='store_true')
44+
version_group.add_argument('--v6-only', action='store_true')
45+
args = parser.parse_args()
46+
47+
if args.debug:
4148
logging.getLogger('zeroconf').setLevel(logging.DEBUG)
49+
if args.v6:
50+
ip_version = IpVersion.All
51+
elif args.v6_only:
52+
ip_version = IpVersion.V6Only
53+
else:
54+
ip_version = IpVersion.V4Only
4255

43-
zeroconf = Zeroconf()
56+
zeroconf = Zeroconf(ip_version=ip_version)
4457
print("\nBrowsing services, press Ctrl-C to exit...\n")
4558
browser = ServiceBrowser(zeroconf, "_http._tcp.local.", handlers=[on_service_state_change])
4659

‎examples/registration.py‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,31 @@
22

33
""" Example of announcing a service (in this case, a fake HTTP server) """
44

5+
import argparse
56
import logging
67
import socket
7-
import sys
88
from time import sleep
99

10-
from zeroconf import ServiceInfo, Zeroconf
10+
from zeroconf import IpVersion, ServiceInfo, Zeroconf
1111

1212
if __name__ == '__main__':
1313
logging.basicConfig(level=logging.DEBUG)
14-
if len(sys.argv) > 1:
15-
assert sys.argv[1:] == ['--debug']
14+
15+
parser = argparse.ArgumentParser()
16+
parser.add_argument('--debug', action='store_true')
17+
version_group = parser.add_mutually_exclusive_group()
18+
version_group.add_argument('--v6', action='store_true')
19+
version_group.add_argument('--v6-only', action='store_true')
20+
args = parser.parse_args()
21+
22+
if args.debug:
1623
logging.getLogger('zeroconf').setLevel(logging.DEBUG)
24+
if args.v6:
25+
ip_version = IpVersion.All
26+
elif args.v6_only:
27+
ip_version = IpVersion.V6Only
28+
else:
29+
ip_version = IpVersion.V4Only
1730

1831
desc = {'path': '/~paulsm/'}
1932

@@ -26,7 +39,7 @@
2639
server="ash-2.local.",
2740
)
2841

29-
zeroconf = Zeroconf()
42+
zeroconf = Zeroconf(ip_version=ip_version)
3043
print("Registration of a service, press Ctrl-C to exit...")
3144
zeroconf.register_service(info)
3245
try:

‎test_zeroconf.py‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from typing import Dict, Optional # noqa # used in type hints
1515
from typing import cast
1616

17+
from nose.plugins.attrib import attr
1718

1819
import zeroconf as r
1920
from zeroconf import (
@@ -440,6 +441,22 @@ def test_launch_and_close(self):
440441
rv = r.Zeroconf(interfaces=r.InterfaceChoice.Default)
441442
rv.close()
442443

444+
@unittest.skipIf(not socket.has_ipv6, 'Requires IPv6')
445+
@attr('IPv6')
446+
def test_launch_and_close_v4_v6(self):
447+
rv = r.Zeroconf(interfaces=r.InterfaceChoice.All, ip_version=r.IpVersion.All)
448+
rv.close()
449+
rv = r.Zeroconf(interfaces=r.InterfaceChoice.Default, ip_version=r.IpVersion.All)
450+
rv.close()
451+
452+
@unittest.skipIf(not socket.has_ipv6, 'Requires IPv6')
453+
@attr('IPv6')
454+
def test_launch_and_close_v6_only(self):
455+
rv = r.Zeroconf(interfaces=r.InterfaceChoice.All, ip_version=r.IpVersion.V6Only)
456+
rv.close()
457+
rv = r.Zeroconf(interfaces=r.InterfaceChoice.Default, ip_version=r.IpVersion.V6Only)
458+
rv.close()
459+
443460

444461
class Exceptions(unittest.TestCase):
445462

@@ -672,6 +689,30 @@ def test_integration_with_listener(self):
672689
finally:
673690
zeroconf_registrar.close()
674691

692+
@unittest.skipIf(not socket.has_ipv6, 'Requires IPv6')
693+
@attr('IPv6')
694+
def test_integration_with_listener_ipv6(self):
695+
696+
type_ = "_test-srvc-type._tcp.local."
697+
name = "xxxyyy"
698+
registration_name = "%s.%s" % (name, type_)
699+
700+
zeroconf_registrar = Zeroconf(ip_version=r.IpVersion.V6Only)
701+
desc = {'path': '/~paulsm/'}
702+
info = ServiceInfo(
703+
type_, registration_name, socket.inet_aton("10.0.1.2"), 80, 0, 0, desc, "ash-2.local."
704+
)
705+
zeroconf_registrar.register_service(info)
706+
707+
try:
708+
service_types = ZeroconfServiceTypes.find(ip_version=r.IpVersion.V6Only, timeout=0.5)
709+
assert type_ in service_types, service_types
710+
service_types = ZeroconfServiceTypes.find(zc=zeroconf_registrar, timeout=0.5)
711+
assert type_ in service_types, service_types
712+
713+
finally:
714+
zeroconf_registrar.close()
715+
675716
def test_integration_with_subtype_and_listener(self):
676717
subtype_ = "_subtype._sub"
677718
type_ = "_type._tcp.local."

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL