コード例 #1
0
ファイル: app.py プロジェクト: om26er/crossbar-fabric-shell
 def convert(self, value, param, ctx):
     try:
         parse_url(value)
     except Exception as e:
         self.fail(style_error(str(e)))
     else:
         return value
コード例 #2
0
 def test_parse_url08(self):
     self.assertEqual(
         parse_url("wss://localhost/ws?foo=bar&moo=23&moo=44"),
         (True, 'localhost', 443, '/ws?foo=bar&moo=23&moo=44', '/ws', {
             'moo': ['23', '44'],
             'foo': ['bar']
         }))
コード例 #3
0
        def do_check_for_activation_file(activation_file, reboot_on_discover):
            if os.path.isfile(activation_file):
                tags = _parse_activation_file(activation_file)
                is_secure, hostname, port, _, _, _ = parse_url(tags['management-url'])
                config = {
                    'type': 'websocket',
                    'url': tags['management-url'],
                    'endpoint': {
                        'type': 'tcp',
                        'host': hostname,
                        'port': port,
                        'timeout': 5
                    }
                }
                if is_secure:
                    config['endpoint']['tls'] = {
                        'hostname': hostname
                    }
                _msg = 'Found auto-activation file "{}", using management URL "{}" - [1]'.format(activation_file,
                                                                                                 config['url'])
                log.info(click.style(_msg, fg='red', bold=True))

                if reboot_on_discover and fn_reboot:
                    # stop the node and enforce complete reboot - which will then pick up the new configuration
                    fn_reboot()

                # return the management uplink transport configuration, as derived from the activation file
                return config
コード例 #4
0
ファイル: client.py プロジェクト: prevas-hnje/labgrid
def start_session(url, realm, extra):
    from autobahn.wamp.types import ComponentConfig
    from autobahn.websocket.util import parse_url
    from autobahn.asyncio.websocket import WampWebSocketClientFactory

    loop = asyncio.get_event_loop()
    ready = asyncio.Event()

    @asyncio.coroutine
    def connected(session):
        ready.set()

    if not extra:
        extra = {}
    extra['loop'] = loop
    extra['connected'] = connected

    session = [None]

    def create():
        cfg = ComponentConfig(realm, extra)
        session[0] = ClientSession(cfg)
        return session[0]

    transport_factory = WampWebSocketClientFactory(create, url=url)
    _, host, port, _, _, _ = parse_url(url)

    coro = loop.create_connection(transport_factory, host, port)
    (transport, protocol) = loop.run_until_complete(coro)
    loop.run_until_complete(ready.wait())
    return session[0]
コード例 #5
0
ファイル: wamp.py プロジェクト: aadebuger/autobahn-python
        def setupService(self):
            """
            Setup the application component.
            """
            is_secure, host, port, resource, path, params = parse_url(self.url)

            # factory for use ApplicationSession
            def create():
                cfg = ComponentConfig(self.realm, self.extra)
                session = self.make(cfg)
                return session

            # create a WAMP-over-WebSocket transport client factory
            transport_factory = self.factory(create, url=self.url)

            # setup the client from a Twisted endpoint

            if is_secure:
                from twisted.application.internet import SSLClient
                ctx = self.context_factory
                if ctx is None:
                    from twisted.internet.ssl import optionsForClientTLS
                    ctx = optionsForClientTLS(host)
                client = SSLClient(host, port, transport_factory, contextFactory=ctx)
            else:
                if self.context_factory is not None:
                    raise Exception("context_factory specified on non-secure URI")
                from twisted.application.internet import TCPClient
                client = TCPClient(host, port, transport_factory)

            client.setServiceParent(self)
コード例 #6
0
ファイル: wamp.py プロジェクト: larsx2/autobahn-python
        def setupService(self):
            """
            Setup the application component.
            """
            is_secure, host, port, resource, path, params = parse_url(self.url)

            # factory for use ApplicationSession
            def create():
                cfg = ComponentConfig(self.realm, self.extra)
                session = self.make(cfg)
                return session

            # create a WAMP-over-WebSocket transport client factory
            transport_factory = self.factory(create, url=self.url)

            # setup the client from a Twisted endpoint

            if is_secure:
                from twisted.application.internet import SSLClient
                ctx = self.context_factory
                if ctx is None:
                    from twisted.internet.ssl import optionsForClientTLS
                    ctx = optionsForClientTLS(host)
                client = SSLClient(host,
                                   port,
                                   transport_factory,
                                   contextFactory=ctx)
            else:
                if self.context_factory is not None:
                    raise Exception(
                        "context_factory specified on non-secure URI")
                from twisted.application.internet import TCPClient
                client = TCPClient(host, port, transport_factory)

            client.setServiceParent(self)
コード例 #7
0
ファイル: app.py プロジェクト: mwalercz/yawsd
 def run(self):
     is_secure, host, port, resource, path, params = (parse_url(self.url))
     self.reactor.connectSSL(host=host,
                             port=port,
                             factory=self.factory,
                             contextFactory=self.ssl_context)
     self.reactor.run()
コード例 #8
0
ファイル: __init__.py プロジェクト: dimddev/NetCatKS
    def run(self, make):
        """
        Run the application component.

        :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession`
           when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`.
        :type make: callable
        """

        is_secure, host, port, resource, path, params = parse_url(self.url)

        # start logging to console
        if self.debug or self.debug_wamp or self.debug_app:
            pass
            # log.startLogging(sys.stdout)

        # factory for use ApplicationSession
        def create():
            """
            Will trying to create an ApplicationSession object
            :return: ApplicationSession
            """
            cfg = ComponentConfig(self.realm, self.extra)

            try:
                session = make(config=cfg)

            except Exception as e:

                # the app component could not be created .. fatal
                self.logger.critical('CREATE RUNNER EXCEPTION {}'.format(e.message))

            else:

                session.debug_app = self.debug_app
                return session

        # create a WAMP-over-WebSocket transport client factory
        transport_factory = WampWebSocketClientFactory(
            create,
            url=self.url
        )

        if is_secure:
            endpoint_descriptor = "ssl:{0}:{1}".format(host, port)

        else:
            endpoint_descriptor = "tcp:{0}:{1}".format(host, port)

        try:
            self.logger.info('Trying to connect to: {}'.format(endpoint_descriptor))
            self.connect(endpoint_descriptor, transport_factory, make)

            return self

        except Exception as e:
            self.logger.error('CLIENT CONNECT ERROR: {}'.format(e.message))
コード例 #9
0
ファイル: wamp.py プロジェクト: hpointu/rabbitmq-to-wamp
 async def _try_connect(self):
     isSecure, host, port, resource, path, params = parse_url(self._url)
     transport_factory = MyFactory(self._create,
                                   url=self._url,
                                   serializers=None)
     return await self._loop.create_connection(transport_factory,
                                               host,
                                               port,
                                               ssl=False)
コード例 #10
0
def make_ws_app(c):
    is_secure, host, port, resource, path, params = (parse_url(
        c('conf')['websocket']['url']))
    return c('loop').create_server(
        protocol_factory=c('factory'),
        host=host,
        port=port,
        ssl=c('secure_context'),
    )
コード例 #11
0
ファイル: __init__.py プロジェクト: dimddev/NetCatKS
    def run(self, make):
        """
        Run the application component.

        :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession`
           when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`.
        :type make: callable
        """

        is_secure, host, port, resource, path, params = parse_url(self.url)

        # start logging to console
        if self.debug or self.debug_wamp or self.debug_app:
            pass
            # log.startLogging(sys.stdout)

        # factory for use ApplicationSession
        def create():
            """
            Will trying to create an ApplicationSession object
            :return: ApplicationSession
            """
            cfg = ComponentConfig(self.realm, self.extra)

            try:
                session = make(config=cfg)

            except Exception as e:

                # the app component could not be created .. fatal
                self.logger.critical('CREATE RUNNER EXCEPTION {}'.format(
                    e.message))

            else:

                session.debug_app = self.debug_app
                return session

        # create a WAMP-over-WebSocket transport client factory
        transport_factory = WampWebSocketClientFactory(create, url=self.url)

        if is_secure:
            endpoint_descriptor = "ssl:{0}:{1}".format(host, port)

        else:
            endpoint_descriptor = "tcp:{0}:{1}".format(host, port)

        try:
            self.logger.info(
                'Trying to connect to: {}'.format(endpoint_descriptor))
            self.connect(endpoint_descriptor, transport_factory, make)

            return self

        except Exception as e:
            self.logger.error('CLIENT CONNECT ERROR: {}'.format(e.message))
