Various bugfix for Wi-Fi direct mode

This commit is contained in:
Mygod
2018-01-05 01:33:03 +08:00
parent 7e30ddf26d
commit 62449a98ea
4 changed files with 37 additions and 26 deletions

View File

@@ -63,21 +63,9 @@ class HotspotService : Service(), WifiP2pManager.ChannelListener {
val service get() = this@HotspotService val service get() = this@HotspotService
var data: MainActivity.Data? = null var data: MainActivity.Data? = null
fun shutdown() { fun shutdown() = when (status) {
when (status) { Status.ACTIVE_P2P -> removeGroup()
Status.ACTIVE_P2P -> p2pManager.removeGroup(channel, object : WifiP2pManager.ActionListener { else -> clean()
override fun onSuccess() = clean()
override fun onFailure(reason: Int) {
if (reason == WifiP2pManager.BUSY) clean() else { // assuming it's already gone
Toast.makeText(this@HotspotService, "Failed to remove P2P group (${formatReason(reason)})",
Toast.LENGTH_SHORT).show()
LocalBroadcastManager.getInstance(this@HotspotService)
.sendBroadcast(Intent(STATUS_CHANGED))
}
}
})
else -> clean()
}
} }
} }
@@ -199,10 +187,10 @@ class HotspotService : Service(), WifiP2pManager.ChannelListener {
return START_NOT_STICKY return START_NOT_STICKY
} }
private fun startFailure(msg: String) { private fun startFailure(msg: String, group: WifiP2pGroup? = null) {
Toast.makeText(this@HotspotService, msg, Toast.LENGTH_SHORT).show() Toast.makeText(this@HotspotService, msg, Toast.LENGTH_SHORT).show()
showNotification() showNotification()
clean() if (group != null) removeGroup() else clean()
} }
private fun doStart() = p2pManager.createGroup(channel, object : WifiP2pManager.ActionListener { private fun doStart() = p2pManager.createGroup(channel, object : WifiP2pManager.ActionListener {
override fun onFailure(reason: Int) = startFailure("Failed to create P2P group (${formatReason(reason)})") override fun onFailure(reason: Int) = startFailure("Failed to create P2P group (${formatReason(reason)})")
@@ -234,15 +222,28 @@ class HotspotService : Service(), WifiP2pManager.ChannelListener {
val routing = try { val routing = try {
Routing(upstream, downstream, owner) Routing(upstream, downstream, owner)
} catch (_: Routing.InterfaceNotFoundException) { } catch (_: Routing.InterfaceNotFoundException) {
startFailure(getString(R.string.exception_interface_not_found)) startFailure(getString(R.string.exception_interface_not_found), group)
return return
}.p2pRule().forward().dnsRedirect(dns) }.p2pRule().forward().dnsRedirect(dns)
if (routing.start()) { if (routing.start()) {
this.routing = routing this.routing = routing
doStart(group) doStart(group)
} else startFailure("Something went wrong, please check logcat.") } else startFailure("Something went wrong, please check logcat.", group)
} }
private fun removeGroup() {
p2pManager.removeGroup(channel, object : WifiP2pManager.ActionListener {
override fun onSuccess() = clean()
override fun onFailure(reason: Int) {
if (reason == WifiP2pManager.BUSY) clean() else { // assuming it's already gone
Toast.makeText(this@HotspotService, "Failed to remove P2P group (${formatReason(reason)})",
Toast.LENGTH_SHORT).show()
status = Status.ACTIVE_P2P
LocalBroadcastManager.getInstance(this@HotspotService).sendBroadcast(Intent(STATUS_CHANGED))
}
}
})
}
private fun unregisterReceiver() { private fun unregisterReceiver() {
if (receiverRegistered) { if (receiverRegistered) {
unregisterReceiver(receiver) unregisterReceiver(receiver)

View File

@@ -87,7 +87,7 @@ class MainActivity : AppCompatActivity(), ServiceConnection, Toolbar.OnMenuItemC
} }
holder.binding.device = device holder.binding.device = device
holder.binding.ipAddress = when (position) { holder.binding.ipAddress = when (position) {
0 -> binder?.service?.routing?.hostAddress 0 -> binder?.service?.routing?.hostAddress?.hostAddress
else -> arpCache[device?.deviceAddress] else -> arpCache[device?.deviceAddress]
} }
holder.binding.executePendingBindings() holder.binding.executePendingBindings()

View File

@@ -20,7 +20,7 @@ class Routing(private val upstream: String, val downstream: String, ownerAddress
class InterfaceNotFoundException : IOException() class InterfaceNotFoundException : IOException()
val hostAddress: String val hostAddress: InetAddress
private val subnetPrefixLength: Short private val subnetPrefixLength: Short
private val startScript = LinkedList<String>() private val startScript = LinkedList<String>()
private val stopScript = LinkedList<String>() private val stopScript = LinkedList<String>()
@@ -28,19 +28,28 @@ class Routing(private val upstream: String, val downstream: String, ownerAddress
val address = NetworkInterface.getByName(downstream)?.interfaceAddresses val address = NetworkInterface.getByName(downstream)?.interfaceAddresses
?.singleOrNull { if (ownerAddress == null) it.address is Inet4Address else it.address == ownerAddress } ?.singleOrNull { if (ownerAddress == null) it.address is Inet4Address else it.address == ownerAddress }
?: throw InterfaceNotFoundException() ?: throw InterfaceNotFoundException()
hostAddress = address.address.hostAddress hostAddress = address.address
subnetPrefixLength = address.networkPrefixLength subnetPrefixLength = address.networkPrefixLength
} }
fun p2pRule(): Routing { fun p2pRule(): Routing {
// clear suffix bits
val address = hostAddress.address
var done = subnetPrefixLength.toInt()
while (done < address.size shl 3) {
val index = done shr 3
address[index] = (address[index].toInt() and (0x7f00 shr (done and 7))).toByte()
done = (index + 1) shl 3
}
val hostAddress = InetAddress.getByAddress(address).hostAddress
startScript.add("echo 1 >/proc/sys/net/ipv4/ip_forward") // Wi-Fi direct doesn't enable ip_forward startScript.add("echo 1 >/proc/sys/net/ipv4/ip_forward") // Wi-Fi direct doesn't enable ip_forward
startScript.add("ip route add default dev $upstream scope link table 62") startScript.add("ip route add default dev $upstream scope link table 62")
startScript.add("ip route add $hostAddress/$subnetPrefixLength dev $downstream scope link table 62") startScript.add("ip route add $hostAddress/$subnetPrefixLength dev $downstream scope link table 62")
startScript.add("ip route add broadcast 255.255.255.255 dev $downstream scope link table 62") startScript.add("ip route add broadcast 255.255.255.255 dev $downstream scope link table 62")
startScript.add("ip rule add iif $downstream lookup 62") startScript.add("ip rule add iif $downstream lookup 62")
stopScript.addFirst("ip route del default dev $upstream scope link table 62") stopScript.addFirst("ip route del default dev $upstream scope link table 62")
stopScript.addFirst("ip route del $hostAddress/$subnetPrefixLength dev $downstream scope link table 62") // removing each rule may fail if downstream is already removed
stopScript.addFirst("ip route del broadcast 255.255.255.255 dev $downstream scope link table 62") stopScript.addFirst("ip route flush table 62")
stopScript.addFirst("ip rule del iif $downstream lookup 62") stopScript.addFirst("ip rule del iif $downstream lookup 62")
return this return this
} }
@@ -65,6 +74,7 @@ class Routing(private val upstream: String, val downstream: String, ownerAddress
} }
fun dnsRedirect(dns: String): Routing { fun dnsRedirect(dns: String): Routing {
val hostAddress = hostAddress.hostAddress
startScript.add("iptables -t nat -A PREROUTING -i $downstream -p tcp -d $hostAddress --dport 53 -j DNAT --to-destination $dns") startScript.add("iptables -t nat -A PREROUTING -i $downstream -p tcp -d $hostAddress --dport 53 -j DNAT --to-destination $dns")
startScript.add("iptables -t nat -A PREROUTING -i $downstream -p udp -d $hostAddress --dport 53 -j DNAT --to-destination $dns") startScript.add("iptables -t nat -A PREROUTING -i $downstream -p udp -d $hostAddress --dport 53 -j DNAT --to-destination $dns")
stopScript.addFirst("iptables -t nat -D PREROUTING -i $downstream -p tcp -d $hostAddress --dport 53 -j DNAT --to-destination $dns") stopScript.addFirst("iptables -t nat -D PREROUTING -i $downstream -p tcp -d $hostAddress --dport 53 -j DNAT --to-destination $dns")

View File

@@ -23,8 +23,8 @@ fun Bundle.put(key: String, map: Array<String>): Bundle {
return this return this
} }
const val NOISYSU_TAG = "NoisySU" private const val NOISYSU_TAG = "NoisySU"
const val NOISYSU_SUFFIX = "SUCCESS\n" private const val NOISYSU_SUFFIX = "SUCCESS\n"
fun loggerSuStream(command: String): InputStream { fun loggerSuStream(command: String): InputStream {
val process = ProcessBuilder("su", "-c", command) val process = ProcessBuilder("su", "-c", command)
.redirectErrorStream(true) .redirectErrorStream(true)