コード例 #1
0
ファイル: router.py プロジェクト: Tsunami2069/crossbar
    def start_router_transport(self, id, config, details=None):
        """
        Start a transport on this router.

        :param id: The ID of the transport to start.
        :type id: str
        :param config: The transport configuration.
        :type config: dict
        """
        self.log.debug("{}.start_router_transport".format(self.__class__.__name__),
                       id=id, config=config)

        # prohibit starting a transport twice
        #
        if id in self.transports:
            emsg = "Could not start transport: a transport with ID '{}' is already running (or starting)".format(id)
            self.log.error(emsg)
            raise ApplicationError(u'crossbar.error.already_running', emsg)

        # check configuration
        #
        try:
            checkconfig.check_router_transport(config)
        except Exception as e:
            emsg = "Invalid router transport configuration: {}".format(e)
            self.log.error(emsg)
            raise ApplicationError(u"crossbar.error.invalid_configuration", emsg)
        else:
            self.log.debug("Starting {}-transport on router.".format(config['type']))

        # standalone WAMP-RawSocket transport
        #
        if config['type'] == 'rawsocket':

            transport_factory = WampRawSocketServerFactory(self._router_session_factory, config)
            transport_factory.noisy = False

        # standalone WAMP-WebSocket transport
        #
        elif config['type'] == 'websocket':

            transport_factory = WampWebSocketServerFactory(self._router_session_factory, self.config.extra.cbdir, config, self._templates)
            transport_factory.noisy = False

        # Flash-policy file server pseudo transport
        #
        elif config['type'] == 'flashpolicy':

            transport_factory = FlashPolicyFactory(config.get('allowed_domain', None), config.get('allowed_ports', None))

        # WebSocket testee pseudo transport
        #
        elif config['type'] == 'websocket.testee':

            transport_factory = WebSocketTesteeServerFactory(config, self._templates)

        # Stream testee pseudo transport
        #
        elif config['type'] == 'stream.testee':

            transport_factory = StreamTesteeServerFactory()

        # Twisted Web based transport
        #
        elif config['type'] == 'web':

            options = config.get('options', {})

            # create Twisted Web root resource
            #
            root_config = config['paths']['/']

            root_type = root_config['type']
            root_options = root_config.get('options', {})

            # Static file hierarchy root resource
            #
            if root_type == 'static':

                if 'directory' in root_config:

                    root_dir = os.path.abspath(os.path.join(self.config.extra.cbdir, root_config['directory']))

                elif 'package' in root_config:

                    if 'resource' not in root_config:
                        raise ApplicationError(u"crossbar.error.invalid_configuration", "missing resource")

                    try:
                        mod = importlib.import_module(root_config['package'])
                    except ImportError as e:
                        emsg = "Could not import resource {} from package {}: {}".format(root_config['resource'], root_config['package'], e)
                        self.log.error(emsg)
                        raise ApplicationError(u"crossbar.error.invalid_configuration", emsg)
                    else:
                        try:
                            root_dir = os.path.abspath(pkg_resources.resource_filename(root_config['package'], root_config['resource']))
                        except Exception as e:
                            emsg = "Could not import resource {} from package {}: {}".format(root_config['resource'], root_config['package'], e)
                            self.log.error(emsg)
                            raise ApplicationError(u"crossbar.error.invalid_configuration", emsg)
                        else:
                            mod_version = getattr(mod, '__version__', '?.?.?')
                            self.log.info("Loaded static Web resource '{}' from package '{} {}' (filesystem path {})".format(root_config['resource'], root_config['package'], mod_version, root_dir))

                else:
                    raise ApplicationError(u"crossbar.error.invalid_configuration", "missing web spec")

                root_dir = root_dir.encode('ascii', 'ignore')  # http://stackoverflow.com/a/20433918/884770
                self.log.debug("Starting Web service at root directory {}".format(root_dir))

                # create resource for file system hierarchy
                #
                if root_options.get('enable_directory_listing', False):
                    static_resource_class = StaticResource
                else:
                    static_resource_class = StaticResourceNoListing

                cache_timeout = root_options.get('cache_timeout', DEFAULT_CACHE_TIMEOUT)

                root = static_resource_class(root_dir, cache_timeout=cache_timeout)

                # set extra MIME types
                #
                root.contentTypes.update(EXTRA_MIME_TYPES)
                if 'mime_types' in root_options:
                    root.contentTypes.update(root_options['mime_types'])
                patchFileContentTypes(root)

                # render 404 page on any concrete path not found
                #
                root.childNotFound = Resource404(self._templates, root_dir)

            # WSGI root resource
            #
            elif root_type == 'wsgi':

                if not _HAS_WSGI:
                    raise ApplicationError(u"crossbar.error.invalid_configuration", "WSGI unsupported")

                # wsgi_options = root_config.get('options', {})

                if 'module' not in root_config:
                    raise ApplicationError(u"crossbar.error.invalid_configuration", "missing WSGI app module")

                if 'object' not in root_config:
                    raise ApplicationError(u"crossbar.error.invalid_configuration", "missing WSGI app object")

                # import WSGI app module and object
                mod_name = root_config['module']
                try:
                    mod = importlib.import_module(mod_name)
                except ImportError as e:
                    raise ApplicationError(u"crossbar.error.invalid_configuration", "WSGI app module '{}' import failed: {} - Python search path was {}".format(mod_name, e, sys.path))
                else:
                    obj_name = root_config['object']
                    if obj_name not in mod.__dict__:
                        raise ApplicationError(u"crossbar.error.invalid_configuration", "WSGI app object '{}' not in module '{}'".format(obj_name, mod_name))
                    else:
                        app = getattr(mod, obj_name)

                # create a Twisted Web WSGI resource from the user's WSGI application object
                try:
                    wsgi_resource = WSGIResource(self._reactor, self._reactor.getThreadPool(), app)
                except Exception as e:
                    raise ApplicationError(u"crossbar.error.invalid_configuration", "could not instantiate WSGI resource: {}".format(e))
                else:
                    # create a root resource serving everything via WSGI
                    root = WSGIRootResource(wsgi_resource, {})

            # Redirecting root resource
            #
            elif root_type == 'redirect':

                redirect_url = root_config['url'].encode('ascii', 'ignore')
                root = RedirectResource(redirect_url)

            # Publisher resource (part of REST-bridge)
            #
            elif root_type == 'publisher':

                # create a vanilla session: the publisher will use this to inject events
                #
                publisher_session_config = ComponentConfig(realm=root_config['realm'], extra=None)
                publisher_session = ApplicationSession(publisher_session_config)

                # add the publishing session to the router
                #
                self._router_session_factory.add(publisher_session, authrole=root_config.get('role', 'anonymous'))

                # now create the publisher Twisted Web resource and add it to resource tree
                #
                root = PublisherResource(root_config.get('options', {}), publisher_session)

            # Webhook resource (part of REST-bridge)
            #
            elif root_type == 'webhook':

                # create a vanilla session: the webhook will use this to inject events
                #
                webhook_session_config = ComponentConfig(realm=root_config['realm'], extra=None)
                webhook_session = ApplicationSession(webhook_session_config)

                # add the publishing session to the router
                #
                self._router_session_factory.add(webhook_session, authrole=root_config.get('role', 'anonymous'))

                # now create the webhook Twisted Web resource and add it to resource tree
                #
                root = WebhookResource(root_config.get('options', {}), webhook_session)

            # Caller resource (part of REST-bridge)
            #
            elif root_type == 'caller':

                # create a vanilla session: the caller will use this to inject calls
                #
                caller_session_config = ComponentConfig(realm=root_config['realm'], extra=None)
                caller_session = ApplicationSession(caller_session_config)

                # add the calling session to the router
                #
                self._router_session_factory.add(caller_session, authrole=root_config.get('role', 'anonymous'))

                # now create the caller Twisted Web resource and add it to resource tree
                #
                root = CallerResource(root_config.get('options', {}), caller_session)

            # Generic Twisted Web resource
            #
            elif root_type == 'resource':

                try:
                    klassname = root_config['classname']

                    self.log.debug("Starting class '{}'".format(klassname))

                    c = klassname.split('.')
                    module_name, klass_name = '.'.join(c[:-1]), c[-1]
                    module = importlib.import_module(module_name)
                    make = getattr(module, klass_name)
                    root = make(root_config.get('extra', {}))

                except Exception as e:
                    emsg = "Failed to import class '{}' - {}".format(klassname, e)
                    self.log.error(emsg)
                    self.log.error("PYTHONPATH: {pythonpath}",
                                   pythonpath=sys.path)
                    raise ApplicationError(u"crossbar.error.class_import_failed", emsg)

            # Invalid root resource
            #
            else:
                raise ApplicationError(u"crossbar.error.invalid_configuration", "invalid Web root path type '{}'".format(root_type))

            # create Twisted Web resources on all non-root paths configured
            #
            self.add_paths(root, config.get('paths', {}))

            # create the actual transport factory
            #
            transport_factory = Site(root)
            transport_factory.noisy = False

            # Web access logging
            #
            if not options.get('access_log', False):
                transport_factory.log = lambda _: None

            # Traceback rendering
            #
            transport_factory.displayTracebacks = options.get('display_tracebacks', False)

            # HSTS
            #
            if options.get('hsts', False):
                if 'tls' in config['endpoint']:
                    hsts_max_age = int(options.get('hsts_max_age', 31536000))
                    transport_factory.requestFactory = createHSTSRequestFactory(transport_factory.requestFactory, hsts_max_age)
                else:
                    self.log.warn("Warning: HSTS requested, but running on non-TLS - skipping HSTS")

            # enable Hixie-76 on Twisted Web
            #
            if options.get('hixie76_aware', False):
                transport_factory.protocol = HTTPChannelHixie76Aware  # needed if Hixie76 is to be supported

        # Unknown transport type
        #
        else:
            # should not arrive here, since we did check_transport() in the beginning
            raise Exception("logic error")

        # create transport endpoint / listening port from transport factory
        #
        d = create_listening_port_from_config(config['endpoint'], transport_factory, self.config.extra.cbdir, self._reactor)

        def ok(port):
            self.transports[id] = RouterTransport(id, config, transport_factory, port)
            self.log.debug("Router transport '{}'' started and listening".format(id))
            return

        def fail(err):
            emsg = "Cannot listen on transport endpoint: {}".format(err.value)
            self.log.error(emsg)
            raise ApplicationError(u"crossbar.error.cannot_listen", emsg)

        d.addCallbacks(ok, fail)
        return d