コード例 #12
0
def create_management_session(url='wss://master.xbr.network/ws',
                              realm='com.crossbario.fabric',
                              privkey_file='default.priv'):

    txaio.start_logging(level='info')

    privkey_file = os.path.join(os.path.expanduser('~/.crossbar'),
                                privkey_file)

    # for authenticating the management client, we need a Ed25519 public/private key pair
    # here, we are reusing the user key - so this needs to exist before
    privkey_hex = None
    user_id = None

    if not os.path.exists(privkey_file):
        raise Exception(
            'private key file {} does not exist'.format(privkey_file))
    else:
        with open(privkey_file, 'r') as f:
            data = f.read()
            for line in data.splitlines():
                if line.startswith('private-key-ed25519'):
                    privkey_hex = line.split(':')[1].strip()
                if line.startswith('user-id'):
                    user_id = line.split(':')[1].strip()

    if privkey_hex is None:
        raise Exception('no private key found in keyfile!')

    if user_id is None:
        raise Exception('no user ID found in keyfile!')

    url_is_secure, _, _, _, _, _ = parse_url(url)

    key = cryptosign.CryptosignKey.from_bytes(binascii.a2b_hex(privkey_hex))
    extra = {
        'key': key,
        'authid': user_id,
        'ready': Deferred(),
        'return_code': None,
        'command': CmdListManagementRealms(),

        # WAMP-cryptosign TLS channel binding
        'channel_binding': 'tls-unique' if url_is_secure else None,
    }

    runner = ApplicationRunner(url=url, realm=realm, extra=extra)
    runner.run(ManagementClientSession, start_reactor=False)

    return extra['ready']
コード例 #13
0
ファイル: autoreconnect.py プロジェクト: bobbyluig/Eclipse
    def __init__(self, url, realm, extra=None, serializers=None,
                 debug=False, debug_wamp=False, debug_app=False,
                 ssl=None, loop=None, retry_strategy=PersistentStrategy()):
        """
        :param url: The WebSocket URL of the WAMP router to connect to (e.g. `ws://somehost.com:8090/somepath`)
        :type url: unicode
        :param realm: The WAMP realm to join the application session to.
        :type realm: unicode
        :param extra: Optional extra configuration to forward to the application component.
        :type extra: dict
        :param serializers: A list of WAMP serializers to use (or None for default serializers).
           Serializers must implement :class:`autobahn.wamp.interfaces.ISerializer`.
        :type serializers: list
        :param debug: Turn on low-level debugging.
        :type debug: bool
        :param debug_wamp: Turn on WAMP-level debugging.
        :type debug_wamp: bool
        :param debug_app: Turn on app-level debugging.
        :type debug_app: bool
        :param ssl: An (optional) SSL context instance or a bool. See
           the documentation for the `loop.create_connection` asyncio
           method, to which this value is passed as the ``ssl=``
           kwarg.
        :type ssl: :class:`ssl.SSLContext` or bool
        """
        self.url = url
        self.realm = realm
        self.extra = extra or dict()
        self.debug = debug
        self.debug_wamp = debug_wamp
        self.debug_app = debug_app
        self.serializers = serializers
        self.loop = loop or asyncio.get_event_loop()
        self.retry_strategy = retry_strategy
        self.closing = False
        self.transport_factory = None
        self.active_protocol = None

        self.isSecure, self.host, self.port, _, _, _ = parse_url(url)

        if ssl is None:
            self.ssl = self.isSecure
        else:
            if ssl and not self.isSecure:
                raise RuntimeError(
                    'ssl argument value passed to %s conflicts with the "ws:" '
                    'prefix of the url argument. Did you mean to use "wss:"?' %
                    self.__class__.__name__)
            self.ssl = ssl
コード例 #14
0
def wamp_configured(cls):
   "get host, port & ssl from wmp_url"

   (isSecureURL, host, port, resource, path, params) = parse_url(cls.wmp_url)

   cls._host = host
   cls._port = port

   if not getattr(cls, "wmp_ssl", None):
      cls._ssl = isSecureURL
   elif cls.wmp_ssl and not isSecureURL:
      raise RuntimeError(
         'the wmp_ssl class variable of %s conflicts with the "ws:" prefix '
         'of the wmp_url variable. Did you mean to use "wss:"?' % cls.__name__)
   else:
      cls._ssl = cls.wmp_ssl

   return cls
コード例 #15
0
    def run(self, make):
        # 1) factory for use ApplicationSession
        def create():
            cfg = ComponentConfig(self.realm, self.extra)
            try:
                session = make(cfg)
            except Exception as e:
                # the app component could not be created .. fatal
                print(e)
                asyncio.get_event_loop().stop()
            else:
                session.debug_app = self.debug_app
                return session

        isSecure, host, port, resource, path, params = parse_url(self.url)

        if self.ssl is None:
            ssl = isSecure
        else:
            if self.ssl and not isSecure:
                raise RuntimeError(
                    'ssl argument value passed to %s conflicts with the "ws:" '
                    'prefix of the url argument. Did you mean to use "wss:"?' %
                    self.__class__.__name__)
            ssl = self.ssl

        # 2) create a WAMP-over-WebSocket transport client factory
        transport_factory = WampWebSocketClientFactory(create, url=self.url, serializers=self.serializers)
        # transport_factory.setProtocolOptions(failByDrop=False, openHandshakeTimeout=90, closeHandshakeTimeout=5)

        # 3) start the client
        loop = asyncio.get_event_loop()
        txaio.use_asyncio()
        txaio.config.loop = loop
        coro = loop.create_connection(transport_factory, host, port, ssl=ssl)
        (transport, protocol) = loop.run_until_complete(coro)

        try:
            loop.add_signal_handler(signal.SIGTERM, loop.stop)
        except NotImplementedError:
            # signals are not available on Windows
            pass
コード例 #16
0
def _normalize_transport(transport, check_native_endpoint=None):
    """
    Check a WAMP connecting transport configuration, and add any
    defaults that we can. These are:

    - type: websocket
    - endpoint: if not specified, fill in from URL
    """
    if type(transport) != dict:
        raise RuntimeError(
            'invalid type {} for transport configuration - must be a dict'.
            format(type(transport)))

    if 'type' not in transport:
        transport['type'] = 'websocket'

    if transport['type'] not in ['websocket', 'rawsocket']:
        raise RuntimeError('invalid transport type {}'.format(
            transport['type']))

    if transport['type'] == 'websocket':
        if 'url' not in transport:
            raise ValueError("Missing 'url' in transport")
        if 'endpoint' not in transport:
            is_secure, host, port, resource, path, params = parse_url(
                transport['url'])
            transport['endpoint'] = {
                'type': 'tcp',
                'host': host,
                'port': port,
                'tls': False if not is_secure else dict(hostname=host),
            }
        _normalize_endpoint(transport['endpoint'], check_native_endpoint)
        # XXX can/should we check e.g. serializers here?

    elif transport['type'] == 'rawsocket':
        if 'endpoint' not in transport:
            raise ValueError("Missing 'endpoint' in transport")

    else:
        assert False, 'should not arrive here'
コード例 #17
0
def _normalize_transport(transport, check_native_endpoint=None):
    """
    Check a WAMP connecting transport configuration, and add any
    defaults that we can. These are:

    - type: websocket
    - endpoint: if not specified, fill in from URL
    """
    if type(transport) != dict:
        raise RuntimeError('invalid type {} for transport configuration - must be a dict'.format(type(transport)))

    if 'type' not in transport:
        transport['type'] = 'websocket'

    if transport['type'] not in ['websocket', 'rawsocket']:
        raise RuntimeError('invalid transport type {}'.format(transport['type']))

    if transport['type'] == 'websocket':
        if 'url' not in transport:
            raise ValueError("Missing 'url' in transport")
        if 'endpoint' not in transport:
            is_secure, host, port, resource, path, params = parse_url(transport['url'])
            transport['endpoint'] = {
                'type': 'tcp',
                'host': host,
                'port': port,
                'tls': False if not is_secure else dict(hostname=host),
            }
        _normalize_endpoint(transport['endpoint'], check_native_endpoint)
        # XXX can/should we check e.g. serializers here?

    elif transport['type'] == 'rawsocket':
        if 'endpoint' not in transport:
            raise ValueError("Missing 'endpoint' in transport")

    else:
        assert False, 'should not arrive here'
