Give the hotspot's owner a route to its guests too
Binding the join socket to the Wi-Fi network covers a phone that has joined a hotspot. It does nothing for the phone that is sharing one: that phone has no Wi-Fi *client* network, so there was nothing to bind to and the code gave up — leaving the socket on the default network, which is mobile data, and a connection to a guest going out over cellular to die. ConnectivityManager does not offer the tethering interface as a Network, so there is no network to name. Binding this end of the socket to one of our own addresses on the guest's subnet picks the route instead, which is the only lever available. The subnet test assumes a /24, which every Android hotspot hands out, and getting it wrong costs a bind that would not have helped anyway. This is the direction that was left broken: the owner of the hotspot trying to join a game hosted by one of its guests. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_0132V9gE6DF9itz2z3Hn7BK9
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
package org.prolibertate.games.net
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
@@ -103,4 +105,32 @@ class ManualAddressTest {
|
||||
val shown = HostEndpoint(listOf("192.168.43.1"), 47654).primary!!
|
||||
assertEquals(ManualAddress("192.168.43.1", 47654), parseManualAddress(shown))
|
||||
}
|
||||
|
||||
// -- Choosing which of our own addresses to send from --------------------
|
||||
|
||||
/**
|
||||
* The phone sharing the hotspot has no Wi-Fi network to bind to, so it
|
||||
* picks a source address on the guest's subnet instead. Getting this wrong
|
||||
* sends the connection out over mobile data.
|
||||
*/
|
||||
@Test
|
||||
fun `addresses on one hotspot subnet match`() {
|
||||
assertTrue(sameSubnet("192.168.43.1", "192.168.43.117"))
|
||||
assertTrue(sameSubnet("192.168.1.20", "192.168.1.20"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `addresses on different subnets do not`() {
|
||||
assertFalse(sameSubnet("192.168.43.1", "192.168.1.5"))
|
||||
assertFalse(sameSubnet("192.168.43.1", "10.0.0.5"))
|
||||
}
|
||||
|
||||
/** Anything that is not a dotted quad is not a match, rather than a crash. */
|
||||
@Test
|
||||
fun `nonsense is not a match`() {
|
||||
assertFalse(sameSubnet("", "192.168.43.1"))
|
||||
assertFalse(sameSubnet("192.168.43", "192.168.43.1"))
|
||||
assertFalse(sameSubnet("pixel-9.local", "192.168.43.1"))
|
||||
assertFalse(sameSubnet("192.168.43.1.7", "192.168.43.1"))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user