コード例 #2
0
ファイル: router.py プロジェクト: siscia/crossbar
    def start_router_transport(self, id, config, details=None):
        """
        Start a transport on this router worker.

        :param id: The ID of the transport to start.
        :type id: str
        :param config: The transport configuration.
        :type config: dict
        """
        self.log.debug("{}.start_router_transport".format(self.__class__.__name__),
                       id=id, config=config)

        # prohibit starting a transport twice
        #
        if id in self.transports:
            emsg = "Could not start transport: a transport with ID '{}' is already running (or starting)".format(id)
            self.log.error(emsg)
            raise ApplicationError(u'crossbar.error.already_running', emsg)

        # check configuration
        #
        try:
            checkconfig.check_router_transport(config)
        except Exception as e:
            emsg = "Invalid router transport configuration: {}".format(e)
            self.log.error(emsg)
            raise ApplicationError(u"crossbar.error.invalid_configuration", emsg)
        else:
            self.log.debug("Starting {}-transport on router.".format(config['type']))

        # standalone WAMP-RawSocket transport
        #
        if config['type'] == 'rawsocket':

            transport_factory = WampRawSocketServerFactory(self._router_session_factory, config)
            transport_factory.noisy = False

        # standalone WAMP-WebSocket transport
        #
        elif config['type'] == 'websocket':

            transport_factory = WampWebSocketServerFactory(self._router_session_factory, self.config.extra.cbdir, config, self._templates)
            transport_factory.noisy = False

        # Flash-policy file server pseudo transport
        #
        elif config['type'] == 'flashpolicy':

            transport_factory = FlashPolicyFactory(config.get('allowed_domain', None), config.get('allowed_ports', None))

        # WebSocket testee pseudo transport
        #
        elif config['type'] == 'websocket.testee':

            transport_factory = WebSocketTesteeServerFactory(config, self._templates)

        # Stream testee pseudo transport
        #
        elif config['type'] == 'stream.testee':

            transport_factory = StreamTesteeServerFactory()

        # Twisted Web based transport
        #
        elif config['type'] == 'web':

            options = config.get('options', {})

            # create Twisted Web root resource
            #
            if '/' in config['paths']:
                root_config = config['paths']['/']
                root = self._create_resource(root_config, nested=False)
            else:
                root = Resource404(self._templates, b'')

            # create Twisted Web resources on all non-root paths configured
            #
            self._add_paths(root, config.get('paths', {}))

            # create the actual transport factory
            #
            transport_factory = Site(root)
            transport_factory.noisy = False

            # Web access logging
            #
            if not options.get('access_log', False):
                transport_factory.log = lambda _: None

            # Traceback rendering
            #
            transport_factory.displayTracebacks = options.get('display_tracebacks', False)

            # HSTS
            #
            if options.get('hsts', False):
                if 'tls' in config['endpoint']:
                    hsts_max_age = int(options.get('hsts_max_age', 31536000))
                    transport_factory.requestFactory = createHSTSRequestFactory(transport_factory.requestFactory, hsts_max_age)
                else:
                    self.log.warn("Warning: HSTS requested, but running on non-TLS - skipping HSTS")

        # Unknown transport type
        #
        else:
            # should not arrive here, since we did check_transport() in the beginning
            raise Exception("logic error")

        # create transport endpoint / listening port from transport factory
        #
        d = create_listening_port_from_config(config['endpoint'],
                                              self.config.extra.cbdir,
                                              transport_factory,
                                              self._reactor,
                                              self.log)

        def ok(port):
            self.transports[id] = RouterTransport(id, config, transport_factory, port)
            self.log.debug("Router transport '{}'' started and listening".format(id))
            return

        def fail(err):
            emsg = "Cannot listen on transport endpoint: {log_failure}"
            self.log.error(emsg, log_failure=err)
            raise ApplicationError(u"crossbar.error.cannot_listen", emsg)

        d.addCallbacks(ok, fail)
        return d
コード例 #3
0
    def start_router_transport(self, id, config, details=None):
        """
        Start a transport on this router and return when the transport has started.

        **Usage:**

        This procedure is registered under

        * ``crossbar.node.<node_id>.worker.<worker_id>.start_router_transport``

        The procedure takes a WAMP transport configuration with a listening endpoint, e.g.

        .. code-block:: javascript

            {
                "type": "websocket",
                "endpoint": {
                    "type": "tcp",
                    "port": 8080
                }
            }

        **Errors:**

        The procedure may raise the following errors:

        * ``crossbar.error.invalid_configuration`` - the provided transport configuration is invalid
        * ``crossbar.error.already_running`` - a transport with the given ID is already running (or starting)
        * ``crossbar.error.cannot_listen`` - could not listen on the configured listening endpoint of the transport
        * ``crossbar.error.class_import_failed`` - a side-by-side component could not be instantiated

        **Events:**

        The procedure will publish an event when the transport **is starting** to

        * ``crossbar.node.<node_id>.worker.<worker_id>.on_router_transport_starting``

        and publish an event when the transport **has started** to

        * ``crossbar.node.<node_id>.worker.<worker_id>.on_router_transport_started``

        :param id: The ID of the transport to start.
        :type id: unicode
        :param config: The transport configuration.
        :type config: dict
        """
        self.log.debug("{}.start_router_transport".format(self.__class__.__name__),
                       id=id, config=config)

        # prohibit starting a transport twice
        #
        if id in self.transports:
            emsg = "Could not start transport: a transport with ID '{}' is already running (or starting)".format(id)
            self.log.error(emsg)
            raise ApplicationError(u'crossbar.error.already_running', emsg)

        # check configuration
        #
        try:
            checkconfig.check_router_transport(config)
        except Exception as e:
            emsg = "Invalid router transport configuration: {}".format(e)
            self.log.error(emsg)
            raise ApplicationError(u"crossbar.error.invalid_configuration", emsg)
        else:
            self.log.debug("Starting {}-transport on router.".format(config['type']))

        # standalone WAMP-RawSocket transport
        #
        if config['type'] == 'rawsocket':

            transport_factory = WampRawSocketServerFactory(self._router_session_factory, config)
            transport_factory.noisy = False

        # standalone WAMP-WebSocket transport
        #
        elif config['type'] == 'websocket':

            transport_factory = WampWebSocketServerFactory(self._router_session_factory, self.config.extra.cbdir, config, self._templates)
            transport_factory.noisy = False

        # Flash-policy file server pseudo transport
        #
        elif config['type'] == 'flashpolicy':

            transport_factory = FlashPolicyFactory(config.get('allowed_domain', None), config.get('allowed_ports', None))

        # WebSocket testee pseudo transport
        #
        elif config['type'] == 'websocket.testee':

            transport_factory = WebSocketTesteeServerFactory(config, self._templates)

        # Stream testee pseudo transport
        #
        elif config['type'] == 'stream.testee':

            transport_factory = StreamTesteeServerFactory()

        # Twisted Web based transport
        #
        elif config['type'] == 'web':

            options = config.get('options', {})

            # create Twisted Web root resource
            #
            root_config = config['paths']['/']

            root_type = root_config['type']
            root_options = root_config.get('options', {})

            # Static file hierarchy root resource
            #
            if root_type == 'static':

                if 'directory' in root_config:

                    root_dir = os.path.abspath(os.path.join(self.config.extra.cbdir, root_config['directory']))

                elif 'package' in root_config:

                    if 'resource' not in root_config:
                        raise ApplicationError(u"crossbar.error.invalid_configuration", "missing resource")

                    try:
                        mod = importlib.import_module(root_config['package'])
                    except ImportError as e:
                        emsg = "Could not import resource {} from package {}: {}".format(root_config['resource'], root_config['package'], e)
                        self.log.error(emsg)
                        raise ApplicationError(u"crossbar.error.invalid_configuration", emsg)
                    else:
                        try:
                            root_dir = os.path.abspath(pkg_resources.resource_filename(root_config['package'], root_config['resource']))
                        except Exception as e:
                            emsg = "Could not import resource {} from package {}: {}".format(root_config['resource'], root_config['package'], e)
                            self.log.error(emsg)
                            raise ApplicationError(u"crossbar.error.invalid_configuration", emsg)
                        else:
                            mod_version = getattr(mod, '__version__', '?.?.?')
                            self.log.info("Loaded static Web resource '{}' from package '{} {}' (filesystem path {})".format(root_config['resource'], root_config['package'], mod_version, root_dir))

                else:
                    raise ApplicationError(u"crossbar.error.invalid_configuration", "missing web spec")

                root_dir = root_dir.encode('ascii', 'ignore')  # http://stackoverflow.com/a/20433918/884770
                self.log.debug("Starting Web service at root directory {}".format(root_dir))

                # create resource for file system hierarchy
                #
                if root_options.get('enable_directory_listing', False):
                    static_resource_class = StaticResource
                else:
                    static_resource_class = StaticResourceNoListing

                cache_timeout = root_options.get('cache_timeout', DEFAULT_CACHE_TIMEOUT)

                root = static_resource_class(root_dir, cache_timeout=cache_timeout)

                # set extra MIME types
                #
                root.contentTypes.update(EXTRA_MIME_TYPES)
                if 'mime_types' in root_options:
                    root.contentTypes.update(root_options['mime_types'])
                patchFileContentTypes(root)

                # render 404 page on any concrete path not found
                #
                root.childNotFound = Resource404(self._templates, root_dir)

            # WSGI root resource
            #
            elif root_type == 'wsgi':

                if not _HAS_WSGI:
                    raise ApplicationError(u"crossbar.error.invalid_configuration", "WSGI unsupported")

                # wsgi_options = root_config.get('options', {})

                if 'module' not in root_config:
                    raise ApplicationError(u"crossbar.error.invalid_configuration", "missing WSGI app module")

                if 'object' not in root_config:
                    raise ApplicationError(u"crossbar.error.invalid_configuration", "missing WSGI app object")

                # import WSGI app module and object
                mod_name = root_config['module']
                try:
                    mod = importlib.import_module(mod_name)
                except ImportError as e:
                    raise ApplicationError(u"crossbar.error.invalid_configuration", "WSGI app module '{}' import failed: {} - Python search path was {}".format(mod_name, e, sys.path))
                else:
                    obj_name = root_config['object']
                    if obj_name not in mod.__dict__:
                        raise ApplicationError(u"crossbar.error.invalid_configuration", "WSGI app object '{}' not in module '{}'".format(obj_name, mod_name))
                    else:
                        app = getattr(mod, obj_name)

                # create a Twisted Web WSGI resource from the user's WSGI application object
                try:
                    wsgi_resource = WSGIResource(self._reactor, self._reactor.getThreadPool(), app)
                except Exception as e:
                    raise ApplicationError(u"crossbar.error.invalid_configuration", "could not instantiate WSGI resource: {}".format(e))
                else:
                    # create a root resource serving everything via WSGI
                    root = WSGIRootResource(wsgi_resource, {})

            # Redirecting root resource
            #
            elif root_type == 'redirect':

                redirect_url = root_config['url'].encode('ascii', 'ignore')
                root = RedirectResource(redirect_url)

            # Publisher resource (part of REST-bridge)
            #
            elif root_type == 'publisher':

                # create a vanilla session: the publisher will use this to inject events
                #
                publisher_session_config = ComponentConfig(realm=root_config['realm'], extra=None)
                publisher_session = ApplicationSession(publisher_session_config)

                # add the publishing session to the router
                #
                self._router_session_factory.add(publisher_session, authrole=root_config.get('role', 'anonymous'))

                # now create the publisher Twisted Web resource and add it to resource tree
                #
                root = PublisherResource(root_config.get('options', {}), publisher_session)

            # Webhook resource (part of REST-bridge)
            #
            elif root_type == 'webhook':

                # create a vanilla session: the webhook will use this to inject events
                #
                webhook_session_config = ComponentConfig(realm=root_config['realm'], extra=None)
                webhook_session = ApplicationSession(webhook_session_config)

                # add the publishing session to the router
                #
                self._router_session_factory.add(webhook_session, authrole=root_config.get('role', 'anonymous'))

                # now create the webhook Twisted Web resource and add it to resource tree
                #
                root = WebhookResource(root_config.get('options', {}), webhook_session)

            # Caller resource (part of REST-bridge)
            #
            elif root_type == 'caller':

                # create a vanilla session: the caller will use this to inject calls
                #
                caller_session_config = ComponentConfig(realm=root_config['realm'], extra=None)
                caller_session = ApplicationSession(caller_session_config)

                # add the calling session to the router
                #
                self._router_session_factory.add(caller_session, authrole=root_config.get('role', 'anonymous'))

                # now create the caller Twisted Web resource and add it to resource tree
                #
                root = CallerResource(root_config.get('options', {}), caller_session)

            # Generic Twisted Web resource
            #
            elif root_type == 'resource':

                try:
                    klassname = root_config['classname']

                    self.log.debug("Starting class '{}'".format(klassname))

                    c = klassname.split('.')
                    module_name, klass_name = '.'.join(c[:-1]), c[-1]
                    module = importlib.import_module(module_name)
                    make = getattr(module, klass_name)
                    root = make(root_config.get('extra', {}))

                except Exception as e:
                    emsg = "Failed to import class '{}' - {}".format(klassname, e)
                    self.log.error(emsg)
                    self.log.error("PYTHONPATH: {pythonpath}",
                                   pythonpath=sys.path)
                    raise ApplicationError(u"crossbar.error.class_import_failed", emsg)

            # Invalid root resource
            #
            else:
                raise ApplicationError(u"crossbar.error.invalid_configuration", "invalid Web root path type '{}'".format(root_type))

            # create Twisted Web resources on all non-root paths configured
            #
            self.add_paths(root, config.get('paths', {}))

            # create the actual transport factory
            #
            transport_factory = Site(root)
            transport_factory.noisy = False

            # Web access logging
            #
            if not options.get('access_log', False):
                transport_factory.log = lambda _: None

            # Traceback rendering
            #
            transport_factory.displayTracebacks = options.get('display_tracebacks', False)

            # HSTS
            #
            if options.get('hsts', False):
                if 'tls' in config['endpoint']:
                    hsts_max_age = int(options.get('hsts_max_age', 31536000))
                    transport_factory.requestFactory = createHSTSRequestFactory(transport_factory.requestFactory, hsts_max_age)
                else:
                    self.log.warn("Warning: HSTS requested, but running on non-TLS - skipping HSTS")

        # Unknown transport type
        #
        else:
            # should not arrive here, since we did check_transport() in the beginning
            raise Exception("logic error")

        # create transport endpoint / listening port from transport factory
        #
        d = create_listening_port_from_config(config['endpoint'], transport_factory, self.config.extra.cbdir, self._reactor)

        def ok(port):
            self.transports[id] = RouterTransport(id, config, transport_factory, port)
            self.log.debug("Router transport '{}'' started and listening".format(id))
            return

        def fail(err):
            emsg = "Cannot listen on transport endpoint: {}".format(err.value)
            self.log.error(emsg)
            raise ApplicationError(u"crossbar.error.cannot_listen", emsg)

        d.addCallbacks(ok, fail)
        return d