コード例 #18
0
ファイル: component.py プロジェクト: Jenselme/AutobahnPython
def _normalize_transport(transport, check_native_endpoint=None):
    """
    Check a WAMP connecting transport configuration, and add any
    defaults that we can. These are:

    - type: websocket
    - endpoint: if not specified, fill in from URL
    """
    if type(transport) != dict:
        raise RuntimeError("invalid type {} for transport configuration - must be a dict".format(type(transport)))

    if "type" not in transport:
        transport["type"] = "websocket"

    if transport["type"] not in ["websocket", "rawsocket"]:
        raise RuntimeError("invalid transport type {}".format(transport["type"]))

    if transport["type"] == "websocket":
        if "url" not in transport:
            raise ValueError("Missing 'url' in transport")
        if "endpoint" not in transport:
            is_secure, host, port, resource, path, params = parse_url(transport["url"])
            transport["endpoint"] = {
                "type": "tcp",
                "host": host,
                "port": port,
                "tls": False if not is_secure else dict(hostname=host),
            }
        _normalize_endpoint(transport["endpoint"], check_native_endpoint)
        # XXX can/should we check e.g. serializers here?

    elif transport["type"] == "rawsocket":
        if "endpoint" not in transport:
            raise ValueError("Missing 'endpoint' in transport")

    else:
        assert False, "should not arrive here"
コード例 #19
0
    def _start(self):
        if self.session:
            return

        import asyncio
        import txaio
        txaio.use_asyncio()
        txaio.config.loop = self.loop = asyncio.get_event_loop()

        from autobahn.wamp import protocol
        from autobahn.wamp.types import ComponentConfig
        from autobahn.websocket.util import parse_url
        from autobahn.asyncio.websocket import WampWebSocketClientFactory

        from ..remote.client import ClientSession

        @asyncio.coroutine
        def _connected(session):
            self.ready.set()

        def create():
            cfg = ComponentConfig(self.realm, {
                'loop': self.loop,
                'func': _connected,
            })
            self.session = ClientSession(cfg)
            return self.session

        transport_factory = WampWebSocketClientFactory(create, url=self.url)
        _, host, port, _, _, _ = parse_url(self.url)

        self.ready = asyncio.Event()
        coro = self.loop.create_connection(transport_factory, host, port)
        (transport, protocol) = self.loop.run_until_complete(coro)
        print(transport, protocol)
        self.loop.run_until_complete(self.ready.wait())
コード例 #20
0
ファイル: component.py プロジェクト: Alf-11/autobahn-python
    def __init__(self, main=None, setup=None, transports=None, config=None):
        """

        :param main: A callable that runs user code for the component. The component will be
            started with a "main-like" procedure. When a transport has been connected and
            a session has been established and joined a realm, the user code will be run until it finishes
            which signals that the component has run to completion.
        :type main: callable
        :param setup: A callable that runs user code for the component. The component will be
            started with a "setup-like" procedure. When a transport has been connected and
            a session has been established and joined a realm, the user code will be run until it finishes
            which signals that the component is now "ready". The component will continue to run until
            it explicitly closes the session or the underlying transport closes.
        :type setup: callable
        :param transports: Transport configurations for creating transports.
        :type transports: None or unicode or list
        :param config: Session configuration.
        :type config: None or dict
        """
        ObservableMixin.__init__(self)

        if main is None and setup is None:
            raise RuntimeError('either a "main" or "setup" procedure must be provided for a component')

        if main is not None and setup is not None:
            raise RuntimeError('either a "main" or "setup" procedure must be provided for a component (not both)')

        if main is not None and not callable(main):
            raise RuntimeError('"main" must be a callable if given')

        if setup is not None and not callable(setup):
            raise RuntimeError('"setup" must be a callable if given')

        if setup:
            self._entry = setup
            self._entry_type = Component.TYPE_SETUP
        elif main:
            self._entry = main
            self._entry_type = Component.TYPE_MAIN
        else:
            assert(False), 'logic error'

        # use WAMP-over-WebSocket to localhost when no transport is specified at all
        if transports is None:
            transports = u'ws://127.0.0.1:8080/ws'

        # allows to provide an URL instead of a list of transports
        if type(transports) == six.text_type:
            url = transports
            is_secure, host, port, resource, path, params = parse_url(url)
            transport = {
                'type': 'websocket',
                'url': url,
                'endpoint': {
                    'type': 'tcp',
                    'host': host,
                    'port': port
                }
            }
            if is_secure:
                # FIXME
                transport['endpoint']['tls'] = {}
            transports = [transport]

        # now check and save list of transports
        self._transports = []
        idx = 0
        for transport in transports:
            check_transport(transport)
            self._transports.append(Transport(idx, transport))
            idx += 1

        self._realm = u'realm1'
        self._extra = None
コード例 #21
0
def _create_transport(index, transport, check_native_endpoint=None):
    """
    Internal helper to insert defaults and create _Transport instances.

    :param transport: a (possibly valid) transport configuration
    :type transport: dict

    :returns: a _Transport instance

    :raises: ValueError on invalid configuration
    """
    if type(transport) != dict:
        raise ValueError('invalid type {} for transport configuration - must be a dict'.format(type(transport)))

    valid_transport_keys = [
        'type', 'url', 'endpoint', 'serializer', 'serializers', 'options',
        'max_retries', 'max_retry_delay', 'initial_retry_delay',
        'retry_delay_growth', 'retry_delay_jitter',
    ]
    for k in transport.keys():
        if k not in valid_transport_keys:
            raise ValueError(
                "'{}' is not a valid configuration item".format(k)
            )

    kind = 'websocket'
    if 'type' in transport:
        if transport['type'] not in ['websocket', 'rawsocket']:
            raise ValueError('Invalid transport type {}'.format(transport['type']))
        kind = transport['type']
    else:
        transport['type'] = 'websocket'

    options = dict()
    if 'options' in transport:
        options = transport['options']
        if not isinstance(options, dict):
            raise ValueError(
                'options must be a dict, not {}'.format(type(options))
            )

    if kind == 'websocket':
        for key in ['url']:
            if key not in transport:
                raise ValueError("Transport requires '{}' key".format(key))
        # endpoint not required; we will deduce from URL if it's not provided
        # XXX not in the branch I rebased; can this go away? (is it redundant??)
        if 'endpoint' not in transport:
            is_secure, host, port, resource, path, params = parse_url(transport['url'])
            endpoint_config = {
                'type': 'tcp',
                'host': host,
                'port': port,
                'tls': is_secure,
            }
        else:
            # note: we're avoiding mutating the incoming "configuration"
            # dict, so this should avoid that too...
            endpoint_config = transport['endpoint']
            _validate_endpoint(endpoint_config, check_native_endpoint)

        if 'serializer' in transport:
            raise ValueError("'serializer' is only for rawsocket; use 'serializers'")
        if 'serializers' in transport:
            if not isinstance(transport['serializers'], (list, tuple)):
                raise ValueError("'serializers' must be a list of strings")
            if not all([
                    isinstance(s, (six.text_type, str))
                    for s in transport['serializers']]):
                raise ValueError("'serializers' must be a list of strings")
            valid_serializers = ('msgpack', 'json')
            for serial in transport['serializers']:
                if serial not in valid_serializers:
                    raise ValueError(
                        "Invalid serializer '{}' (expected one of: {})".format(
                            serial,
                            ', '.join([repr(s) for s in valid_serializers]),
                        )
                    )
        serializer_config = transport.get('serializers', [u'msgpack', u'json'])

    elif kind == 'rawsocket':
        if 'endpoint' not in transport:
            raise ValueError("Missing 'endpoint' in transport")
        endpoint_config = transport['endpoint']
        if 'serializers' in transport:
            raise ValueError("'serializers' is only for websocket; use 'serializer'")
        # always a list; len == 1 for rawsocket
        if 'serializer' in transport:
            if not isinstance(transport['serializer'], (six.text_type, str)):
                raise ValueError("'serializer' must be a string")
            serializer_config = [transport['serializer']]
        else:
            serializer_config = [u'msgpack']

    else:
        assert False, 'should not arrive here'

    kw = {}
    for key in ['max_retries', 'max_retry_delay', 'initial_retry_delay',
                'retry_delay_growth', 'retry_delay_jitter']:
        if key in transport:
            kw[key] = transport[key]

    return _Transport(
        index,
        kind=kind,
        url=transport['url'],
        endpoint=endpoint_config,
        serializers=serializer_config,
        options=options,
        **kw
    )
