コード例 #1
0
ファイル: diffusion.py プロジェクト: lijing2001/BET365
 def _get_offer(self):
     return PerMessageDeflateOffer(
         accept_max_window_bits=True,
         accept_no_context_takeover=False,
         request_max_window_bits=0,
         request_no_context_takeover=False,
     )
コード例 #2
0
def connect2WS(b_in_main_thread):
    tokens = get_tokens()
    pstk = tokens['pstk']
    token = tokens['token']
    uid = generateUID(token.split('.')[0], tokens['SERVER_TIME'])

    if not pstk:
        print('get pstk failed, maybe in maintance')
        return

    USER_AGENT = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Mobile Safari/537.36"
    url = 'wss://premws-pt1.bet365.it/zap/?uid={}'.format(uid)

    global_var.factory = DataSourceClientFactory(url,
                                                 useragent=USER_AGENT,
                                                 protocols=['zap-protocol-v1'])

    global_var.factory.session_id = pstk
    global_var.factory.token = token

    def accept(response):
        if isinstance(response, PerMessageDeflateResponse):
            return PerMessageDeflateResponseAccept(response)

    global_var.factory.setProtocolOptions(perMessageCompressionAccept=accept)
    global_var.factory.setProtocolOptions(perMessageCompressionOffers=[
        PerMessageDeflateOffer(accept_max_window_bits=True,
                               accept_no_context_takeover=True,
                               request_max_window_bits=0,
                               request_no_context_takeover=True)
    ])

    if global_var.factory.isSecure:
        contextFactory = ssl.ClientContextFactory()
    else:
        contextFactory = None

    while True:
        try:
            if b_in_main_thread:
                connectWS(global_var.factory, contextFactory, timeout=60)
            else:
                reactor.callFromThread(connectWS,
                                       global_var.factory,
                                       contextFactory,
                                       timeout=60)
        except:
            print('failed to connect ws server!')
            time.sleep(5)
        else:
            break
コード例 #3
0
    def __init__(self, url, agent):
        self.agent = agent
        WebSocketClientFactory.__init__(self, url, useragent=agent)

        self.setProtocolOptions(failByDrop=False)  # spec conformance

        # enable permessage-deflate WebSocket protocol extension
        offers = [PerMessageDeflateOffer()]
        self.setProtocolOptions(perMessageCompressionOffers=offers)

        def accept(response):
            if isinstance(response, PerMessageDeflateResponse):
                return PerMessageDeflateResponseAccept(response)

        self.setProtocolOptions(perMessageCompressionAccept=accept)
コード例 #4
0
    def __init__(self,
                 factory,
                 url,
                 reactor=None,
                 enableCompression=True,
                 autoFragmentSize=0,
                 subprotocol=None,
                 debug=False):
        """
      Constructor.

      :param factory: Stream-based factory to be wrapped.
      :type factory: A subclass of `twisted.internet.protocol.Factory`
      :param url: WebSocket URL of the server this client factory will connect to.
      :type url: str
      """
        self._factory = factory
        self._subprotocols = ['binary', 'base64']
        if subprotocol:
            self._subprotocols.append(subprotocol)

        WebSocketClientFactory.__init__(self,
                                        url=url,
                                        reactor=reactor,
                                        protocols=self._subprotocols,
                                        debug=debug)

        ## automatically fragment outgoing traffic into WebSocket frames
        ## of this size
        self.setProtocolOptions(autoFragmentSize=autoFragmentSize)

        ## play nice and perform WS closing handshake
        self.setProtocolOptions(failByDrop=False)

        if enableCompression:
            ## Enable WebSocket extension "permessage-deflate".
            ##

            ## The extensions offered to the server ..
            offers = [PerMessageDeflateOffer()]
            self.setProtocolOptions(perMessageCompressionOffers=offers)

            ## Function to accept responses from the server ..
            def accept(response):
                if isinstance(response, PerMessageDeflateResponse):
                    return PerMessageDeflateResponseAccept(response)

            self.setProtocolOptions(perMessageCompressionAccept=accept)
コード例 #5
0
    def __init__(self, url):
        self.agent = autobahn.twisted.__ident__
        WebSocketClientFactory.__init__(self, url, useragent=self.agent)

        self.setProtocolOptions(failByDrop=False)  # spec conformance

        # enable permessage-deflate WebSocket protocol extension
        offers = [PerMessageDeflateOffer()]
        self.setProtocolOptions(perMessageCompressionOffers=offers)

        def accept(response):
            if isinstance(response, PerMessageDeflateResponse):
                return PerMessageDeflateResponseAccept(response)

        self.setProtocolOptions(perMessageCompressionAccept=accept)

        # setup client testee stuff
        self.endCaseId = None
        self.currentCaseId = 0
        self.updateReports = True
        self.resource = "/getCaseCount"