コード例 #4
0
    def start_router_transport(self, id, config, details=None):
        """
      Start a transport on this router.

      :param id: The ID of the transport to start.
      :type id: str
      :param config: The transport configuration.
      :type config: dict
      """
        if self.debug:
            log.msg(
                "{}.start_router_transport".format(self.__class__.__name__),
                id, config)

        ## prohibit starting a transport twice
        ##
        if id in self.transports:
            emsg = "ERROR: could not start transport - a transport with ID '{}'' is already running (or starting)".format(
                id)
            log.msg(emsg)
            raise ApplicationError('crossbar.error.already_running', emsg)

        ## check configuration
        ##
        try:
            checkconfig.check_router_transport(config)
        except Exception as e:
            emsg = "ERROR: invalid router transport configuration ({})".format(
                e)
            log.msg(emsg)
            raise ApplicationError("crossbar.error.invalid_configuration",
                                   emsg)
        else:
            if self.debug:
                log.msg("Starting {}-transport on router.".format(
                    config['type']))

        ## standalone WAMP-RawSocket transport
        ##
        if config['type'] == 'rawsocket':

            transport_factory = CrossbarWampRawSocketServerFactory(
                self.session_factory, config)
            transport_factory.noisy = False

        ## standalone WAMP-WebSocket transport
        ##
        elif config['type'] == 'websocket':

            transport_factory = CrossbarWampWebSocketServerFactory(
                self.session_factory, self.config.extra.cbdir, config,
                self._templates)
            transport_factory.noisy = False

        ## Flash-policy file server pseudo transport
        ##
        elif config['type'] == 'flashpolicy':

            transport_factory = FlashPolicyFactory(
                config.get('allowed_domain', None),
                config.get('allowed_ports', None))

        ## WebSocket testee pseudo transport
        ##
        elif config['type'] == 'websocket.testee':

            transport_factory = WebSocketTesteeServerFactory(
                config, self._templates)

        ## Stream testee pseudo transport
        ##
        elif config['type'] == 'stream.testee':

            transport_factory = StreamTesteeServerFactory()

        ## Twisted Web based transport
        ##
        elif config['type'] == 'web':

            options = config.get('options', {})

            ## create Twisted Web root resource
            ##
            root_config = config['paths']['/']

            root_type = root_config['type']
            root_options = root_config.get('options', {})

            ## Static file hierarchy root resource
            ##
            if root_type == 'static':

                if 'directory' in root_config:

                    root_dir = os.path.abspath(
                        os.path.join(self.config.extra.cbdir,
                                     root_config['directory']))

                elif 'package' in root_config:

                    if not 'resource' in root_config:
                        raise ApplicationError(
                            "crossbar.error.invalid_configuration",
                            "missing resource")

                    try:
                        mod = importlib.import_module(root_config['package'])
                    except ImportError as e:
                        emsg = "ERROR: could not import resource '{}' from package '{}' - {}".format(
                            root_config['resource'], root_config['package'], e)
                        log.msg(emsg)
                        raise ApplicationError(
                            "crossbar.error.invalid_configuration", emsg)
                    else:
                        try:
                            root_dir = os.path.abspath(
                                pkg_resources.resource_filename(
                                    root_config['package'],
                                    root_config['resource']))
                        except Exception as e:
                            emsg = "ERROR: could not import resource '{}' from package '{}' - {}".format(
                                root_config['resource'],
                                root_config['package'], e)
                            log.msg(emsg)
                            raise ApplicationError(
                                "crossbar.error.invalid_configuration", emsg)
                        else:
                            mod_version = getattr(mod, '__version__', '?.?.?')
                            log.msg(
                                "Loaded static Web resource '{}' from package '{} {}' (filesystem path {})"
                                .format(root_config['resource'],
                                        root_config['package'], mod_version,
                                        root_dir))

                else:
                    raise ApplicationError(
                        "crossbar.error.invalid_configuration",
                        "missing web spec")

                root_dir = root_dir.encode(
                    'ascii',
                    'ignore')  # http://stackoverflow.com/a/20433918/884770
                if self.debug:
                    log.msg("Starting Web service at root directory {}".format(
                        root_dir))

                ## create resource for file system hierarchy
                ##
                if root_options.get('enable_directory_listing', False):
                    root = File(root_dir)
                else:
                    root = FileNoListing(root_dir)

                ## set extra MIME types
                ##
                root.contentTypes.update(EXTRA_MIME_TYPES)
                if 'mime_types' in root_options:
                    root.contentTypes.update(root_options['mime_types'])
                patchFileContentTypes(root)

                ## render 404 page on any concrete path not found
                ##
                root.childNotFound = Resource404(self._templates, root_dir)

            ## WSGI root resource
            ##
            elif root_type == 'wsgi':

                if not _HAS_WSGI:
                    raise ApplicationError(
                        "crossbar.error.invalid_configuration",
                        "WSGI unsupported")

                wsgi_options = root_config.get('options', {})

                if not 'module' in root_config:
                    raise ApplicationError(
                        "crossbar.error.invalid_configuration",
                        "missing module")

                if not 'object' in root_config:
                    raise ApplicationError(
                        "crossbar.error.invalid_configuration",
                        "missing object")

                try:
                    mod = importlib.import_module(root_config['module'])
                except ImportError:
                    raise ApplicationError(
                        "crossbar.error.invalid_configuration",
                        "module import failed")
                else:
                    if not root_config['object'] in mod.__dict__:
                        raise ApplicationError(
                            "crossbar.error.invalid_configuration",
                            "object not in module")
                    else:
                        app = getattr(mod, root_config['object'])

                ## create a Twisted Web WSGI resource from the user's WSGI application object
                try:
                    wsgi_resource = WSGIResource(reactor,
                                                 reactor.getThreadPool(), app)
                except Exception as e:
                    raise ApplicationError(
                        "crossbar.error.invalid_configuration",
                        "could not instantiate WSGI resource: {}".format(e))
                else:
                    ## create a root resource serving everything via WSGI
                    root = WSGIRootResource(wsgi_resource, {})

            ## Redirecting root resource
            ##
            elif root_type == 'redirect':

                redirect_url = root_config['url'].encode('ascii', 'ignore')
                root = RedirectResource(redirect_url)

            ## Pusher resource
            ##
            elif root_type == 'pusher':

                ## create a vanilla session: the pusher will use this to inject events
                ##
                pusher_session_config = ComponentConfig(
                    realm=root_config['realm'], extra=None)
                pusher_session = ApplicationSession(pusher_session_config)

                ## add the pushing session to the router
                ##
                self.session_factory.add(pusher_session,
                                         authrole=root_config.get(
                                             'role', 'anonymous'))

                ## now create the pusher Twisted Web resource and add it to resource tree
                ##
                root = PusherResource(root_config.get('options', {}),
                                      pusher_session)

            ## Invalid root resource
            ##
            else:
                raise ApplicationError(
                    "crossbar.error.invalid_configuration",
                    "invalid Web root path type '{}'".format(root_type))

            ## create Twisted Web resources on all non-root paths configured
            ##
            self.add_paths(root, config.get('paths', {}))

            ## create the actual transport factory
            ##
            transport_factory = Site(root)
            transport_factory.noisy = False

            ## Web access logging
            ##
            if not options.get('access_log', False):
                transport_factory.log = lambda _: None

            ## Traceback rendering
            ##
            transport_factory.displayTracebacks = options.get(
                'display_tracebacks', False)

            ## HSTS
            ##
            if options.get('hsts', False):
                if 'tls' in config['endpoint']:
                    hsts_max_age = int(options.get('hsts_max_age', 31536000))
                    transport_factory.requestFactory = createHSTSRequestFactory(
                        transport_factory.requestFactory, hsts_max_age)
                else:
                    log.msg(
                        "Warning: HSTS requested, but running on non-TLS - skipping HSTS"
                    )

            ## enable Hixie-76 on Twisted Web
            ##
            if options.get('hixie76_aware', False):
                transport_factory.protocol = HTTPChannelHixie76Aware  # needed if Hixie76 is to be supported

        ## Unknown transport type
        ##
        else:
            ## should not arrive here, since we did check_transport() in the beginning
            raise Exception("logic error")

        ## create transport endpoint / listening port from transport factory
        ##
        d = create_listening_port_from_config(config['endpoint'],
                                              transport_factory,
                                              self.config.extra.cbdir, reactor)

        def ok(port):
            self.transports[id] = RouterTransport(id, config,
                                                  transport_factory, port)
            if self.debug:
                log.msg(
                    "Router transport '{}'' started and listening".format(id))
            return

        def fail(err):
            emsg = "ERROR: cannot listen on transport endpoint ({})".format(
                err.value)
            log.msg(emsg)
            raise ApplicationError("crossbar.error.cannot_listen", emsg)

        d.addCallbacks(ok, fail)
        return d
