Multi-module Android app, built bottom-up from a verifiable core. core-protocol is pure Kotlin/JVM (no Android SDK): SPKI-pinned control plane (enroll/profile/session over HttpsURLConnection — API-1 compatible, hostname verification off, trust is the pin), HKDF-SHA256 session keys, ELT1 UDP data plane (HMAC gate, ECHO+observation, MTU probe) — byte-compatible with the Go server. Unit tests incl. the RFC 5869 HKDF vector (key derivation provably matches the server). LiveServerTest + scripts/test-fmr.sh prove the client end-to-end against the deployed fmr server: profile (8 caps), session, ECHO rtt~11ms with the observation block returning our observed NAT port, MTU 1400->1400, observations. Live test self-skips without ECHOLOT_LIVE_*. Two client bugs caught live: java.net.http hostname verification (→ HttpsURLConnection, also the Android-minSdk-26 choice) and ECHO padding needed for the observation to survive anti-amplification. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
40 lines
1.4 KiB
Kotlin
40 lines
1.4 KiB
Kotlin
// SPDX-FileCopyrightText: 2026 Echolot contributors
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
plugins {
|
|
alias(libs.plugins.kotlin.jvm)
|
|
alias(libs.plugins.kotlin.serialization)
|
|
}
|
|
|
|
// Pure Kotlin/JVM: the client half of probe-protocol.md. No Android deps, so
|
|
// the Android app modules can depend on it and it stays unit-testable (incl.
|
|
// live integration tests) on any JDK. Crypto, HTTP and UDP come from the JDK
|
|
// (javax.crypto, java.net.http, java.net) — only JSON needs a library.
|
|
dependencies {
|
|
implementation(libs.kotlinx.serialization.json)
|
|
testImplementation(kotlin("test"))
|
|
}
|
|
|
|
kotlin {
|
|
// Build with the available JDK (Android Studio's JBR is 21) but emit
|
|
// Java-17 bytecode so the Android app modules can consume this library.
|
|
jvmToolchain(21)
|
|
compilerOptions {
|
|
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
|
|
}
|
|
}
|
|
java {
|
|
sourceCompatibility = JavaVersion.VERSION_17
|
|
targetCompatibility = JavaVersion.VERSION_17
|
|
}
|
|
|
|
tasks.test {
|
|
useJUnitPlatform()
|
|
// The live end-to-end test against a real server only runs when
|
|
// ECHOLOT_LIVE_URL is set; otherwise it self-skips (see LiveServerTest).
|
|
listOf("ECHOLOT_LIVE_URL", "ECHOLOT_LIVE_PIN", "ECHOLOT_LIVE_CRED",
|
|
"ECHOLOT_LIVE_UDP", "ECHOLOT_LIVE_TARGET").forEach { k ->
|
|
System.getenv(k)?.let { environment(k, it) }
|
|
}
|
|
}
|