irmen / Pyro5

Pyro 5 - Python remote objects
https://pyro5.readthedocs.io
MIT License
305 stars 36 forks source link

Please provide an method to retrieve local IP address of a connected Proxy object #38

Closed eudoxos closed 2 years ago

eudoxos commented 3 years ago

This is an enhancement request for steamlined functioning in zero-configuration setups.

I often need to expose an object to a non-localhost network interface (which IP address is it? I use some heuristics for that) and then register it to the nameserver (discovered via broadcast), like this:

ip=guessLocalIP(ip)
daemon=Pyro5.api.Daemon(host=ip,port=0,...)
uri=daemon.register(object)
ns=Pyro5.api.locate_ns()
ns.register('objectName',uri)

This will obviously fail for more complex networking setup.

I could expose the daemon on 0.0.0.0 but then the URI is not working, although the port is technically bound and reachable.

It is reasonable to suppose that the nameserver is on the same network as where the Daemon wants to be (that's the point, after all), so extracting local IP from the nameserver proxy should be very reliable:

ns=Pyro5.api.locate_ns()
daemon=Pyro5.api.Daemon(host=ns._getLocalIP(),port=0,...)
uri=daemon.register(object)
ns.register('objectName',uri)

I am aware that I could call ns._pyroConnection.sock.getsockname()[0] but having that exposed in the API looks like a good idea to me.

irmen commented 3 years ago

I think what you want is already exposed in the API. It may be a bit hidden though. https://pyro5.readthedocs.io/en/latest/tipstricks.html?highlight=client_sock_addr#Pyro5.current_context.client_sock_addr

Also look at the 'callcontext' example, it shows how it can be used.

Is this what you mean?

eudoxos commented 3 years ago

I am not sure that is what I am after. The callcontext example create Proxy to an already existing URI, whereas I do not know the URI yet: it contains IP not yet known unde which I am reachable from the NS.

If it is not clear yet, the scenario is like this. There is a NS running somewhere, I can discover it via locate_ns. I want to create a local Daemon and register it on the NS (so that it can be found and contacted by other clients) but don't know the correct local IP address. I can go around guessing it, or just get it from the NS connection itself.

Would you consider exposing the (host,port) tuple in Proxy._pyroConnection.sock.getsockname() (host,port tuple) as a part of the API, e.g. as Proxy._pyroLocalSocket property?

irmen commented 3 years ago

Before thinking about changing the API, what about this routine, which tries to give you a "externally visible local IP address":

https://pyro5.readthedocs.io/en/latest/api/socketutil.html#Pyro5.socketutil.get_ip_address

irmen commented 3 years ago

@eudoxos have you tried my suggestion? Would it work?

eudoxos commented 3 years ago

I tried what you suggested, though it seems like a workaround in the case that there is a bound connection to the NS already (get_ip_address creates a connection to find the IP address). Thanks for the pointer to the function, I can think of places where it is useful, but in that particular case I still stick to _pyroConnection.sock.

irmen commented 2 years ago

added the _pyroLocalSocket property.