コード例 #5
0
ファイル: router.py プロジェクト: snowattitudes/crossbar
    def start_router_transport(self, id, config, details=None):
        """
        Start a transport on this router and return when the transport has started.

        **Usage:**

        This procedure is registered under

        * ``crossbar.node.<node_id>.worker.<worker_id>.start_router_transport``

        The procedure takes a WAMP transport configuration with a listening endpoint, e.g.

        .. code-block:: javascript

            {
                "type": "websocket",
                "endpoint": {
                    "type": "tcp",
                    "port": 8080
                }
            }

        **Errors:**

        The procedure may raise the following errors:

        * ``crossbar.error.invalid_configuration`` - the provided transport configuration is invalid
        * ``crossbar.error.already_running`` - a transport with the given ID is already running (or starting)
        * ``crossbar.error.cannot_listen`` - could not listen on the configured listening endpoint of the transport
        * ``crossbar.error.class_import_failed`` - a side-by-side component could not be instantiated

        **Events:**

        The procedure will publish an event when the transport **is starting** to

        * ``crossbar.node.<node_id>.worker.<worker_id>.on_router_transport_starting``

        and publish an event when the transport **has started** to

        * ``crossbar.node.<node_id>.worker.<worker_id>.on_router_transport_started``

        :param id: The ID of the transport to start.
        :type id: unicode
        :param config: The transport configuration.
        :type config: dict
        """
        self.log.debug("{}.start_router_transport".format(self.__class__.__name__), id=id, config=config)

        # prohibit starting a transport twice
        #
        if id in self.transports:
            emsg = "Could not start transport: a transport with ID '{}' is already running (or starting)".format(id)
            self.log.error(emsg)
            raise ApplicationError(u"crossbar.error.already_running", emsg)

        # check configuration
        #
        try:
            checkconfig.check_router_transport(config)
        except Exception as e:
            emsg = "Invalid router transport configuration: {}".format(e)
            self.log.error(emsg)
            raise ApplicationError(u"crossbar.error.invalid_configuration", emsg)
        else:
            self.log.debug("Starting {}-transport on router.".format(config["type"]))

        # standalone WAMP-RawSocket transport
        #
        if config["type"] == "rawsocket":

            transport_factory = WampRawSocketServerFactory(self._router_session_factory, config)
            transport_factory.noisy = False

        # standalone WAMP-WebSocket transport
        #
        elif config["type"] == "websocket":

            transport_factory = WampWebSocketServerFactory(
                self._router_session_factory, self.config.extra.cbdir, config, self._templates
            )
            transport_factory.noisy = False

        # Flash-policy file server pseudo transport
        #
        elif config["type"] == "flashpolicy":

            transport_factory = FlashPolicyFactory(
                config.get("allowed_domain", None), config.get("allowed_ports", None)
            )

        # WebSocket testee pseudo transport
        #
        elif config["type"] == "websocket.testee":

            transport_factory = WebSocketTesteeServerFactory(config, self._templates)

        # Stream testee pseudo transport
        #
        elif config["type"] == "stream.testee":

            transport_factory = StreamTesteeServerFactory()

        # Twisted Web based transport
        #
        elif config["type"] == "web":

            options = config.get("options", {})

            # create Twisted Web root resource
            #
            if "/" in config["paths"]:
                root_config = config["paths"]["/"]
                root = self.create_resource(root_config, nested=False)
            else:
                root = Resource404(self._templates, b"")

            # create Twisted Web resources on all non-root paths configured
            #
            self.add_paths(root, config.get("paths", {}))

            # create the actual transport factory
            #
            transport_factory = Site(root)
            transport_factory.noisy = False

            # Web access logging
            #
            if not options.get("access_log", False):
                transport_factory.log = lambda _: None

            # Traceback rendering
            #
            transport_factory.displayTracebacks = options.get("display_tracebacks", False)

            # HSTS
            #
            if options.get("hsts", False):
                if "tls" in config["endpoint"]:
                    hsts_max_age = int(options.get("hsts_max_age", 31536000))
                    transport_factory.requestFactory = createHSTSRequestFactory(
                        transport_factory.requestFactory, hsts_max_age
                    )
                else:
                    self.log.warn("Warning: HSTS requested, but running on non-TLS - skipping HSTS")

        # Unknown transport type
        #
        else:
            # should not arrive here, since we did check_transport() in the beginning
            raise Exception("logic error")

        # create transport endpoint / listening port from transport factory
        #
        d = create_listening_port_from_config(
            config["endpoint"], transport_factory, self.config.extra.cbdir, self._reactor
        )

        def ok(port):
            self.transports[id] = RouterTransport(id, config, transport_factory, port)
            self.log.debug("Router transport '{}'' started and listening".format(id))
            return

        def fail(err):
            emsg = "Cannot listen on transport endpoint: {}".format(err.value)
            self.log.error(emsg)
            raise ApplicationError(u"crossbar.error.cannot_listen", emsg)

        d.addCallbacks(ok, fail)
        return d
