def getMapUpdaterComponentService(self, url, realm, mapUpdater): def create(config): try: session = MapUpdaterComponent(mapUpdater, config) except Exception as e: # the app component could not be created .. fatal print(e) else: session.debug_app = True return session sessionFactory = ApplicationSessionFactory( ComponentConfig(realm, None)) sessionFactory.session = create transportFactory = WampWebSocketClientFactory( sessionFactory, url=url) transportFactory.noisy = False transportFactory.autoPingInterval = 30 transportFactory.autoPingTimeout = 30 isSecure, host, port, resource, path, params = parseWsUrl(url) endpoint = HostnameEndpoint(reactor, host.encode('utf8'), port) if isSecure: contextFactory = optionsForClientTLS(hostname=host) endpoint = wrapClientTLS(contextFactory, endpoint) return ClientService(endpoint, transportFactory)
def connect_application_session(server_factory, MyApplicationSession, component_config=None): """ Connect an ApplicationSession class to the given server factory. """ application_session_factory = ApplicationSessionFactory(component_config) application_session_factory.session = MyApplicationSession client_factory = WampRawSocketClientFactory(application_session_factory) # client_factory = WampWebSocketClientFactory(application_session_factory) server_protocol = server_factory.buildProtocol(None) client_protocol = client_factory.buildProtocol(None) server_transport = FakeTransport(server_protocol, True) client_transport = FakeTransport(client_protocol, False) pump = connect(server_protocol, server_transport, client_protocol, client_transport, debug=False) return client_protocol._session, pump
def startup_client_2(implementation, server_url="ws://localhost:8080/ws", server_bindings="tcp:localhost:8080"): session_factory = ApplicationSessionFactory() session_factory.session = implementation transport_factory = WampWebSocketClientFactory(session_factory, server_url) client = clientFromString(reactor, server_bindings) client.connect(transport_factory)
def start(self): """ Starts this node. This will start a node controller and then spawn new worker processes as needed. The node controller will watch spawned processes, communicate via stdio with the worker, and start and restart the worker processes as needed. """ ## the node controller singleton WAMP application session ## self._node_controller_session = NodeControllerSession(self) ## router and factory that creates router sessions ## self._router_factory = RouterFactory() self._router_session_factory = RouterSessionFactory(self._router_factory) ## add the node controller singleton session to the router ## self._router_session_factory.add(self._node_controller_session) if True: ## create a WAMP-over-WebSocket transport server factory ## from autobahn.twisted.websocket import WampWebSocketServerFactory from twisted.internet.endpoints import serverFromString self._router_server_transport_factory = WampWebSocketServerFactory(self._router_session_factory, "ws://localhost:9000", debug = False) self._router_server_transport_factory.setProtocolOptions(failByDrop = False) ## start the WebSocket server from an endpoint ## self._router_server = serverFromString(self._reactor, "tcp:9000") self._router_server.listen(self._router_server_transport_factory) ## factory that creates router session transports. these are for clients ## that talk WAMP-WebSocket over pipes with spawned worker processes and ## for any uplink session to a management service ## self._router_client_transport_factory = WampWebSocketClientFactory(self._router_session_factory, "ws://localhost", debug = False) self._router_client_transport_factory.setProtocolOptions(failByDrop = False) if False: management_session_factory = ApplicationSessionFactory() management_session_factory.session = NodeManagementSession management_session_factory.node_controller_session = node_controller_session management_transport_factory = WampWebSocketClientFactory(management_session_factory, "ws://127.0.0.1:7000") management_transport_factory.setProtocolOptions(failByDrop = False) management_client = clientFromString(self._reactor, "tcp:127.0.0.1:7000") management_client.connect(management_transport_factory) ## startup the node from configuration file ## self._node_controller_session.run_node_config(self._config)
def start_remote_management_client(self): from crossbar.management import NodeManagementSession management_session_factory = ApplicationSessionFactory() management_session_factory.session = NodeManagementSession management_session_factory.node_controller_session = node_controller_session management_transport_factory = WampWebSocketClientFactory(management_session_factory, "ws://127.0.0.1:7000") management_transport_factory.setProtocolOptions(failByDrop = False) management_client = clientFromString(self._reactor, "tcp:127.0.0.1:7000") management_client.connect(management_transport_factory)
def connect(self, ip, port, realm): self._realm = realm self._url = 'ws://' + ip + ':' + port + '/ws' self._reactor_thread = None self._session_factoryWriter = None self._session_factoryReader = None cfgReader = ComponentConfig(self._realm, self._extra) cfgWriter = ComponentConfig(self._realm, self._extra) self._session_factoryReader = ApplicationSessionFactory(cfgReader) self._session_factoryReader.session = ClientReader self._session_factoryWriter = ApplicationSessionFactory(cfgWriter) self._session_factoryWriter.session = ClientWriter self._factoryReader = WampWebSocketClientFactory( self._session_factoryReader, url=self._url, # debug = self._debug, debug_wamp = self._debug_wamp ) self._factoryWriter = WampWebSocketClientFactory( self._session_factoryWriter, url=self._url, # debug = self._debug, debug_wamp = self._debug_wamp ) self._reactor_thread = threading.Thread(target=reactor.run, args=(False, )) self._reactor_thread.daemon = True endpoint_descriptor = 'tcp:' + ip + ':' + port self._clientReader = clientFromString(reactor, endpoint_descriptor) self._clientReader.connect(self._factoryReader) self._clientWriter = clientFromString(reactor, endpoint_descriptor) self._clientWriter.connect(self._factoryWriter) self._reactor_thread.start() return self
def connect_application_session(server_factory, MyApplicationSession, component_config=None): """ Connect an ApplicationSession class to the given server factory. """ application_session_factory = ApplicationSessionFactory(component_config) application_session_factory.session = MyApplicationSession client_factory = WampRawSocketClientFactory(application_session_factory) server_protocol = server_factory.buildProtocol(None) client_protocol = client_factory.buildProtocol(None) server_transport = FakeTransport(server_protocol, True) client_transport = FakeTransport(client_protocol, False) pump = connect(server_protocol, server_transport, client_protocol, client_transport, debug=False) return client_protocol._session, pump
def wampClient(wampAddress, wampClientEndpoint, topic, key): """ Sets up an Autobahn|python WAMPv2 client. Code modified from WAMP documentation. """ component_config = types.ComponentConfig(realm = "realm1", extra = {'key': unicode(key), 'topic': unicode(topic)}) session_factory = ApplicationSessionFactory(config = component_config) session_factory._myConnection = [] session_factory.session = SubpubTileset ## create a WAMP-over-WebSocket transport client factory #transport_factory = WampWebSocketClientFactory(session_factory, wampAddress, debug = False) transport_factory = MyClientFactory(session_factory, wampAddress, debug = False, debug_wamp = False) transport_factory.setProtocolOptions(failByDrop = False) ## start a WebSocket client from an endpoint client = clientFromString(reactor, wampClientEndpoint) client.connect(transport_factory) return session_factory._myConnection
from autobahn.twisted.choosereactor import install_reactor from autobahn.twisted.websocket import WampWebSocketClientFactory from autobahn.twisted.wamp import ApplicationSessionFactory from autobahn.twisted.wamp import ApplicationSession from autobahn.wamp import types class MySession(ApplicationSession): def onJoin(self, details): print("Session attached to realm!") log.startLogging(sys.stdout) reactor = install_reactor() print("Running on reactor {}".format(reactor)) session_factory = ApplicationSessionFactory( types.ComponentConfig(realm=u"realm1")) session_factory.session = MySession transport_factory = WampWebSocketClientFactory(session_factory, url="ws://localhost", debug=True) client = clientFromString(reactor, "unix:/tmp/cbsocket") client.connect(transport_factory) reactor.run()
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() if __name__ == '__main__': ## 0) start logging to console log.startLogging(sys.stdout) ## 1) create a WAMP application session factory session_factory = ApplicationSessionFactory() session_factory.session = MyFrontendComponent ## 2) create a WAMP-over-WebSocket transport client factory transport_factory = WampWebSocketClientFactory(session_factory, debug = False) ## 3) start the client from a Twisted endpoint client = clientFromString(reactor, "tcp:127.0.0.1:8080") client.connect(transport_factory) ## 4) now enter the Twisted reactor loop reactor.run()
def run(): """ Entry point into (native) worker processes. This wires up stuff such that a worker instance is talking WAMP-over-stdio to the node controller. """ import os import sys import platform import signal # Ignore SIGINT so we get consistent behavior on control-C versus # sending SIGINT to the controller process. When the controller is # shutting down, it sends TERM to all its children but ctrl-C # handling will send a SIGINT to all the processes in the group # (so then the controller sends a TERM but the child already or # will very shortly get a SIGINT as well). Twisted installs signal # handlers, but not for SIGINT if there's already a custom one # present. def ignore(sig, frame): log.msg("Ignoring SIGINT in worker.") signal.signal(signal.SIGINT, ignore) # create the top-level parser # import argparse parser = argparse.ArgumentParser() parser.add_argument('-d', '--debug', action='store_true', help='Debug on (optional).') parser.add_argument('--reactor', default=None, choices=['select', 'poll', 'epoll', 'kqueue', 'iocp'], help='Explicit Twisted reactor selection (optional).') parser.add_argument('-c', '--cbdir', type=str, help="Crossbar.io node directory (required).") parser.add_argument('-n', '--node', type=str, help='Crossbar.io node ID (required).') parser.add_argument('-w', '--worker', type=str, help='Crossbar.io worker ID (required).') parser.add_argument('-r', '--realm', type=str, help='Crossbar.io node (management) realm (required).') parser.add_argument('-t', '--type', choices=['router', 'container'], help='Worker type (required).') parser.add_argument('--title', type=str, default=None, help='Worker process title to set (optional).') options = parser.parse_args() # make sure logging to something else than stdio is setup _first_ # from twisted.python import log from crossbar.twisted.processutil import BareFormatFileLogObserver flo = BareFormatFileLogObserver(sys.stderr) log.startLoggingWithObserver(flo.emit) try: import setproctitle except ImportError: log.msg( "Warning: could not set worker process title (setproctitle not installed)" ) else: # set process title if requested to # if options.title: setproctitle.setproctitle(options.title) else: WORKER_TYPE_TO_TITLE = { 'router': 'crossbar-worker [router]', 'container': 'crossbar-worker [container]' } setproctitle.setproctitle( WORKER_TYPE_TO_TITLE[options.type].strip()) # we use an Autobahn utility to import the "best" available Twisted reactor # from autobahn.twisted.choosereactor import install_reactor reactor = install_reactor(options.reactor) from twisted.python.reflect import qual log.msg("Running under {} using {} reactor".format( platform.python_implementation(), qual(reactor.__class__).split('.')[-1])) options.cbdir = os.path.abspath(options.cbdir) os.chdir(options.cbdir) # log.msg("Starting from node directory {}".format(options.cbdir)) from crossbar.worker.router import RouterWorkerSession from crossbar.worker.container import ContainerWorkerSession WORKER_TYPE_TO_CLASS = { 'router': RouterWorkerSession, 'container': ContainerWorkerSession } from autobahn.twisted.websocket import WampWebSocketServerProtocol class WorkerServerProtocol(WampWebSocketServerProtocol): def connectionLost(self, reason): try: # this log message is unlikely to reach the controller (unless # only stdin/stdout pipes were lost, but not stderr) log.msg("Connection to node controller lost.") WampWebSocketServerProtocol.connectionLost(self, reason) except: pass finally: # loosing the connection to the node controller is fatal: # stop the reactor and exit with error if reactor.running: reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1) reactor.stop() # if the reactor *isn't* running, we're already shutting down try: # create a WAMP application session factory # from autobahn.twisted.wamp import ApplicationSessionFactory from autobahn.wamp.types import ComponentConfig session_config = ComponentConfig(realm=options.realm, extra=options) session_factory = ApplicationSessionFactory(session_config) session_factory.session = WORKER_TYPE_TO_CLASS[options.type] # create a WAMP-over-WebSocket transport server factory # from autobahn.twisted.websocket import WampWebSocketServerFactory transport_factory = WampWebSocketServerFactory(session_factory, "ws://localhost", debug=False, debug_wamp=False) transport_factory.protocol = WorkerServerProtocol transport_factory.setProtocolOptions(failByDrop=False) # create a protocol instance and wire up to stdio # from twisted.internet import stdio proto = transport_factory.buildProtocol(None) stdio.StandardIO(proto) # now start reactor loop # log.msg("Entering event loop ..") reactor.run() except Exception as e: log.msg("Unhandled exception: {}".format(e)) if reactor.running: reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1) reactor.stop() else: sys.exit(1)
def run(): """ Entry point into background worker process. This wires up stuff such that a WorkerProcess instance is talking WAMP over stdio to the node controller. """ ## create the top-level parser ## import argparse parser = argparse.ArgumentParser() parser.add_argument('-d', '--debug', action = 'store_true', help = 'Debug on.') parser.add_argument('--reactor', default = None, choices = ['select', 'poll', 'epoll', 'kqueue', 'iocp'], help = 'Explicit Twisted reactor selection') parser.add_argument('--cbdir', type = str, default = None, help = "Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)") parser.add_argument('-n', '--name', default = None, help = 'Optional process name to set.') options = parser.parse_args() ## make sure logging to something else than stdio is setup _first_ ## from crossbar.twisted.process import BareFormatFileLogObserver flo = BareFormatFileLogObserver(sys.stderr) log.startLoggingWithObserver(flo.emit) ## the worker's PID ## pid = os.getpid() try: import setproctitle except ImportError: log.msg("Warning, could not set process title (setproctitle not installed)") else: ## set process title if requested to ## if options.name: setproctitle.setproctitle(options.name) else: setproctitle.setproctitle("Crossbar.io Worker") ## Crossbar.io node directory ## if hasattr(options, 'cbdir') and not options.cbdir: if os.environ.has_key("CROSSBAR_DIR"): options.cbdir = os.environ['CROSSBAR_DIR'] else: options.cbdir = '.crossbar' options.cbdir = os.path.abspath(options.cbdir) log.msg("Starting from node directory {}.".format(options.cbdir)) ## we use an Autobahn utility to import the "best" available Twisted reactor ## from autobahn.twisted.choosereactor import install_reactor reactor = install_reactor(options.reactor) from twisted.python.reflect import qual log.msg("Running on {} reactor.".format(qual(reactor.__class__).split('.')[-1])) from autobahn.twisted.websocket import WampWebSocketServerProtocol class WorkerServerProtocol(WampWebSocketServerProtocol): def connectionLost(self, reason): try: log.msg("Connection to node controller lost.") WampWebSocketServerProtocol.connectionLost(self, reason) except: pass finally: ## loosing the connection to the node controller (the pipes) is fatal. ## stop the reactor and exit with error if reactor.running: reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1) reactor.stop() else: sys.exit(1) try: ## create a WAMP application session factory ## from autobahn.twisted.wamp import ApplicationSessionFactory session_factory = ApplicationSessionFactory() session_factory.options = options session_factory.session = WorkerProcess ## create a WAMP-over-WebSocket transport server factory ## from autobahn.twisted.websocket import WampWebSocketServerFactory transport_factory = WampWebSocketServerFactory(session_factory, "ws://localhost", debug = False) transport_factory.protocol = WorkerServerProtocol transport_factory.setProtocolOptions(failByDrop = False) ## create a protocol instance and wire up to stdio ## from twisted.internet import stdio proto = transport_factory.buildProtocol(None) stdio.StandardIO(proto) ## now start reactor loop ## log.msg("Entering event loop ..") #reactor.callLater(4, reactor.stop) reactor.run() except Exception as e: log.msg("Unhandled exception - {}".format(e)) if reactor.running: reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1) reactor.stop() else: sys.exit(1)
from twisted.python import log from twisted.internet.endpoints import clientFromString from autobahn.twisted.choosereactor import install_reactor from autobahn.twisted.websocket import WampWebSocketClientFactory from autobahn.twisted.wamp import ApplicationSessionFactory from autobahn.twisted.wamp import ApplicationSession from autobahn.wamp import types class MySession(ApplicationSession): def onJoin(self, details): print("Session attached to realm!") log.startLogging(sys.stdout) reactor = install_reactor() print("Running on reactor {}".format(reactor)) session_factory = ApplicationSessionFactory(types.ComponentConfig(realm=u"realm1")) session_factory.session = MySession transport_factory = WampWebSocketClientFactory(session_factory, url="ws://localhost", debug=True) client = clientFromString(reactor, "unix:/tmp/cbsocket") client.connect(transport_factory) reactor.run()
if args.debug: 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() if args.debug: print("Running on reactor {}".format(reactor)) ## create a WAMP application session factory ## from autobahn.twisted.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) ## create a WAMP-over-WebSocket transport client factory
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
def run(): """ Entry point into (native) worker processes. This wires up stuff such that a worker instance is talking WAMP-over-stdio to the node controller. """ import os import sys import platform # create the top-level parser # import argparse parser = argparse.ArgumentParser() parser.add_argument('-d', '--debug', action='store_true', help='Debug on (optional).') parser.add_argument('--reactor', default=None, choices=['select', 'poll', 'epoll', 'kqueue', 'iocp'], help='Explicit Twisted reactor selection (optional).') parser.add_argument('-c', '--cbdir', type=str, help="Crossbar.io node directory (required).") parser.add_argument('-n', '--node', type=str, help='Crossbar.io node ID (required).') parser.add_argument('-w', '--worker', type=str, help='Crossbar.io worker ID (required).') parser.add_argument('-r', '--realm', type=str, help='Crossbar.io node (management) realm (required).') parser.add_argument('-t', '--type', choices=['router', 'container'], help='Worker type (required).') parser.add_argument('--title', type=str, default=None, help='Worker process title to set (optional).') options = parser.parse_args() # make sure logging to something else than stdio is setup _first_ # from twisted.python import log from crossbar.twisted.processutil import BareFormatFileLogObserver flo = BareFormatFileLogObserver(sys.stderr) log.startLoggingWithObserver(flo.emit) try: import setproctitle except ImportError: log.msg("Warning: could not set worker process title (setproctitle not installed)") else: # set process title if requested to # if options.title: setproctitle.setproctitle(options.title) else: WORKER_TYPE_TO_TITLE = { 'router': 'crossbar-worker [router]', 'container': 'crossbar-worker [container]' } setproctitle.setproctitle(WORKER_TYPE_TO_TITLE[options.type].strip()) # we use an Autobahn utility to import the "best" available Twisted reactor # from autobahn.twisted.choosereactor import install_reactor reactor = install_reactor(options.reactor) from twisted.python.reflect import qual log.msg("Running under {} using {} reactor".format(platform.python_implementation(), qual(reactor.__class__).split('.')[-1])) options.cbdir = os.path.abspath(options.cbdir) os.chdir(options.cbdir) # log.msg("Starting from node directory {}".format(options.cbdir)) from crossbar.worker.router import RouterWorkerSession from crossbar.worker.container import ContainerWorkerSession WORKER_TYPE_TO_CLASS = { 'router': RouterWorkerSession, 'container': ContainerWorkerSession } from autobahn.twisted.websocket import WampWebSocketServerProtocol class WorkerServerProtocol(WampWebSocketServerProtocol): def connectionLost(self, reason): try: # this log message is unlikely to reach the controller (unless # only stdin/stdout pipes were lost, but not stderr) log.msg("Connection to node controller lost.") WampWebSocketServerProtocol.connectionLost(self, reason) except: pass finally: # loosing the connection to the node controller is fatal: # stop the reactor and exit with error if reactor.running: reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1) reactor.stop() else: sys.exit(1) try: # create a WAMP application session factory # from autobahn.twisted.wamp import ApplicationSessionFactory from autobahn.wamp.types import ComponentConfig session_config = ComponentConfig(realm=options.realm, extra=options) session_factory = ApplicationSessionFactory(session_config) session_factory.session = WORKER_TYPE_TO_CLASS[options.type] # create a WAMP-over-WebSocket transport server factory # from autobahn.twisted.websocket import WampWebSocketServerFactory transport_factory = WampWebSocketServerFactory(session_factory, "ws://localhost", debug=False, debug_wamp=False) transport_factory.protocol = WorkerServerProtocol transport_factory.setProtocolOptions(failByDrop=False) # create a protocol instance and wire up to stdio # from twisted.internet import stdio proto = transport_factory.buildProtocol(None) stdio.StandardIO(proto) # now start reactor loop # log.msg("Entering event loop ..") reactor.run() except Exception as e: log.msg("Unhandled exception: {}".format(e)) if reactor.running: reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1) reactor.stop() else: sys.exit(1)
raise Exception("should not arrive here") from autobahn.twisted.websocket import WampWebSocketClientFactory, WampWebSocketClientProtocol ## start the server from an endpoint ## server = serverFromString(reactor, args.server) server.listen(transport_factory) clients = [] clients_d = [] for C in client_components: ## create a WAMP application session factory ## from autobahn.twisted.wamp import ApplicationSessionFactory session_factory = ApplicationSessionFactory(config) one_done = Deferred() config.all_done.append(one_done) def make_make(Klass, done): def make(config): c = Klass(config, done) config.components.append(c) return c return make ## .. and set the session class on the factory ## session_factory.session = make_make(C, one_done)
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
def run(options, reactor=None): """ Entry point into (native) worker processes. This wires up stuff such that a worker instance is talking WAMP-over-stdio to the node controller. """ import os import sys import platform import signal # make sure logging to something else than stdio is setup _first_ # from crossbar._logging import make_JSON_observer, cb_logging_aware from txaio import make_logger, start_logging from twisted.logger import globalLogPublisher from twisted.python.reflect import qual log = make_logger() # Print a magic phrase that tells the capturing logger that it supports # Crossbar's rich logging print(cb_logging_aware, file=sys.__stderr__) sys.__stderr__.flush() flo = make_JSON_observer(sys.__stderr__) globalLogPublisher.addObserver(flo) # Ignore SIGINT so we get consistent behavior on control-C versus # sending SIGINT to the controller process. When the controller is # shutting down, it sends TERM to all its children but ctrl-C # handling will send a SIGINT to all the processes in the group # (so then the controller sends a TERM but the child already or # will very shortly get a SIGINT as well). Twisted installs signal # handlers, but not for SIGINT if there's already a custom one # present. def ignore(sig, frame): log.debug("Ignoring SIGINT in worker.") signal.signal(signal.SIGINT, ignore) # actually begin logging start_logging(None, options.loglevel) # we use an Autobahn utility to import the "best" available Twisted reactor # from autobahn.twisted.choosereactor import install_reactor reactor = install_reactor(options.reactor) # eg: crossbar.worker.container.ContainerWorkerSession l = options.klass.split('.') worker_module, worker_klass = '.'.join(l[:-1]), l[-1] # now load the worker module and class _mod = importlib.import_module(worker_module) klass = getattr(_mod, worker_klass) log.info( 'Started {worker_title} worker "{worker_id}" on node "{node_id}" [{klass} / {python}-{reactor}]', worker_title=klass.WORKER_TITLE, klass=options.klass, node_id=options.node, worker_id=options.worker, pid=os.getpid(), python=platform.python_implementation(), reactor=qual(reactor.__class__).split('.')[-1], ) # set process title if requested to # try: import setproctitle except ImportError: log.debug( "Could not set worker process title (setproctitle not installed)") else: if options.title: setproctitle.setproctitle(options.title) else: setproctitle.setproctitle('crossbar-worker [{}]'.format( options.klass)) # node directory # options.cbdir = os.path.abspath(options.cbdir) os.chdir(options.cbdir) # log.msg("Starting from node directory {}".format(options.cbdir)) # set process title if requested to # try: import setproctitle except ImportError: log.debug( "Could not set worker process title (setproctitle not installed)") else: if options.title: setproctitle.setproctitle(options.title) else: setproctitle.setproctitle('crossbar-worker [{}]'.format( options.klass)) from twisted.internet.error import ConnectionDone from autobahn.twisted.websocket import WampWebSocketServerProtocol class WorkerServerProtocol(WampWebSocketServerProtocol): def connectionLost(self, reason): # the behavior here differs slightly whether we're shutting down orderly # or shutting down because of "issues" if isinstance(reason.value, ConnectionDone): was_clean = True else: was_clean = False try: # this log message is unlikely to reach the controller (unless # only stdin/stdout pipes were lost, but not stderr) if was_clean: log.info("Connection to node controller closed cleanly") else: log.warn("Connection to node controller lost: {reason}", reason=reason) # give the WAMP transport a change to do it's thing WampWebSocketServerProtocol.connectionLost(self, reason) except: # we're in the process of shutting down .. so ignore .. pass finally: # after the connection to the node controller is gone, # the worker is "orphane", and should exit # determine process exit code if was_clean: exit_code = 0 else: exit_code = 1 # exit the whole worker process when the reactor has stopped reactor.addSystemEventTrigger('after', 'shutdown', os._exit, exit_code) # stop the reactor try: reactor.stop() except ReactorNotRunning: pass try: # create a WAMP application session factory # from autobahn.twisted.wamp import ApplicationSessionFactory from autobahn.wamp.types import ComponentConfig session_config = ComponentConfig(realm=options.realm, extra=options) session_factory = ApplicationSessionFactory(session_config) session_factory.session = klass # create a WAMP-over-WebSocket transport server factory # from autobahn.twisted.websocket import WampWebSocketServerFactory transport_factory = WampWebSocketServerFactory(session_factory, u'ws://localhost') transport_factory.protocol = WorkerServerProtocol transport_factory.setProtocolOptions(failByDrop=False) # create a protocol instance and wire up to stdio # from twisted.python.runtime import platform as _platform from twisted.internet import stdio proto = transport_factory.buildProtocol(None) if _platform.isWindows(): stdio.StandardIO(proto) else: stdio.StandardIO(proto, stdout=3) # now start reactor loop # if False: log.info("vmprof enabled.") import os import vmprof PROFILE_FILE = 'vmprof_{}.dat'.format(os.getpid()) outfd = os.open(PROFILE_FILE, os.O_RDWR | os.O_CREAT | os.O_TRUNC) vmprof.enable(outfd, period=0.01) log.info("Entering event loop...") reactor.run() vmprof.disable() else: log.debug("Entering event loop...") reactor.run() except Exception as e: log.info("Unhandled exception: {e}", e=e) if reactor.running: reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1) reactor.stop() else: sys.exit(1)
def run(): """ Entry point into (native) worker processes. This wires up stuff such that a worker instance is talking WAMP-over-stdio to the node controller. """ import os import sys import platform import signal # Ignore SIGINT so we get consistent behavior on control-C versus # sending SIGINT to the controller process. When the controller is # shutting down, it sends TERM to all its children but ctrl-C # handling will send a SIGINT to all the processes in the group # (so then the controller sends a TERM but the child already or # will very shortly get a SIGINT as well). Twisted installs signal # handlers, but not for SIGINT if there's already a custom one # present. def ignore(sig, frame): log.debug("Ignoring SIGINT in worker.") signal.signal(signal.SIGINT, ignore) # create the top-level parser # import argparse parser = argparse.ArgumentParser() parser.add_argument('-d', '--debug', action='store_true', help='Debug on (optional).') parser.add_argument('--reactor', default=None, choices=['select', 'poll', 'epoll', 'kqueue', 'iocp'], help='Explicit Twisted reactor selection (optional).') parser.add_argument('-c', '--cbdir', type=str, help="Crossbar.io node directory (required).") parser.add_argument('-n', '--node', type=str, help='Crossbar.io node ID (required).') parser.add_argument('-w', '--worker', type=str, help='Crossbar.io worker ID (required).') parser.add_argument('-r', '--realm', type=str, help='Crossbar.io node (management) realm (required).') parser.add_argument('-t', '--type', choices=['router', 'container'], help='Worker type (required).') parser.add_argument('--title', type=str, default=None, help='Worker process title to set (optional).') options = parser.parse_args() # make sure logging to something else than stdio is setup _first_ # from twisted.logger import globalLogBeginner from crossbar._logging import Logger, make_JSON_observer log = Logger() _stderr = sys.stderr flo = make_JSON_observer(_stderr) globalLogBeginner.beginLoggingTo([flo]) try: import setproctitle except ImportError: log.info("Warning: could not set worker process title (setproctitle not installed)") else: # set process title if requested to # if options.title: setproctitle.setproctitle(options.title) else: WORKER_TYPE_TO_TITLE = { 'router': 'crossbar-worker [router]', 'container': 'crossbar-worker [container]' } setproctitle.setproctitle(WORKER_TYPE_TO_TITLE[options.type].strip()) # we use an Autobahn utility to import the "best" available Twisted reactor # from autobahn.twisted.choosereactor import install_reactor reactor = install_reactor(options.reactor) from twisted.python.reflect import qual log.info("Running under {python} using {reactor} reactor", python=platform.python_implementation(), reactor=qual(reactor.__class__).split('.')[-1]) options.cbdir = os.path.abspath(options.cbdir) os.chdir(options.cbdir) # log.msg("Starting from node directory {}".format(options.cbdir)) from crossbar.worker.router import RouterWorkerSession from crossbar.worker.container import ContainerWorkerSession WORKER_TYPE_TO_CLASS = { 'router': RouterWorkerSession, 'container': ContainerWorkerSession } from autobahn.twisted.websocket import WampWebSocketServerProtocol class WorkerServerProtocol(WampWebSocketServerProtocol): def connectionLost(self, reason): try: # this log message is unlikely to reach the controller (unless # only stdin/stdout pipes were lost, but not stderr) log.warn("Connection to node controller lost.") WampWebSocketServerProtocol.connectionLost(self, reason) except: pass finally: # loosing the connection to the node controller is fatal: # stop the reactor and exit with error if reactor.running: reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1) reactor.stop() # if the reactor *isn't* running, we're already shutting down try: # create a WAMP application session factory # from autobahn.twisted.wamp import ApplicationSessionFactory from autobahn.wamp.types import ComponentConfig session_config = ComponentConfig(realm=options.realm, extra=options) session_factory = ApplicationSessionFactory(session_config) session_factory.session = WORKER_TYPE_TO_CLASS[options.type] # create a WAMP-over-WebSocket transport server factory # from autobahn.twisted.websocket import WampWebSocketServerFactory transport_factory = WampWebSocketServerFactory(session_factory, "ws://localhost", debug=False, debug_wamp=False) transport_factory.protocol = WorkerServerProtocol transport_factory.setProtocolOptions(failByDrop=False) # create a protocol instance and wire up to stdio # from twisted.internet import stdio proto = transport_factory.buildProtocol(None) stdio.StandardIO(proto) # now start reactor loop # log.info("Entering event loop...") reactor.run() except Exception as e: log.info("Unhandled exception: {}".format(e)) if reactor.running: reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1) reactor.stop() else: sys.exit(1)
def run(): """ Entry point into (native) worker processes. This wires up stuff such that a worker instance is talking WAMP-over-stdio to the node controller. """ import os import sys import platform import signal # Ignore SIGINT so we get consistent behavior on control-C versus # sending SIGINT to the controller process. When the controller is # shutting down, it sends TERM to all its children but ctrl-C # handling will send a SIGINT to all the processes in the group # (so then the controller sends a TERM but the child already or # will very shortly get a SIGINT as well). Twisted installs signal # handlers, but not for SIGINT if there's already a custom one # present. def ignore(sig, frame): log.debug("Ignoring SIGINT in worker.") signal.signal(signal.SIGINT, ignore) # create the top-level parser # import argparse parser = argparse.ArgumentParser() parser.add_argument('--reactor', default=None, choices=['select', 'poll', 'epoll', 'kqueue', 'iocp'], help='Explicit Twisted reactor selection (optional).') parser.add_argument( '--loglevel', default="info", choices=['none', 'error', 'warn', 'info', 'debug', 'trace'], help='Initial log level.') parser.add_argument('-c', '--cbdir', type=six.text_type, help="Crossbar.io node directory (required).") parser.add_argument('-r', '--realm', type=six.text_type, help='Crossbar.io node (management) realm (required).') parser.add_argument('-t', '--type', choices=['router', 'container', 'websocket-testee'], help='Worker type (required).') parser.add_argument('-w', '--worker', type=six.text_type, help='Crossbar.io worker ID (required).') parser.add_argument('--title', type=six.text_type, default=None, help='Worker process title to set (optional).') parser.add_argument( '--expose_controller', type=bool, default=False, help= 'Expose node controller session to all components (this feature requires Crossbar.io Fabric extension).' ) parser.add_argument( '--expose_shared', type=bool, default=False, help= 'Expose a shared object to all components (this feature requires Crossbar.io Fabric extension).' ) options = parser.parse_args() # make sure logging to something else than stdio is setup _first_ # from crossbar._logging import make_JSON_observer, cb_logging_aware from txaio import make_logger, start_logging from twisted.logger import globalLogPublisher log = make_logger() # Print a magic phrase that tells the capturing logger that it supports # Crossbar's rich logging print(cb_logging_aware, file=sys.__stderr__) sys.__stderr__.flush() flo = make_JSON_observer(sys.__stderr__) globalLogPublisher.addObserver(flo) start_logging(None, options.loglevel) # we use an Autobahn utility to import the "best" available Twisted reactor # from autobahn.twisted.choosereactor import install_reactor reactor = install_reactor(options.reactor) WORKER_TYPE_TO_TITLE = { 'router': 'Router', 'container': 'Container', 'websocket-testee': 'WebSocket Testee' } from twisted.python.reflect import qual log.info( '{worker_title} worker "{worker_id}" process {pid} starting on {python}-{reactor} ..', worker_title=WORKER_TYPE_TO_TITLE[options.type], worker_id=options.worker, pid=os.getpid(), python=platform.python_implementation(), reactor=qual(reactor.__class__).split('.')[-1]) # set process title if requested to # try: import setproctitle except ImportError: log.debug( "Could not set worker process title (setproctitle not installed)") else: if options.title: setproctitle.setproctitle(options.title) else: WORKER_TYPE_TO_PROCESS_TITLE = { 'router': 'crossbar-worker [router]', 'container': 'crossbar-worker [container]', 'websocket-testee': 'crossbar-worker [websocket-testee]' } setproctitle.setproctitle( WORKER_TYPE_TO_PROCESS_TITLE[options.type].strip()) # node directory # options.cbdir = os.path.abspath(options.cbdir) os.chdir(options.cbdir) # log.msg("Starting from node directory {}".format(options.cbdir)) from crossbar.worker.router import RouterWorkerSession from crossbar.worker.container import ContainerWorkerSession from crossbar.worker.testee import WebSocketTesteeWorkerSession WORKER_TYPE_TO_CLASS = { 'router': RouterWorkerSession, 'container': ContainerWorkerSession, 'websocket-testee': WebSocketTesteeWorkerSession } from twisted.internet.error import ConnectionDone from autobahn.twisted.websocket import WampWebSocketServerProtocol class WorkerServerProtocol(WampWebSocketServerProtocol): def connectionLost(self, reason): # the behavior here differs slightly whether we're shutting down orderly # or shutting down because of "issues" if isinstance(reason.value, ConnectionDone): was_clean = True else: was_clean = False try: # this log message is unlikely to reach the controller (unless # only stdin/stdout pipes were lost, but not stderr) if was_clean: log.info("Connection to node controller closed cleanly") else: log.warn("Connection to node controller lost: {reason}", reason=reason) # give the WAMP transport a change to do it's thing WampWebSocketServerProtocol.connectionLost(self, reason) except: # we're in the process of shutting down .. so ignore .. pass finally: # after the connection to the node controller is gone, # the worker is "orphane", and should exit # determine process exit code if was_clean: exit_code = 0 else: exit_code = 1 # exit the whole worker process when the reactor has stopped reactor.addSystemEventTrigger('after', 'shutdown', os._exit, exit_code) # stop the reactor try: reactor.stop() except ReactorNotRunning: pass try: # create a WAMP application session factory # from autobahn.twisted.wamp import ApplicationSessionFactory from autobahn.wamp.types import ComponentConfig session_config = ComponentConfig(realm=options.realm, extra=options) session_factory = ApplicationSessionFactory(session_config) session_factory.session = WORKER_TYPE_TO_CLASS[options.type] # create a WAMP-over-WebSocket transport server factory # from autobahn.twisted.websocket import WampWebSocketServerFactory transport_factory = WampWebSocketServerFactory(session_factory, u'ws://localhost') transport_factory.protocol = WorkerServerProtocol transport_factory.setProtocolOptions(failByDrop=False) # create a protocol instance and wire up to stdio # from twisted.python.runtime import platform as _platform from twisted.internet import stdio proto = transport_factory.buildProtocol(None) if _platform.isWindows(): stdio.StandardIO(proto) else: stdio.StandardIO(proto, stdout=3) # now start reactor loop # if False: log.info("vmprof enabled.") import os import vmprof PROFILE_FILE = 'vmprof_{}.dat'.format(os.getpid()) outfd = os.open(PROFILE_FILE, os.O_RDWR | os.O_CREAT | os.O_TRUNC) vmprof.enable(outfd, period=0.01) log.info("Entering event loop...") reactor.run() vmprof.disable() else: log.debug("Entering event loop...") reactor.run() except Exception as e: log.info("Unhandled exception: {e}", e=e) if reactor.running: reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1) reactor.stop() else: sys.exit(1)
def run(): """ Entry point into (native) worker processes. This wires up stuff such that a worker instance is talking WAMP-over-stdio to the node controller. """ import os import sys import platform import signal # Ignore SIGINT so we get consistent behavior on control-C versus # sending SIGINT to the controller process. When the controller is # shutting down, it sends TERM to all its children but ctrl-C # handling will send a SIGINT to all the processes in the group # (so then the controller sends a TERM but the child already or # will very shortly get a SIGINT as well). Twisted installs signal # handlers, but not for SIGINT if there's already a custom one # present. def ignore(sig, frame): log.debug("Ignoring SIGINT in worker.") signal.signal(signal.SIGINT, ignore) # create the top-level parser # import argparse parser = argparse.ArgumentParser() parser.add_argument('--reactor', default=None, choices=['select', 'poll', 'epoll', 'kqueue', 'iocp'], help='Explicit Twisted reactor selection (optional).') parser.add_argument('--loglevel', default="info", choices=['none', 'error', 'warn', 'info', 'debug', 'trace'], help='Initial log level.') parser.add_argument('-c', '--cbdir', type=str, help="Crossbar.io node directory (required).") parser.add_argument('-n', '--node', type=str, help='Crossbar.io node ID (required).') parser.add_argument('-w', '--worker', type=str, help='Crossbar.io worker ID (required).') parser.add_argument('-r', '--realm', type=str, help='Crossbar.io node (management) realm (required).') parser.add_argument('-t', '--type', choices=['router', 'container'], help='Worker type (required).') parser.add_argument('--title', type=str, default=None, help='Worker process title to set (optional).') options = parser.parse_args() # make sure logging to something else than stdio is setup _first_ # from crossbar._logging import make_JSON_observer, cb_logging_aware, _stderr from crossbar._logging import make_logger, log_publisher, start_logging from crossbar._logging import set_global_log_level # Set the global log level set_global_log_level(options.loglevel) log = make_logger() # Print a magic phrase that tells the capturing logger that it supports # Crossbar's rich logging print(cb_logging_aware, file=_stderr) _stderr.flush() flo = make_JSON_observer(_stderr) log_publisher.addObserver(flo) start_logging() try: import setproctitle except ImportError: log.debug("Could not set worker process title (setproctitle not installed)") else: # set process title if requested to # if options.title: setproctitle.setproctitle(options.title) else: WORKER_TYPE_TO_TITLE = { 'router': 'crossbar-worker [router]', 'container': 'crossbar-worker [container]' } setproctitle.setproctitle(WORKER_TYPE_TO_TITLE[options.type].strip()) # we use an Autobahn utility to import the "best" available Twisted reactor # from autobahn.twisted.choosereactor import install_reactor reactor = install_reactor(options.reactor) from twisted.python.reflect import qual log.info("Worker running under {python}-{reactor}", python=platform.python_implementation(), reactor=qual(reactor.__class__).split('.')[-1]) options.cbdir = os.path.abspath(options.cbdir) os.chdir(options.cbdir) # log.msg("Starting from node directory {}".format(options.cbdir)) from crossbar.worker.router import RouterWorkerSession from crossbar.worker.container import ContainerWorkerSession WORKER_TYPE_TO_CLASS = { 'router': RouterWorkerSession, 'container': ContainerWorkerSession } from autobahn.twisted.websocket import WampWebSocketServerProtocol class WorkerServerProtocol(WampWebSocketServerProtocol): def connectionLost(self, reason): try: # this log message is unlikely to reach the controller (unless # only stdin/stdout pipes were lost, but not stderr) log.warn("Connection to node controller lost.") WampWebSocketServerProtocol.connectionLost(self, reason) except: pass finally: # losing the connection to the node controller is fatal: # stop the reactor and exit with error log.info("No more controller connection; shutting down.") reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1) try: reactor.stop() except ReactorNotRunning: pass try: # create a WAMP application session factory # from autobahn.twisted.wamp import ApplicationSessionFactory from autobahn.wamp.types import ComponentConfig session_config = ComponentConfig(realm=options.realm, extra=options) session_factory = ApplicationSessionFactory(session_config) session_factory.session = WORKER_TYPE_TO_CLASS[options.type] # create a WAMP-over-WebSocket transport server factory # from autobahn.twisted.websocket import WampWebSocketServerFactory transport_factory = WampWebSocketServerFactory(session_factory, "ws://localhost", debug=False, debug_wamp=False) transport_factory.protocol = WorkerServerProtocol transport_factory.setProtocolOptions(failByDrop=False) # create a protocol instance and wire up to stdio # from twisted.python.runtime import platform as _platform from twisted.internet import stdio proto = transport_factory.buildProtocol(None) if _platform.isWindows(): stdio.StandardIO(proto) else: stdio.StandardIO(proto, stdout=3) # now start reactor loop # if False: log.info("vmprof enabled.") import os import vmprof PROFILE_FILE = 'vmprof_{}.dat'.format(os.getpid()) outfd = os.open(PROFILE_FILE, os.O_RDWR | os.O_CREAT | os.O_TRUNC) vmprof.enable(outfd, period=0.01) log.info("Entering event loop...") reactor.run() vmprof.disable() else: log.debug("Entering event loop...") reactor.run() except Exception as e: log.info("Unhandled exception: {}".format(e)) if reactor.running: reactor.addSystemEventTrigger('after', 'shutdown', os._exit, 1) reactor.stop() else: sys.exit(1)
def run(): """ Entry point into background worker process. This wires up stuff such that a WorkerProcess instance is talking WAMP over stdio to the node controller. """ ## create the top-level parser ## import argparse parser = argparse.ArgumentParser() parser.add_argument('-d', '--debug', action = 'store_true', help = 'Debug on.') parser.add_argument('--reactor', default = None, choices = ['select', 'poll', 'epoll', 'kqueue', 'iocp'], help = 'Explicit Twisted reactor selection') parser.add_argument('--cbdir', type = str, default = None, help = "Crossbar.io node directory (overrides ${CROSSBAR_DIR} and the default ./.crossbar)") parser.add_argument('-l', '--logfile', default = None, help = 'Log to log file instead of stderr.') options = parser.parse_args() ## make sure logging to something else than stdio is setup _first_ ## if options.logfile: log.startLogging(open(options.logfile, 'a')) else: log.startLogging(sys.stderr) pid = os.getpid() ## Crossbar.io node directory ## if hasattr(options, 'cbdir') and not options.cbdir: if os.environ.has_key("CROSSBAR_DIR"): options.cbdir = os.environ['CROSSBAR_DIR'] else: options.cbdir = '.crossbar' options.cbdir = os.path.abspath(options.cbdir) ## we use an Autobahn utility to import the "best" available Twisted reactor ## from autobahn.twisted.choosereactor import install_reactor reactor = install_reactor(options.reactor) ## from twisted.python.reflect import qual log.msg("Worker {}: starting at node directory {} on {} ..".format(pid, options.cbdir, qual(reactor.__class__).split('.')[-1])) try: ## create a WAMP application session factory ## from autobahn.twisted.wamp import ApplicationSessionFactory session_factory = ApplicationSessionFactory() session_factory.options = options session_factory.session = WorkerProcess ## create a WAMP-over-WebSocket transport server factory ## from autobahn.twisted.websocket import WampWebSocketServerFactory transport_factory = WampWebSocketServerFactory(session_factory, "ws://localhost", debug = False) transport_factory.setProtocolOptions(failByDrop = False) ## create a protocol instance and wire up to stdio ## from twisted.internet import stdio proto = transport_factory.buildProtocol(None) stdio.StandardIO(proto) ## now start reactor loop ## log.msg("Worker {}: entering event loop ..".format(pid)) reactor.run() except Exception as e: log.msg("Worker {}: Unhandled exception - {}".format(pid, e)) raise e sys.exit(1)
def test_minimal(self): embedded_components, client_components = [], [ Case2_Backend, Case2_Frontend ] ## create a WAMP router factory ## router_factory = RouterFactory() ## create a WAMP router session factory ## session_factory = RouterSessionFactory(router_factory) ## .. and create and add an WAMP application session to ## run next to the router ## config = types.ComponentConfig(realm=self.realm, extra={'caselog': 'case1.log'}) try: log = io.open('caselog.log', 'w') except Exception as e: print(e) return # log = io.open(config.extra['caselog'], 'w') config.log = log config.dlog = [] config.components = [] config.all_done = [] for C in embedded_components: one_done = Deferred() config.all_done.append(one_done) c = C(config, one_done) config.components.append(c) session_factory.add(c) if self.transport == "websocket": ## create a WAMP-over-WebSocket transport server factory ## transport_factory = WampWebSocketServerFactory( session_factory, debug_wamp=self.debug) transport_factory.setProtocolOptions(failByDrop=False, openHandshakeTimeout=0, closeHandshakeTimeout=0) elif self.transport in ['rawsocket-json', 'rawsocket-msgpack']: ## create a WAMP-over-RawSocket transport server factory ## if self.transport == 'rawsocket-msgpack': serializer = MsgPackSerializer() elif self.transport == 'rawsocket-json': serializer = JsonSerializer() else: raise Exception("should not arrive here") transport_factory = WampRawSocketServerFactory( session_factory, serializer, debug=self.debug) else: raise Exception("should not arrive here") ## start the server from an endpoint ## from twisted.internet import reactor server = serverFromString(reactor, self.server) d = server.listen(transport_factory) def onlisten(port): config.port = port d.addCallback(onlisten) clients = [] clients_d = [] for C in client_components: ## create a WAMP application session factory ## session_factory = ApplicationSessionFactory(config) one_done = Deferred() config.all_done.append(one_done) def make_make(Klass, done): def make(config): c = Klass(config, done) config.components.append(c) return c return make ## .. and set the session class on the factory ## session_factory.session = make_make(C, one_done) if self.transport == "websocket": serializers = [JsonSerializer()] ## create a WAMP-over-WebSocket transport client factory ## transport_factory = WampWebSocketClientFactory( session_factory, serializers=serializers, url=self.url, debug_wamp=self.debug) if True: def maker(Klass): class TestClientProtocol( WampWebSocketClientProtocol): def onOpen(self): self.txcnt = 0 self.rxcnt = 0 WampWebSocketClientProtocol.onOpen(self) def sendMessage(self, bytes, isBinary): self.txcnt += 1 print("> : {:>3} : {:<20} : {}".format( self.txcnt, Klass.__name__, bytes)) WampWebSocketClientProtocol.sendMessage( self, bytes, isBinary) def onMessage(self, bytes, isBinary): self.rxcnt += 1 print("< : {:>3} : {:<20} : {}".format( self.rxcnt, Klass.__name__, bytes)) WampWebSocketClientProtocol.onMessage( self, bytes, isBinary) return TestClientProtocol transport_factory.protocol = maker(C) else: transport_factory.protocol = WampWebSocketClientProtocol transport_factory.setProtocolOptions( failByDrop=False, openHandshakeTimeout=0, closeHandshakeTimeout=0) elif self.transport in ['rawsocket-json', 'rawsocket-msgpack']: ## create a WAMP-over-RawSocket transport client factory ## if self.transport == 'rawsocket-msgpack': serializer = MsgPackSerializer() elif self.transport == 'rawsocket-json': serializer = JsonSerializer() else: raise Exception("should not arrive here") transport_factory = WampRawSocketClientFactory( session_factory, serializer, debug=self.debug) ## start the client from an endpoint ## cl = clientFromString(reactor, self.client) clients_d.append(cl.connect(transport_factory)) clients.append(cl) config.connected_clients = None def client_connected(res): config.connected_clients = [ proto for success, proto in res if success ] DeferredList(clients_d).addCallback(client_connected) d = DeferredList(config.all_done, consumeErrors=True) #d = config.components[1]._done def done(res): log.flush() log.close() if config.port: config.port.stopListening() if config.connected_clients: for proto in config.connected_clients: proto.transport.abortConnection() print("Log length: {}".format(len(config.dlog))) print(config.dlog) #from twisted.internet import reactor #reactor.callLater(1, reactor.stop) def error(err): print(err) d.addCallbacks(done, error) # d2 = Deferred() return d
## if args.debug: 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() if args.debug: print("Running on reactor {}".format(reactor)) ## create a WAMP application session factory ## from autobahn.twisted.wamp import ApplicationSessionFactory from autobahn.wamp import types session_factory = ApplicationSessionFactory( types.ComponentConfig(realm=args.realm)) ## 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