Opened 6 years ago

Closed 6 years ago

#267 closed enhancement (fixed)

add rref.getConnectionInfo ?

Reported by: Brian Warner Owned by:
Priority: major Milestone: 0.12.5
Component: network Version: 0.12.3
Keywords: Cc:

Description

In tahoe#2818, dawuud noticed that the Tahoe "connected servers" list was rendering ugly things like UNIXAddress('/var/run/tor/socks') for servers which had used a (unix-domain) Tor SOCKS connection handler. This display uses rref.getPeer(), which usually returns a twisted.internet.address.IPv4Address. That ticket is about switching tahoe to use rref.getLocationHints() instead, which provides more information about the intended target of the original FURL.

(Tahoe client+server nodes used to run client data over a TCP connection initiated by the server, since they used to share a Tub for both purposes. So getPeer() was handy to discover whether you were using an outbound connection to them, or re-using an inbound connection they'd made to you. But Tahoe doesn't use the same Tub for those two purposes anymore, so it no longer needs a way to display the distinction)

However it would be useful (and perhaps comforting) to report exactly *how* the server connection was made: which connection handler was in charge. E.g. it'd be nice to know that we're using Tor to connect to a TCP hint.

So maybe we should add a new API, like rref.getConnectionInfo(), which would report:

  • which hint was successful
  • which connection handler managed that hint (as a short string)

It might be interesting to include when the connection was established, but we've already got rref.getDataLastReceivedAt, which is arguably more precise (connections being an illusion, after all).

Maybe rref.describeConnection(), which could return a string like tcp(HOST:PORT) or tor(HOST:PORT). This string would be provided by the connection handler by a new API (a sibiling of hint_to_endpoint) that would take the hint and return a string (independent of returning an endpoint). Or maybe we change the hint_to_endpoint API to return a 3-tuple (negotiation_hostname, endpoint, description). For backwards compatibility, we could either add a new method name, or use the old one but add a kwarg to ask for the 3-tuple instead of the old 2-tuple. In any case, these description strings would be fetched when we get the endpoint, then stored on the Broker if/when the endpoint wins negotiation, so we don't keep a reference to the connection handler after all the endpoints have been generated.

Would it be useful for the caller to get parsed components of the description? The handler name could work this way, but the other information might be very handler-specific (tcp and tor have HOST and PORT, i2p has HOST but PORT is optional, and other transports in the future might not have HOST or PORT at all). Maybe a dictionary that has "description" as a composite string, "handler" as a string, and other arguments that depend on the handler type. So renderers could do specific things if they recognize the handler, but fall back on the composite string if they don't.

Change History (5)

comment:1 Changed 6 years ago by Brian Warner

It occurred to me that we might combine this with #268 (error indicators for Reconnectors). I'm thinking we could define a new ConnectionStatus object, which can tell you:

  • is the connection established, or lost
  • if established, which hint was used, and which handler. (or which Listener, if it got established via an inbound connection)
  • if lost, what was the Failure

For #267 we'd add rref.getConnectionStatus that would return one of these things. For #268, we'd add a new .connectTo method whose callback would get two arguments:

  • rref or None
  • ConnectionStatus

Each time the reconnector tried and failed, the callback would be fired with (None, CS), and CS.established would be False, and CS.failure would be the Failure. If it tries and succeeds, the callback fires with (rref, CS), and CS.established would be True, and CS.something would provide the hint/handler/listener info.

I'm leaning against having ConnectionStatus be "live" (meaning it would delegate its properties to the possibly-disconnected Broker, so it's "established" state might change over time when the connection is lost). Instead, it'd be a passive snapshot of connection state, only accurate to the moment you called getConnectionStatus. Its properties would be simple attributes, rather than method calls.

If you call rref.callRemote() and get an errback with DeadReferenceError, then any subsequent rref.getConnectionStatus().established will be False.

comment:2 Changed 6 years ago by Brian Warner

Milestone: eventually0.12.4

comment:3 Changed 6 years ago by Brian Warner

Milestone: 0.12.40.12.5

Ticket retargeted after milestone closed

comment:4 Changed 6 years ago by Brian Warner

Implemented in [5a62fbe404]. I went with a more static approach (instead of callbacks): whenever the application wants to render the status, it fetches a fresh ConnectionInfo object, and queries its properties. I used getter methods, but I could be convinced to replace them with simple attributes (since everything is static, and there's no need to do any work each time the state is queried).

comment:5 Changed 6 years ago by Brian Warner

Resolution: fixed
Status: newclosed

Ok, I'm satisfied with how this one is working, closing this now.

Note: See TracTickets for help on using tickets.