コード例 #6
0
    def start_router_transport(self, id, config, details=None):
        """
        Start a transport on this router worker.

        :param id: The ID of the transport to start.
        :type id: str
        :param config: The transport configuration.
        :type config: dict
        """
        self.log.debug("{}.start_router_transport".format(
            self.__class__.__name__),
                       id=id,
                       config=config)

        # prohibit starting a transport twice
        #
        if id in self.transports:
            emsg = "Could not start transport: a transport with ID '{}' is already running (or starting)".format(
                id)
            self.log.error(emsg)
            raise ApplicationError(u'crossbar.error.already_running', emsg)

        # check configuration
        #
        try:
            checkconfig.check_router_transport(config)
        except Exception as e:
            emsg = "Invalid router transport configuration: {}".format(e)
            self.log.error(emsg)
            raise ApplicationError(u"crossbar.error.invalid_configuration",
                                   emsg)
        else:
            self.log.debug("Starting {}-transport on router.".format(
                config['type']))

        # standalone WAMP-RawSocket transport
        #
        if config['type'] == 'rawsocket':

            transport_factory = WampRawSocketServerFactory(
                self._router_session_factory, config)
            transport_factory.noisy = False

        # standalone WAMP-WebSocket transport
        #
        elif config['type'] == 'websocket':

            transport_factory = WampWebSocketServerFactory(
                self._router_session_factory, self.config.extra.cbdir, config,
                self._templates)
            transport_factory.noisy = False

        # Flash-policy file server pseudo transport
        #
        elif config['type'] == 'flashpolicy':

            transport_factory = FlashPolicyFactory(
                config.get('allowed_domain', None),
                config.get('allowed_ports', None))

        # WebSocket testee pseudo transport
        #
        elif config['type'] == 'websocket.testee':

            transport_factory = WebSocketTesteeServerFactory(
                config, self._templates)

        # Stream testee pseudo transport
        #
        elif config['type'] == 'stream.testee':

            transport_factory = StreamTesteeServerFactory()

        # Twisted Web based transport
        #
        elif config['type'] == 'web':

            options = config.get('options', {})

            # create Twisted Web root resource
            #
            if '/' in config['paths']:
                root_config = config['paths']['/']
                root = self._create_resource(root_config, nested=False)
            else:
                root = Resource404(self._templates, b'')

            # create Twisted Web resources on all non-root paths configured
            #
            self._add_paths(root, config.get('paths', {}))

            # create the actual transport factory
            #
            transport_factory = Site(root)
            transport_factory.noisy = False

            # Web access logging
            #
            if not options.get('access_log', False):
                transport_factory.log = lambda _: None

            # Traceback rendering
            #
            transport_factory.displayTracebacks = options.get(
                'display_tracebacks', False)

            # HSTS
            #
            if options.get('hsts', False):
                if 'tls' in config['endpoint']:
                    hsts_max_age = int(options.get('hsts_max_age', 31536000))
                    transport_factory.requestFactory = createHSTSRequestFactory(
                        transport_factory.requestFactory, hsts_max_age)
                else:
                    self.log.warn(
                        "Warning: HSTS requested, but running on non-TLS - skipping HSTS"
                    )

        # Unknown transport type
        #
        else:
            # should not arrive here, since we did check_transport() in the beginning
            raise Exception("logic error")

        # create transport endpoint / listening port from transport factory
        #
        d = create_listening_port_from_config(config['endpoint'],
                                              self.config.extra.cbdir,
                                              transport_factory, self._reactor,
                                              self.log)

        def ok(port):
            self.transports[id] = RouterTransport(id, config,
                                                  transport_factory, port)
            self.log.debug(
                "Router transport '{}'' started and listening".format(id))
            return

        def fail(err):
            emsg = "Cannot listen on transport endpoint: {log_failure}"
            self.log.error(emsg, log_failure=err)
            raise ApplicationError(u"crossbar.error.cannot_listen", emsg)

        d.addCallbacks(ok, fail)
        return d
コード例 #7
0
ファイル: router.py プロジェクト: honeyflyfish/crossbar
    def start_router_transport(self, id, config, details=None):
        """
        Start a transport on this router and return when the transport has started.

        **Usage:**

        This procedure is registered under

        * ``crossbar.node.<node_id>.worker.<worker_id>.start_router_transport``

        The procedure takes a WAMP transport configuration with a listening endpoint, e.g.

        .. code-block:: javascript

            {
                "type": "websocket",
                "endpoint": {
                    "type": "tcp",
                    "port": 8080
                }
            }

        **Errors:**

        The procedure may raise the following errors:

        * ``crossbar.error.invalid_configuration`` - the provided transport configuration is invalid
        * ``crossbar.error.already_running`` - a transport with the given ID is already running (or starting)
        * ``crossbar.error.cannot_listen`` - could not listen on the configured listening endpoint of the transport
        * ``crossbar.error.class_import_failed`` - a side-by-side component could not be instantiated

        **Events:**

        The procedure will publish an event when the transport **is starting** to

        * ``crossbar.node.<node_id>.worker.<worker_id>.on_router_transport_starting``

        and publish an event when the transport **has started** to

        * ``crossbar.node.<node_id>.worker.<worker_id>.on_router_transport_started``

        :param id: The ID of the transport to start.
        :type id: unicode
        :param config: The transport configuration.
        :type config: dict
        """
        self.log.debug("{}.start_router_transport".format(self.__class__.__name__), id=id, config=config)

        # prohibit starting a transport twice
        #
        if id in self.transports:
            emsg = "Could not start transport: a transport with ID '{}' is already running (or starting)".format(id)
            self.log.error(emsg)
            raise ApplicationError(u"crossbar.error.already_running", emsg)

        # check configuration
        #
        try:
            checkconfig.check_router_transport(config)
        except Exception as e:
            emsg = "Invalid router transport configuration: {}".format(e)
            self.log.error(emsg)
            raise ApplicationError(u"crossbar.error.invalid_configuration", emsg)
        else:
            self.log.debug("Starting {}-transport on router.".format(config["type"]))

        # standalone WAMP-RawSocket transport
        #
        if config["type"] == "rawsocket":

            transport_factory = WampRawSocketServerFactory(self._router_session_factory, config)
            transport_factory.noisy = False

        # standalone WAMP-WebSocket transport
        #
        elif config["type"] == "websocket":

            transport_factory = WampWebSocketServerFactory(
                self._router_session_factory, self.config.extra.cbdir, config, self._templates
            )
            transport_factory.noisy = False

        # Flash-policy file server pseudo transport
        #
        elif config["type"] == "flashpolicy":

            transport_factory = FlashPolicyFactory(
                config.get("allowed_domain", None), config.get("allowed_ports", None)
            )

        # WebSocket testee pseudo transport
        #
        elif config["type"] == "websocket.testee":

            transport_factory = WebSocketTesteeServerFactory(config, self._templates)

        # Stream testee pseudo transport
        #
        elif config["type"] == "stream.testee":

            transport_factory = StreamTesteeServerFactory()

        # Twisted Web based transport
        #
        elif config["type"] == "web":

            options = config.get("options", {})

            # create Twisted Web root resource
            #
            root_config = config["paths"]["/"]

            root_type = root_config["type"]
            root_options = root_config.get("options", {})

            # Static file hierarchy root resource
            #
            if root_type == "static":

                if "directory" in root_config:

                    root_dir = os.path.abspath(os.path.join(self.config.extra.cbdir, root_config["directory"]))

                elif "package" in root_config:

                    if "resource" not in root_config:
                        raise ApplicationError(u"crossbar.error.invalid_configuration", "missing resource")

                    try:
                        mod = importlib.import_module(root_config["package"])
                    except ImportError as e:
                        emsg = "Could not import resource {} from package {}: {}".format(
                            root_config["resource"], root_config["package"], e
                        )
                        self.log.error(emsg)
                        raise ApplicationError(u"crossbar.error.invalid_configuration", emsg)
                    else:
                        try:
                            root_dir = os.path.abspath(
                                pkg_resources.resource_filename(root_config["package"], root_config["resource"])
                            )
                        except Exception as e:
                            emsg = "Could not import resource {} from package {}: {}".format(
                                root_config["resource"], root_config["package"], e
                            )
                            self.log.error(emsg)
                            raise ApplicationError(u"crossbar.error.invalid_configuration", emsg)
                        else:
                            mod_version = getattr(mod, "__version__", "?.?.?")
                            self.log.info(
                                "Loaded static Web resource '{}' from package '{} {}' (filesystem path {})".format(
                                    root_config["resource"], root_config["package"], mod_version, root_dir
                                )
                            )

                else:
                    raise ApplicationError(u"crossbar.error.invalid_configuration", "missing web spec")

                root_dir = root_dir.encode("ascii", "ignore")  # http://stackoverflow.com/a/20433918/884770
                self.log.debug("Starting Web service at root directory {}".format(root_dir))

                # create resource for file system hierarchy
                #
                if root_options.get("enable_directory_listing", False):
                    static_resource_class = StaticResource
                else:
                    static_resource_class = StaticResourceNoListing

                cache_timeout = root_options.get("cache_timeout", DEFAULT_CACHE_TIMEOUT)

                root = static_resource_class(root_dir, cache_timeout=cache_timeout)

                # set extra MIME types
                #
                root.contentTypes.update(EXTRA_MIME_TYPES)
                if "mime_types" in root_options:
                    root.contentTypes.update(root_options["mime_types"])
                patchFileContentTypes(root)

                # render 404 page on any concrete path not found
                #
                root.childNotFound = Resource404(self._templates, root_dir)

            # WSGI root resource
            #
            elif root_type == "wsgi":

                if not _HAS_WSGI:
                    raise ApplicationError(u"crossbar.error.invalid_configuration", "WSGI unsupported")

                # wsgi_options = root_config.get('options', {})

                if "module" not in root_config:
                    raise ApplicationError(u"crossbar.error.invalid_configuration", "missing WSGI app module")

                if "object" not in root_config:
                    raise ApplicationError(u"crossbar.error.invalid_configuration", "missing WSGI app object")

                # import WSGI app module and object
                mod_name = root_config["module"]
                try:
                    mod = importlib.import_module(mod_name)
                except ImportError as e:
                    raise ApplicationError(
                        u"crossbar.error.invalid_configuration",
                        "WSGI app module '{}' import failed: {} - Python search path was {}".format(
                            mod_name, e, sys.path
                        ),
                    )
                else:
                    obj_name = root_config["object"]
                    if obj_name not in mod.__dict__:
                        raise ApplicationError(
                            u"crossbar.error.invalid_configuration",
                            "WSGI app object '{}' not in module '{}'".format(obj_name, mod_name),
                        )
                    else:
                        app = getattr(mod, obj_name)

                # create a Twisted Web WSGI resource from the user's WSGI application object
                try:
                    wsgi_resource = WSGIResource(self._reactor, self._reactor.getThreadPool(), app)
                except Exception as e:
                    raise ApplicationError(
                        u"crossbar.error.invalid_configuration", "could not instantiate WSGI resource: {}".format(e)
                    )
                else:
                    # create a root resource serving everything via WSGI
                    root = WSGIRootResource(wsgi_resource, {})

            # Redirecting root resource
            #
            elif root_type == "redirect":

                redirect_url = root_config["url"].encode("ascii", "ignore")
                root = RedirectResource(redirect_url)

            # Publisher resource (part of REST-bridge)
            #
            elif root_type == "publisher":

                # create a vanilla session: the publisher will use this to inject events
                #
                publisher_session_config = ComponentConfig(realm=root_config["realm"], extra=None)
                publisher_session = ApplicationSession(publisher_session_config)

                # add the publishing session to the router
                #
                self._router_session_factory.add(publisher_session, authrole=root_config.get("role", "anonymous"))

                # now create the publisher Twisted Web resource and add it to resource tree
                #
                root = PublisherResource(root_config.get("options", {}), publisher_session)

            # Webhook resource (part of REST-bridge)
            #
            elif root_type == "webhook":

                # create a vanilla session: the webhook will use this to inject events
                #
                webhook_session_config = ComponentConfig(realm=root_config["realm"], extra=None)
                webhook_session = ApplicationSession(webhook_session_config)

                # add the publishing session to the router
                #
                self._router_session_factory.add(webhook_session, authrole=root_config.get("role", "anonymous"))

                # now create the webhook Twisted Web resource and add it to resource tree
                #
                root = WebhookResource(root_config.get("options", {}), webhook_session)

            # Caller resource (part of REST-bridge)
            #
            elif root_type == "caller":

                # create a vanilla session: the caller will use this to inject calls
                #
                caller_session_config = ComponentConfig(realm=root_config["realm"], extra=None)
                caller_session = ApplicationSession(caller_session_config)

                # add the calling session to the router
                #
                self._router_session_factory.add(caller_session, authrole=root_config.get("role", "anonymous"))

                # now create the caller Twisted Web resource and add it to resource tree
                #
                root = CallerResource(root_config.get("options", {}), caller_session)

            # Generic Twisted Web resource
            #
            elif root_type == "resource":

                try:
                    klassname = root_config["classname"]

                    self.log.debug("Starting class '{}'".format(klassname))

                    c = klassname.split(".")
                    module_name, klass_name = ".".join(c[:-1]), c[-1]
                    module = importlib.import_module(module_name)
                    make = getattr(module, klass_name)
                    root = make(root_config.get("extra", {}))

                except Exception as e:
                    emsg = "Failed to import class '{}' - {}".format(klassname, e)
                    self.log.error(emsg)
                    self.log.error("PYTHONPATH: {pythonpath}", pythonpath=sys.path)
                    raise ApplicationError(u"crossbar.error.class_import_failed", emsg)

            # Invalid root resource
            #
            else:
                raise ApplicationError(
                    u"crossbar.error.invalid_configuration", "invalid Web root path type '{}'".format(root_type)
                )

            # create Twisted Web resources on all non-root paths configured
            #
            self.add_paths(root, config.get("paths", {}))

            # create the actual transport factory
            #
            transport_factory = Site(root)
            transport_factory.noisy = False

            # Web access logging
            #
            if not options.get("access_log", False):
                transport_factory.log = lambda _: None

            # Traceback rendering
            #
            transport_factory.displayTracebacks = options.get("display_tracebacks", False)

            # HSTS
            #
            if options.get("hsts", False):
                if "tls" in config["endpoint"]:
                    hsts_max_age = int(options.get("hsts_max_age", 31536000))
                    transport_factory.requestFactory = createHSTSRequestFactory(
                        transport_factory.requestFactory, hsts_max_age
                    )
                else:
                    self.log.warn("Warning: HSTS requested, but running on non-TLS - skipping HSTS")

        # Unknown transport type
        #
        else:
            # should not arrive here, since we did check_transport() in the beginning
            raise Exception("logic error")

        # create transport endpoint / listening port from transport factory
        #
        d = create_listening_port_from_config(
            config["endpoint"], transport_factory, self.config.extra.cbdir, self._reactor
        )

        def ok(port):
            self.transports[id] = RouterTransport(id, config, transport_factory, port)
            self.log.debug("Router transport '{}'' started and listening".format(id))
            return

        def fail(err):
            emsg = "Cannot listen on transport endpoint: {}".format(err.value)
            self.log.error(emsg)
            raise ApplicationError(u"crossbar.error.cannot_listen", emsg)

        d.addCallbacks(ok, fail)
        return d