コード例 #6
0
    def run(self, make, start_loop=True, log_level='info'):
        """
        Run the application component. Under the hood, this runs the event
        loop (unless `start_loop=False` is passed) so won't return
        until the program is done.

        :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_loop: When ``True`` (the default) this method
            start a new asyncio loop.
        :type start_loop: bool

        :returns: None is returned, unless you specify
            `start_loop=False` in which case the coroutine from calling
            `loop.create_connection()` is returned. This will yield the
            (transport, protocol) pair.
        """
        if callable(make):

            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
        else:
            create = make

        if self.url.startswith(u'rs'):
            # try to parse RawSocket URL ..
            isSecure, host, port = parse_rs_url(self.url)

            # use the first configured serializer if any (which means, auto-choose "best")
            serializer = self.serializers[0] if self.serializers else None

            # create a WAMP-over-RawSocket transport client factory
            transport_factory = WampRawSocketClientFactory(
                create, serializer=serializer)

        else:
            # try to parse WebSocket URL ..
            isSecure, host, port, resource, path, params = parse_ws_url(
                self.url)

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

            # client WebSocket settings - similar to:
            # - http://crossbar.io/docs/WebSocket-Compression/#production-settings
            # - http://crossbar.io/docs/WebSocket-Options/#production-settings

            # The permessage-deflate extensions offered to the server ..
            offers = [PerMessageDeflateOffer()]

            # Function to accept permessage_delate responses from the server ..
            def accept(response):
                if isinstance(response, PerMessageDeflateResponse):
                    return PerMessageDeflateResponseAccept(response)

            # set WebSocket options for all client connections
            transport_factory.setProtocolOptions(
                maxFramePayloadSize=1048576,
                maxMessagePayloadSize=1048576,
                autoFragmentSize=65536,
                failByDrop=False,
                openHandshakeTimeout=2.5,
                closeHandshakeTimeout=1.,
                tcpNoDelay=True,
                autoPingInterval=10.,
                autoPingTimeout=5.,
                autoPingSize=4,
                perMessageCompressionOffers=offers,
                perMessageCompressionAccept=accept)
        # SSL context for client connection
        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

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

        # start a asyncio loop
        if not start_loop:
            return coro
        else:
            (transport, protocol) = loop.run_until_complete(coro)

            # start logging
            txaio.start_logging(level=log_level)

            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()
コード例 #7
0
    if len(sys.argv) > 2 and sys.argv[2] == 'debug':
        log.startLogging(sys.stdout)
        debug = True
    else:
        debug = False

    factory = WebSocketClientFactory(sys.argv[1],
                                     debug=debug,
                                     debugCodePaths=debug)

    factory.protocol = EchoClientProtocol

    # Enable WebSocket extension "permessage-deflate".
    ##

    # The extensions offered to the server ..
    offers = [PerMessageDeflateOffer()]
    factory.setProtocolOptions(perMessageCompressionOffers=offers)

    # Function to accept responses from the server ..
    def accept(response):
        if isinstance(response, PerMessageDeflateResponse):
            return PerMessageDeflateResponseAccept(response)

    factory.setProtocolOptions(perMessageCompressionAccept=accept)

    # run client
    ##
    connectWS(factory)
    reactor.run()
コード例 #8
0
    factory = WebSocketClientFactory(url,
                                     useragent=USER_AGENT,
                                     protocols=['zap-protocol-v1'])
    factory.protocol = MyClientProtocol
    factory.headers = {}

    factory.session_id = get_session_id()

    def accept(response):
        if isinstance(response, PerMessageDeflateResponse):
            return PerMessageDeflateResponseAccept(response)

    factory.setProtocolOptions(perMessageCompressionAccept=accept)
    factory.setProtocolOptions(perMessageCompressionOffers=[
        PerMessageDeflateOffer(
            accept_max_window_bits=True,
            accept_no_context_takeover=True,
            request_max_window_bits=0,
            request_no_context_takeover=True,
        )
    ])
    # reactor.callFromThread(connectWS, factory)
    # reactor.run()
    if factory.isSecure:
        contextFactory = ssl.ClientContextFactory()
    else:
        contextFactory = None
    connectWS(factory, contextFactory)
    reactor.run()
コード例 #9
0
    def run(self, make, start_reactor=True, auto_reconnect=False, log_level='info', endpoint=None, reactor=None):
        """
        Run the application component.

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

        :param start_reactor: When ``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`
        """
        self.log.debug('{klass}.run()', klass=self.__class__.__name__)

        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=log_level)

        if callable(make):
            # factory for use ApplicationSession
            def create():
                cfg = ComponentConfig(self.realm, self.extra, runner=self)
                try:
                    session = make(cfg)
                except Exception:
                    self.log.failure('ApplicationSession could not be instantiated: {log_failure.value}')
                    if start_reactor and reactor.running:
                        reactor.stop()
                    raise
                else:
                    return session
        else:
            create = make

        if self.url.startswith(u'rs'):
            # try to parse RawSocket URL ..
            isSecure, host, port = parse_rs_url(self.url)

            # use the first configured serializer if any (which means, auto-choose "best")
            serializer = self.serializers[0] if self.serializers else None

            # create a WAMP-over-RawSocket transport client factory
            transport_factory = WampRawSocketClientFactory(create, serializer=serializer)

        else:
            # try to parse WebSocket URL ..
            isSecure, host, port, resource, path, params = parse_ws_url(self.url)

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

            # client WebSocket settings - similar to:
            # - http://crossbar.io/docs/WebSocket-Compression/#production-settings
            # - http://crossbar.io/docs/WebSocket-Options/#production-settings

            # The permessage-deflate extensions offered to the server ..
            offers = [PerMessageDeflateOffer()]

            # Function to accept permessage_delate responses from the server ..
            def accept(response):
                if isinstance(response, PerMessageDeflateResponse):
                    return PerMessageDeflateResponseAccept(response)

            # set WebSocket options for all client connections
            transport_factory.setProtocolOptions(maxFramePayloadSize=1048576,
                                                 maxMessagePayloadSize=1048576,
                                                 autoFragmentSize=65536,
                                                 failByDrop=False,
                                                 openHandshakeTimeout=2.5,
                                                 closeHandshakeTimeout=1.,
                                                 tcpNoDelay=True,
                                                 autoPingInterval=10.,
                                                 autoPingTimeout=5.,
                                                 autoPingSize=4,
                                                 perMessageCompressionOffers=offers,
                                                 perMessageCompressionAccept=accept)

        # supress pointless log noise
        transport_factory.noisy = False

        if endpoint:
            client = endpoint
        else:
            # 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)

        # 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):
            self._connect_successes += 1
            reactor.addSystemEventTrigger('before', 'shutdown', cleanup, proto)
            return proto

        use_service = False
        if auto_reconnect:
            try:
                # since Twisted 16.1.0
                from twisted.application.internet import ClientService
                from twisted.application.internet import backoffPolicy
                use_service = True
            except ImportError:
                use_service = False

        if use_service:
            # this code path is automatically reconnecting ..
            self.log.debug('using t.a.i.ClientService')

            if self.max_retries or self.initial_retry_delay or self.max_retry_delay or self.retry_delay_growth or self.retry_delay_jitter:
                kwargs = {}
                for key, val in [('initialDelay', self.initial_retry_delay),
                                 ('maxDelay', self.max_retry_delay),
                                 ('factor', self.retry_delay_growth),
                                 ('jitter', lambda: random.random() * self.retry_delay_jitter)]:
                    if val:
                        kwargs[key] = val

                # retry policy that will only try to reconnect if we connected
                # successfully at least once before (so it fails on host unreachable etc ..)
                def retry(failed_attempts):
                    if self._connect_successes > 0 and (self.max_retries == -1 or failed_attempts < self.max_retries):
                        return backoffPolicy(**kwargs)(failed_attempts)
                    else:
                        print('hit stop')
                        self.stop()
                        return 100000000000000
            else:
                retry = backoffPolicy()

            self._client_service = ClientService(client, transport_factory, retryPolicy=retry)
            self._client_service.startService()

            d = self._client_service.whenConnected()

        else:
            # this code path is only connecting once!
            self.log.debug('using t.i.e.connect()')

            d = client.connect(transport_factory)

        # 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
