more asyncio work

This commit is contained in:
Tobias Oberstein
2014-04-10 21:44:02 +02:00
parent aa554328ad
commit d075101d1c
55 changed files with 2767 additions and 12 deletions

View File

@@ -72,7 +72,7 @@ class FutureMixin:
return future.add_done_callback(done)
def _gather_futures(self, futures, consume_exceptions = True):
return asyncio.gather(futures, return_exception = consume_exceptions)
return asyncio.gather(*futures, return_exceptions = consume_exceptions)

View File

@@ -189,7 +189,7 @@ class BaseSession:
if isinstance(exc, exception.ApplicationError):
msg = message.Error(request_type, request, six.u(exc.error), args = list(exc.args), kwargs = exc.kwargs)
else:
if self._ecls_to_uri_pat.has_key(exc.__class__):
if exc.__class__ in self._ecls_to_uri_pat:
error = self._ecls_to_uri_pat[exc.__class__][0]._uri
else:
error = u"wamp.error.runtime_error"
@@ -219,7 +219,7 @@ class BaseSession:
exc = None
if self._uri_to_ecls.has_key(msg.error):
if msg.error in self._uri_to_ecls:
ecls = self._uri_to_ecls[msg.error]
try:
## the following might fail, eg. TypeError when
@@ -575,7 +575,11 @@ class ApplicationSession(BaseSession):
log.err(err)
del self._invocations[msg.request]
reply = self._message_from_exception(message.Invocation.MESSAGE_TYPE, msg.request, err.value)
if hasattr(err, 'value'):
exc = err.value
else:
exc = err
reply = self._message_from_exception(message.Invocation.MESSAGE_TYPE, msg.request, exc)
self._transport.send(reply)
self._invocations[msg.request] = d
@@ -881,7 +885,8 @@ class ApplicationSession(BaseSession):
## decorated with "wamp.procedure"
##
dl = []
for k in inspect.getmembers(endpoint.__class__, inspect.ismethod):
# for k in inspect.getmembers(endpoint.__class__, inspect.ismethod):
for k in inspect.getmembers(endpoint.__class__, inspect.isfunction):
proc = k[1]
if "_wampuris" in proc.__dict__:
pat = proc.__dict__["_wampuris"][0]

View File