コード例 #8
0
ファイル: router.py プロジェクト: Inspire2Innovate/crossbar
   def start_router_transport(self, id, config, details = None):
      """
      Start a transport on this router.

      :param id: The ID of the transport to start.
      :type id: str
      :param config: The transport configuration.
      :type config: dict
      """
      if self.debug:
         log.msg("{}.start_router_transport".format(self.__class__.__name__), id, config)

      ## prohibit starting a transport twice
      ##
      if id in self.transports:
         emsg = "ERROR: could not start transport - a transport with ID '{}'' is already running (or starting)".format(id)
         log.msg(emsg)
         raise ApplicationError('crossbar.error.already_running', emsg)

      ## check configuration
      ##
      try:
         checkconfig.check_router_transport(config)
      except Exception as e:
         emsg = "ERROR: invalid router transport configuration ({})".format(e)
         log.msg(emsg)
         raise ApplicationError("crossbar.error.invalid_configuration", emsg)
      else:
         if self.debug:
            log.msg("Starting {}-transport on router.".format(config['type']))


      ## standalone WAMP-RawSocket transport
      ##
      if config['type'] == 'rawsocket':

         transport_factory = CrossbarWampRawSocketServerFactory(self.session_factory, config)
         transport_factory.noisy = False


      ## standalone WAMP-WebSocket transport
      ##
      elif config['type'] == 'websocket':

         transport_factory = CrossbarWampWebSocketServerFactory(self.session_factory, self.config.extra.cbdir, config, self._templates)
         transport_factory.noisy = False


      ## Twisted Web based transport
      ##
      elif config['type'] == 'web':

         options = config.get('options', {})

         ## create Twisted Web root resource
         ##
         root_config = config['paths']['/']

         root_type = root_config['type']
         root_options = root_config.get('options', {})


         ## Static file hierarchy root resource
         ##
         if root_type == 'static':

            if 'directory' in root_config:

               root_dir = os.path.abspath(os.path.join(self.config.extra.cbdir, root_config['directory']))

            elif 'package' in root_config:

               if not 'resource' in root_config:
                  raise ApplicationError("crossbar.error.invalid_configuration", "missing resource")

               try:
                  mod = importlib.import_module(root_config['package'])
               except ImportError as e:
                  emsg = "ERROR: could not import resource '{}' from package '{}' - {}".format(root_config['resource'], root_config['package'], e)
                  log.msg(emsg)
                  raise ApplicationError("crossbar.error.invalid_configuration", emsg)
               else:
                  try:
                     root_dir = os.path.abspath(pkg_resources.resource_filename(root_config['package'], root_config['resource']))
                  except Exception as e:
                     emsg = "ERROR: could not import resource '{}' from package '{}' - {}".format(root_config['resource'], root_config['package'], e)
                     log.msg(emsg)
                     raise ApplicationError("crossbar.error.invalid_configuration", emsg)
                  else:
                     mod_version = getattr(mod, '__version__', '?.?.?')
                     log.msg("Loaded static Web resource '{}' from package '{} {}' (filesystem path {})".format(root_config['resource'], root_config['package'], mod_version, root_dir))

            else:
               raise ApplicationError("crossbar.error.invalid_configuration", "missing web spec")

            root_dir = root_dir.encode('ascii', 'ignore') # http://stackoverflow.com/a/20433918/884770
            if self.debug:
               log.msg("Starting Web service at root directory {}".format(root_dir))


            ## create resource for file system hierarchy
            ##
            if root_options.get('enable_directory_listing', False):
               root = File(root_dir)
            else:
               root = FileNoListing(root_dir)

            ## set extra MIME types
            ##
            root.contentTypes.update(EXTRA_MIME_TYPES)
            if 'mime_types' in root_options:
               root.contentTypes.update(root_options['mime_types'])
            patchFileContentTypes(root)

            ## render 404 page on any concrete path not found
            ##
            root.childNotFound = Resource404(self._templates, root_dir)


         ## WSGI root resource
         ##
         elif root_type == 'wsgi':

            if not _HAS_WSGI:
               raise ApplicationError("crossbar.error.invalid_configuration", "WSGI unsupported")

            wsgi_options = root_config.get('options', {})

            if not 'module' in root_config:
               raise ApplicationError("crossbar.error.invalid_configuration", "missing module")

            if not 'object' in root_config:
               raise ApplicationError("crossbar.error.invalid_configuration", "missing object")

            try:
               mod = importlib.import_module(root_config['module'])
            except ImportError:
               raise ApplicationError("crossbar.error.invalid_configuration", "module import failed")
            else:
               if not root_config['object'] in mod.__dict__:
                  raise ApplicationError("crossbar.error.invalid_configuration", "object not in module")
               else:
                  app = getattr(mod, root_config['object'])

            ## create a Twisted Web WSGI resource from the user's WSGI application object
            try:
               wsgi_resource = WSGIResource(reactor, reactor.getThreadPool(), app)
            except Exception as e:
               raise ApplicationError("crossbar.error.invalid_configuration", "could not instantiate WSGI resource: {}".format(e))
            else:
               ## create a root resource serving everything via WSGI
               root = WSGIRootResource(wsgi_resource, {})


         ## Redirecting root resource
         ##
         elif root_type == 'redirect':

            redirect_url = root_config['url'].encode('ascii', 'ignore')
            root = RedirectResource(redirect_url)


         ## Pusher resource
         ##
         elif root_type == 'pusher':

            ## create a vanilla session: the pusher will use this to inject events
            ##
            pusher_session_config = ComponentConfig(realm = root_config['realm'], extra = None)
            pusher_session = ApplicationSession(pusher_session_config)

            ## add the pushing session to the router
            ##
            self.session_factory.add(pusher_session, authrole = root_config.get('role', 'anonymous'))

            ## now create the pusher Twisted Web resource and add it to resource tree
            ##
            root = PusherResource(root_config.get('options', {}), pusher_session)


         ## Invalid root resource
         ##
         else:
            raise ApplicationError("crossbar.error.invalid_configuration", "invalid Web root path type '{}'".format(root_type))


         ## create Twisted Web resources on all non-root paths configured
         ##
         for path in sorted(config.get('paths', [])):

            if path != "/":

               path_config = config['paths'][path]

               ## websocket_echo
               ## websocket_testee
               ## s3mirror
               ## websocket_stdio
               ##

               ## WAMP-WebSocket resource
               ##
               if path_config['type'] == 'websocket':

                  ws_factory = CrossbarWampWebSocketServerFactory(self.session_factory, self.config.extra.cbdir, path_config, self._templates)

                  ## FIXME: Site.start/stopFactory should start/stop factories wrapped as Resources
                  ws_factory.startFactory()

                  ws_resource = WebSocketResource(ws_factory)
                  root.putChild(path, ws_resource)


               ## Static file hierarchy resource
               ##
               elif path_config['type'] == 'static':

                  static_options = path_config.get('options', {})

                  if 'directory' in path_config:

                     static_dir = os.path.abspath(os.path.join(self.config.extra.cbdir, path_config['directory']))

                  elif 'package' in path_config:

                     if not 'resource' in path_config:
                        raise ApplicationError("crossbar.error.invalid_configuration", "missing resource")

                     try:
                        mod = importlib.import_module(path_config['package'])
                     except ImportError as e:
                        emsg = "ERROR: could not import resource '{}' from package '{}' - {}".format(path_config['resource'], path_config['package'], e)
                        log.msg(emsg)
                        raise ApplicationError("crossbar.error.invalid_configuration", emsg)
                     else:
                        try:
                           static_dir = os.path.abspath(pkg_resources.resource_filename(path_config['package'], path_config['resource']))
                        except Exception as e:
                           emsg = "ERROR: could not import resource '{}' from package '{}' - {}".format(path_config['resource'], path_config['package'], e)
                           log.msg(emsg)
                           raise ApplicationError("crossbar.error.invalid_configuration", emsg)

                  else:

                     raise ApplicationError("crossbar.error.invalid_configuration", "missing web spec")

                  static_dir = static_dir.encode('ascii', 'ignore') # http://stackoverflow.com/a/20433918/884770

                  ## create resource for file system hierarchy
                  ##
                  if static_options.get('enable_directory_listing', False):
                     static_resource = File(static_dir)
                  else:
                     static_resource = FileNoListing(static_dir)

                  ## set extra MIME types
                  ##
                  static_resource.contentTypes.update(EXTRA_MIME_TYPES)
                  if 'mime_types' in static_options:
                     static_resource.contentTypes.update(static_options['mime_types'])
                  patchFileContentTypes(static_resource)

                  ## render 404 page on any concrete path not found
                  ##
                  static_resource.childNotFound = Resource404(self._templates, static_dir)

                  root.putChild(path, static_resource)


               ## WSGI resource
               ##
               elif path_config['type'] == 'wsgi':

                  if not _HAS_WSGI:
                     raise ApplicationError("crossbar.error.invalid_configuration", "WSGI unsupported")

                  wsgi_options = path_config.get('options', {})

                  if not 'module' in path_config:
                     raise ApplicationError("crossbar.error.invalid_configuration", "missing module")

                  if not 'object' in path_config:
                     raise ApplicationError("crossbar.error.invalid_configuration", "missing object")

                  try:
                     mod = importlib.import_module(path_config['module'])
                  except ImportError as e:
                     raise ApplicationError("crossbar.error.invalid_configuration", "module import failed - {}".format(e))
                  else:
                     if not path_config['object'] in mod.__dict__:
                        raise ApplicationError("crossbar.error.invalid_configuration", "object not in module")
                     else:
                        app = getattr(mod, path_config['object'])

                  ## create a Twisted Web WSGI resource from the user's WSGI application object
                  try:
                     wsgi_resource = WSGIResource(reactor, reactor.getThreadPool(), app)
                  except Exception as e:
                     raise ApplicationError("crossbar.error.invalid_configuration", "could not instantiate WSGI resource: {}".format(e))
                  else:
                     root.putChild(path, wsgi_resource)


               ## Redirecting resource
               ##
               elif path_config['type'] == 'redirect':
                  redirect_url = path_config['url'].encode('ascii', 'ignore')
                  redirect_resource = RedirectResource(redirect_url)
                  root.putChild(path, redirect_resource)


               ## JSON value resource
               ##
               elif path_config['type'] == 'json':
                  value = path_config['value']

                  json_resource = JsonResource(value)
                  root.putChild(path, json_resource)


               ## CGI script resource
               ##
               elif path_config['type'] == 'cgi':

                  cgi_processor = path_config['processor']
                  cgi_directory = os.path.abspath(os.path.join(self.config.extra.cbdir, path_config['directory']))
                  cgi_directory = cgi_directory.encode('ascii', 'ignore') # http://stackoverflow.com/a/20433918/884770

                  cgi_resource = CgiDirectory(cgi_directory, cgi_processor, Resource404(self._templates, cgi_directory))

                  root.putChild(path, cgi_resource)


               ## WAMP-Longpoll transport resource
               ##
               elif path_config['type'] == 'longpoll':

                  path_options = path_config.get('options', {})

                  lp_resource = WampLongPollResource(self.session_factory,
                     timeout = path_options.get('request_timeout', 10),
                     killAfter = path_options.get('session_timeout', 30),
                     queueLimitBytes = path_options.get('queue_limit_bytes', 128 * 1024),
                     queueLimitMessages = path_options.get('queue_limit_messages', 100),
                     debug = path_options.get('debug', False),
                     debug_transport_id = path_options.get('debug_transport_id', None)
                  )
                  lp_resource._templates = self._templates

                  root.putChild(path, lp_resource)


               ## Pusher resource
               ##
               elif path_config['type'] == 'pusher':

                  ## create a vanilla session: the pusher will use this to inject events
                  ##
                  pusher_session_config = ComponentConfig(realm = path_config['realm'], extra = None)
                  pusher_session = ApplicationSession(pusher_session_config)

                  ## add the pushing session to the router
                  ##
                  self.session_factory.add(pusher_session, authrole = path_config.get('role', 'anonymous'))

                  ## now create the pusher Twisted Web resource and add it to resource tree
                  ##
                  pusher_resource = PusherResource(path_config.get('options', {}), pusher_session)
                  root.putChild(path, pusher_resource)


               ## Schema Docs resource
               ##
               elif path_config['type'] == 'schemadoc':

                  realm = path_config['realm']

                  if not realm in self.realm_to_id:
                     raise ApplicationError("crossbar.error.no_such_object", "No realm with URI '{}' configured".format(realm))

                  realm_id = self.realm_to_id[realm]

                  realm_schemas = self.realms[realm_id].session._schemas

                  schemadoc_resource = SchemaDocResource(self._templates, realm, realm_schemas)
                  root.putChild(path, schemadoc_resource)

               else:
                  raise ApplicationError("crossbar.error.invalid_configuration", "invalid Web path type '{}'".format(path_config['type']))


         ## create the actual transport factory
         ##
         transport_factory = Site(root)
         transport_factory.noisy = False


         ## Web access logging
         ##
         if not options.get('access_log', False):
            transport_factory.log = lambda _: None

         ## Traceback rendering
         ##
         transport_factory.displayTracebacks = options.get('display_tracebacks', False)

         ## HSTS
         ##
         if options.get('hsts', False):
            if 'tls' in config['endpoint']:
               hsts_max_age = int(options.get('hsts_max_age', 31536000))
               transport_factory.requestFactory = createHSTSRequestFactory(transport_factory.requestFactory, hsts_max_age)
            else:
               log.msg("Warning: HSTS requested, but running on non-TLS - skipping HSTS")

         ## enable Hixie-76 on Twisted Web
         ##
         if options.get('hixie76_aware', False):
            transport_factory.protocol = HTTPChannelHixie76Aware # needed if Hixie76 is to be supported

      else:
         ## should not arrive here, since we did check_transport() in the beginning
         raise Exception("logic error")


      ## create transport endpoint / listening port from transport factory
      ##
      d = create_listening_port_from_config(config['endpoint'], transport_factory, self.config.extra.cbdir, reactor)

      def ok(port):
         self.transports[id] = RouterTransport(id, config, transport_factory, port)
         if self.debug:
            log.msg("Router transport '{}'' started and listening".format(id))
         return

      def fail(err):
         emsg = "ERROR: cannot listen on transport endpoint ({})".format(err.value)
         log.msg(emsg)
         raise ApplicationError("crossbar.error.cannot_listen", emsg)

      d.addCallbacks(ok, fail)
      return d
