def _create_transport_factory(reactor, transport, session_factory): """ Create a WAMP-over-XXX transport factory. """ if transport.type == u'websocket': serializers = create_transport_serializers(transport) factory = WampWebSocketClientFactory(session_factory, url=transport.url, serializers=serializers) elif transport.type == u'rawsocket': serializer = create_transport_serializer(transport.serializers[0]) factory = WampRawSocketClientFactory(session_factory, serializer=serializer) else: assert (False), 'should not arrive here' # set the options one at a time so we can give user better feedback for k, v in transport.options.items(): try: factory.setProtocolOptions(**{k: v}) except (TypeError, KeyError): # this allows us to document options as snake_case # until everything internally is upgraded from # camelCase try: factory.setProtocolOptions( **{_camel_case_from_snake_case(k): v}) except (TypeError, KeyError): raise ValueError("Unknown {} transport option: {}={}".format( transport.type, k, v)) return factory
def _create_transport_factory(reactor, transport, session_factory): """ Create a WAMP-over-XXX transport factory. """ if transport.type == u'websocket': serializers = _create_transport_serializers(transport) factory = WampWebSocketClientFactory(session_factory, url=transport.url, serializers=serializers) elif transport.type == u'rawsocket': serializer = _create_transport_serializer(transport.serializers[0]) factory = WampRawSocketClientFactory(session_factory, serializer=serializer) else: assert(False), 'should not arrive here' # set the options one at a time so we can give user better feedback for k, v in transport.options.items(): try: factory.setProtocolOptions(**{k: v}) except (TypeError, KeyError): # this allows us to document options as snake_case # until everything internally is upgraded from # camelCase try: factory.setProtocolOptions( **{_camel_case_from_snake_case(k): v} ) except (TypeError, KeyError): raise ValueError( "Unknown {} transport option: {}={}".format(transport.type, k, v) ) return 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 start_component(self, component, router): """ Starts a Class or WAMPlet in this component container. """ if component['type'] == 'wamplet': try: dist = component['dist'] name = component['entry'] if self.debug: log.msg("Worker {}: starting WAMPlet '{}/{}' in realm '{}' ..".format(self._pid, dist, name, router['realm'])) ## make is supposed to make instances of ApplicationSession make = pkg_resources.load_entry_point(dist, 'autobahn.twisted.wamplet', name) except Exception as e: log.msg("Worker {}: failed to import class - {}".format(e)) raise ApplicationError("crossbar.error.class_import_failed", str(e)) elif component['type'] == 'class': try: klassname = component['name'] if self.debug: log.msg("Worker {}: starting class '{}' in realm '{}' ..".format(self._pid, klassname, router['realm'])) import importlib c = klassname.split('.') mod, kls = '.'.join(c[:-1]), c[-1] app = importlib.import_module(mod) ## make is supposed to be of class ApplicationSession make = getattr(app, kls) except Exception as e: log.msg("Worker {}: failed to import class - {}".format(e)) raise ApplicationError("crossbar.error.class_import_failed", str(e)) else: raise ApplicationError("crossbar.error.invalid_configuration", "unknown component type '{}'".format(component['type'])) def create(): cfg = ComponentConfig(realm = router['realm'], extra = component.get('extra', None)) c = make(cfg) return c ## create a WAMP-over-WebSocket transport client factory ## from autobahn.twisted.websocket import WampWebSocketClientFactory transport_factory = WampWebSocketClientFactory(create, router['url'], debug = self.debug) transport_factory.setProtocolOptions(failByDrop = False) ## start a WebSocket client from an endpoint ## from twisted.internet import reactor from twisted.internet.endpoints import TCP4ClientEndpoint, SSL4ClientEndpoint, UNIXClientEndpoint from twisted.internet.endpoints import clientFromString from crossbar.twisted.tlsctx import TlsClientContextFactory if False: self._client = clientFromString(reactor, router['endpoint']) else: try: endpoint_config = router.get('endpoint') ## a TCP4 endpoint ## if endpoint_config['type'] == 'tcp': ## the host to connect ot ## host = str(endpoint_config['host']) ## the port to connect to ## port = int(endpoint_config['port']) ## connection timeout in seconds ## timeout = int(endpoint_config.get('timeout', 10)) if 'tls' in endpoint_config: ctx = TlsClientContextFactory() ## create a TLS client endpoint ## self._client = SSL4ClientEndpoint(reactor, host, port, ctx, timeout = timeout) else: ## create a non-TLS client endpoint ## self._client = TCP4ClientEndpoint(reactor, host, port, timeout = timeout) ## a Unix Domain Socket endpoint ## elif endpoint_config['type'] == 'unix': ## the path ## path = os.path.abspath(os.path.join(self._cbdir, endpoint_config['path'])) ## connection timeout in seconds ## timeout = int(endpoint_config['type'].get('timeout', 10)) ## create the endpoint ## self._client = UNIXClientEndpoint(reactor, path, timeout = timeout) else: raise ApplicationError("crossbar.error.invalid_configuration", "invalid endpoint type '{}'".format(endpoint_config['type'])) except Exception as e: log.msg("endpoint creation failed: {}".format(e)) raise e retry = True retryDelay = 1000 def try_connect(): if self.debug: log.msg("Worker {}: connecting to router ..".format(self._pid)) d = self._client.connect(transport_factory) def success(res): if self.debug: log.msg("Worker {}: client connected to router".format(self._pid)) def error(err): log.msg("Worker {}: client failed to connect to router - {}".format(self._pid, err)) if retry: log.msg("Worker {}: retrying in {} ms".format(self._pid, retryDelay)) reactor.callLater(float(retryDelay) / 1000., try_connect) else: log.msg("Worker {}: giving up.".format(seld._pid)) d.addCallbacks(success, error) try_connect()
## 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 ## from autobahn.twisted.websocket import WampWebSocketClientFactory transport_factory = WampWebSocketClientFactory(session_factory, args.wsurl, debug = args.debug) transport_factory.setProtocolOptions(failByDrop = False) ## start a WebSocket client from an endpoint ## client = clientFromString(reactor, args.websocket) client.connect(transport_factory) ## now enter the Twisted reactor loop ## reactor.run()
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.twisted.websocket import WampWebSocketClientFactory transport_factory = WampWebSocketClientFactory(session_factory, url=args.url, debug_wamp=args.debug) 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.twisted.rawsocket import WampRawSocketClientFactory
def start(self, transport, klassname, realm): """ Dynamically start an application component to run next to the router in "embedded mode". """ ## dynamically load the application component .. ## try: if self.debug: log.msg("Worker {}: starting class '{}' in realm '{}' ..".format(self._pid, klassname, realm)) import importlib c = klassname.split('.') mod, klass = '.'.join(c[:-1]), c[-1] app = importlib.import_module(mod) SessionKlass = getattr(app, klass) except Exception as e: if self.debug: log.msg("Worker {}: failed to import class - {}".format(e)) raise ApplicationError("crossbar.error.class_import_failed", str(e)) else: ## create a WAMP application session factory ## #from autobahn.twisted.wamp import ApplicationSessionFactory #session_factory = ApplicationSessionFactory() session_factory = ComponentSessionFactory(realm) session_factory.session = SessionKlass ## create a WAMP-over-WebSocket transport client factory ## from autobahn.twisted.websocket import WampWebSocketClientFactory transport_factory = WampWebSocketClientFactory(session_factory, transport['url'], debug = self.debug) transport_factory.setProtocolOptions(failByDrop = False) ## start a WebSocket client from an endpoint ## from twisted.internet import reactor from twisted.internet.endpoints import TCP4ClientEndpoint, SSL4ClientEndpoint, UNIXClientEndpoint from twisted.internet.endpoints import clientFromString from tlsctx import TlsClientContextFactory if False: self._client = clientFromString(reactor, transport['endpoint']) else: try: endpoint_config = transport.get('endpoint') ## a TCP4 endpoint ## if endpoint_config['type'] == 'tcp': ## the host to connect ot ## host = str(endpoint_config['host']) ## the port to connect to ## port = int(endpoint_config['port']) ## connection timeout in seconds ## timeout = int(endpoint_config.get('timeout', 10)) if 'tls' in endpoint_config: ctx = TlsClientContextFactory() ## create a TLS client endpoint ## self._client = SSL4ClientEndpoint(reactor, host, port, ctx, timeout = timeout) else: ## create a non-TLS client endpoint ## self._client = TCP4ClientEndpoint(reactor, host, port, timeout = timeout) ## a Unix Domain Socket endpoint ## elif endpoint_config['type'] == 'unix': ## the path ## path = str(endpoint_config['path']) ## connection timeout in seconds ## timeout = int(endpoint_config['type'].get('timeout', 10)) ## create the endpoint ## self._client = UNIXClientEndpoint(reactor, path, timeout = timeout) else: raise ApplicationError("crossbar.error.invalid_configuration", "invalid endpoint type '{}'".format(endpoint_config['type'])) except Exception as e: log.msg("endpoint creation failed: {}".format(e)) raise e retry = True retryDelay = 1000 def try_connect(): print "Trying to connect .." d = self._client.connect(transport_factory) def success(res): if True or self.debug: log.msg("Worker {}: client connected to router".format(self._pid)) def error(err): log.msg("Worker {}: client failed to connect to router - {}".format(self._pid, err)) if retry: log.msg("Worker {}: retrying in {} ms".format(self._pid, retryDelay)) reactor.callLater(float(retryDelay) / 1000., try_connect) else: log.msg("Worker {}: giving up.".format(seld._pid)) d.addCallbacks(success, error) try_connect()
class Node: """ A Crossbar.io node is the running a controller process and one or multiple worker processes. A single Crossbar.io node runs exactly one instance of this class, hence this class can be considered a system singleton. """ def __init__(self, reactor, cbdir, debug = False): """ Ctor. :param reactor: Reactor to run on. :type reactor: obj :param cbdir: Crossbar.io node directory to run from. :type cbdir: str """ self.debug = debug self._reactor = reactor self._cbdir = cbdir self._worker_processes = {} ## node name: FIXME self._node_name = "{}-{}".format(socket.getfqdn(), os.getpid()) self._node_name.replace('-', '_') self._node_name = '918234' ## node management self._management_url = "ws://127.0.0.1:7000" #self._management_url = "wss://cloud.crossbar.io" self._management_realm = "crossbar.cloud.aliceblue" ## load Crossbar.io node configuration ## cf = os.path.join(self._cbdir, 'config.json') with open(cf, 'rb') as infile: self._config = json.load(infile) 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 connect(self, auto_reconnect=True): def init(proto): reactor.addSystemEventTrigger('before', 'shutdown', cleanup, proto) return proto def cleanup(proto): session = getattr(proto, '_session', None) if session is None: return if session.is_attached(): return session.leave() elif session.is_connected(): return session.disconnect() from twisted.internet import reactor transport_factory = WampWebSocketClientFactory(self, str(self.address)) transport_factory.setProtocolOptions( maxFramePayloadSize=1048576, maxMessagePayloadSize=1048576, autoFragmentSize=65536, failByDrop=False, openHandshakeTimeout=OPEN_HANDSHAKE_TIMEOUT, closeHandshakeTimeout=CLOSE_HANDSHAKE_TIMEOUT, tcpNoDelay=True, autoPingInterval=AUTO_PING_INTERVAL, autoPingTimeout=AUTO_PING_TIMEOUT, autoPingSize=4, ) if self.address.ssl: if self._cert_manager: cert_data = self._cert_manager.read_certificate() authority = twisted_ssl.Certificate.loadPEM(cert_data) else: authority = None context_factory = optionsForClientTLS(X509_COMMON_NAME, trustRoot=authority) self._client = SSL4ClientEndpoint(reactor, self.address.host, self.address.port, context_factory) else: if self._use_ipv6: endpoint_cls = TCP6ClientEndpoint else: endpoint_cls = TCP4ClientEndpoint self._client = endpoint_cls(reactor, self.address.host, self.address.port) if auto_reconnect: self._reconnect_service = ClientService( endpoint=self._client, factory=transport_factory, retryPolicy=backoffPolicy(factor=BACKOFF_POLICY_FACTOR)) self._reconnect_service.startService() deferred = self._reconnect_service.whenConnected() else: deferred = self._client.connect(transport_factory) deferred.addCallback(init) deferred.addErrback(self.ready.errback) return self.ready