diff --git a/autobahn/_version.py b/autobahn/_version.py index cd7a68b5..046a3f77 100644 --- a/autobahn/_version.py +++ b/autobahn/_version.py @@ -24,4 +24,4 @@ # ############################################################################### -__version__ = u'0.18.0' +__version__ = u'0.18.1' diff --git a/autobahn/asyncio/wamp.py b/autobahn/asyncio/wamp.py index 31b877d9..5c75c67a 100644 --- a/autobahn/asyncio/wamp.py +++ b/autobahn/asyncio/wamp.py @@ -29,12 +29,6 @@ import signal import six -from autobahn.util import public -from autobahn.wamp import protocol -from autobahn.wamp.types import ComponentConfig -from autobahn.websocket.util import parse_url -from autobahn.asyncio.websocket import WampWebSocketClientFactory - try: import asyncio except ImportError: @@ -43,7 +37,20 @@ except ImportError: import trollius as asyncio import txaio -txaio.use_asyncio() +txaio.use_asyncio() # noqa + +from autobahn.util import public +from autobahn.wamp import protocol +from autobahn.wamp.types import ComponentConfig + +from autobahn.websocket.util import parse_url as parse_ws_url +from autobahn.rawsocket.util import parse_url as parse_rs_url + +from autobahn.asyncio.websocket import WampWebSocketClientFactory +from autobahn.asyncio.rawsocket import WampRawSocketClientFactory + +from autobahn.websocket.compress import PerMessageDeflateOffer, \ + PerMessageDeflateResponse, PerMessageDeflateResponseAccept __all__ = ( 'ApplicationSession', @@ -92,7 +99,7 @@ class ApplicationRunner(object): log = txaio.make_logger() - def __init__(self, url, realm, extra=None, serializers=None, ssl=None): + def __init__(self, url, realm, extra=None, serializers=None, ssl=None, proxy=None, headers=None): """ :param url: The WebSocket URL of the WAMP router to connect to (e.g. `ws://somehost.com:8090/somepath`) @@ -113,15 +120,25 @@ class ApplicationRunner(object): method, to which this value is passed as the ``ssl`` keyword parameter. :type ssl: :class:`ssl.SSLContext` or bool + + :param proxy: Explicit proxy server to use; a dict with ``host`` and ``port`` keys + :type proxy: dict or None + + :param headers: Additional headers to send (only applies to WAMP-over-WebSocket). + :type headers: dict """ assert(type(url) == six.text_type) assert(realm is None or type(realm) == six.text_type) assert(extra is None or type(extra) == dict) + assert(headers is None or type(proxy) == dict) + assert(proxy is None or type(headers) == dict) self.url = url self.realm = realm self.extra = extra or dict() self.serializers = serializers self.ssl = ssl + self.proxy = proxy + self.headers = headers @public def run(self, make, start_loop=True): @@ -152,8 +169,46 @@ class ApplicationRunner(object): else: create = make - isSecure, host, port, resource, path, params = parse_url(self.url) + if self.url.startswith(u'rs'): + # try to parse RawSocket URL .. + isSecure, host, port = parse_rs_url(self.url) + # create a WAMP-over-RawSocket transport client factory + transport_factory = WampRawSocketClientFactory(create) + + else: + # try to parse WebSocket URL .. + isSecure, host, port, resource, path, params = parse_ws_url(self.url) + + # create a WAMP-over-WebSocket transport client factory + transport_factory = WampWebSocketClientFactory(create, url=self.url, serializers=self.serializers, proxy=self.proxy, headers=self.headers) + + # client WebSocket settings - similar to: + # - http://crossbar.io/docs/WebSocket-Compression/#production-settings + # - http://crossbar.io/docs/WebSocket-Options/#production-settings + + # The permessage-deflate extensions offered to the server .. + offers = [PerMessageDeflateOffer()] + + # Function to accept permessage_delate responses from the server .. + def accept(response): + if isinstance(response, PerMessageDeflateResponse): + return PerMessageDeflateResponseAccept(response) + + # set WebSocket options for all client connections + transport_factory.setProtocolOptions(maxFramePayloadSize=1048576, + maxMessagePayloadSize=1048576, + autoFragmentSize=65536, + failByDrop=False, + openHandshakeTimeout=2.5, + closeHandshakeTimeout=1., + tcpNoDelay=True, + autoPingInterval=10., + autoPingTimeout=5., + autoPingSize=4, + perMessageCompressionOffers=offers, + perMessageCompressionAccept=accept) + # SSL context for client connection if self.ssl is None: ssl = isSecure else: @@ -164,22 +219,17 @@ class ApplicationRunner(object): self.__class__.__name__) ssl = self.ssl - # 2) create a WAMP-over-WebSocket transport client factory - transport_factory = WampWebSocketClientFactory(create, url=self.url, serializers=self.serializers) - - # 3) start the client + # start the client connection loop = asyncio.get_event_loop() txaio.use_asyncio() txaio.config.loop = loop coro = loop.create_connection(transport_factory, host, port, ssl=ssl) (transport, protocol) = loop.run_until_complete(coro) + # start a asyncio loop if not start_loop: - return protocol - else: - # start logging txaio.start_logging(level='info') diff --git a/autobahn/twisted/wamp.py b/autobahn/twisted/wamp.py index 481dd916..f3524c3c 100644 --- a/autobahn/twisted/wamp.py +++ b/autobahn/twisted/wamp.py @@ -133,11 +133,15 @@ class ApplicationRunner(object): :param proxy: Explicit proxy server to use; a dict with ``host`` and ``port`` keys :type proxy: dict or None + + :param headers: Additional headers to send (only applies to WAMP-over-WebSocket). + :type headers: dict """ assert(type(url) == six.text_type) assert(realm is None or type(realm) == six.text_type) assert(extra is None or type(extra) == dict) - assert(proxy is None or type(proxy) == dict) + assert(headers is None or type(proxy) == dict) + assert(proxy is None or type(headers) == dict) self.url = url self.realm = realm self.extra = extra or dict() diff --git a/examples/Makefile b/examples/Makefile index e4638e25..8235f87e 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -22,5 +22,10 @@ flake8: pylint: pylint -d line-too-long,invalid-name . -examples: - python run-all-examples.py +examples_rawsocket: + AUTOBAHN_DEMO_ROUTER=rs://127.0.0.1:8080 python run-all-examples.py + +examples_websocket: + AUTOBAHN_DEMO_ROUTER=ws://127.0.0.1:8080/ws python run-all-examples.py + +examples: examples_websocket examples_rawsocket diff --git a/examples/router/.crossbar/config-no-tls.json b/examples/router/.crossbar/config-no-tls.json deleted file mode 100644 index c8c2d44b..00000000 --- a/examples/router/.crossbar/config-no-tls.json +++ /dev/null @@ -1,109 +0,0 @@ -{ - "version": 2, - "workers": [ - { - "type": "router", - "realms": [ - { - "name": "crossbardemo", - "roles": [ - { - "name": "anonymous", - "permissions": [ - { - "uri": "", - "match": "prefix", - "allow": { - "call": true, - "register": true, - "publish": true, - "subscribe": true - }, - "disclose": { - "caller": false, - "publisher": false - }, - "cache": true - } - ] - }, - { - "name": "authenticated", - "permissions": [ - { - "uri": "", - "match": "prefix", - "allow": { - "call": true, - "register": true, - "publish": true, - "subscribe": true - }, - "disclose": { - "caller": false, - "publisher": false - }, - "cache": true - } - ] - } - ] - } - ], - "transports": [ - { - "type": "mqtt", - "endpoint": { - "type": "tcp", - "port": 1883 - }, - "options": { - "realm": "crossbardemo", - "role": "anonymous" - } - }, - { - "type": "web", - "endpoint": { - "type": "tcp", - "port": 8080 - }, - "paths": { - "/": { - "type": "static", - "directory": "../..", - "options": { - "enable_directory_listing": true, - "mime_types": { - ".md": "text/plain", - ".py": "text/plain" - } - } - }, - "ws": { - "type": "websocket" - }, - "auth_ws": { - "type": "websocket", - "auth": { - "wampcra": { - "type": "static", - "users": { - "username": { - "secret": "p4ssw0rd", - "role": "authenticated" - } - } - }, - "anonymous": { - "type": "static", - "role": "anonymous" - } - } - } - } - } - ] - } - ] -} diff --git a/examples/router/.crossbar/config-with-tls.json b/examples/router/.crossbar/config-with-tls.json deleted file mode 100644 index 348b3dc1..00000000 --- a/examples/router/.crossbar/config-with-tls.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "version": 2, - "workers": [ - { - "type": "router", - "realms": [ - { - "name": "crossbardemo", - "roles": [ - { - "name": "anonymous", - "permissions": [ - { - "uri": "", - "match": "prefix", - "allow": { - "call": true, - "register": true, - "publish": true, - "subscribe": true - }, - "disclose": { - "caller": false, - "publisher": false - }, - "cache": true - } - ] - } - ] - } - ], - "transports": [ - { - "type": "mqtt", - "endpoint": { - "type": "tcp", - "port": 1883 - }, - "options": { - "realm": "crossbardemo", - "role": "anonymous" - } - }, - { - "type": "web", - "endpoint": { - "type": "tcp", - "port": 8080 - }, - "paths": { - "/": { - "type": "static", - "directory": "../..", - "options": { - "enable_directory_listing": true, - "mime_types": { - ".md": "text/plain", - ".py": "text/plain" - } - } - }, - "ws": { - "type": "websocket" - }, - "auth_ws": { - "type": "websocket", - "auth": { - "wampcra": { - "type": "static", - "users": { - "username": { - "secret": "p4ssw0rd", - "role": "authenticated" - } - } - } - } - } - } - }, - { - "type": "websocket", - "endpoint": { - "type": "tcp", - "interface": "localhost", - "port": 8083, - "tls": { - "key": "server.key", - "certificate": "server.crt" - } - } - } - ] - } - ] -} diff --git a/examples/router/.crossbar/config.json b/examples/router/.crossbar/config.json deleted file mode 120000 index 07101fa9..00000000 --- a/examples/router/.crossbar/config.json +++ /dev/null @@ -1 +0,0 @@ -config-with-tls.json \ No newline at end of file diff --git a/examples/router/.crossbar/config.json b/examples/router/.crossbar/config.json new file mode 100644 index 00000000..f92187fb --- /dev/null +++ b/examples/router/.crossbar/config.json @@ -0,0 +1,115 @@ +{ + "version": 2, + "workers": [ + { + "type": "router", + "realms": [ + { + "name": "crossbardemo", + "roles": [ + { + "name": "anonymous", + "permissions": [ + { + "uri": "", + "match": "prefix", + "allow": { + "call": true, + "register": true, + "publish": true, + "subscribe": true + }, + "disclose": { + "caller": false, + "publisher": false + }, + "cache": true + } + ] + }, + { + "name": "authenticated", + "permissions": [ + { + "uri": "", + "match": "prefix", + "allow": { + "call": true, + "register": true, + "publish": true, + "subscribe": true + }, + "disclose": { + "caller": false, + "publisher": false + }, + "cache": true + } + ] + } + ] + } + ], + "transports": [ + { + "type": "mqtt", + "endpoint": { + "type": "tcp", + "port": 1883 + }, + "options": { + "realm": "crossbardemo", + "role": "anonymous" + } + }, + { + "type": "universal", + "endpoint": { + "type": "tcp", + "port": 8080 + }, + "rawsocket": { + }, + "websocket": { + "ws": { + "type": "websocket" + }, + "auth_ws": { + "type": "websocket", + "auth": { + "wampcra": { + "type": "static", + "users": { + "username": { + "secret": "p4ssw0rd", + "role": "authenticated" + } + } + }, + "anonymous": { + "type": "static", + "role": "anonymous" + } + } + } + }, + "web": { + "paths": { + "/": { + "type": "static", + "directory": "../..", + "options": { + "enable_directory_listing": true, + "mime_types": { + ".md": "text/plain", + ".py": "text/plain" + } + } + } + } + } + } + ] + } + ] +} diff --git a/examples/router/.crossbar/key.priv b/examples/router/.crossbar/key.priv new file mode 100644 index 00000000..b436ed11 --- /dev/null +++ b/examples/router/.crossbar/key.priv @@ -0,0 +1,7 @@ +Crossbar.io node private key - KEEP THIS SAFE! + +creator: oberstet@thinkpad-t430s +created-at: 2017-03-26T22:01:20.440Z +machine-id: 7a3357418649414dbd536c31c6bd0ee8 +public-key-ed25519: a81b5e80ff63ebb5f31af8afbfd7d0af5983befe3cbfca48b62026d43847c885 +private-key-ed25519: af032ab972a29a530463ba9a5beed1636af538103d5d4b413a623b6ebd60d202 diff --git a/examples/router/.crossbar/key.pub b/examples/router/.crossbar/key.pub new file mode 100644 index 00000000..3d803051 --- /dev/null +++ b/examples/router/.crossbar/key.pub @@ -0,0 +1,6 @@ +Crossbar.io node public key + +creator: oberstet@thinkpad-t430s +created-at: 2017-03-26T22:01:20.440Z +machine-id: 7a3357418649414dbd536c31c6bd0ee8 +public-key-ed25519: a81b5e80ff63ebb5f31af8afbfd7d0af5983befe3cbfca48b62026d43847c885 diff --git a/examples/run-all-examples.py b/examples/run-all-examples.py index 344649d8..8ee7dd0a 100755 --- a/examples/run-all-examples.py +++ b/examples/run-all-examples.py @@ -94,7 +94,7 @@ class CrossbarProcessProtocol(ProcessProtocol): def start_crossbar(): finished = Deferred() launched = Deferred() - protocol = CrossbarProcessProtocol(finished, launched, Fore.RED) + protocol = CrossbarProcessProtocol(finished, launched, Fore.YELLOW) exe = 'crossbar' args = [exe, 'start', '--cbdir', './router/.crossbar'] @@ -194,10 +194,10 @@ def main(reactor): print_banner("Running example: " + exdir) print(" starting backend") - back_proto = yield start_example(backend, Fore.BLUE, ' backend: ', exe=py) + back_proto = yield start_example(backend, Fore.GREEN, ' backend: ', exe=py) yield sleep(1) print(" starting frontend") - front_proto = yield start_example(frontend, Fore.YELLOW, 'frontend: ', exe=py) + front_proto = yield start_example(frontend, Fore.BLUE, 'frontend: ', exe=py) yield sleep(3) for p in [back_proto, front_proto]: