Move MAC utils to MacAddressCompat
This commit is contained in:
@@ -9,16 +9,16 @@ import be.mygod.vpnhotspot.App.Companion.app
|
||||
import be.mygod.vpnhotspot.R
|
||||
import be.mygod.vpnhotspot.net.InetAddressComparator
|
||||
import be.mygod.vpnhotspot.net.IpNeighbour
|
||||
import be.mygod.vpnhotspot.net.MacAddressCompat
|
||||
import be.mygod.vpnhotspot.net.TetherType
|
||||
import be.mygod.vpnhotspot.room.AppDatabase
|
||||
import be.mygod.vpnhotspot.room.ClientRecord
|
||||
import be.mygod.vpnhotspot.room.macToString
|
||||
import be.mygod.vpnhotspot.util.makeIpSpan
|
||||
import be.mygod.vpnhotspot.util.makeMacSpan
|
||||
import java.net.InetAddress
|
||||
import java.util.*
|
||||
|
||||
open class Client(val mac: Long, val iface: String) {
|
||||
open class Client(val mac: MacAddressCompat, val iface: String) {
|
||||
companion object DiffCallback : DiffUtil.ItemCallback<Client>() {
|
||||
override fun areItemsTheSame(oldItem: Client, newItem: Client) =
|
||||
oldItem.iface == newItem.iface && oldItem.mac == newItem.mac
|
||||
@@ -26,7 +26,7 @@ open class Client(val mac: Long, val iface: String) {
|
||||
}
|
||||
|
||||
val ip = TreeMap<InetAddress, IpNeighbour.State>(InetAddressComparator)
|
||||
val macString by lazy { mac.macToString() }
|
||||
val macString by lazy { mac.toString() }
|
||||
private val record = AppDatabase.instance.clientRecordDao.lookupOrDefaultSync(mac)
|
||||
private val macIface get() = SpannableStringBuilder(makeMacSpan(macString)).apply {
|
||||
append('%')
|
||||
@@ -65,7 +65,7 @@ open class Client(val mac: Long, val iface: String) {
|
||||
}.trimEnd()
|
||||
}
|
||||
|
||||
fun obtainRecord() = record.value ?: ClientRecord(mac)
|
||||
fun obtainRecord() = record.value ?: ClientRecord(mac.addr)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
|
||||
@@ -10,11 +10,11 @@ import androidx.lifecycle.ViewModel
|
||||
import be.mygod.vpnhotspot.App.Companion.app
|
||||
import be.mygod.vpnhotspot.RepeaterService
|
||||
import be.mygod.vpnhotspot.net.IpNeighbour
|
||||
import be.mygod.vpnhotspot.net.MacAddressCompat
|
||||
import be.mygod.vpnhotspot.net.TetheringManager
|
||||
import be.mygod.vpnhotspot.net.TetheringManager.localOnlyTetheredIfaces
|
||||
import be.mygod.vpnhotspot.net.TetheringManager.tetheredIfaces
|
||||
import be.mygod.vpnhotspot.net.monitor.IpNeighbourMonitor
|
||||
import be.mygod.vpnhotspot.room.macToLong
|
||||
import be.mygod.vpnhotspot.util.broadcastReceiver
|
||||
|
||||
class ClientViewModel : ViewModel(), ServiceConnection, IpNeighbourMonitor.Callback {
|
||||
@@ -31,15 +31,15 @@ class ClientViewModel : ViewModel(), ServiceConnection, IpNeighbourMonitor.Callb
|
||||
val clients = MutableLiveData<List<Client>>()
|
||||
|
||||
private fun populateClients() {
|
||||
val clients = HashMap<Pair<String, Long>, Client>()
|
||||
val clients = HashMap<Pair<String, MacAddressCompat>, Client>()
|
||||
val group = repeater?.group
|
||||
val p2pInterface = group?.`interface`
|
||||
if (p2pInterface != null) {
|
||||
for (client in p2p) clients[Pair(p2pInterface, client.deviceAddress.macToLong())] =
|
||||
for (client in p2p) clients[p2pInterface to MacAddressCompat.fromString(client.deviceAddress)] =
|
||||
WifiP2pClient(p2pInterface, client)
|
||||
}
|
||||
for (neighbour in neighbours) {
|
||||
val key = Pair(neighbour.dev, neighbour.lladdr)
|
||||
val key = neighbour.dev to neighbour.lladdr
|
||||
var client = clients[key]
|
||||
if (client == null) {
|
||||
if (!tetheredInterfaces.contains(neighbour.dev)) continue
|
||||
|
||||
@@ -30,13 +30,13 @@ import be.mygod.vpnhotspot.Empty
|
||||
import be.mygod.vpnhotspot.R
|
||||
import be.mygod.vpnhotspot.databinding.FragmentClientsBinding
|
||||
import be.mygod.vpnhotspot.databinding.ListitemClientBinding
|
||||
import be.mygod.vpnhotspot.net.MacAddressCompat
|
||||
import be.mygod.vpnhotspot.net.TetherType
|
||||
import be.mygod.vpnhotspot.net.monitor.IpNeighbourMonitor
|
||||
import be.mygod.vpnhotspot.net.monitor.TrafficRecorder
|
||||
import be.mygod.vpnhotspot.room.AppDatabase
|
||||
import be.mygod.vpnhotspot.room.ClientStats
|
||||
import be.mygod.vpnhotspot.room.TrafficRecord
|
||||
import be.mygod.vpnhotspot.room.macToString
|
||||
import be.mygod.vpnhotspot.util.SpanFormatter
|
||||
import be.mygod.vpnhotspot.util.toPluralInt
|
||||
import be.mygod.vpnhotspot.widget.SmartSnackbar
|
||||
@@ -46,11 +46,11 @@ import java.text.NumberFormat
|
||||
|
||||
class ClientsFragment : Fragment() {
|
||||
@Parcelize
|
||||
data class NicknameArg(val mac: Long, val nickname: CharSequence) : Parcelable
|
||||
data class NicknameArg(val mac: MacAddressCompat, val nickname: CharSequence) : Parcelable
|
||||
class NicknameDialogFragment : AlertDialogFragment<NicknameArg, Empty>() {
|
||||
override fun AlertDialog.Builder.prepare(listener: DialogInterface.OnClickListener) {
|
||||
setView(R.layout.dialog_nickname)
|
||||
setTitle(getString(R.string.clients_nickname_title, arg.mac.macToString()))
|
||||
setTitle(getString(R.string.clients_nickname_title, arg.mac.toString()))
|
||||
setPositiveButton(android.R.string.ok, listener)
|
||||
setNegativeButton(android.R.string.cancel, null)
|
||||
setNeutralButton(emojize(getText(R.string.clients_nickname_set_to_vendor)), listener)
|
||||
@@ -153,7 +153,7 @@ class ClientsFragment : Fragment() {
|
||||
withContext(Dispatchers.Unconfined) {
|
||||
StatsDialogFragment().withArg(StatsArg(
|
||||
client.title.value ?: return@withContext,
|
||||
AppDatabase.instance.trafficRecordDao.queryStats(client.mac)
|
||||
AppDatabase.instance.trafficRecordDao.queryStats(client.mac.addr)
|
||||
)).show(this@ClientsFragment)
|
||||
}
|
||||
}
|
||||
@@ -181,7 +181,7 @@ class ClientsFragment : Fragment() {
|
||||
override fun onBindViewHolder(holder: ClientViewHolder, position: Int) {
|
||||
val client = getItem(position)
|
||||
holder.binding.client = client
|
||||
holder.binding.rate = rates.computeIfAbsent(Pair(client.iface, client.mac)) { TrafficRate() }
|
||||
holder.binding.rate = rates.computeIfAbsent(client.iface to client.mac) { TrafficRate() }
|
||||
holder.binding.executePendingBindings()
|
||||
}
|
||||
|
||||
@@ -196,7 +196,9 @@ class ClientsFragment : Fragment() {
|
||||
check(newRecord.receivedPackets == oldRecord.receivedPackets)
|
||||
check(newRecord.receivedBytes == oldRecord.receivedBytes)
|
||||
} else {
|
||||
val rate = rates.computeIfAbsent(Pair(newRecord.downstream, newRecord.mac)) { TrafficRate() }
|
||||
val rate = rates.computeIfAbsent(newRecord.downstream to MacAddressCompat(newRecord.mac)) {
|
||||
TrafficRate()
|
||||
}
|
||||
if (rate.send < 0 || rate.receive < 0) {
|
||||
rate.send = 0
|
||||
rate.receive = 0
|
||||
@@ -211,7 +213,7 @@ class ClientsFragment : Fragment() {
|
||||
|
||||
private lateinit var binding: FragmentClientsBinding
|
||||
private val adapter = ClientAdapter()
|
||||
private var rates = mutableMapOf<Pair<String, Long>, TrafficRate>()
|
||||
private var rates = mutableMapOf<Pair<String, MacAddressCompat>, TrafficRate>()
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
binding = FragmentClientsBinding.inflate(inflater, container, false)
|
||||
|
||||
@@ -5,8 +5,8 @@ import android.os.Build
|
||||
import androidx.annotation.MainThread
|
||||
import be.mygod.vpnhotspot.App.Companion.app
|
||||
import be.mygod.vpnhotspot.R
|
||||
import be.mygod.vpnhotspot.net.MacAddressCompat
|
||||
import be.mygod.vpnhotspot.room.AppDatabase
|
||||
import be.mygod.vpnhotspot.room.macToString
|
||||
import be.mygod.vpnhotspot.widget.SmartSnackbar
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
@@ -22,26 +22,26 @@ import java.net.URL
|
||||
* This class generates a default nickname for new clients.
|
||||
*/
|
||||
object MacLookup {
|
||||
class UnexpectedError(val mac: Long, val error: String) : JSONException("") {
|
||||
class UnexpectedError(val mac: MacAddressCompat, val error: String) : JSONException("") {
|
||||
private fun formatMessage(context: Context) =
|
||||
context.getString(R.string.clients_mac_lookup_unexpected_error, mac.macToString(), error)
|
||||
context.getString(R.string.clients_mac_lookup_unexpected_error, mac.toString(), error)
|
||||
override val message get() = formatMessage(app.english)
|
||||
override fun getLocalizedMessage() = formatMessage(app)
|
||||
}
|
||||
|
||||
private val macLookupBusy = mutableMapOf<Long, Pair<HttpURLConnection, Job>>()
|
||||
private val macLookupBusy = mutableMapOf<MacAddressCompat, Pair<HttpURLConnection, Job>>()
|
||||
private val countryCodeRegex = "([A-Z]{2})\\s*\$".toRegex() // http://en.wikipedia.org/wiki/ISO_3166-1
|
||||
|
||||
@MainThread
|
||||
fun abort(mac: Long) = macLookupBusy.remove(mac)?.let { (conn, job) ->
|
||||
fun abort(mac: MacAddressCompat) = macLookupBusy.remove(mac)?.let { (conn, job) ->
|
||||
job.cancel()
|
||||
if (Build.VERSION.SDK_INT >= 26) conn.disconnect() else GlobalScope.launch(Dispatchers.IO) { conn.disconnect() }
|
||||
}
|
||||
|
||||
@MainThread
|
||||
fun perform(mac: Long, explicit: Boolean = false) {
|
||||
fun perform(mac: MacAddressCompat, explicit: Boolean = false) {
|
||||
abort(mac)
|
||||
val conn = URL("https://macvendors.co/api/" + mac.macToString()).openConnection() as HttpURLConnection
|
||||
val conn = URL("https://macvendors.co/api/$mac").openConnection() as HttpURLConnection
|
||||
macLookupBusy[mac] = conn to GlobalScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
val response = conn.inputStream.bufferedReader().readText()
|
||||
@@ -69,7 +69,7 @@ object MacLookup {
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractCountry(mac: Long, response: String, obj: JSONObject): MatchResult? {
|
||||
private fun extractCountry(mac: MacAddressCompat, response: String, obj: JSONObject): MatchResult? {
|
||||
countryCodeRegex.matchEntire(obj.optString("country"))?.also { return it }
|
||||
val address = obj.optString("address")
|
||||
if (address.isBlank()) return null
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package be.mygod.vpnhotspot.client
|
||||
|
||||
import android.net.wifi.p2p.WifiP2pDevice
|
||||
import be.mygod.vpnhotspot.net.MacAddressCompat
|
||||
import be.mygod.vpnhotspot.net.TetherType
|
||||
import be.mygod.vpnhotspot.room.macToLong
|
||||
|
||||
class WifiP2pClient(p2pInterface: String, p2p: WifiP2pDevice) : Client(p2p.deviceAddress!!.macToLong(), p2pInterface) {
|
||||
class WifiP2pClient(p2pInterface: String, p2p: WifiP2pDevice) :
|
||||
Client(MacAddressCompat.fromString(p2p.deviceAddress!!), p2pInterface) {
|
||||
override val icon: Int get() = TetherType.WIFI_P2P.icon
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user