コード例 #10
0
    def start_main():
        global is_valit
        is_valit = False

        USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36"
        url_auto = "wss://pshudws.365pushodds.com/zap/?uid=" + str(random.random())[2:]
        factory_auto = MyFactory(
            url_auto, useragent=USER_AGENT, protocols=['zap-protocol-v1'])

        # factory_auto = MyFactory(
        #     url_auto, useragent=USER_AGENT, protocols=['zap-protocol-v1'], proxy={'host': "127.0.0.1", 'port': 8888})
        factory_auto.protocol = SubClientProtocol
        factory_auto.headers = {}

        factory_auto.nst_token = get_nst_token()
        factory_auto.session_id = get_session_id()

        def accept(response):
            if isinstance(response, PerMessageDeflateResponse):
                return PerMessageDeflateResponseAccept(response)

        factory_auto.setProtocolOptions(perMessageCompressionAccept=accept)
        factory_auto.setProtocolOptions(perMessageCompressionOffers=[PerMessageDeflateOffer(
            accept_max_window_bits=True,
            accept_no_context_takeover=True,
            request_max_window_bits=0,
            request_no_context_takeover=True,
        )])
        if factory_auto.isSecure:
            contextFactory_auto = ssl.ClientContextFactory()
        else:
            contextFactory_auto = None


        url = "wss://premws-pt3.365pushodds.com/zap/?uid=" + str(random.random())[2:]
        factory = MyFactory(
            url, useragent=USER_AGENT, protocols=['zap-protocol-v1'])
        # factory = MyFactory(
        #     url, useragent=USER_AGENT, protocols=['zap-protocol-v1'], proxy={'host': "127.0.0.1", 'port': 8888})
        factory.protocol = MyClientProtocol
        factory.headers = {}

        factory.session_id = factory_auto.session_id
        factory.nst_token = factory_auto.nst_token
        # factory.session_id = '44263EAB3A86367F8DF053097CF36FBB000003'

        factory.setProtocolOptions(perMessageCompressionAccept=accept)
        factory.setProtocolOptions(perMessageCompressionOffers=[PerMessageDeflateOffer(
            accept_max_window_bits=True,
            accept_no_context_takeover=True,
            request_max_window_bits=0,
            request_no_context_takeover=True,
        )])
        # reactor.callFromThread(connectWS, factory)
        # reactor.run()
        if factory.isSecure:
            contextFactory = ssl.ClientContextFactory()
        else:
            contextFactory = None
        connectWS(factory, contextFactory)
        connectWS(factory_auto, contextFactory_auto)

        reactor.callLater(900, stopReactor)

        reactor.run()
コード例 #11
0
ファイル: test_websockets.py プロジェクト: webmaks/aiorest-ws
# -*- coding: utf-8 -*-
import pytest

from autobahn.websocket.compress import PerMessageDeflateOffer, \
    PerMessageDeflateOfferAccept

from aiorest_ws.utils.websocket import deflate_offer_accept


@pytest.mark.parametrize("offers, expected", [
    ([
        PerMessageDeflateOffer(),
    ], PerMessageDeflateOfferAccept),
    ([
        None,
    ], type(None)),
    ([], type(None)),
])
def test_deflate_offer_accept(offers, expected):
    assert type(deflate_offer_accept(offers)) is expected