コード例 #22
0
ファイル: component.py プロジェクト: Hrabal/autobahn-python
def _create_transport(index, transport, check_native_endpoint=None):
    """
    Internal helper to insert defaults and create _Transport instances.

    :param transport: a (possibly valid) transport configuration
    :type transport: dict

    :returns: a _Transport instance

    :raises: ValueError on invalid configuration
    """
    if type(transport) != dict:
        raise ValueError('invalid type {} for transport configuration - must be a dict'.format(type(transport)))

    valid_transport_keys = [
        'type', 'url', 'endpoint', 'serializer', 'serializers', 'options',
        'max_retries', 'max_retry_delay', 'initial_retry_delay',
        'retry_delay_growth', 'retry_delay_jitter',
    ]
    for k in transport.keys():
        if k not in valid_transport_keys:
            raise ValueError(
                "'{}' is not a valid configuration item".format(k)
            )

    kind = 'websocket'
    if 'type' in transport:
        if transport['type'] not in ['websocket', 'rawsocket']:
            raise ValueError('Invalid transport type {}'.format(transport['type']))
        kind = transport['type']
    else:
        transport['type'] = 'websocket'

    options = dict()
    if 'options' in transport:
        options = transport['options']
        if not isinstance(options, dict):
            raise ValueError(
                'options must be a dict, not {}'.format(type(options))
            )

    if kind == 'websocket':
        for key in ['url']:
            if key not in transport:
                raise ValueError("Transport requires '{}' key".format(key))
        # endpoint not required; we will deduce from URL if it's not provided
        # XXX not in the branch I rebased; can this go away? (is it redundant??)
        if 'endpoint' not in transport:
            is_secure, host, port, resource, path, params = parse_url(transport['url'])
            endpoint_config = {
                'type': 'tcp',
                'host': host,
                'port': port,
                'tls': is_secure,
            }
        else:
            # note: we're avoiding mutating the incoming "configuration"
            # dict, so this should avoid that too...
            endpoint_config = transport['endpoint']
            _validate_endpoint(endpoint_config, check_native_endpoint)

        if 'serializer' in transport:
            raise ValueError("'serializer' is only for rawsocket; use 'serializers'")
        if 'serializers' in transport:
            if not isinstance(transport['serializers'], (list, tuple)):
                raise ValueError("'serializers' must be a list of strings")
            if not all([
                    isinstance(s, (six.text_type, str))
                    for s in transport['serializers']]):
                raise ValueError("'serializers' must be a list of strings")
            valid_serializers = ('msgpack', 'json')
            for serial in transport['serializers']:
                if serial not in valid_serializers:
                    raise ValueError(
                        "Invalid serializer '{}' (expected one of: {})".format(
                            serial,
                            ', '.join([repr(s) for s in valid_serializers]),
                        )
                    )
        serializer_config = transport.get('serializers', [u'msgpack', u'json'])

    elif kind == 'rawsocket':
        if 'endpoint' not in transport:
            raise ValueError("Missing 'endpoint' in transport")
        endpoint_config = transport['endpoint']
        if 'serializers' in transport:
            raise ValueError("'serializers' is only for websocket; use 'serializer'")
        # always a list; len == 1 for rawsocket
        if 'serializer' in transport:
            if not isinstance(transport['serializer'], (six.text_type, str)):
                raise ValueError("'serializer' must be a string")
            serializer_config = [transport['serializer']]
        else:
            serializer_config = [u'msgpack']

    else:
        assert False, 'should not arrive here'

    kw = {}
    for key in ['max_retries', 'max_retry_delay', 'initial_retry_delay',
                'retry_delay_growth', 'retry_delay_jitter']:
        if key in transport:
            kw[key] = transport[key]

    return _Transport(
        index,
        kind=kind,
        url=transport['url'],
        endpoint=endpoint_config,
        serializers=serializer_config,
        options=options,
        **kw
    )
コード例 #23
0
        def resetDelay(self):
            ReconnectingClientFactory.resetDelay(self)
            self.failed_counter = 0

    # create a WAMP application session factory
    component_config = types.ComponentConfig(realm=CROSSBAR_REALM)
    client = MyComponent(component_config)

    # Hack to have only one Client inst. and no client_factory
    def _get_session():
        return client

    # You can set a custom URL by setting the env. variable WAMP_URL.
    # e.g. WAMP_URL=ws://localhost:8091 python main.py
    transport_factory = MyClientFactory(_get_session, url=WAMP_URL)
    transport_factory.setProtocolOptions(autoPingInterval=10, autoPingTimeout=60)

    # Setup proper logging from Autobahn
    import txaio
    txaio.use_twisted()
    txaio.config.loop = reactor
    # txaio.start_logging(level='debug')

    # start the client from a Twisted endpoint
    isSecure, host, port, resource, path, params = parse_url(WAMP_URL)
    transport_factory.host = host
    transport_factory.port = port
    WAMP_connector = websocket.connectWS(transport_factory, timeout=5)

    reactor.run()
コード例 #24
0
    def __init__(self, main=None, setup=None, transports=None, config=None):
        """

        :param main: A callable that runs user code for the component. The component will be
            started with a "main-like" procedure. When a transport has been connected and
            a session has been established and joined a realm, the user code will be run until it finishes
            which signals that the component has run to completion.
        :type main: callable
        :param setup: A callable that runs user code for the component. The component will be
            started with a "setup-like" procedure. When a transport has been connected and
            a session has been established and joined a realm, the user code will be run until it finishes
            which signals that the component is now "ready". The component will continue to run until
            it explicitly closes the session or the underlying transport closes.
        :type setup: callable
        :param transports: Transport configurations for creating transports.
        :type transports: None or unicode or list
        :param config: Session configuration.
        :type config: None or dict
        """
        ObservableMixin.__init__(self)

        if main is None and setup is None:
            raise RuntimeError(
                'either a "main" or "setup" procedure must be provided for a component'
            )

        if main is not None and setup is not None:
            raise RuntimeError(
                'either a "main" or "setup" procedure must be provided for a component (not both)'
            )

        if main is not None and not callable(main):
            raise RuntimeError('"main" must be a callable if given')

        if setup is not None and not callable(setup):
            raise RuntimeError('"setup" must be a callable if given')

        if setup:
            self._entry = setup
            self._entry_type = Component.TYPE_SETUP
        elif main:
            self._entry = main
            self._entry_type = Component.TYPE_MAIN
        else:
            assert (False), 'logic error'

        # use WAMP-over-WebSocket to localhost when no transport is specified at all
        if transports is None:
            transports = u'ws://127.0.0.1:8080/ws'

        # allows to provide an URL instead of a list of transports
        if type(transports) == six.text_type:
            url = transports
            is_secure, host, port, resource, path, params = parse_url(url)
            transport = {
                'type': 'websocket',
                'url': url,
                'endpoint': {
                    'type': 'tcp',
                    'host': host,
                    'port': port
                }
            }
            if is_secure:
                # FIXME
                transport['endpoint']['tls'] = {}
            transports = [transport]

        # now check and save list of transports
        self._transports = []
        idx = 0
        for transport in transports:
            check_transport(transport)
            self._transports.append(Transport(idx, transport))
            idx += 1

        self._realm = u'realm1'
        self._extra = None
コード例 #25
0
 def test_parse_url02(self):
     self.assertEqual(parse_url("ws://localhost:80"), (False, 'localhost', 80, '/', '/', {}))
