Implement MAC lookup (#68)
* Implement MAC lookup * Refine error processing * Use long to store MAC consistently * Link back to macvendors.co * Undo some havoc * Do not show mac spans for TV * Show MAC and IP in a consistent order * Add IP spans by ipinfo.io * Add SpanFormatter * Fix IPv6 ipinfo.io link * Refine SpanFormatter * Fix pressing the link
This commit is contained in:
@@ -4,9 +4,11 @@ import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.TypeConverters
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import be.mygod.vpnhotspot.App.Companion.app
|
||||
|
||||
@Database(entities = [ClientRecord::class, TrafficRecord::class], version = 1)
|
||||
@Database(entities = [ClientRecord::class, TrafficRecord::class], version = 2)
|
||||
@TypeConverters(Converters::class)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
companion object {
|
||||
@@ -14,6 +16,9 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
val instance by lazy {
|
||||
Room.databaseBuilder(app.deviceStorage, AppDatabase::class.java, DB_NAME)
|
||||
.addMigrations(
|
||||
Migration2
|
||||
)
|
||||
.allowMainThreadQueries()
|
||||
.build()
|
||||
}
|
||||
@@ -21,4 +26,9 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
|
||||
abstract val clientRecordDao: ClientRecord.Dao
|
||||
abstract val trafficRecordDao: TrafficRecord.Dao
|
||||
|
||||
object Migration2 : Migration(1, 2) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) =
|
||||
database.execSQL("ALTER TABLE `ClientRecord` ADD COLUMN `macLookupPending` INTEGER NOT NULL DEFAULT 1")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,13 +7,14 @@ import androidx.room.*
|
||||
data class ClientRecord(@PrimaryKey
|
||||
val mac: Long,
|
||||
var nickname: CharSequence = "",
|
||||
var blocked: Boolean = false) {
|
||||
var blocked: Boolean = false,
|
||||
var macLookupPending: Boolean = true) {
|
||||
@androidx.room.Dao
|
||||
abstract class Dao {
|
||||
@Query("SELECT * FROM `ClientRecord` WHERE `mac` = :mac")
|
||||
abstract fun lookup(mac: Long): ClientRecord?
|
||||
abstract suspend fun lookup(mac: Long): ClientRecord?
|
||||
|
||||
fun lookupOrDefault(mac: Long) = lookup(mac) ?: ClientRecord(mac)
|
||||
suspend fun lookupOrDefault(mac: Long) = lookup(mac) ?: ClientRecord(mac)
|
||||
|
||||
@Query("SELECT * FROM `ClientRecord` WHERE `mac` = :mac")
|
||||
abstract fun lookupSync(mac: Long): LiveData<ClientRecord>
|
||||
@@ -23,7 +24,7 @@ data class ClientRecord(@PrimaryKey
|
||||
fun update(value: ClientRecord) = check(updateInternal(value) == value.mac)
|
||||
|
||||
@Transaction
|
||||
open fun upsert(mac: Long, operation: ClientRecord.() -> Unit) = lookupOrDefault(mac).apply {
|
||||
open suspend fun upsert(mac: Long, operation: ClientRecord.() -> Unit) = lookupOrDefault(mac).apply {
|
||||
operation()
|
||||
update(this)
|
||||
}
|
||||
|
||||
@@ -50,8 +50,9 @@ fun String.macToLong(): Long = ByteBuffer.allocate(8).run {
|
||||
long
|
||||
}
|
||||
|
||||
fun Iterable<Byte>.macToString() = joinToString(":") { "%02x".format(it) }
|
||||
fun Long.macToString(): String = ByteBuffer.allocate(8).run {
|
||||
order(ByteOrder.LITTLE_ENDIAN)
|
||||
putLong(this@macToString)
|
||||
array().take(6).joinToString(":") { "%02x".format(it) }
|
||||
array().take(6).macToString()
|
||||
}
|
||||
|
||||
@@ -55,8 +55,9 @@ data class TrafficRecord(
|
||||
SUM(TrafficRecord.receivedBytes) AS receivedBytes
|
||||
FROM TrafficRecord LEFT JOIN TrafficRecord AS Next ON TrafficRecord.id = Next.previousId
|
||||
/* We only want to find the last record for each chain so that we don't double count */
|
||||
WHERE TrafficRecord.mac = :mac AND Next.id IS NULL""")
|
||||
abstract fun queryStats(mac: Long): ClientStats
|
||||
WHERE TrafficRecord.mac = :mac AND Next.id IS NULL
|
||||
""")
|
||||
abstract suspend fun queryStats(mac: Long): ClientStats
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user