コード例 #12
0
ファイル: test_cb_zip_bomb.py プロジェクト: yankos/crossbar
def test_deflate_lots(reactor, crossbar):
    """
    """
    # XXX turning on Deflate seems .. hard
    # XXX also, why do I have to specify max_... in at least 2 places?

    # The extensions offered to the server ..
    offers = [PerMessageDeflateOffer()]

    # Function to accept responses from the server ..
    def accept(response):
        if isinstance(response, PerMessageDeflateResponse):
            return PerMessageDeflateResponseAccept(response,
                                                   max_message_size=1500)

    # we have two components here: one that has a limit on payloads
    # (component0) and one that doesn't (component1). component0 subscribes
    # and then component1 sends it one "small enough" and then one "too big"
    # message (the second should cause component0 to drop its connection).
    component0 = Component(
        transports=[
            {
                u"url": u"ws://localhost:6565/ws",
                u"options": {
                    u"max_frame_payload_size": 1500,
                    u"per_message_compression_offers": offers,
                    u"per_message_compression_accept": accept,
                }
            },
        ],
        realm=u"functest_realm1",
    )
    component1 = Component(
        transports=[
            {
                u"url": u"ws://localhost:6565/ws",
                u"options": {
                    u"per_message_compression_offers": offers,
                    u"per_message_compression_accept": accept,
                }
            },
        ],
        realm=u"functest_realm1",
    )

    listening = Deferred()  # component1 waits until component0 subscribes
    connection_dropped = Deferred()  # we want component0 to do this
    connections = [0]  # how many times component0 has connected

    @component0.on_join
    @inlineCallbacks
    def listen(session, details):
        connections[0] += 1
        if connections[0] == 2:
            print("comp0: re-connected!")
        elif connections[0] == 1:
            # we await (potentially) two messages; if we get the second, the
            # test should fail
            messages = [Deferred(), Deferred()]
            yield session.subscribe(lambda x: messages.pop(0).callback(x),
                                    u"foo")
            listening.callback(None)
            while len(messages):
                msg = yield messages[0]
                print("comp0: message: {}".format(msg))
        print("comp0: done listening")

    @component0.on_disconnect
    def gone(session, was_clean=False):
        print("comp0: session dropped".format(session, was_clean))
        connection_dropped.callback(session)

    @component1.on_join
    @inlineCallbacks
    def send(session, details):
        yield listening
        # this one should be small enough to go through
        yield session.publish(u"foo",
                              u"a" * 20,
                              options=types.PublishOptions(acknowledge=True))

        # this will definitely be over 1500 and should fail (due to the other
        # side's decoder dropping it because the payload is too big). We can't
        # get an error here because the router accepts it, but the other
        # *client* will reject...
        yield session.publish(u"foo",
                              u"a" * 2000,
                              options=types.PublishOptions(acknowledge=True))

    # fail-safe if the test doesn't fail for some other reason, it'll fail
    # after 15s
    timeout = sleep(15)

    done = DeferredList([
        component0.start(reactor),
        component1.start(reactor),
    ])
    yield DeferredList([timeout, done, connection_dropped],
                       fireOnOneErrback=True,
                       fireOnOneCallback=True)

    assert not timeout.called, "shouldn't time out"
    assert connection_dropped.called, "component0 should have dropped connection"
