AutobahnPython w/Twisted: ssl.optionsForClientTLS on websocket.WampWebSocketClientFactory

768 views Asked by At

I'm unable to use 'applicationRunner' because it doesn't support auto-reconnect (GitHub Issues: #295 #389) for websockets. I've reverted to the deprecated approach that uses twisted 'ReconnectingClientFactory'. My issue is that this approach doesn't seem to allow me to add 'ssl.optionsForClientTLS' for strict verification of server hostname and certificate. Is there any way to accomplish this?

Really appreciate any feedback!

class MyClientFactory(websocket.WampWebSocketClientFactory, ReconnectingClientFactory):
    maxDelay = config.maxretry

    def clientConnectionFailed(self, connector, reason):
        logging.debug("Connection Failed: %s", reason)
        ReconnectingClientFactory.clientConnectionFailed(self, connector, reason)

    def clientConnectionLost(self, connector, reason):
        logging.debug("Connection Lost: %s", reason)
        ReconnectingClientFactory.clientConnectionLost(self, connector, reason)

def start():
    log.startLogging(sys.stdout)

    component_config = types.ComponentConfig()
    session_factory = wamp.ApplicationSessionFactory(config=component_config)
    session_factory.session = MyFrontendComponent

    transport_factory = MyClientFactory(session_factory, 'wss://services:8443/ws', debug=True)

    transport_factory.debug = True
    transport_factory.debugCodePaths = True

    websocket.connectWS(transport_factory)

    Thread(target=reactor.run, args=(False,)).start()
1

There are 1 answers

0
50MilesToGo On

Nevermind, figured it out... hopefully this helps anyone else facing the same problem. Turns out 'connectWS' accepts a 'contextFactory' with 'optionsForClientTLS'. Now we have a auto-reconnecting WebSocket with strict certificate validation:

    class MyClientFactory(websocket.WampWebSocketClientFactory, ReconnectingClientFactory):
    maxDelay = 30

    def clientConnectionFailed(self, connector, reason):
        logging.debug("Connection Failed: %s", reason)
        self.retry(connector)

    def clientConnectionLost(self, connector, reason):
        logging.debug("Connection Lost: %s", reason)
        self.retry(connector)


def start():
    log.startLogging(sys.stdout)

    component_config = types.ComponentConfig()
    session_factory = wamp.ApplicationSessionFactory(config=component_config)
    session_factory.session = MyFrontendComponent

    transport_factory = MyClientFactory(session_factory, 'wss://services:8443/ws', debug=True)

    transport_factory.debug = True
    transport_factory.debugCodePaths = True

    context_factory = None

    if transport_factory.isSecure:
        certData = getModule(__name__).filePath.sibling('server_cert.pem').getContent()
        authority = ssl.Certificate.loadPEM(certData)
        context_factory = ssl.optionsForClientTLS(u'services', authority)

    websocket.connectWS(transport_factory, context_factory)

    Thread(target=reactor.run, args=(False,)).start()