コード例 #9
0
ファイル: router.py プロジェクト: david-e/crossbar
    def start_router_transport(self, id, config, details=None):
        """
        Start a transport on this router worker.

        :param id: The ID of the transport to start.
        :type id: str
        :param config: The transport configuration.
        :type config: dict
        """
        self.log.debug("{}.start_router_transport".format(self.__class__.__name__),
                       id=id, config=config)

        # prohibit starting a transport twice
        #
        if id in self.transports:
            emsg = "Could not start transport: a transport with ID '{}' is already running (or starting)".format(id)
            self.log.error(emsg)
            raise ApplicationError(u'crossbar.error.already_running', emsg)

        # check configuration
        #
        try:
            checkconfig.check_router_transport(config)
        except Exception as e:
            emsg = "Invalid router transport configuration: {}".format(e)
            self.log.error(emsg)
            raise ApplicationError(u"crossbar.error.invalid_configuration", emsg)
        else:
            self.log.debug("Starting {}-transport on router.".format(config['type']))

        # standalone WAMP-RawSocket transport
        #
        if config['type'] == 'rawsocket':

            transport_factory = WampRawSocketServerFactory(self._router_session_factory, config)
            transport_factory.noisy = False

        # standalone WAMP-WebSocket transport
        #
        elif config['type'] == 'websocket':

            transport_factory = WampWebSocketServerFactory(self._router_session_factory, self.config.extra.cbdir, config, self._templates)
            transport_factory.noisy = False

        # Flash-policy file server pseudo transport
        #
        elif config['type'] == 'flashpolicy':

            transport_factory = FlashPolicyFactory(config.get('allowed_domain', None), config.get('allowed_ports', None))

        # WebSocket testee pseudo transport
        #
        elif config['type'] == 'websocket.testee':

            transport_factory = WebSocketTesteeServerFactory(config, self._templates)

        # Stream testee pseudo transport
        #
        elif config['type'] == 'stream.testee':

            transport_factory = StreamTesteeServerFactory()

        # Twisted Web based transport
        #
        elif config['type'] == 'web':

            transport_factory = self._create_web_factory(config)

        # Universal transport
        #
        elif config['type'] == 'universal':
            if 'web' in config:
                web_factory = self._create_web_factory(config['web'])
            else:
                web_factory = None

            if 'rawsocket' in config:
                rawsocket_factory = WampRawSocketServerFactory(self._router_session_factory, config['rawsocket'])
                rawsocket_factory.noisy = False
            else:
                rawsocket_factory = None

            if 'websocket' in config:
                websocket_factory_map = {}
                for websocket_url_first_component, websocket_config in config['websocket'].items():
                    websocket_transport_factory = WampWebSocketServerFactory(self._router_session_factory, self.config.extra.cbdir, websocket_config, self._templates)
                    websocket_transport_factory.noisy = False
                    websocket_factory_map[websocket_url_first_component] = websocket_transport_factory
                    self.log.debug('hooked up websocket factory on request URI {request_uri}', request_uri=websocket_url_first_component)
            else:
                websocket_factory_map = None

            transport_factory = UniSocketServerFactory(web_factory, websocket_factory_map, rawsocket_factory)

        # Unknown transport type
        #
        else:
            # should not arrive here, since we did check_transport() in the beginning
            raise Exception("logic error")

        # create transport endpoint / listening port from transport factory
        #
        d = create_listening_port_from_config(config['endpoint'],
                                              self.config.extra.cbdir,
                                              transport_factory,
                                              self._reactor,
                                              self.log)

        def ok(port):
            self.transports[id] = RouterTransport(id, config, transport_factory, port)
            self.log.debug("Router transport '{}'' started and listening".format(id))
            return

        def fail(err):
            emsg = "Cannot listen on transport endpoint: {log_failure}"
            self.log.error(emsg, log_failure=err)
            raise ApplicationError(u"crossbar.error.cannot_listen", emsg)

        d.addCallbacks(ok, fail)
        return d