@@ -18,6 +18,8 @@
from __future__ import absolute_import
import six
class ComponentConfig:
def __init__(self, realm = None, extra = None):
@@ -49,7 +51,7 @@ class Accept(HelloReturn):
class Deny(HelloReturn):
def __init__(self, reason = "wamp.error.not_authorized", message = None):
def __init__(self, reason = u"wamp.error.not_authorized", message = None):
self.reason = reason
self.message = message
@@ -160,7 +162,7 @@ class PublishOptions:
discloseMe = None):
"""
Constructor.
:param acknowledge: If True, acknowledge the publication with a success or
error response.
:type acknowledge: bool
@@ -177,8 +179,8 @@ class PublishOptions:
"""
assert(acknowledge is None or type(acknowledge) == bool)
assert(excludeMe is None or type(excludeMe) == bool)
assert(exclude is None or (type(exclude) == list and all(type(x) in [int, long] for x in exclude)))
assert(eligible is None or (type(eligible) == list and all(type(x) in [int, long] for x in eligible)))
assert(exclude is None or (type(exclude) == list and all(type(x) in six.integer_types for x in exclude)))
assert(eligible is None or (type(eligible) == list and all(type(x) in six.integer_types for x in eligible)))
assert(discloseMe is None or type(discloseMe) == bool)
self.options = {
@@ -205,7 +207,7 @@ class RegisterOptions:
in this keyword argument to the callable.
:type details_arg: str
"""
assert(details_arg is None or type(details_arg) == str)
assert(details_arg is None or type(details_arg) == six.text_type)
self.details_arg = details_arg
self.options = {
'pkeys': pkeys,
@@ -274,9 +276,9 @@ class CallOptions:
:type runOn: str
"""
assert(onProgress is None or callable(onProgress))
assert(timeout is None or (type(timeout) in [int, float] and timeout > 0))
assert(timeout is None or (type(timeout) in six.integer_types + [float] and timeout > 0))
assert(discloseMe is None or type(discloseMe) == bool)
assert(runOn is None or (type(runOn) == str and runOn in ["all", "any", "partition"]))
assert(runOn is None or (type(runOn) == six.text_type and runOn in [u"all", u"any", u"partition"]))
self.options = {
'timeout': timeout,

View File

@@ -0,0 +1 @@
node_modules

View File

@@ -0,0 +1,224 @@
all:
@echo "Targets:"
@echo ""
@echo "Router-only:"
@echo " server"
@echo ""
@echo "RPC Time Service:"
@echo " server_with_rpc_timeservice_backend"
@echo " client_rpc_timeservice_frontend"
@echo " client_rpc_timeservice_backend"
@echo ""
@echo "RPC Slow Square:"
@echo " server_with_rpc_slowsquare_backend"
@echo " client_rpc_slowsquare_frontend"
@echo " client_rpc_slowsquare_backend"
@echo ""
@echo "RPC Arguments:"
@echo " server_with_rpc_arguments_backend"
@echo " client_rpc_arguments_frontend"
@echo " client_rpc_arguments_backend"
@echo ""
@echo "RPC Options:"
@echo " server_with_rpc_options_backend"
@echo " client_rpc_options_frontend"
@echo " client_rpc_options_backend"
@echo ""
@echo "RPC Errors:"
@echo " server_with_rpc_errors_backend"
@echo " client_rpc_errors_frontend"
@echo " client_rpc_errors_backend"
@echo ""
@echo "RPC Complex Result:"
@echo " server_with_rpc_complex_backend"
@echo " client_rpc_complex_frontend"
@echo " client_rpc_complex_backend"
@echo ""
@echo "RPC Progressive Results:"
@echo " server_with_rpc_progress_backend"
@echo " client_rpc_progress_frontend"
@echo " client_rpc_progress_backend"
@echo ""
@echo "RPC Decorators:"
@echo " server_with_rpc_decorators_backend"
@echo " client_rpc_decorators_frontend"
@echo " client_rpc_decorators_backend"
@echo ""
@echo "PubSub Basic:"
@echo " server_with_pubsub_basic_backend"
@echo " client_pubsub_basic_frontend"
@echo " client_pubsub_basic_backend"
@echo ""
@echo "PubSub Complex Event:"
@echo " server_with_pubsub_complex_backend"
@echo " client_pubsub_complex_frontend"
@echo " client_pubsub_complex_backend"
@echo ""
@echo "PubSub Options:"
@echo " server_with_pubsub_options_backend"
@echo " client_pubsub_options_frontend"
@echo " client_pubsub_options_backend"
@echo ""
@echo "PubSub Unsubscribe:"
@echo " server_with_pubsub_unsubscribe_backend"
@echo " client_pubsub_unsubscribe_frontend"
@echo " client_pubsub_unsubscribe_backend"
@echo ""
@echo "PubSub Decorators:"
@echo " server_with_pubsub_decorators_backend"
@echo " client_pubsub_decorators_frontend"
@echo " client_pubsub_decorators_backend"
@echo ""
@echo "Session Series:"
@echo " server_with_session_series_backend"
@echo " client_session_series_frontend"
@echo " client_session_series_backend"
@echo ""
s:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 server.py
s1:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 server.py --component "rpc.timeservice.backend.Component"
f1:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "rpc.timeservice.frontend.Component"
b1:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "rpc.timeservice.backend.Component"
s2:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 server.py --component "rpc.slowsquare.backend.Component"
f2:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "rpc.slowsquare.frontend.Component"
b2:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "rpc.slowsquare.backend.Component"
s3:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 server.py --component "rpc.arguments.backend.Component"
f3:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "rpc.arguments.frontend.Component"
b3:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "rpc.arguments.backend.Component"
s4:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 server.py --component "rpc.options.backend.Component"
f4:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "rpc.options.frontend.Component"
b4:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "rpc.options.backend.Component"
s5:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 server.py --component "rpc.errors.backend.Component"
f5:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "rpc.errors.frontend.Component"
b5:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "rpc.errors.backend.Component"
s6:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 server.py --component "rpc.complex.backend.Component"
f6:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "rpc.complex.frontend.Component"
b6:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "rpc.complex.backend.Component"
s7:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 server.py --component "rpc.progress.backend.Component"
f7:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "rpc.progress.frontend.Component"
b7:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "rpc.progress.backend.Component"
s8:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 server.py --component "rpc.decorators.backend.Component"
f8:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "rpc.decorators.frontend.Component"
b8:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "rpc.decorators.backend.Component"
s9:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 server.py --component "pubsub.basic.backend.Component"
f9:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "pubsub.basic.frontend.Component"
b9:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "pubsub.basic.backend.Component"
s10:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 server.py --component "pubsub.complex.backend.Component"
f10:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "pubsub.complex.frontend.Component"
b10:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "pubsub.complex.backend.Component"
s11:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 server.py --component "pubsub.options.backend.Component"
f11:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "pubsub.options.frontend.Component"
b11:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "pubsub.options.backend.Component"
s12:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 server.py --component "pubsub.unsubscribe.backend.Component"
f12:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "pubsub.unsubscribe.frontend.Component"
b12:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "pubsub.unsubscribe.backend.Component"
s13:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 server.py --component "pubsub.decorators.backend.Component"
f13:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "pubsub.decorators.frontend.Component"
b13:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "pubsub.decorators.backend.Component"
s14:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 server.py --component "session.series.backend.Component"
f14:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "session.series.frontend.Component"
b14:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 client.py --component "session.series.backend.Component"
client_session_fromoutside_backend:
PYTHONPATH=../../../../autobahn ~/python34/bin/python3 session/fromoutside/backend.py

View File

@@ -0,0 +1,206 @@
# WAMP v2 Examples
The examples in this folder serve to illustrate **[WAMP version 2](https://github.com/tavendo/WAMP/blob/master/spec/README.md)** on [**Autobahn**|Python](http://autobahn.ws/):
* WAMP **RPC** and **PubSub** features for application use
* example WAMP **application components** and **routers**
# Application Component Deployment
**[WAMP v2](https://github.com/tavendo/WAMP/blob/master/spec/README.md)** on [**Autobahn**|Python](http://autobahn.ws/) allows to run application components in different deployment configurations without any changes to application code:
![Application Code Deployment Options](figures/app_code_depl_options.png)
## Running the Demos
All demos use the same two example application routers to host the application components for a demo:
* [A WAMP/WebSocket server container](server.py)
* [A WAMP/WebSocket client container](client.py)
The application components of the demos are separate from the example application routres, and each application component demonstrates a different RPC or PubSub feature.
### Router with embedded application backend component
Run the example application router on a WebSocket transport server and start a demo "backend" application component inside the router:
python server.py --component "rpc.timeservice.backend.Component"
Run the demo "frontend" application component over a WebSocket transport client:
python client.py --component "rpc.timeservice.frontend.Component"
### Application backend component in client
Run the example application router on a WebSocket transport server:
python server.py
Run the demo "backend" application component over a WebSocket transport client:
python client.py --component "rpc.timeservice.backend.Component"
Run the demo "frontend" application component over a WebSocket transport client:
python client.py --component "rpc.timeservice.frontend.Component"
### Other Transports
To start a server accepting WAMP connections on TCP port 8080 using a **rawsocket** transport with MsgPack serialization:
```shell
python server.py --debug --endpoint "tcp:8080" --transport "rawsocket-msgpack" \
--component "rpc.timeservice.backend.Component"
```
To start a client connecting to this server:
```shell
python client.py --endpoint "tcp:127.0.0.1:8080" --transport "rawsocket-msgpack" \
--component "rpc.timeservice.frontend.Component"
```
## Available Demos
### Remote Procedure Calls
#### Time Service
A trivial time service - demonstrates basic remote procedure feature.
* `rpc.timeservice.backend.Component`
* `rpc.timeservice.frontend.Component`
#### Slow Square
Demonstrates procedures which return promises and return asynchronously.
* `rpc.slowsquare.backend.Component`
* `rpc.slowsquare.frontend.Component`
#### Arguments
Demonstrates all variants of call arguments.
* `rpc.arguments.backend.Component`
* `rpc.arguments.frontend.Component`
#### Complex Result
Demonstrates complex call results (call results with more than one positional or keyword results).
* `rpc.complex.backend.Component`
* `rpc.complex.frontend.Component`
#### Errors
Demonstrates error raising and catching over remote procedures.
* `rpc.errors.backend.Component`
* `rpc.errors.frontend.Component`
#### Progressive Results
Demonstrates calling remote procedures that produce progressive results.
* `rpc.progress.backend.Component`
* `rpc.progress.frontend.Component`
#### Options
Using options with RPC.
* `rpc.options.backend.Component`
* `rpc.options.backend.Component`
### Publish & Subscribe
#### Time Service
Demonstrates basic publish and subscribe.
* `pubsub.basic.backend.Component`
* `pubsub.basic.frontend.Component`
#### Complex Events
Demonstrates publish and subscribe with complex events.
* `pubsub.complex.backend.Component`
* `pubsub.complex.frontend.Component`
#### Options
Using options with PubSub.
* `pubsub.options.backend.Component`
* `pubsub.options.frontend.Component`
#### Unsubscribing
Shows how to unsubscribe.
* `pubsub.unsubscribe.backend.Component`
* `pubsub.unsubscribe.frontend.Component`
### Session
#### Session Series
Demonstrates how multiple sessions can exist during the lifetime of the underlying transport.
* `session.series.backend.Component`
* `session.series.frontend.Component`
## AutobahnJS-based Demos
In addition, the demo front- and backends are available as AutobahnJS-based versions to run in browsers and NodeJS.
For example, run the example application router on a WebSocket transport server and start a demo "backend" application component inside the router:
python server.py --component "rpc.timeservice.backend.Component"
Then, open the JavaScript frontend in a browser:
rpc/timeservice_frontend.html
To run the frontend from NodeJS, install AutobahnJS
npm install autobahn
npm install when
and then
node rpc/timeservice_frontend.js
To run the backend in NodeJS, run the plain router
python server.py
and then start the backend:
node rpc/timeservice_backend.js
### Deployment Options
Application frontend in browser, application backend in browser:
![Application Code Deployment Options](figures/timeservice1.png)
Application frontend in browser, application backend in NodeJS:
![Application Code Deployment Options](figures/timeservice2.png)
Application frontend in browser, application backend in Python:
![Application Code Deployment Options](figures/timeservice3.png)
Application frontend in browser, application backend in Python (Router embedded):
![Application Code Deployment Options](figures/timeservice4.png)

View File

@@ -0,0 +1,100 @@
###############################################################################
##
## Copyright (C) 2011-2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
if __name__ == '__main__':
import sys, argparse, asyncio
## parse command line arguments
##
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--debug", action = "store_true",
help = "Enable debug output.")
parser.add_argument("-c", "--component", type = str,
help = "Start WAMP client with this application component, e.g. 'timeservice.TimeServiceFrontend'")
parser.add_argument("--host", type = str, default = "127.0.0.1",
help = 'IP or hostname to connect to.')
parser.add_argument("--port", type = int, default = 8080,
help = 'TCP port to connect to.')
parser.add_argument("--transport", choices = ['websocket', 'rawsocket-json', 'rawsocket-msgpack'], default = "websocket",
help = 'WAMP transport type')
parser.add_argument("--url", type = str, default = None,
help = 'The WebSocket URL to connect to, e.g. ws://127.0.0.1:8080/ws.')
args = parser.parse_args()
## create a WAMP application session factory
##
from autobahn.asyncio.wamp import ApplicationSessionFactory
session_factory = ApplicationSessionFactory()
## dynamically load the application component ..
##
import importlib
c = args.component.split('.')
mod, klass = '.'.join(c[:-1]), c[-1]
app = importlib.import_module(mod)
## .. and set the session class on the factory
##
session_factory.session = getattr(app, klass)
if args.transport == "websocket":
## create a WAMP-over-WebSocket transport client factory
##
from autobahn.asyncio.websocket import WampWebSocketClientFactory
transport_factory = WampWebSocketClientFactory(session_factory, url = args.url, debug_wamp = True)
transport_factory.setProtocolOptions(failByDrop = False)
elif args.transport in ['rawsocket-json', 'rawsocket-msgpack']:
## create a WAMP-over-RawSocket transport client factory
##
if args.transport == 'rawsocket-msgpack':
from autobahn.wamp.serializer import MsgPackSerializer
serializer = MsgPackSerializer()
elif args.transport == 'rawsocket-json':
from autobahn.wamp.serializer import JsonSerializer
serializer = JsonSerializer()
else:
raise Exception("should not arrive here")
from autobahn.asyncio.rawsocket import WampRawSocketClientFactory
transport_factory = WampRawSocketClientFactory(session_factory, serializer, debug = args.debug)
## start the client
loop = asyncio.get_event_loop()
coro = loop.create_connection(transport_factory, args.host, args.port)
loop.run_until_complete(coro)
## now enter the asyncio event loop
loop.run_forever()
loop.close()

View File

@@ -0,0 +1,17 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################

View File

@@ -0,0 +1,17 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################

View File

@@ -0,0 +1,47 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from autobahn.twisted.util import sleep
from autobahn.twisted.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component that publishes an event every second.
"""
def __init__(self, realm = "realm1"):
ApplicationSession.__init__(self)
self._realm = realm
def onConnect(self):
self.join(self._realm)
@inlineCallbacks
def onJoin(self, details):
counter = 0
while True:
self.publish('com.myapp.topic1', counter)
counter += 1
yield sleep(1)

View File

@@ -0,0 +1,55 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from autobahn.twisted.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component that subscribes and receives events,
and stop after having received 5 events.
"""
def onConnect(self):
self.join("realm1")
@inlineCallbacks
def onJoin(self, details):
self.received = 0
def on_event(i):
print("Got event: {}".format(i))
self.received += 1
if self.received > 5:
self.leave()
yield self.subscribe(on_event, 'com.myapp.topic1')
def onLeave(self, details):
self.disconnect()
def onDisconnect(self):
reactor.stop()

View File

@@ -0,0 +1,17 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################

View File

@@ -0,0 +1,56 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import random
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from autobahn.wamp.types import SubscribeOptions
from autobahn.twisted.util import sleep
from autobahn.twisted.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component that publishes events with no payload
and with complex payloads every second.
"""
def __init__(self, realm = "realm1"):
ApplicationSession.__init__(self)
self._realm = realm
def onConnect(self):
self.join(self._realm)
@inlineCallbacks
def onJoin(self, details):
counter = 0
while True:
self.publish('com.myapp.heartbeat')
obj = {'counter': counter, 'foo': [1, 2, 3]}
self.publish('com.myapp.topic2', random.randint(0, 100), 23, c = "Hello", d = obj)
counter += 1
yield sleep(1)

View File

@@ -0,0 +1,65 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import random
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from autobahn.wamp.types import SubscribeOptions
from autobahn.twisted.util import sleep
from autobahn.twisted.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component that subscribes and receives events
of no payload and of complex payload, and stops after 5 seconds.
"""
def onConnect(self):
self.join("realm1")
@inlineCallbacks
def onJoin(self, details):
self.received = 0
def on_heartbeat(details = None):
print("Got heartbeat (publication ID {})".format(details.publication))
yield self.subscribe(on_heartbeat, 'com.myapp.heartbeat', options = SubscribeOptions(details_arg = 'details'))
def on_topic2(a, b, c = None, d = None):
print("Got event: {} {} {} {}".format(a, b, c, d))
yield self.subscribe(on_topic2, 'com.myapp.topic2')
reactor.callLater(5, self.leave)
def onLeave(self, details):
self.disconnect()
def onDisconnect(self):
reactor.stop()

View File

@@ -0,0 +1,17 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################

View File

@@ -0,0 +1,48 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from autobahn.twisted.util import sleep
from autobahn.twisted.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component that publishes an event every second.
"""
def __init__(self, realm = "realm1"):
ApplicationSession.__init__(self)
self._realm = realm
def onConnect(self):
self.join(self._realm)
@inlineCallbacks
def onJoin(self, details):
counter = 0
while True:
self.publish('com.myapp.topic1', counter)
self.publish('com.myapp.topic2', "Hello world.")
counter += 1
yield sleep(1)

View File

@@ -0,0 +1,77 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from autobahn import wamp
from autobahn.twisted.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component that subscribes and receives events,
and stop after having received 5 events.
"""
def __init__(self, realm = "realm1"):
ApplicationSession.__init__(self)
self._realm = realm
self.received = 0
def onConnect(self):
self.join(self._realm)
@inlineCallbacks
def onJoin(self, details):
## subscribe all methods on this object decorated with "@wamp.topic"
## as PubSub event handlers
##
results = yield self.subscribe(self)
for success, res in results:
if success:
## res is an Subscription instance
print("Ok, subscribed handler with subscription ID {}".format(res.id))
else:
## res is an Failure instance
print("Failed to subscribe handler: {}".format(res.value))
@wamp.topic('com.myapp.topic1')
def onEvent1(self, i):
print("Got event on topic1: {}".format(i))
self.received += 1
if self.received > 5:
self.leave()
@wamp.topic('com.myapp.topic2')
def onEvent2(self, msg):
print("Got event on topic2: {}".format(msg))
def onLeave(self, details):
self.disconnect()
def onDisconnect(self):
reactor.stop()

View File

@@ -0,0 +1,17 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################

View File

@@ -0,0 +1,57 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from autobahn.wamp.types import PublishOptions, EventDetails, SubscribeOptions
from autobahn.twisted.util import sleep
from autobahn.twisted.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component that publishes an event every second.
"""
def __init__(self, realm = "realm1"):
ApplicationSession.__init__(self)
self._realm = realm
def onConnect(self):
self.join(self._realm)
@inlineCallbacks
def onJoin(self, details):
def on_event(i):
print("Got event: {}".format(i))
yield self.subscribe(on_event, 'com.myapp.topic1')
counter = 0
while True:
publication = yield self.publish('com.myapp.topic1', counter,
options = PublishOptions(acknowledge = True, discloseMe = True, excludeMe = False))
print("Event published with publication ID {}".format(publication.id))
counter += 1
yield sleep(1)

View File

@@ -0,0 +1,58 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from autobahn.wamp.types import PublishOptions, EventDetails, SubscribeOptions
from autobahn.twisted.util import sleep
from autobahn.twisted.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component that subscribes and receives events,
and stop after having received 5 events.
"""
def onConnect(self):
self.join("realm1")
@inlineCallbacks
def onJoin(self, details):
self.received = 0
def on_event(i, details = None):
print("Got event, publication ID {}, publisher {}: {}".format(details.publication, details.publisher, i))
self.received += 1
if self.received > 5:
self.leave()
yield self.subscribe(on_event, 'com.myapp.topic1',
options = SubscribeOptions(details_arg = 'details'))
def onLeave(self, details):
self.disconnect()
def onDisconnect(self):
reactor.stop()

View File

@@ -0,0 +1,17 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################

View File

@@ -0,0 +1,48 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from autobahn.twisted.util import sleep
from autobahn.twisted.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component that publishes an event every second.
"""
def __init__(self, realm = "realm1"):
ApplicationSession.__init__(self)
self._realm = realm
def onConnect(self):
self.join(self._realm)
@inlineCallbacks
def onJoin(self, details):
counter = 0
while True:
self.publish('com.myapp.topic1', counter)
counter += 1
yield sleep(1)

View File

@@ -0,0 +1,72 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from autobahn.twisted.util import sleep
from autobahn.twisted.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component that subscribes and receives events.
After receiving 5 events, it unsubscribes, sleeps and then
resubscribes for another run. Then it stops.
"""
@inlineCallbacks
def test(self):
self.received = 0
@inlineCallbacks
def on_event(i):
print("Got event: {}".format(i))
self.received += 1
if self.received > 5:
self.runs += 1
if self.runs > 1:
self.leave()
else:
yield self.subscription.unsubscribe()
print("Unsubscribed .. continue in 2s ..")
reactor.callLater(2, self.test)
self.subscription = yield self.subscribe(on_event, 'com.myapp.topic1')
print("Subscribed with subscription ID {}".format(self.subscription.id))
def onConnect(self):
self.join("realm1")
@inlineCallbacks
def onJoin(self, details):
self.runs = 0
yield self.test()
def onLeave(self, details):
self.disconnect()
def onDisconnect(self):
reactor.stop()

View File

@@ -0,0 +1,17 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################

View File

@@ -0,0 +1,17 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################

View File

@@ -0,0 +1,53 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
from autobahn.asyncio.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component providing procedures with different kinds of arguments.
"""
def onConnect(self):
self.join(u"realm1")
def onJoin(self, details):
def ping():
return
def add2(a, b):
return a + b
def stars(nick = "somebody", stars = 0):
return u"{} starred {}x".format(nick, stars)
def orders(product, limit = 5):
return [u"Product {}".format(i) for i in range(50)][:limit]
def arglen(*args, **kwargs):
return [len(args), len(kwargs)]
self.register(ping, u'com.arguments.ping')
self.register(add2, u'com.arguments.add2')
self.register(stars, u'com.arguments.stars')
self.register(orders, u'com.arguments.orders')
self.register(arglen, u'com.arguments.arglen')

View File

@@ -0,0 +1,81 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import asyncio
from autobahn.asyncio.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component calling the different backend procedures.
"""
def onConnect(self):
self.join(u"realm1")
@asyncio.coroutine
def onJoin(self, details):
yield from self.call(u'com.arguments.ping')
print("Pinged!")
res = yield from self.call(u'com.arguments.add2', 2, 3)
print("Add2: {}".format(res))
starred = yield from self.call(u'com.arguments.stars')
print("Starred 1: {}".format(starred))
starred = yield from self.call(u'com.arguments.stars', nick = u'Homer')
print("Starred 2: {}".format(starred))
starred = yield from self.call(u'com.arguments.stars', stars = 5)
print("Starred 3: {}".format(starred))
starred = yield from self.call(u'com.arguments.stars', nick = u'Homer', stars = 5)
print("Starred 4: {}".format(starred))
orders = yield from self.call(u'com.arguments.orders', u'coffee')
print("Orders 1: {}".format(orders))
orders = yield from self.call(u'com.arguments.orders', u'coffee', limit = 10)
print("Orders 2: {}".format(orders))
arglengths = yield from self.call(u'com.arguments.arglen')
print("Arglen 1: {}".format(arglengths))
arglengths = yield from self.call(u'com.arguments.arglen', 1, 2, 3)
print("Arglen 1: {}".format(arglengths))
arglengths = yield from self.call(u'com.arguments.arglen', a = 1, b = 2, c = 3)
print("Arglen 2: {}".format(arglengths))
arglengths = yield from self.call(u'com.arguments.arglen', 1, 2, 3, a = 1, b = 2, c = 3)
print("Arglen 3: {}".format(arglengths))
self.leave()
def onLeave(self, details):
self.disconnect()
def onDisconnect(self):
asyncio.get_event_loop().stop()

View File

@@ -0,0 +1,17 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################

View File

@@ -0,0 +1,52 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import asyncio
from autobahn.wamp.types import CallResult
from autobahn.asyncio.wamp import ApplicationSession
class Component(ApplicationSession):
"""
Application component that provides procedures which
return complex results.
"""
def __init__(self, realm = "realm1"):
ApplicationSession.__init__(self)
self._realm = realm
def onConnect(self):
self.join(self._realm)
def onJoin(self, details):
def add_complex(a, ai, b, bi):
return CallResult(c = a + b, ci = ai + bi)
self.register(add_complex, 'com.myapp.add_complex')
def split_name(fullname):
forename, surname = fullname.split()
return CallResult(forename, surname)
self.register(split_name, 'com.myapp.split_name')

View File

@@ -0,0 +1,53 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import asyncio
from autobahn.wamp.types import CallResult
from autobahn.asyncio.wamp import ApplicationSession
class Component(ApplicationSession):
"""
Application component that calls procedures which
produce complex results and showing how to access those.
"""
def onConnect(self):
self.join("realm1")
@asyncio.coroutine
def onJoin(self, details):
res = yield from self.call('com.myapp.add_complex', 2, 3, 4, 5)
print("Result: {} + {}i".format(res.kwresults['c'], res.kwresults['ci']))
res = yield from self.call('com.myapp.split_name', 'Homer Simpson')
print("Forname: {}, Surname: {}".format(res.results[0], res.results[1]))
self.leave()
def onLeave(self, details):
self.disconnect()
def onDisconnect(self):
asyncio.get_event_loop().stop()

View File

@@ -0,0 +1,17 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################

View File

@@ -0,0 +1,73 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import datetime
import asyncio
from autobahn import wamp
from autobahn.asyncio.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component registering RPC endpoints using decorators.
"""
def __init__(self, realm = "realm1"):
ApplicationSession.__init__(self)
self._realm = realm
def onConnect(self):
self.join(self._realm)
@asyncio.coroutine
def onJoin(self, details):
## register all methods on this object decorated with "@wamp.procedure"
## as a RPC endpoint
##
results = yield from self.register(self)
for res in results:
if isinstance(res, wamp.protocol.Registration):
## res is an Registration instance
print("Ok, registered procedure with registration ID {}".format(res.id))
else:
## res is an Failure instance
print("Failed to register procedure: {}".format(res))
@wamp.procedure('com.mathservice.add2')
def add2(self, x, y):
return x + y
@wamp.procedure('com.mathservice.mul2')
def mul2(self, x, y):
return x * y
@wamp.procedure('com.mathservice.div2')
def square(self, x, y):
if y:
return float(x) / float(y)
else:
return 0

View File

@@ -0,0 +1,61 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import asyncio
from autobahn.asyncio.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component calling the different backend procedures.
"""
def __init__(self, realm = "realm1"):
ApplicationSession.__init__(self)
self._realm = realm
def onConnect(self):
self.join(self._realm)
@asyncio.coroutine
def onJoin(self, details):
procs = [u'com.mathservice.add2',
u'com.mathservice.mul2',
u'com.mathservice.div2']
try:
for proc in procs:
res = yield from self.call(proc, 2, 3)
print("{}: {}".format(proc, res))
except Exception as e:
print("Something went wrong: {}".format(e))
self.leave()
def onLeave(self, details):
self.disconnect()
def onDisconnect(self):
asyncio.get_event_loop().stop()

View File

@@ -0,0 +1,17 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################

View File

@@ -0,0 +1,91 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import math
import asyncio
from autobahn import wamp
from autobahn.wamp.exception import ApplicationError
from autobahn.asyncio.wamp import ApplicationSession
@wamp.error("com.myapp.error1")
class AppError1(Exception):
"""
An application specific exception that is decorated with a WAMP URI,
and hence can be automapped by Autobahn.
"""
class Component(ApplicationSession):
"""
Example WAMP application backend that raised exceptions.
"""
def __init__(self, realm = "realm1"):
ApplicationSession.__init__(self)
self._realm = realm
def onConnect(self):
self.join(self._realm)
def onJoin(self, details):
## raising standard exceptions
##
def sqrt(x):
if x == 0:
raise Exception("don't ask folly questions;)")
else:
## this also will raise, if x < 0
return math.sqrt(x)
self.register(sqrt, 'com.myapp.sqrt')
## raising WAMP application exceptions
##
def checkname(name):
if name in ['foo', 'bar']:
raise ApplicationError("com.myapp.error.reserved")
if name.lower() != name.upper():
## forward positional arguments in exceptions
raise ApplicationError("com.myapp.error.mixed_case", name.lower(), name.upper())
if len(name) < 3 or len(name) > 10:
## forward keyword arguments in exceptions
raise ApplicationError("com.myapp.error.invalid_length", min = 3, max = 10)
self.register(checkname, 'com.myapp.checkname')
## defining and automapping WAMP application exceptions
##
self.define(AppError1)
def compare(a, b):
if a < b:
raise AppError1(b - a)
self.register(compare, 'com.myapp.compare')

View File

@@ -0,0 +1,90 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import math
import asyncio
from autobahn import wamp
from autobahn.wamp.exception import ApplicationError
from autobahn.asyncio.wamp import ApplicationSession
@wamp.error("com.myapp.error1")
class AppError1(Exception):
"""
An application specific exception that is decorated with a WAMP URI,
and hence can be automapped by Autobahn.
"""
class Component(ApplicationSession):
"""
Example WAMP application frontend that catches exceptions.
"""
def onConnect(self):
self.join("realm1")
@asyncio.coroutine
def onJoin(self, details):
## catching standard exceptions
##
for x in [2, 0, -2]:
try:
res = yield from self.call('com.myapp.sqrt', x)
except Exception as e:
print("Error: {} {}".format(e, e.args))
else:
print("Result: {}".format(res))
## catching WAMP application exceptions
##
for name in ['foo', 'a', '*'*11, 'Hello']:
try:
res = yield from self.call('com.myapp.checkname', name)
except ApplicationError as e:
print("Error: {} {} {} {}".format(e, e.error, e.args, e.kwargs))
else:
print("Result: {}".format(res))
## defining and automapping WAMP application exceptions
##
self.define(AppError1)
try:
yield from self.call('com.myapp.compare', 3, 17)
except AppError1 as e:
print("Compare Error: {}".format(e))
self.leave()
def onLeave(self, details):
self.disconnect()
def onDisconnect(self):
asyncio.get_event_loop().stop()

View File

@@ -0,0 +1,17 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################

View File

@@ -0,0 +1,56 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import asyncio
from autobahn.wamp.types import CallOptions, RegisterOptions, PublishOptions
from autobahn.asyncio.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component providing procedures with
different kinds of arguments.
"""
def __init__(self, realm = "realm1"):
ApplicationSession.__init__(self)
self._realm = realm
def onConnect(self):
self.join(self._realm)
def onJoin(self, details):
def square(val, details = None):
print("square called from: {}".format(details.caller))
if val < 0:
self.publish('com.myapp.square_on_nonpositive', val)
elif val == 0:
if details.caller:
options = PublishOptions(exclude = [details.caller])
else:
options = None
self.publish('com.myapp.square_on_nonpositive', val, options = options)
return val * val
self.register(square, 'com.myapp.square', RegisterOptions(details_arg = 'details'))

View File

@@ -0,0 +1,55 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import asyncio
from autobahn.wamp.types import CallOptions, RegisterOptions, PublishOptions
from autobahn.asyncio.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component calling the different backend procedures.
"""
def onConnect(self):
self.join("realm1")
@asyncio.coroutine
def onJoin(self, details):
def on_event(val):
print("Someone requested to square non-positive: {}".format(val))
yield from self.subscribe(on_event, 'com.myapp.square_on_nonpositive')
for val in [2, 0, -2]:
res = yield from self.call('com.myapp.square', val, options = CallOptions(discloseMe = True))
print("Squared {} = {}".format(val, res))
self.leave()
def onLeave(self, details):
self.disconnect()
def onDisconnect(self):
asyncio.get_event_loop().stop()

View File

@@ -0,0 +1,17 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################

View File

@@ -0,0 +1,52 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import asyncio
from autobahn.wamp.types import CallOptions, RegisterOptions
from autobahn.asyncio.wamp import ApplicationSession
class Component(ApplicationSession):
"""
Application component that produces progressive results.
"""
def __init__(self, realm = "realm1"):
ApplicationSession.__init__(self)
self._realm = realm
def onConnect(self):
self.join(self._realm)
def onJoin(self, details):
@asyncio.coroutine
def longop(n, details = None):
if details.progress:
for i in range(n):
details.progress(i)
yield from asyncio.sleep(1)
else:
yield from asyncio.sleep(1 * n)
return n
self.register(longop, 'com.myapp.longop', RegisterOptions(details_arg = 'details'))

View File

@@ -0,0 +1,53 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import asyncio
from autobahn.wamp.types import CallOptions, RegisterOptions
from autobahn.asyncio.wamp import ApplicationSession
class Component(ApplicationSession):
"""
Application component that consumes progressive results.
"""
def onConnect(self):
self.join("realm1")
@asyncio.coroutine
def onJoin(self, details):
def on_progress(i):
print("Progress: {}".format(i))
res = yield from self.call('com.myapp.longop', 3, options = CallOptions(onProgress = on_progress))
print("Final: {}".format(res))
self.leave()
def onLeave(self, details):
self.disconnect()
def onDisconnect(self):
asyncio.get_event_loop().stop()

View File

@@ -0,0 +1,17 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################

View File

@@ -0,0 +1,52 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import asyncio
from autobahn.asyncio.wamp import ApplicationSession
class Component(ApplicationSession):
"""
A math service application component.
"""
def __init__(self, realm = "realm1"):
ApplicationSession.__init__(self)
self._realm = realm
def onConnect(self):
self.join(self._realm)
def onJoin(self, details):
def square(x):
return x * x
self.register(square, 'com.math.square')
@asyncio.coroutine
def slowsquare(x, delay = 1):
yield from asyncio.sleep(delay)
return x * x
self.register(slowsquare, 'com.math.slowsquare')

View File

@@ -0,0 +1,62 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import time
import asyncio
from functools import partial
from autobahn.asyncio.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component using the time service.
"""
def onConnect(self):
self.join("realm1")
@asyncio.coroutine
def onJoin(self, details):
def got(started, msg, f):
res = f.result()
duration = 1000. * (time.clock() - started)
print("{}: {} in {}".format(msg, res, duration))
t1 = time.clock()
d1 = self.call('com.math.slowsquare', 3)
d1.add_done_callback(partial(got, t1, "Slow Square"))
t2 = time.clock()
d2 = self.call('com.math.square', 3)
d2.add_done_callback(partial(got, t2, "Quick Square"))
yield from asyncio.gather(d1, d2)
print("All finished.")
self.leave()
def onLeave(self, details):
self.disconnect()
def onDisconnect(self):
asyncio.get_event_loop().stop()

View File

@@ -0,0 +1,17 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################

View File

@@ -0,0 +1,45 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import datetime
from autobahn.asyncio.wamp import ApplicationSession
class Component(ApplicationSession):
"""
A simple time service application component.
"""
def __init__(self, realm = "realm1"):
ApplicationSession.__init__(self)
self._realm = realm
def onConnect(self):
self.join(self._realm)
def onJoin(self, details):
def utcnow():
now = datetime.datetime.utcnow()
return now.strftime("%Y-%m-%dT%H:%M:%SZ")
self.register(utcnow, 'com.timeservice.now')

View File

@@ -0,0 +1,52 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import datetime
import asyncio
from autobahn.asyncio.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component using the time service.
"""
def onConnect(self):
self.join("realm1")
@asyncio.coroutine
def onJoin(self, details):
try:
now = yield from self.call('com.timeservice.now')
except Exception as e:
print("Error: {}".format(e))
else:
print("Current time from time service: {}".format(now))
self.leave()
def onLeave(self, details):
self.disconnect()
def onDisconnect(self):
asyncio.get_event_loop().stop()

View File

@@ -0,0 +1,117 @@
###############################################################################
##
## Copyright (C) 2011-2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
if __name__ == '__main__':
import sys, argparse, asyncio
## parse command line arguments
##
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--debug", action = "store_true",
help = "Enable debug output.")
parser.add_argument("-c", "--component", type = str, default = None,
help = "Start WAMP server with this application component, e.g. 'timeservice.TimeServiceBackend', or None.")
parser.add_argument("--interface", type = str, default = "127.0.0.1",
help = 'IP of interface to listen on.')
parser.add_argument("--port", type = int, default = 8080,
help = 'TCP port to listen on.')
parser.add_argument("--transport", choices = ['websocket', 'rawsocket-json', 'rawsocket-msgpack'], default = "websocket",
help = 'WAMP transport type')
args = parser.parse_args()
## create a WAMP router factory
##
from autobahn.wamp.router import RouterFactory
router_factory = RouterFactory()
## create a WAMP router session factory
##
from autobahn.asyncio.wamp import RouterSessionFactory
session_factory = RouterSessionFactory(router_factory)
## if asked to start an embedded application component ..
##
if args.component:
## dynamically load the application component ..
##
import importlib
c = args.component.split('.')
mod, klass = '.'.join(c[:-1]), c[-1]
app = importlib.import_module(mod)
SessionKlass = getattr(app, klass)
## .. and create and add an WAMP application session to
## run next to the router
##
session_factory.add(SessionKlass())
if args.transport == "websocket":
## create a WAMP-over-WebSocket transport server factory
##
from autobahn.asyncio.websocket import WampWebSocketServerFactory
transport_factory = WampWebSocketServerFactory(session_factory, debug_wamp = args.debug)
transport_factory.setProtocolOptions(failByDrop = False)
elif args.transport in ['rawsocket-json', 'rawsocket-msgpack']:
## create a WAMP-over-RawSocket transport server factory
##
if args.transport == 'rawsocket-msgpack':
from autobahn.wamp.serializer import MsgPackSerializer
serializer = MsgPackSerializer()
elif args.transport == 'rawsocket-json':
from autobahn.wamp.serializer import JsonSerializer
serializer = JsonSerializer()
else:
raise Exception("should not arrive here")
from autobahn.asyncio.rawsocket import WampRawSocketServerFactory
transport_factory = WampRawSocketServerFactory(session_factory, serializer, debug = args.debug)
else:
raise Exception("should not arrive here")
## start the server from an endpoint
##
loop = asyncio.get_event_loop()
coro = loop.create_server(transport_factory, args.interface, args.port)
server = loop.run_until_complete(coro)
try:
## now enter the asyncio event loop
loop.run_forever()
except KeyboardInterrupt:
pass
finally:
server.close()
loop.close()

View File

@@ -0,0 +1,17 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################

View File

@@ -0,0 +1,13 @@
This example demonstrates how to access an app session instance from outside - via the session factory.
It runs an application component as a client connected to a WAMP router.
Start a WAMP router:
python ../../server.py
Start the backend component (which will run inside a client connecting to the router):
python client.py
Open `frontend.html` in your browser.

View File

@@ -0,0 +1,116 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
from twisted.internet.defer import inlineCallbacks
from autobahn.twisted.util import sleep
from autobahn.twisted.wamp import ApplicationSession
class MyAppComponent(ApplicationSession):
def __init__(self, realm = "realm1"):
ApplicationSession.__init__(self)
self._realm = realm
def onConnect(self):
self.join(self._realm)
def onJoin(self, details):
if not self.factory._myAppSession:
self.factory._myAppSession = self
def onLeave(self, details):
if self.factory._myAppSession == self:
self.factory._myAppSession = None
if __name__ == '__main__':
import sys
from twisted.python import log
from twisted.internet.endpoints import clientFromString
log.startLogging(sys.stdout)
## we use an Autobahn utility to import the "best" available Twisted reactor
##
from autobahn.twisted.choosereactor import install_reactor
reactor = install_reactor()
print("Running on reactor {}".format(reactor))
## create a WAMP application session factory
##
from autobahn.twisted.wamp import ApplicationSessionFactory
session_factory = ApplicationSessionFactory()
## .. and set the session class on the factory
##
session_factory.session = MyAppComponent
## since we are running this component as a client, there
## will be only 1 app session instance anyway. We'll store a
## reference on the session factory, so we can access it
## from "outside" the session instance later (see below)
##
session_factory._myAppSession = None
## create a WAMP-over-WebSocket transport client factory
##
from autobahn.twisted.websocket import WampWebSocketClientFactory
transport_factory = WampWebSocketClientFactory(session_factory, "ws://127.0.0.1:8080/ws")
## start a WebSocket client from an endpoint
##
client = clientFromString(reactor, "tcp:127.0.0.1:8080")
client.connect(transport_factory)
## publish an event every second from the (single) application session
## that get created by the session factory
##
@inlineCallbacks
def pub():
counter = 0
while True:
## here we can access the app session that was created ..
##
if session_factory._myAppSession:
session_factory._myAppSession.publish('com.myapp.topic123', counter)
print("published event", counter)
else:
print("no session")
counter += 1
yield sleep(1)
pub()
## now enter the Twisted reactor loop
##
reactor.run()

View File

@@ -0,0 +1,17 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################

View File

@@ -0,0 +1,48 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import datetime
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from autobahn.twisted.wamp import ApplicationSession
class Component(ApplicationSession):
"""
A simple time service application component.
"""
def __init__(self, realm = "realm1"):
ApplicationSession.__init__(self)
self._realm = realm
def onConnect(self):
self.join(self._realm)
def onJoin(self, details):
def utcnow():
now = datetime.datetime.utcnow()
return now.strftime("%Y-%m-%dT%H:%M:%SZ")
self.register(utcnow, 'com.timeservice.now')

View File

@@ -0,0 +1,70 @@
###############################################################################
##
## Copyright (C) 2014 Tavendo GmbH
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
##
###############################################################################
import datetime
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from autobahn.twisted.wamp import ApplicationSession
class Component(ApplicationSession):
"""
An application component using the time service
during 3 subsequent WAMP sessions, while the
underlying transport continues to exist.
"""
def __init__(self):
ApplicationSession.__init__(self)
self.count = 0
def onConnect(self):
print("Transport connected.")
self.join("realm1")
@inlineCallbacks
def onJoin(self, details):
print("Realm joined (WAMP session started).")
try:
now = yield self.call('com.timeservice.now')
except Exception as e:
print("Error: {}".format(e))
else:
print("Current time from time service: {}".format(now))
self.leave()
def onLeave(self, details):
print("Realm left (WAMP session ended).")
self.count += 1
if self.count < 3:
self.join("realm1")
else:
self.disconnect()
def onDisconnect(self):
print("Transport disconnected.")
reactor.stop()