From 2a47f931043406effb0bec6dc8927ce6bdf50890 Mon Sep 17 00:00:00 2001 From: Tim Coote Date: Wed, 6 May 2020 15:44:20 +0100 Subject: [PATCH 1/7] adjust documentation on host addresses to refer to IPv4 only --- src/robotremoteserver.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/robotremoteserver.py b/src/robotremoteserver.py index 62fc5ed..0ac7f59 100644 --- a/src/robotremoteserver.py +++ b/src/robotremoteserver.py @@ -55,7 +55,8 @@ def __init__(self, library, host='127.0.0.1', port=8270, port_file=None, :param library: Test library instance or module to host. :param host: Address to listen. Use ``'0.0.0.0'`` to listen - to all available interfaces. + to all available interfaces that have an IPv4 + address. :param port: Port to listen. Use ``0`` to select a free port automatically. Can be given as an integer or as a string. From c45effa1877d73512358f7c69c8fd2b4f14b8621 Mon Sep 17 00:00:00 2001 From: Tim Coote Date: Wed, 6 May 2020 16:19:32 +0100 Subject: [PATCH 2/7] code change for _log to handle IPv6 version of server_address --- src/robotremoteserver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/robotremoteserver.py b/src/robotremoteserver.py index 0ac7f59..d7de355 100644 --- a/src/robotremoteserver.py +++ b/src/robotremoteserver.py @@ -150,7 +150,7 @@ def _announce_stop(self, log, port_file): def _log(self, action, log=True, warn=False): if log: - address = '%s:%s' % self.server_address + address = '%s:%s' % self.server_address [:2] if warn: print('*WARN*', end=' ') print('Robot Framework remote server at %s %s.' % (address, action)) From 1596e61c42610778587063b31bdbc6ba8ca10e46 Mon Sep 17 00:00:00 2001 From: Tim Coote Date: Wed, 6 May 2020 16:21:06 +0100 Subject: [PATCH 3/7] update README.rst --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 476f0ed..19e9d1e 100644 --- a/README.rst +++ b/README.rst @@ -73,7 +73,7 @@ accepts the following configuration parameters when it is initialized: Argument Default Explanation ===================== ================= ======================================== ``library`` Test library instance or module to host. Mandatory argument. - ``host`` ``'127.0.0.1'`` Address to listen. Use ``'0.0.0.0'`` to listen to all available interfaces. + ``host`` ``'127.0.0.1'`` Address to listen. Use ``'0.0.0.0'`` to listen to all available IPv4 addresses. ``port`` ``8270`` Port to listen. Use ``0`` to select a free port automatically. Can be given as an integer or as a string. The default port ``8270`` is `registered by IANA`__ for remote server usage. ``port_file`` ``None`` File to write the port that is used. ``None`` (default) means no such file is written. ``allow_stop`` ``'DEPRECATED'`` Deprecated since version 1.1. Use ``allow_remote_stop`` instead. From 4822c379c7e1357241095cc145d3fae251ec47e2 Mon Sep 17 00:00:00 2001 From: Tim Coote Date: Thu, 7 May 2020 13:17:18 +0100 Subject: [PATCH 4/7] Incoroporating IPv6 into robotremoteserver.py --- README.rst | 23 +++++++++++++++++++++++ example/exipv6.py | 18 ++++++++++++++++++ example/tests.robot | 2 +- src/robotremoteserver.py | 8 +++++++- 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 example/exipv6.py diff --git a/README.rst b/README.rst index 19e9d1e..123f7ab 100644 --- a/README.rst +++ b/README.rst @@ -243,6 +243,29 @@ using ``stop`` argument on the command line or by using the ``stop_remote_server`` function programmatically. Testing and stopping should work also with other Robot Framework remote server implementations. +Simple IPv6 Support +------------------- + +RobotRemoteServer instances can bind to IPv6 addresses as well as IPv4 addresses; +both specific addresses and the 'any available address' equivalent to IPv4's +'0.0.0.0': '::'. + +To use IPv6 addresses, it is necessary to set the class variable `TCPServer.address_family` +*before* the `import` of `RobotRemoteServer`, as shown in the example below. + +.. sourcecode:: python + + import socketserver + import socket + + socketserver.TCPServer.address_family = socket.AF_INET6 + + from robotremoteserver import RobotRemoteServer + from mylibrary import MyLibrary + + RobotRemoteServer (MyLibrary (), host = "::") + + Listing keywords and viewing documentation ------------------------------------------ diff --git a/example/exipv6.py b/example/exipv6.py new file mode 100644 index 0000000..855dccf --- /dev/null +++ b/example/exipv6.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python + +import sys + +import socketserver +import socket + +socketserver.TCPServer.address_family = socket.AF_INET6 + +from robotremoteserver import RobotRemoteServer + +from examplelibrary import ExampleLibrary + +if __name__ == '__main__': + #RobotRemoteServer(ExampleLibrary(), host="::", *sys.argv[1:]) + #RobotRemoteServer(ExampleLibrary(), host="::ffff:192.168.194.81", *sys.argv[1:]) + #RobotRemoteServer(ExampleLibrary(), host="192.168.194.81", *sys.argv[1:]) + RobotRemoteServer(ExampleLibrary(), host="::ffff:0.0.0.0", *sys.argv[1:]) diff --git a/example/tests.robot b/example/tests.robot index 6e05fb6..9982953 100644 --- a/example/tests.robot +++ b/example/tests.robot @@ -2,7 +2,7 @@ Library Remote http://${ADDRESS}:${PORT} *** Variables *** -${ADDRESS} 127.0.0.1 +${ADDRESS} localhost ${PORT} 8270 *** Test Cases *** diff --git a/src/robotremoteserver.py b/src/robotremoteserver.py index d7de355..bc324be 100644 --- a/src/robotremoteserver.py +++ b/src/robotremoteserver.py @@ -24,6 +24,12 @@ import threading import traceback +import socketserver +import socket + +socketserver.TCPServer.address_family = socket.AF_INET6 + + if sys.version_info < (3,): from SimpleXMLRPCServer import SimpleXMLRPCServer from StringIO import StringIO @@ -49,7 +55,7 @@ class RobotRemoteServer(object): - def __init__(self, library, host='127.0.0.1', port=8270, port_file=None, + def __init__(self, library, host='::1', port=8270, port_file=None, allow_stop='DEPRECATED', serve=True, allow_remote_stop=True): """Configure and start-up remote server. From 76df5c50ae05ce90609f9f77a7818aafe529d331 Mon Sep 17 00:00:00 2001 From: Tim Coote Date: Thu, 7 May 2020 14:18:24 +0100 Subject: [PATCH 5/7] documentation and example --- example/exipv6.py | 8 ++++++++ example/tests.robot | 2 +- src/robotremoteserver.py | 8 +------- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/example/exipv6.py b/example/exipv6.py index 855dccf..2620f38 100644 --- a/example/exipv6.py +++ b/example/exipv6.py @@ -1,4 +1,6 @@ #!/usr/bin/env python +# example of how to get RobotRemtoteServer working with IPv6: set up socketserver.TTCPServer.addresse_family +# class variable before importing RobotRemoteServer. Then use IPv6 notation, rather than IPv4 import sys @@ -12,7 +14,13 @@ from examplelibrary import ExampleLibrary if __name__ == '__main__': + # listen on any IPv6 address, including all IPv4 addresses on the host #RobotRemoteServer(ExampleLibrary(), host="::", *sys.argv[1:]) + # listen on local loopback interface + #RobotRemoteServer(ExampleLibrary(), host="::1", *sys.argv[1:]) + # example encoding of IPv4 RFC1918 address as IPv6 address #RobotRemoteServer(ExampleLibrary(), host="::ffff:192.168.194.81", *sys.argv[1:]) + # IPv4 notation will fail #RobotRemoteServer(ExampleLibrary(), host="192.168.194.81", *sys.argv[1:]) + # listen on any IPv4 address RobotRemoteServer(ExampleLibrary(), host="::ffff:0.0.0.0", *sys.argv[1:]) diff --git a/example/tests.robot b/example/tests.robot index 9982953..bbc2996 100644 --- a/example/tests.robot +++ b/example/tests.robot @@ -2,7 +2,7 @@ Library Remote http://${ADDRESS}:${PORT} *** Variables *** -${ADDRESS} localhost +${ADDRESS} ::1 ${PORT} 8270 *** Test Cases *** diff --git a/src/robotremoteserver.py b/src/robotremoteserver.py index bc324be..d7de355 100644 --- a/src/robotremoteserver.py +++ b/src/robotremoteserver.py @@ -24,12 +24,6 @@ import threading import traceback -import socketserver -import socket - -socketserver.TCPServer.address_family = socket.AF_INET6 - - if sys.version_info < (3,): from SimpleXMLRPCServer import SimpleXMLRPCServer from StringIO import StringIO @@ -55,7 +49,7 @@ class RobotRemoteServer(object): - def __init__(self, library, host='::1', port=8270, port_file=None, + def __init__(self, library, host='127.0.0.1', port=8270, port_file=None, allow_stop='DEPRECATED', serve=True, allow_remote_stop=True): """Configure and start-up remote server. From c87dd387467bda0c1fb5c355de875ebb417651ff Mon Sep 17 00:00:00 2001 From: Tim Coote Date: Thu, 7 May 2020 14:48:25 +0100 Subject: [PATCH 6/7] add documentation to highlight IPv4/IPv6 differences --- example/tests.robot | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/example/tests.robot b/example/tests.robot index bbc2996..03656e6 100644 --- a/example/tests.robot +++ b/example/tests.robot @@ -2,7 +2,13 @@ Library Remote http://${ADDRESS}:${PORT} *** Variables *** -${ADDRESS} ::1 +# localhost may be a suitable alias for the local IP stack loopback address +${ADDRESS} localhost +# alternatively, use a protocol specific loopback address +# IPv6 loopback address +#${ADDRESS} ::1 +# IPv4 loopback address +#${ADDRESS} 127.0.0.1 ${PORT} 8270 *** Test Cases *** From 859f04186b16c92856701f3c74f17329d3582a9b Mon Sep 17 00:00:00 2001 From: Tim Coote Date: Thu, 7 May 2020 14:54:34 +0100 Subject: [PATCH 7/7] breaking change to robotremoteserver.py --- src/robotremoteserver.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/robotremoteserver.py b/src/robotremoteserver.py index d7de355..bc324be 100644 --- a/src/robotremoteserver.py +++ b/src/robotremoteserver.py @@ -24,6 +24,12 @@ import threading import traceback +import socketserver +import socket + +socketserver.TCPServer.address_family = socket.AF_INET6 + + if sys.version_info < (3,): from SimpleXMLRPCServer import SimpleXMLRPCServer from StringIO import StringIO @@ -49,7 +55,7 @@ class RobotRemoteServer(object): - def __init__(self, library, host='127.0.0.1', port=8270, port_file=None, + def __init__(self, library, host='::1', port=8270, port_file=None, allow_stop='DEPRECATED', serve=True, allow_remote_stop=True): """Configure and start-up remote server.