`UdsChannelBuilder` does not work with WiFi Proxy on Android
UdsChannelBuilder does not work with WiFi Proxy on Android.
What version of gRPC-Java are you using?
1.70.0
What is your environment?
Android
What did you expect to see?
gRPC connection to work
What did you see instead?
TRANSIENT_FAILURE
[{0}] Failed to resolve name. status={1}
[{0}] Failed to resolve name. status={1}
[{0}] Failed to resolve name. status={1}
[{0}] Failed to resolve name. status={1}
[{0}] Failed to resolve name. status={1}
[{0}] Failed to resolve name. status={1}
[{0}] Failed to resolve name. status={1}
Steps to reproduce the bug
Setup UdsChannelBuilder and connect to a server.
Connect to a WiFi on Android
On the WiFi you are connected press the pen symbol to add a proxy
Add a dummy proxy
The UdsChannelBuilder will be unable to connect and ends up in TRANSIENT_FAILURE state.
I've managed to find a workaround by setting proxyDetector to be null:
private val channel =
UdsChannelBuilder.forPath(
rpcSocketFile.absolutePath,
LocalSocketAddress.Namespace.FILESYSTEM,
)
.proxyDetector { null }
.build()
Adding a log to the proxy detector I can see that a lookup happens:
Proxy detector invoked for: 127.0.0.1/<unresolved>:80
I believe the bug goes as follows:
Under the hood the UdsChannelBuilder uses a ManagedChannelImpl, however it with a bit of a hack uses 127.0.0.1, see here https://github.com/grpc/grpc-java/blob/57124d6b29d180de2ab7f21baeb4a2246e490c1a/android/src/main/java/io/grpc/android/UdsChannelBuilder.java#L79
By default if no ProxyDetector is set but if none is set a default is applied in ManagedChannelImpl here https://github.com/grpc/grpc-java/blob/57124d6b29d180de2ab7f21baeb4a2246e490c1a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java#L579
So default proxy detector will then yield an error when trying to lookup 127.0.0.1, maybe because internet didn't work through the proxy? My guess is that this is then emitted as an error and thus it enters here https://github.com/grpc/grpc-java/blob/57124d6b29d180de2ab7f21baeb4a2246e490c1a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java#L1836 where it logs the error and also puts the channel in TransientFailure.
I'm not sure about the best way to address this, it is a bit weird that the entire stack depends on IP, especially for UDS. So that is a bit hard to change, I guess one could provide an empty proxyDetector by default like I did in my workaround above.
A UDS name resolver wouldn't check the proxySelector, so disabling the proxy selector (setting a noop) sounds fine. It is annoying we don't know what error actually happened, though.
I guess one could provide an empty proxyDetector by default like I did in my workaround above
Contribution is welcome if you are so inclined.
If WiFi Proxy is configured and pointing to a domain name, and yet the network is completely busted, then I can see ProxySelector unconditionally saying to proxy, then ProxyDetectorImpl resolving the proxy's address. But if the network is busted, then that fails. Maybe that's not what's being experienced, but it at least looks possible and would explain why a hard-coded IP address could still fail. And that behavior doesn't seem wrong in general, only wrong in this case we were going to throw away the result.
We actually have enough plumbing now we can make a UDS name resolver, but disabling the proxy detector is probably a fair workaround.