コード例 #26
0
 def test_parse_url05(self):
     self.assertEqual(parse_url("wss://localhost/ws"), (True, 'localhost', 443, '/ws', '/ws', {}))
コード例 #27
0
ファイル: wamp.py プロジェクト: sashantp/autobahn-python
    def run(self, make):
        """
        Run the application component.

        :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession`
           when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`.
        :type make: callable
        """

        # 1) factory for use ApplicationSession
        def create():
            cfg = ComponentConfig(self.realm, self.extra)
            try:
                session = make(cfg)
            except Exception as e:
                self.log.error(
                    'ApplicationSession could not be instantiated: {}'.format(
                        e))
                loop = asyncio.get_event_loop()
                if loop.is_running():
                    loop.stop()
                raise
            else:
                return session

        isSecure, host, port, resource, path, params = parse_url(self.url)

        if self.ssl is None:
            ssl = isSecure
        else:
            if self.ssl and not isSecure:
                raise RuntimeError(
                    'ssl argument value passed to %s conflicts with the "ws:" '
                    'prefix of the url argument. Did you mean to use "wss:"?' %
                    self.__class__.__name__)
            ssl = self.ssl

        # 2) create a WAMP-over-WebSocket transport client factory
        transport_factory = WampWebSocketClientFactory(
            create, url=self.url, serializers=self.serializers)

        # 3) start the client
        loop = asyncio.get_event_loop()
        txaio.use_asyncio()
        txaio.config.loop = loop
        coro = loop.create_connection(transport_factory, host, port, ssl=ssl)
        (transport, protocol) = loop.run_until_complete(coro)

        # start logging
        txaio.start_logging(level='info')

        try:
            loop.add_signal_handler(signal.SIGTERM, loop.stop)
        except NotImplementedError:
            # signals are not available on Windows
            pass

        # 4) now enter the asyncio event loop
        try:
            loop.run_forever()
        except KeyboardInterrupt:
            # wait until we send Goodbye if user hit ctrl-c
            # (done outside this except so SIGTERM gets the same handling)
            pass

        # give Goodbye message a chance to go through, if we still
        # have an active session
        if protocol._session:
            loop.run_until_complete(protocol._session.leave())

        loop.close()
コード例 #28
0
    def run_context(self, ctx, command=None):

        # cfg contains the command lines options and arguments that
        # click collected for us
        cfg = ctx.obj
        cmd = ctx.command.name

        self.log.info('{klass}.run_context: running shell command "{cmd}"',
                      klass=self.__class__.__name__,
                      cmd=cmd)

        yes_to_all = cfg.yes_to_all if hasattr(cfg, 'yes_to_all') else False

        # if cmd not in ['auth', 'shell']:
        #    raise click.ClickException('"{}" command can only be run in shell'.format(cmd))

        if self._output_verbosity == Application.OUTPUT_VERBOSITY_VERBOSE:
            click.echo('Crossbar.io Shell: {}'.format(
                style_ok('v{}'.format(__version__))))

        # load user profile and key for given profile name
        key, profile = self.load_profile(dotdir=cfg.dotdir,
                                         profile=cfg.profile,
                                         yes_to_all=yes_to_all,
                                         verbose=(ctx.command.name == 'init'))

        if ctx.command.name == 'init':
            return

        # set the Fabric URL to connect to from the profile or default
        url = profile.url or 'wss://fabric.crossbario.com'

        # users always authenticate with the user_id from the key, which
        # filled from the email the user provided
        authid = key.user_id

        # the realm can be set from command line, env var, the profile
        # or can be None, which means the user will be joined to the global
        # Crossbar.io users realm ('com.crossbario.fabric')
        realm = cfg.realm or profile.realm or None

        # the authrole can be set from command line, env var, the profile
        # or can be None, in which case the role is chosen automatically
        # from the list of roles the user us authorized for
        authrole = cfg.role or profile.role or None

        # this will be fired when the ShellClient below actually has joined
        # the respective realm on Crossbar.io (either the global users
        # realm, or a management realm the user has a role on)
        done = txaio.create_future()

        url_is_secure, _, _, _, _, _ = parse_url(url)

        extra = {
            # these are forward on the actual client connection
            'authid': authid,
            'authrole': authrole,

            # these are native Python object and only used client-side
            'key': key.key,
            'done': done,
            'command': command,

            # WAMP-cryptosign authentication: TLS channel binding
            'channel_binding': 'tls-unique' if url_is_secure else None,
        }

        cert_options = None
        if profile.tls_hostname:
            self.log.info(
                'Setting up TLS context (server CA/intermediate certificates, etc) from profile:'
            )
            tls_config = {
                'hostname': profile.tls_hostname,
                'ca_certificates': profile.tls_certificates
            }
            cert_options = _create_tls_client_context(tls_config, '.crossbar',
                                                      self.log)

        # for the "auth" command, forward additional command line options
        if ctx.command.name == 'auth':
            # user provides authentication code to verify
            extra['activation_code'] = cfg.code

            # user requests sending of a new authentication code (while an old one is still pending)
            extra['request_new_activation_code'] = cfg.new_code

        # this is the WAMP ApplicationSession that connects the CLI to Crossbar.io
        self.session = client.ShellClient(ComponentConfig(realm, extra))

        runner = ApplicationRunner(url, realm, ssl=cert_options)

        if self._output_verbosity == Application.OUTPUT_VERBOSITY_VERBOSE:
            click.echo('Connecting to {} ..'.format(url))

        connect_done = runner.run(self.session, start_reactor=False)

        def on_connect_success(res):
            self.log.info('{klass}.on_connect_success(res={res})',
                          klass=self.__class__.__name__,
                          res=pformat(res))

        def on_connect_error(err):
            self.log.warn('{klass}.on_connect_error(err={err})',
                          klass=self.__class__.__name__,
                          err=err)

            if isinstance(err, Failure):
                err = err.value

            txaio.reject(done, err)

            # raise SystemExit(1)

        txaio.add_callbacks(connect_done, on_connect_success, on_connect_error)

        def on_success(res):
            self.log.info('{klass}.on_success(res={res})',
                          klass=self.__class__.__name__,
                          res=pformat(res))

            session_details, result = res

            if cmd == 'auth':

                self._print_welcome(url, session_details)

            elif cmd == 'shell':

                # click.clear()
                self._print_welcome(url, session_details)

                # FIXME:

                # prompt_kwargs = {
                #     'history': self._history,
                # }
                #
                # from crossbar.shell import repl
                #
                # shell_task = loop.create_task(
                #     repl.repl(
                #         ctx,
                #         get_bottom_toolbar_tokens=self._get_bottom_toolbar_tokens,
                #         # get_prompt_tokens=self._get_prompt_tokens,
                #         style=self._style,
                #         prompt_kwargs=prompt_kwargs))
                #
                # try:
                #     loop.run_until_complete(shell_task)
                # except Exception as e:
                #     print(e)

            else:
                if result:
                    self._output_result(result)

        def on_error(err):
            self.log.warn('{klass}.on_error(err={err})',
                          klass=self.__class__.__name__,
                          err=err)

            if isinstance(err, Failure):
                err = err.value

            if isinstance(err, ApplicationError):

                self.log.warn('{message} - {error}',
                              message=err.args[0] if err.args else '',
                              error=err.error)

                # some ApplicationErrors are actually signaling progress
                # in the authentication flow, some are real errors

                exit_code = None

                if err.error.startswith('fabric.auth-failed.'):
                    error = err.error.split('.')[2]
                    message = err.args[0]

                    if error == 'new-user-auth-code-sent':

                        click.echo(
                            '\nThanks for registering! {}'.format(message))
                        click.echo(
                            style_ok(
                                'Please check your inbox and run "crossbar shell auth --code <THE CODE YOU GOT BY EMAIL>.\n'
                            ))

                    elif error == 'registered-user-auth-code-sent':

                        click.echo('\nWelcome back! {}'.format(message))
                        click.echo(
                            style_ok(
                                'Please check your inbox and run "crossbar shell auth --code <THE CODE YOU GOT BY EMAIL>.\n'
                            ))

                    elif error == 'pending-activation':

                        click.echo()
                        click.echo(style_ok(message))
                        click.echo()
                        click.echo(
                            'Tip: to activate, run "crossbar shell auth --code <THE CODE YOU GOT BY EMAIL>"'
                        )
                        click.echo(
                            'Tip: you can request sending a new code with "crossbar shell auth --new-code"'
                        )
                        click.echo()

                    elif error == 'no-pending-activation':

                        exit_code = 1
                        click.echo()
                        click.echo(
                            style_error('{} [{}]'.format(message, err.error)))
                        click.echo()

                    elif error == 'email-failure':

                        exit_code = 1
                        click.echo()
                        click.echo(
                            style_error('{} [{}]'.format(message, err.error)))
                        click.echo()

                    elif error == 'invalid-activation-code':

                        exit_code = 1
                        click.echo()
                        click.echo(
                            style_error('{} [{}]'.format(message, err.error)))
                        click.echo()

                    else:

                        exit_code = 1
                        click.echo(style_error('{}'.format(error)))
                        click.echo(style_error(message))

                elif err.error.startswith('crossbar.error.'):

                    error = err.error.split('.')[2]
                    message = err.args[0]

                    if error == 'invalid_configuration':

                        click.echo()
                        click.echo(
                            style_error('{} [{}]'.format(message, err.error)))
                        click.echo()
                    else:

                        exit_code = 1
                        click.echo(
                            style_error('{} [{}]'.format(message, err.error)))

                else:

                    click.echo(style_error('{}'.format(err)))
                    exit_code = 1

                if exit_code:
                    raise SystemExit(exit_code)

            else:
                click.echo(style_error('{}'.format(err)))
                raise SystemExit(1)

        txaio.add_callbacks(done, on_success, on_error)

        def doit(reactor):
            return done

        react(doit)
