Revert "Migrate to better MAC lookup"

This reverts commit 0adb857b2d.
This commit is contained in:
Mygod
2021-05-07 14:36:49 -04:00
parent 919bfe93dc
commit 1ec73a44fb
2 changed files with 30 additions and 42 deletions

View File

@@ -12,10 +12,8 @@ import kotlinx.coroutines.*
import org.json.JSONException import org.json.JSONException
import org.json.JSONObject import org.json.JSONObject
import timber.log.Timber import timber.log.Timber
import java.io.IOException
import java.net.HttpURLConnection import java.net.HttpURLConnection
import java.net.URL import java.net.URL
import kotlin.math.max
/** /**
* This class generates a default nickname for new clients. * This class generates a default nickname for new clients.
@@ -28,63 +26,54 @@ object MacLookup {
override fun getLocalizedMessage() = formatMessage(app) override fun getLocalizedMessage() = formatMessage(app)
} }
private data class Work(@Volatile var conn: HttpURLConnection, var job: Job? = null) private val macLookupBusy = mutableMapOf<MacAddressCompat, Pair<HttpURLConnection, Job>>()
private val macLookupBusy = mutableMapOf<MacAddressCompat, Work>() private val countryCodeRegex = "([A-Z]{2})\\s*\$".toRegex() // http://en.wikipedia.org/wiki/ISO_3166-1
@MainThread @MainThread
fun abort(mac: MacAddressCompat) = macLookupBusy.remove(mac)?.let { work -> fun abort(mac: MacAddressCompat) = macLookupBusy.remove(mac)?.let { (conn, job) ->
work.job!!.cancel() job.cancel()
if (Build.VERSION.SDK_INT < 26) GlobalScope.launch(Dispatchers.IO) { if (Build.VERSION.SDK_INT < 26) GlobalScope.launch(Dispatchers.IO) {
work.conn.disconnect() conn.disconnect()
} else work.conn.disconnect() } else conn.disconnect()
} }
@MainThread @MainThread
fun perform(mac: MacAddressCompat, explicit: Boolean = false) { fun perform(mac: MacAddressCompat, explicit: Boolean = false) {
abort(mac) abort(mac)
val url = URL("https://api.maclookup.app/v2/macs/${mac.toOui()}") val conn = URL("https://macvendors.co/api/$mac").openConnection() as HttpURLConnection
val work = Work(url.openConnection() as HttpURLConnection) macLookupBusy[mac] = conn to GlobalScope.launch(Dispatchers.IO) {
work.job = GlobalScope.launch(Dispatchers.IO) {
try { try {
var response: String val response = conn.inputStream.bufferedReader().readText()
var obj: JSONObject val obj = JSONObject(response).getJSONObject("result")
while (true) { obj.opt("error")?.also { throw UnexpectedError(mac, it.toString()) }
response = work.conn.inputStream.bufferedReader().readText()
obj = JSONObject(response)
if (obj.getBoolean("success")) break
if (obj.getInt("errorCode") != 429) throw UnexpectedError(mac, response)
work.conn = url.openConnection() as HttpURLConnection
delay(max(1, work.conn.getHeaderField("Retry-After")?.toLongOrNull().let {
if (it == null) {
Timber.w(UnexpectedError(mac,
work.conn.headerFields.entries.joinToString { (k, v) -> "$k: $v" }))
1
} else it
}) * 1000)
}
if (!obj.getBoolean("found")) {
// no vendor found, we should not retry in the future
AppDatabase.instance.clientRecordDao.upsert(mac) { macLookupPending = false }
return@launch
}
val country = obj.getString("country")
val company = obj.getString("company") val company = obj.getString("company")
val result = if (country.length != 2) { val match = extractCountry(mac, response, obj)
Timber.w(UnexpectedError(mac, response)) val result = if (match != null) {
company String(match.groupValues[1].flatMap { listOf('\uD83C', it + 0xDDA5) }.toCharArray()) + ' ' + company
} else String(country.flatMap { listOf('\uD83C', it + 0xDDA5) }.toCharArray()) + ' ' + company } else company
AppDatabase.instance.clientRecordDao.upsert(mac) { AppDatabase.instance.clientRecordDao.upsert(mac) {
nickname = result nickname = result
macLookupPending = false macLookupPending = false
} }
} catch (e: JSONException) { } catch (e: JSONException) {
Timber.w(e) if ((e as? UnexpectedError)?.error == "no result") {
// no vendor found, we should not retry in the future
AppDatabase.instance.clientRecordDao.upsert(mac) { macLookupPending = false }
} else Timber.w(e)
if (explicit) SmartSnackbar.make(e).show() if (explicit) SmartSnackbar.make(e).show()
} catch (e: IOException) { } catch (e: Throwable) {
Timber.d(e) Timber.d(e)
if (explicit) SmartSnackbar.make(e).show() if (explicit) SmartSnackbar.make(e).show()
} }
} }
macLookupBusy[mac] = work }
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
countryCodeRegex.find(address)?.also { return it }
Timber.w(UnexpectedError(mac, response))
return null
} }
} }

View File

@@ -86,8 +86,7 @@ fun makeIpSpan(ip: InetAddress) = ip.hostAddress.let {
} }
} }
fun makeMacSpan(mac: String) = if (app.hasTouch) SpannableString(mac).apply { fun makeMacSpan(mac: String) = if (app.hasTouch) SpannableString(mac).apply {
setSpan(CustomTabsUrlSpan("https://maclookup.app/search/result?mac=" + mac.substring(0, 13)), setSpan(CustomTabsUrlSpan("https://macvendors.co/results/$mac"), 0, length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
0, length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
} else mac } else mac
fun NetworkInterface.formatAddresses(macOnly: Boolean = false) = SpannableStringBuilder().apply { fun NetworkInterface.formatAddresses(macOnly: Boolean = false) = SpannableStringBuilder().apply {