コード例 #13
0
ファイル: wamp.py プロジェクト: jameshilliard/autobahn-python
    def run(self,
            make,
            start_reactor: bool = True,
            auto_reconnect: bool = False,
            log_level: str = 'info',
            endpoint: Optional[IStreamClientEndpoint] = None,
            reactor: Optional[IReactorCore] = None
            ) -> Union[type(None), Deferred]:
        """
        Run the application component.

        :param make: A factory that produces instances of :class:`autobahn.twisted.wamp.ApplicationSession`
           when called with an instance of :class:`autobahn.wamp.types.ComponentConfig`.
        :param start_reactor: When ``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.
        :param auto_reconnect:
        :param log_level:
        :param endpoint:
        :param reactor:
        :return: 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`
        """
        self.log.debug('{klass}.run()', klass=self.__class__.__name__)

        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=log_level)

        if callable(make):
            # factory for use ApplicationSession
            def create():
                cfg = ComponentConfig(self.realm, self.extra, runner=self)
                try:
                    session = make(cfg)
                except Exception:
                    self.log.failure(
                        'ApplicationSession could not be instantiated: {log_failure.value}'
                    )
                    if start_reactor and reactor.running:
                        reactor.stop()
                    raise
                else:
                    return session
        else:
            create = make

        if self.url.startswith('rs'):
            # try to parse RawSocket URL
            isSecure, host, port = parse_rs_url(self.url)

            # use the first configured serializer if any (which means, auto-choose "best")
            serializer = self.serializers[0] if self.serializers else None

            # create a WAMP-over-RawSocket transport client factory
            transport_factory = WampRawSocketClientFactory(
                create, serializer=serializer)

        else:
            # try to parse WebSocket URL
            isSecure, host, port, resource, path, params = parse_ws_url(
                self.url)

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

            # client WebSocket settings - similar to:
            # - http://crossbar.io/docs/WebSocket-Compression/#production-settings
            # - http://crossbar.io/docs/WebSocket-Options/#production-settings

            # The permessage-deflate extensions offered to the server
            offers = [PerMessageDeflateOffer()]

            # Function to accept permessage-deflate responses from the server
            def accept(response):
                if isinstance(response, PerMessageDeflateResponse):
                    return PerMessageDeflateResponseAccept(response)

            # default WebSocket options for all client connections
            protocol_options = {
                'version': WebSocketProtocol.DEFAULT_SPEC_VERSION,
                'utf8validateIncoming': True,
                'acceptMaskedServerFrames': False,
                'maskClientFrames': True,
                'applyMask': True,
                'maxFramePayloadSize': 1048576,
                'maxMessagePayloadSize': 1048576,
                'autoFragmentSize': 65536,
                'failByDrop': True,
                'echoCloseCodeReason': False,
                'serverConnectionDropTimeout': 1.,
                'openHandshakeTimeout': 2.5,
                'closeHandshakeTimeout': 1.,
                'tcpNoDelay': True,
                'perMessageCompressionOffers': offers,
                'perMessageCompressionAccept': accept,
                'autoPingInterval': 10.,
                'autoPingTimeout': 5.,
                'autoPingSize': 12,

                # see: https://github.com/crossbario/autobahn-python/issues/1327 and
                # _cancelAutoPingTimeoutCall
                'autoPingRestartOnAnyTraffic': True,
            }

            # let user override above default options
            if self.websocket_options:
                protocol_options.update(self.websocket_options)

            # set websocket protocol options on Autobahn/Twisted protocol factory, from where it will
            # be applied for every Autobahn/Twisted protocol instance from the factory
            transport_factory.setProtocolOptions(**protocol_options)

        # supress pointless log noise
        transport_factory.noisy = False

        if endpoint:
            client = endpoint
        else:
            # 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)

        # 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):
            self._connect_successes += 1
            reactor.addSystemEventTrigger('before', 'shutdown', cleanup, proto)
            return proto

        use_service = False
        if auto_reconnect:
            try:
                # since Twisted 16.1.0
                from twisted.application.internet import ClientService
                from twisted.application.internet import backoffPolicy
                use_service = True
            except ImportError:
                use_service = False

        if use_service:
            # this code path is automatically reconnecting ..
            self.log.debug('using t.a.i.ClientService')

            if (self.max_retries is not None
                    or self.initial_retry_delay is not None
                    or self.max_retry_delay is not None
                    or self.retry_delay_growth is not None
                    or self.retry_delay_jitter is not None):

                if self.max_retry_delay > 0:
                    kwargs = {}

                    def _jitter():
                        j = 1 if self.retry_delay_jitter is None else self.retry_delay_jitter
                        return random.random() * j

                    for key, val in [('initialDelay',
                                      self.initial_retry_delay),
                                     ('maxDelay', self.max_retry_delay),
                                     ('factor', self.retry_delay_growth),
                                     ('jitter', _jitter)]:
                        if val is not None:
                            kwargs[key] = val

                    # retry policy that will only try to reconnect if we connected
                    # successfully at least once before (so it fails on host unreachable etc ..)
                    def retry(failed_attempts):
                        if self._connect_successes > 0 and (
                                self.max_retries == -1
                                or failed_attempts < self.max_retries):
                            return backoffPolicy(**kwargs)(failed_attempts)
                        else:
                            print('hit stop')
                            self.stop()
                            return 100000000000000
                else:
                    # immediately reconnect (zero delay)
                    def retry(_):
                        return 0
            else:
                retry = backoffPolicy()

            # https://twistedmatrix.com/documents/current/api/twisted.application.internet.ClientService.html
            self._client_service = ClientService(client,
                                                 transport_factory,
                                                 retryPolicy=retry)
            self._client_service.startService()

            d = self._client_service.whenConnected()

        else:
            # this code path is only connecting once!
            self.log.debug('using t.i.e.connect()')

            d = client.connect(transport_factory)

        # 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 the ApplicationSession sets an "error" key on the self.config.extra dictionary, which
            # has been set to the self.extra dictionary, extract the Exception from that and re-raise
            # it as the very last one (see below) exciting back to the caller of self.run()
            app_error = self.extra.get('error', None)

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

        else:
            # let the caller handle any errors
            return d
コード例 #14
0
if __name__ == '__main__':
    USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36"
    url = 'wss://premws-pt3.365lpodds.com/zap/'

    factory = WebSocketClientFactory(
        url, useragent=USER_AGENT, protocols=['zap-protocol-v1'])
    factory.protocol = MyClientProtocol
    factory.headers = {}

    factory.session_id = get_session_id()

    def accept(response):
        if isinstance(response, PerMessageDeflateResponse):
            return PerMessageDeflateResponseAccept(response)
    factory.setProtocolOptions(perMessageCompressionAccept=accept)
    factory.setProtocolOptions(perMessageCompressionOffers=[PerMessageDeflateOffer(
        accept_max_window_bits=True,
        accept_no_context_takeover=True,
        request_max_window_bits=0,
        request_no_context_takeover=True,
    )])
    # reactor.callFromThread(connectWS, factory)
    # reactor.run()
    if factory.isSecure:
        contextFactory = ssl.ClientContextFactory()
    else:
        contextFactory = None
    connectWS(factory, contextFactory)
    reactor.run()