コード例 #29
0
 def reset_url(self):
     websocket_uri, url, port = self.link.get_url()
     self.url = websocket_uri
     (self.isSecure, self.host, self.port, self.resource, self.path, self.params) = parse_url(websocket_uri)
コード例 #30
0
ファイル: wamp.py プロジェクト: larsx2/autobahn-python
    def run(self, make, start_reactor=True):
        """
        Run the application component.

        :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession`
           when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`.
        :type make: callable

        :param start_reactor: if True (the default) this method starts
           the Twisted reactor and doesn't return until the reactor
           stops. If there are any problems starting the reactor or
           connect()-ing, we stop the reactor and raise the exception
           back to the caller.

        :returns: None is returned, unless you specify
            ``start_reactor=False`` in which case the Deferred that
            connect() returns is returned; this will callback() with
            an IProtocol instance, which will actually be an instance
            of :class:`WampWebSocketClientProtocol`
        """
        if start_reactor:
            # only select framework, set loop and start logging when we are asked
            # start the reactor - otherwise we are running in a program that likely
            # already tool care of all this.
            from twisted.internet import reactor
            txaio.use_twisted()
            txaio.config.loop = reactor
            txaio.start_logging(level='info')

        isSecure, host, port, resource, path, params = parse_url(self.url)

        # factory for use ApplicationSession
        def create():
            cfg = ComponentConfig(self.realm, self.extra)
            try:
                session = make(cfg)
            except Exception as e:
                if start_reactor:
                    # the app component could not be created .. fatal
                    self.log.error(str(e))
                    reactor.stop()
                else:
                    # if we didn't start the reactor, it's up to the
                    # caller to deal with errors
                    raise
            else:
                return session

        # create a WAMP-over-WebSocket transport client factory
        transport_factory = WampWebSocketClientFactory(
            create,
            url=self.url,
            serializers=self.serializers,
            proxy=self.proxy)

        # supress pointless log noise like
        # "Starting factory <autobahn.twisted.websocket.WampWebSocketClientFactory object at 0x2b737b480e10>""
        transport_factory.noisy = False

        # if user passed ssl= but isn't using isSecure, we'll never
        # use the ssl argument which makes no sense.
        context_factory = None
        if self.ssl is not None:
            if not isSecure:
                raise RuntimeError(
                    'ssl= argument value passed to %s conflicts with the "ws:" '
                    'prefix of the url argument. Did you mean to use "wss:"?' %
                    self.__class__.__name__)
            context_factory = self.ssl
        elif isSecure:
            from twisted.internet.ssl import optionsForClientTLS
            context_factory = optionsForClientTLS(host)

        from twisted.internet import reactor
        if self.proxy is not None:
            from twisted.internet.endpoints import TCP4ClientEndpoint
            client = TCP4ClientEndpoint(reactor, self.proxy['host'],
                                        self.proxy['port'])
            transport_factory.contextFactory = context_factory
        elif isSecure:
            from twisted.internet.endpoints import SSL4ClientEndpoint
            assert context_factory is not None
            client = SSL4ClientEndpoint(reactor, host, port, context_factory)
        else:
            from twisted.internet.endpoints import TCP4ClientEndpoint
            client = TCP4ClientEndpoint(reactor, host, port)

        d = client.connect(transport_factory)

        # as the reactor shuts down, we wish to wait until we've sent
        # out our "Goodbye" message; leave() returns a Deferred that
        # fires when the transport gets to STATE_CLOSED
        def cleanup(proto):
            if hasattr(proto, '_session') and proto._session is not None:
                if proto._session.is_attached():
                    return proto._session.leave()
                elif proto._session.is_connected():
                    return proto._session.disconnect()

        # when our proto was created and connected, make sure it's cleaned
        # up properly later on when the reactor shuts down for whatever reason
        def init_proto(proto):
            reactor.addSystemEventTrigger('before', 'shutdown', cleanup, proto)
            return proto

        # if we connect successfully, the arg is a WampWebSocketClientProtocol
        d.addCallback(init_proto)

        # if the user didn't ask us to start the reactor, then they
        # get to deal with any connect errors themselves.
        if start_reactor:
            # if an error happens in the connect(), we save the underlying
            # exception so that after the event-loop exits we can re-raise
            # it to the caller.

            class ErrorCollector(object):
                exception = None

                def __call__(self, failure):
                    self.exception = failure.value
                    reactor.stop()

            connect_error = ErrorCollector()
            d.addErrback(connect_error)

            # now enter the Twisted reactor loop
            reactor.run()

            # if we exited due to a connection error, raise that to the
            # caller
            if connect_error.exception:
                raise connect_error.exception

        else:
            # let the caller handle any errors
            return d
