crossbario / autobahn-python

WebSocket and WAMP in Python for Twisted and asyncio
https://crossbar.io/autobahn
MIT License
2.48k stars 766 forks source link

Router discovery over DNS-SD #334

Open oberstet opened 9 years ago

oberstet commented 9 years ago

With classic RPC, the caller needs to know how to address each and every callee it wants to call. With WAMP routed RPC, the client (acting as a caller) only needs to know how to address it's upstream router. You are right, it still needs this bit of info. Today, the recommended way would be using a command line argument providing the hostname or URL of the router to connect to. Or hardcoding would work of course also. I agree that it would be nice to be able to use something like Zeroconf (http://en.wikipedia.org/wiki/Zero-configuration_networking) instead. However, this is not related to WAMP as a protocol, but the WAMP client library implementation that needs to provide that feature. Establishing a WAMP transport (which includes finding the necessary info bits) is outside the WAMP protocol itself.

http://en.wikipedia.org/wiki/Zero-configuration_networking#DNS-based_service_discovery

oberstet commented 9 years ago

The idea would be: a WAMP client runs on a host. The host has it's IP, DNS servers and and it's Domain handed out by DHCP. Then it asks DNS for "WAMP Routing Service" for it's Domain. And that is supposed to hand out the URL of the WAMP router to connect to.

That cool, it's not enough: most likely, the client will need to authenticate at the router. Which brings up the question where to get the auth credentials from.

raveslave commented 9 years ago

The challenge here is https/wss on local networks, i.e. home appliances / "iot devices" which can't have real certificates as they'll be accessed either via an IP-no or dynamic hostname.

Looping traffic via a public centralised server would work but not ideal as many applications will need this working when offline as well. Tricky one... Any thoughs / ideas?

oberstet commented 7 years ago

Here is an example of a service announcing using https://github.com/jstasiak/python-zeroconf:

from zeroconf import ServiceInfo, Zeroconf

class WebSocketManager(service.Service, object):
    ws_service_name = 'Verasonics WebSocket'
    wsPort = None
    wsInfo = None

    def __init__(self, factory, portCallback):
        factory.protocol = BroadcastServerProtocol
        self.factory = factory
        self.portCallback = portCallback
        self.zeroconf = Zeroconf()

    def privilegedStartService(self):
        self.wsPort = reactor.listenTCP(0, self.factory)
        port = self.wsPort.getHost().port

        fqdn = socket.gethostname()
        ip_addr = socket.gethostbyname(fqdn)
        hostname = fqdn.split('.')[0]

        wsDesc = {'service': 'Verasonics Frame', 'version': '1.0.0'}
        self.wsInfo = ServiceInfo('_verasonics-ws._tcp.local.',
                                  hostname + ' ' + self.ws_service_name + '._verasonics-ws._tcp.local.',
                                  socket.inet_aton(ip_addr), port, 0, 0,
                                  wsDesc, hostname + '.local.')
        self.zeroconf.register_service(self.wsInfo)
        self.portCallback(port)

        return super(WebSocketManager, self).privilegedStartService()

    def stopService(self):
        self.zeroconf.unregister_service(self.wsInfo)

        self.wsPort.stopListening()
        return super(WebSocketManager , self).stopService()