コード例 #10
0
ファイル: router.py プロジェクト: snowattitudes/crossbar
    def start_router_transport(self, id, config, details=None):
        """
        Start a transport on this router and return when the transport has started.

        **Usage:**

        This procedure is registered under

        * ``crossbar.node.<node_id>.worker.<worker_id>.start_router_transport``

        The procedure takes a WAMP transport configuration with a listening endpoint, e.g.

        .. code-block:: javascript

            {
                "type": "websocket",
                "endpoint": {
                    "type": "tcp",
                    "port": 8080
                }
            }

        **Errors:**

        The procedure may raise the following errors:

        * ``crossbar.error.invalid_configuration`` - the provided transport configuration is invalid
        * ``crossbar.error.already_running`` - a transport with the given ID is already running (or starting)
        * ``crossbar.error.cannot_listen`` - could not listen on the configured listening endpoint of the transport
        * ``crossbar.error.class_import_failed`` - a side-by-side component could not be instantiated

        **Events:**

        The procedure will publish an event when the transport **is starting** to

        * ``crossbar.node.<node_id>.worker.<worker_id>.on_router_transport_starting``

        and publish an event when the transport **has started** to

        * ``crossbar.node.<node_id>.worker.<worker_id>.on_router_transport_started``

        :param id: The ID of the transport to start.
        :type id: unicode
        :param config: The transport configuration.
        :type config: dict
        """
        self.log.debug("{}.start_router_transport".format(
            self.__class__.__name__),
                       id=id,
                       config=config)

        # prohibit starting a transport twice
        #
        if id in self.transports:
            emsg = "Could not start transport: a transport with ID '{}' is already running (or starting)".format(
                id)
            self.log.error(emsg)
            raise ApplicationError(u'crossbar.error.already_running', emsg)

        # check configuration
        #
        try:
            checkconfig.check_router_transport(config)
        except Exception as e:
            emsg = "Invalid router transport configuration: {}".format(e)
            self.log.error(emsg)
            raise ApplicationError(u"crossbar.error.invalid_configuration",
                                   emsg)
        else:
            self.log.debug("Starting {}-transport on router.".format(
                config['type']))

        # standalone WAMP-RawSocket transport
        #
        if config['type'] == 'rawsocket':

            transport_factory = WampRawSocketServerFactory(
                self._router_session_factory, config)
            transport_factory.noisy = False

        # standalone WAMP-WebSocket transport
        #
        elif config['type'] == 'websocket':

            transport_factory = WampWebSocketServerFactory(
                self._router_session_factory, self.config.extra.cbdir, config,
                self._templates)
            transport_factory.noisy = False

        # Flash-policy file server pseudo transport
        #
        elif config['type'] == 'flashpolicy':

            transport_factory = FlashPolicyFactory(
                config.get('allowed_domain', None),
                config.get('allowed_ports', None))

        # WebSocket testee pseudo transport
        #
        elif config['type'] == 'websocket.testee':

            transport_factory = WebSocketTesteeServerFactory(
                config, self._templates)

        # Stream testee pseudo transport
        #
        elif config['type'] == 'stream.testee':

            transport_factory = StreamTesteeServerFactory()

        # Twisted Web based transport
        #
        elif config['type'] == 'web':

            options = config.get('options', {})

            # create Twisted Web root resource
            #
            if '/' in config['paths']:
                root_config = config['paths']['/']
                root = self.create_resource(root_config, nested=False)
            else:
                root = Resource404(self._templates, b'')

            # create Twisted Web resources on all non-root paths configured
            #
            self.add_paths(root, config.get('paths', {}))

            # create the actual transport factory
            #
            transport_factory = Site(root)
            transport_factory.noisy = False

            # Web access logging
            #
            if not options.get('access_log', False):
                transport_factory.log = lambda _: None

            # Traceback rendering
            #
            transport_factory.displayTracebacks = options.get(
                'display_tracebacks', False)

            # HSTS
            #
            if options.get('hsts', False):
                if 'tls' in config['endpoint']:
                    hsts_max_age = int(options.get('hsts_max_age', 31536000))
                    transport_factory.requestFactory = createHSTSRequestFactory(
                        transport_factory.requestFactory, hsts_max_age)
                else:
                    self.log.warn(
                        "Warning: HSTS requested, but running on non-TLS - skipping HSTS"
                    )

        # Unknown transport type
        #
        else:
            # should not arrive here, since we did check_transport() in the beginning
            raise Exception("logic error")

        # create transport endpoint / listening port from transport factory
        #
        d = create_listening_port_from_config(config['endpoint'],
                                              transport_factory,
                                              self.config.extra.cbdir,
                                              self._reactor)

        def ok(port):
            self.transports[id] = RouterTransport(id, config,
                                                  transport_factory, port)
            self.log.debug(
                "Router transport '{}'' started and listening".format(id))
            return

        def fail(err):
            emsg = "Cannot listen on transport endpoint: {}".format(err.value)
            self.log.error(emsg)
            raise ApplicationError(u"crossbar.error.cannot_listen", emsg)

        d.addCallbacks(ok, fail)
        return d
コード例 #11
0
    def start_router_transport(self, id, config, details=None):
        """
        Start a transport on this router worker.

        :param id: The ID of the transport to start.
        :type id: str
        :param config: The transport configuration.
        :type config: dict
        """
        self.log.debug("{name}.start_router_transport", name=self.__class__.__name__)

        # prohibit starting a transport twice
        #
        if id in self.transports:
            emsg = "Could not start transport: a transport with ID '{}' is already running (or starting)".format(id)
            self.log.error(emsg)
            raise ApplicationError(u'crossbar.error.already_running', emsg)

        # check configuration
        #
        try:
            checkconfig.check_router_transport(config)
        except Exception as e:
            emsg = "Invalid router transport configuration: {}".format(e)
            self.log.error(emsg)
            raise ApplicationError(u"crossbar.error.invalid_configuration", emsg)
        else:
            self.log.debug("Starting {ttype}-transport on router.", ttype=config['type'])

        # standalone WAMP-RawSocket transport
        #
        if config['type'] == 'rawsocket':

            transport_factory = WampRawSocketServerFactory(self._router_session_factory, config)
            transport_factory.noisy = False

        # standalone WAMP-WebSocket transport
        #
        elif config['type'] == 'websocket':

            transport_factory = WampWebSocketServerFactory(self._router_session_factory, self.config.extra.cbdir, config, self._templates)
            transport_factory.noisy = False

        # Flash-policy file server pseudo transport
        #
        elif config['type'] == 'flashpolicy':

            transport_factory = FlashPolicyFactory(config.get('allowed_domain', None), config.get('allowed_ports', None))

        # WebSocket testee pseudo transport
        #
        elif config['type'] == 'websocket.testee':

            transport_factory = WebSocketTesteeServerFactory(config, self._templates)

        # Stream testee pseudo transport
        #
        elif config['type'] == 'stream.testee':

            transport_factory = StreamTesteeServerFactory()

        # Twisted Web based transport
        #
        elif config['type'] == 'web':

            transport_factory = self._create_web_factory(config)

        # Universal transport
        #
        elif config['type'] == 'universal':
            if 'web' in config:
                web_factory = self._create_web_factory(config['web'])
            else:
                web_factory = None

            if 'rawsocket' in config:
                rawsocket_factory = WampRawSocketServerFactory(self._router_session_factory, config['rawsocket'])
                rawsocket_factory.noisy = False
            else:
                rawsocket_factory = None

            if 'websocket' in config:
                websocket_factory_map = {}
                for websocket_url_first_component, websocket_config in config['websocket'].items():
                    websocket_transport_factory = WampWebSocketServerFactory(self._router_session_factory, self.config.extra.cbdir, websocket_config, self._templates)
                    websocket_transport_factory.noisy = False
                    websocket_factory_map[websocket_url_first_component] = websocket_transport_factory
                    self.log.debug('hooked up websocket factory on request URI {request_uri}', request_uri=websocket_url_first_component)
            else:
                websocket_factory_map = None

            transport_factory = UniSocketServerFactory(web_factory, websocket_factory_map, rawsocket_factory)

        # Unknown transport type
        #
        else:
            # should not arrive here, since we did check_transport() in the beginning
            raise Exception("logic error")

        # create transport endpoint / listening port from transport factory
        #
        d = create_listening_port_from_config(config['endpoint'],
                                              self.config.extra.cbdir,
                                              transport_factory,
                                              self._reactor,
                                              self.log)

        def ok(port):
            self.transports[id] = RouterTransport(id, config, transport_factory, port)
            self.log.debug("Router transport '{id}'' started and listening", id)
            return

        def fail(err):
            emsg = "Cannot listen on transport endpoint: {log_failure}"
            self.log.error(emsg, log_failure=err)
            raise ApplicationError(u"crossbar.error.cannot_listen", emsg)

        d.addCallbacks(ok, fail)
        return d