コード例 #31
0
ファイル: wamp.py プロジェクト: aadebuger/autobahn-python
    def run(self, make, start_reactor=True):
        """
        Run the application component.

        :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession`
           when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`.
        :type make: callable

        :param start_reactor: if True (the default) this method starts
           the Twisted reactor and doesn't return until the reactor
           stops. If there are any problems starting the reactor or
           connect()-ing, we stop the reactor and raise the exception
           back to the caller.

        :returns: None is returned, unless you specify
            ``start_reactor=False`` in which case the Deferred that
            connect() returns is returned; this will callback() with
            an IProtocol instance, which will actually be an instance
            of :class:`WampWebSocketClientProtocol`
        """
        if start_reactor:
            # only select framework, set loop and start logging when we are asked
            # start the reactor - otherwise we are running in a program that likely
            # already tool care of all this.
            from twisted.internet import reactor
            txaio.use_twisted()
            txaio.config.loop = reactor
            txaio.start_logging(level='info')

        isSecure, host, port, resource, path, params = parse_url(self.url)

        # factory for use ApplicationSession
        def create():
            cfg = ComponentConfig(self.realm, self.extra)
            try:
                session = make(cfg)
            except Exception as e:
                if start_reactor:
                    # the app component could not be created .. fatal
                    self.log.error(str(e))
                    reactor.stop()
                else:
                    # if we didn't start the reactor, it's up to the
                    # caller to deal with errors
                    raise
            else:
                return session

        # create a WAMP-over-WebSocket transport client factory
        transport_factory = WampWebSocketClientFactory(create, url=self.url, serializers=self.serializers, proxy=self.proxy)

        # supress pointless log noise like
        # "Starting factory <autobahn.twisted.websocket.WampWebSocketClientFactory object at 0x2b737b480e10>""
        transport_factory.noisy = False

        # if user passed ssl= but isn't using isSecure, we'll never
        # use the ssl argument which makes no sense.
        context_factory = None
        if self.ssl is not None:
            if not isSecure:
                raise RuntimeError(
                    'ssl= argument value passed to %s conflicts with the "ws:" '
                    'prefix of the url argument. Did you mean to use "wss:"?' %
                    self.__class__.__name__)
            context_factory = self.ssl
        elif isSecure:
            from twisted.internet.ssl import optionsForClientTLS
            context_factory = optionsForClientTLS(host)

        from twisted.internet import reactor
        if self.proxy is not None:
            from twisted.internet.endpoints import TCP4ClientEndpoint
            client = TCP4ClientEndpoint(reactor, self.proxy['host'], self.proxy['port'])
            transport_factory.contextFactory = context_factory
        elif isSecure:
            from twisted.internet.endpoints import SSL4ClientEndpoint
            assert context_factory is not None
            client = SSL4ClientEndpoint(reactor, host, port, context_factory)
        else:
            from twisted.internet.endpoints import TCP4ClientEndpoint
            client = TCP4ClientEndpoint(reactor, host, port)

        d = client.connect(transport_factory)

        # as the reactor shuts down, we wish to wait until we've sent
        # out our "Goodbye" message; leave() returns a Deferred that
        # fires when the transport gets to STATE_CLOSED
        def cleanup(proto):
            if hasattr(proto, '_session') and proto._session is not None:
                if proto._session.is_attached():
                    return proto._session.leave()
                elif proto._session.is_connected():
                    return proto._session.disconnect()

        # when our proto was created and connected, make sure it's cleaned
        # up properly later on when the reactor shuts down for whatever reason
        def init_proto(proto):
            reactor.addSystemEventTrigger('before', 'shutdown', cleanup, proto)
            return proto

        # if we connect successfully, the arg is a WampWebSocketClientProtocol
        d.addCallback(init_proto)

        # if the user didn't ask us to start the reactor, then they
        # get to deal with any connect errors themselves.
        if start_reactor:
            # if an error happens in the connect(), we save the underlying
            # exception so that after the event-loop exits we can re-raise
            # it to the caller.

            class ErrorCollector(object):
                exception = None

                def __call__(self, failure):
                    self.exception = failure.value
                    reactor.stop()
            connect_error = ErrorCollector()
            d.addErrback(connect_error)

            # now enter the Twisted reactor loop
            reactor.run()

            # if we exited due to a connection error, raise that to the
            # caller
            if connect_error.exception:
                raise connect_error.exception

        else:
            # let the caller handle any errors
            return d
コード例 #32
0
 def test_parse_url02(self):
     self.assertEqual(parse_url("ws://localhost:80"),
                      (False, 'localhost', 80, '/', '/', {}))
コード例 #33
0
 def test_parse_url04(self):
     self.assertEqual(parse_url("wss://localhost:443"),
                      (True, 'localhost', 443, '/', '/', {}))
コード例 #34
0
 def test_parse_url06(self):
     self.assertEqual(parse_url("wss://localhost/ws?foo=bar"),
                      (True, 'localhost', 443, '/ws?foo=bar', '/ws', {
                          'foo': ['bar']
                      }))
コード例 #35
0
        super().__init__(*args, **kwargs)
        self.emitter = emitter

    def buildProtocol(self, addr):
        conn = self.protocol(self, self.emitter)
        self.emitter.ws_conn = conn
        return conn


if __name__ == '__main__':
    from ws_message_emitter import WSMessageEmitter
    log.startLogging(sys.stdout)
    ws_url = sys.argv[1]
    session_id, type_code = sys.argv[2:4]
    record_code = sys.argv[4]
    try:
        peg_proportion = float(sys.argv[5])
    except ValueError:
        peg_proportion = None
    emitter = WSMessageEmitter(session_id,
                               type_code,
                               filter_value=record_code,
                               **get_ws_confs(type_code),
                               peg_proportion=peg_proportion)
    emitter.read_from_db(**db_creds)
    factory = ExogenousEventClientFactory(emitter, ws_url)
    url_parsed = parse_url(ws_url)
    host, port = url_parsed[1], url_parsed[2]
    reactor.connectTCP(host, port, factory)
    reactor.run()
コード例 #36
0
 def test_parse_url08(self):
     self.assertEqual(parse_url("wss://localhost/ws?foo=bar&moo=23&moo=44"), (True, 'localhost', 443, '/ws?foo=bar&moo=23&moo=44', '/ws', {'moo': ['23', '44'], 'foo': ['bar']}))
コード例 #37
0
ファイル: server.py プロジェクト: Alf-11/autobahn-python
    parser.add_argument('--silence', dest='silence', action="store_true", default=False, help='Silence log output.')
    parser.add_argument('--debug', dest='debug', action="store_true", default=False, help='Enable WebSocket debug output.')
    parser.add_argument('--interval', dest='interval', type=int, default=5, help='Worker stats update interval.')
    parser.add_argument('--profile', dest='profile', action="store_true", default=False, help='Enable profiling.')

    parser.add_argument('--fd', dest='fd', type=int, default=None, help='If given, this is a worker which will use provided FD and all other options are ignored.')
    parser.add_argument('--cpuid', dest='cpuid', type=int, default=None, help='If given, this is a worker which will use provided CPU core to set its affinity.')

    options = parser.parse_args()

    if options.profile and not hasStatprof:
        raise Exception("profiling requested, but statprof not installed")

    # parse WS URI into components and forward via options
    # FIXME: add TLS support
    isSecure, host, wsport, resource, path, params = parse_url(options.wsuri)
    options.wsport = wsport

    # if not options.silence:
    #   log.startLogging(sys.stdout)

    if options.fd is not None:
        # run worker
        worker(options)
    else:
        if not options.silence:
            for m in startupMsgs:
                print m
        # run master
        master(options)
コード例 #38
0
 def test_parse_url04(self):
     self.assertEqual(parse_url("wss://localhost:443"), (True, 'localhost', 443, '/', '/', {}))
コード例 #39
0
 def test_parse_url05(self):
     self.assertEqual(parse_url("wss://localhost/ws"), (True, "localhost", 443, "/ws", "/ws", {}))
コード例 #40
0
        '--cpuid',
        dest='cpuid',
        type=int,
        default=None,
        help=
        'If given, this is a worker which will use provided CPU core to set its affinity.'
    )

    options = parser.parse_args()

    if options.profile and not hasStatprof:
        raise Exception("profiling requested, but statprof not installed")

    # parse WS URI into components and forward via options
    # FIXME: add TLS support
    isSecure, host, wsport, resource, path, params = parse_url(options.wsuri)
    options.wsport = wsport

    # if not options.silence:
    #   log.startLogging(sys.stdout)

    if options.fd is not None:
        # run worker
        worker(options)
    else:
        if not options.silence:
            for m in startupMsgs:
                print m
        # run master
        master(options)
コード例 #41
0
 def test_parse_url06(self):
     self.assertEqual(
         parse_url("wss://localhost/ws?foo=bar"), (True, "localhost", 443, "/ws?foo=bar", "/ws", {"foo": ["bar"]})
     )
コード例 #42
0
                        return PerMessageDeflateOfferAccept(offer)

            self.setProtocolOptions(perMessageCompressionAccept=accept)


if __name__ == '__main__':

    parser = argparse.ArgumentParser(description='Autobahn Testee Server (Twisted)')
    parser.add_argument('--url', dest='url', type=str, default=u'ws://127.0.0.1:9001', help='The WebSocket fuzzing server URL.')
    parser.add_argument('--loglevel', dest='loglevel', type=str, default=u'info', help='Log level, eg "info" or "debug".')

    options = parser.parse_args()

    txaio.start_logging(level=options.loglevel)

    factory = TesteeServerFactory(options.url)

    _, _, port, _, _, _ = parse_url(options.url)

    loop = asyncio.get_event_loop()
    coro = loop.create_server(factory, port=port)
    server = loop.run_until_complete(coro)

    try:
        loop.run_forever()
    except KeyboardInterrupt:
        pass
    finally:
        server.close()
        loop.close()
コード例 #43
0
 def test_parse_url08(self):
     self.assertEqual(
         parse_url("wss://localhost/ws?foo=bar&moo=23&moo=44"),
         (True, "localhost", 443, "/ws?foo=bar&moo=23&moo=44", "/ws", {"moo": ["23", "44"], "foo": ["bar"]}),
     )
コード例 #44
0
def compute_mgmt_uplink_config(log, cbdir, config, fn_reboot=None, use_activation_file=True, use_default_fabric=False):
    """
    Determine the transport configuration of the management uplink for this node
    in the following order (using the first one that succeeds):

    * node activation file
    * management URL environment variable
    * node configuration file
    * built-in default ("master.xbr.network")

    :param cbdir:
    :param config:
    :param fn_reboot:
    :param use_activation_file:
    :param use_default_fabric:
    :return:
    """
    fabric_transport_config = None

    # [1] pick up auto-activation files dropped by a master node (`${CBDIR}/key.activate`)
    if not fabric_transport_config and use_activation_file:
        def do_check_for_activation_file(activation_file, reboot_on_discover):
            if os.path.isfile(activation_file):
                tags = _parse_activation_file(activation_file)
                is_secure, hostname, port, _, _, _ = parse_url(tags['management-url'])
                config = {
                    'type': 'websocket',
                    'url': tags['management-url'],
                    'endpoint': {
                        'type': 'tcp',
                        'host': hostname,
                        'port': port,
                        'timeout': 5
                    }
                }
                if is_secure:
                    config['endpoint']['tls'] = {
                        'hostname': hostname
                    }
                _msg = 'Found auto-activation file "{}", using management URL "{}" - [1]'.format(activation_file,
                                                                                                 config['url'])
                log.info(click.style(_msg, fg='red', bold=True))

                if reboot_on_discover and fn_reboot:
                    # stop the node and enforce complete reboot - which will then pick up the new configuration
                    fn_reboot()

                # return the management uplink transport configuration, as derived from the activation file
                return config

        # an activation file must be placed next to the node key pair (key.pub, key.priv)
        activation_file = os.path.join(cbdir, 'key.activate')

        # check and maybe load config from activation file
        fabric_transport_config = do_check_for_activation_file(activation_file, reboot_on_discover=False)

        # if there wasn't an activation file, periodically check for ..
        if not fabric_transport_config:
            lc = LoopingCall(do_check_for_activation_file, activation_file, reboot_on_discover=True)
            lc.start(1)
            log.info('Looping call to check for node activation file started! - [1]')

    # [2] management uplink configured via env var
    if not fabric_transport_config:
        url = os.environ['CROSSBAR_FABRIC_URL'].strip() if 'CROSSBAR_FABRIC_URL' in os.environ else ''
        if url != '':
            secure, host, tcp_port, _, _, _ = parse_url(url)
            fabric_transport_config = {
                'type': 'websocket',
                'url': url,
                'endpoint': {
                    'type': 'tcp',
                    'host': host,
                    'port': tcp_port,
                    'timeout': 5
                }
            }
            if secure:
                fabric_transport_config['endpoint']['tls'] = {
                    'hostname': host
                }
            log.info(
                click.style('Using management uplink at "{}" (from envvar) - [2]'.format(url),
                            fg='red', bold=True))

    # [3] user has configured a custom management uplink in the node configuration
    if not fabric_transport_config:
        if 'controller' in config and 'fabric' in config['controller'] and config['controller']['fabric']:

            fabric_config = config['controller']['fabric']

            # allow to deactivate the management uplink connecting transport by setting "transport" to null
            fabric_transport_config = fabric_config.get('transport', None)

            if fabric_transport_config:
                url = fabric_transport_config.get('url', None)
                log.info(
                    click.style('Using management uplink at "{}" (from node configuration) - [3]'.format(url),
                                fg='red', bold=True))
            else:
                log.info(
                    click.style('Management uplink deactivated - [3]',
                                fg='red', bold=True))

    # [4] use hard-coded default management uplink
    if not fabric_transport_config and use_default_fabric:
        # default CFC (= our cloud hosted CFC service)
        fabric_transport_config = {
            'type': 'websocket',
            'url': 'wss://master.xbr.network/ws',
            'endpoint': {
                'type': 'tcp',
                'host': 'master.xbr.network',
                'port': 443,
                'timeout': 5,
                'tls': {
                    'hostname': 'master.xbr.network'
                }
            }
        }
        log.info(
            click.style(
                'Using default fabric controller at URL "{}" (from envvar) - [4]'.format(fabric_transport_config['url']),
                fg='red', bold=True))

    return fabric_transport_config
コード例 #45
0
 def test_parse_url02(self):
     self.assertEqual(parse_url("ws://localhost:80"), (False, "localhost", 80, "/", "/", {}))
コード例 #46
0
 def reset_url(self):
     websocket_uri, url, port = self.link.get_url()
     self.url = websocket_uri
     (self.isSecure, self.host, self.port, self.resource, self.path,
      self.params) = parse_url(websocket_uri)
コード例 #47
0
 def test_parse_url04(self):
     self.assertEqual(parse_url("wss://localhost:443"), (True, "localhost", 443, "/", "/", {}))
コード例 #48
0
                        type=str,
                        default=u'ws://127.0.0.1:9001',
                        help='The WebSocket fuzzing server URL.')
    parser.add_argument('--loglevel',
                        dest='loglevel',
                        type=str,
                        default=u'info',
                        help='Log level, eg "info" or "debug".')

    options = parser.parse_args()

    txaio.start_logging(level=options.loglevel)

    factory = TesteeClientFactory(options.url, autobahn.asyncio.__ident__)

    _, host, port, _, _, _ = parse_url(options.url)

    loop = asyncio.get_event_loop()

    factory.resource = u'/getCaseCount'
    factory.endCaseId = None
    factory.currentCaseId = 0
    factory.updateReports = True

    while True:

        factory._done = txaio.create_future()
        coro = loop.create_connection(factory, host, port)
        loop.run_until_complete(coro)
        loop.run_until_complete(factory._done)
コード例 #49
0
 def test_parse_url06(self):
     self.assertEqual(parse_url("wss://localhost/ws?foo=bar"), (True, 'localhost', 443, '/ws?foo=bar', '/ws', {'foo': ['bar']}))
コード例 #50
0
ファイル: wamp.py プロジェクト: Alf-11/autobahn-python
    def run(self, make):
        """
        Run the application component.

        :param make: A factory that produces instances of :class:`autobahn.asyncio.wamp.ApplicationSession`
           when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`.
        :type make: callable
        """
        # 1) factory for use ApplicationSession
        def create():
            cfg = ComponentConfig(self.realm, self.extra)
            try:
                session = make(cfg)
            except Exception:
                self.log.failure("App session could not be created! ")
                asyncio.get_event_loop().stop()
            else:
                return session

        isSecure, host, port, resource, path, params = parse_url(self.url)

        if self.ssl is None:
            ssl = isSecure
        else:
            if self.ssl and not isSecure:
                raise RuntimeError(
                    'ssl argument value passed to %s conflicts with the "ws:" '
                    'prefix of the url argument. Did you mean to use "wss:"?' %
                    self.__class__.__name__)
            ssl = self.ssl

        # 2) create a WAMP-over-WebSocket transport client factory
        transport_factory = WampWebSocketClientFactory(create, url=self.url, serializers=self.serializers)

        # 3) start the client
        loop = asyncio.get_event_loop()
        txaio.use_asyncio()
        txaio.config.loop = loop
        coro = loop.create_connection(transport_factory, host, port, ssl=ssl)
        (transport, protocol) = loop.run_until_complete(coro)

        # start logging
        txaio.start_logging(level='info')

        try:
            loop.add_signal_handler(signal.SIGTERM, loop.stop)
        except NotImplementedError:
            # signals are not available on Windows
            pass

        # 4) now enter the asyncio event loop
        try:
            loop.run_forever()
        except KeyboardInterrupt:
            # wait until we send Goodbye if user hit ctrl-c
            # (done outside this except so SIGTERM gets the same handling)
            pass

        # give Goodbye message a chance to go through, if we still
        # have an active session
        if protocol._session:
            loop.run_until_complete(protocol._session.leave())

        loop.close()
コード例 #51
0
 def test_parse_url05(self):
     self.assertEqual(parse_url("wss://localhost/ws"),
                      (True, 'localhost', 443, '/ws', '/ws', {}))