Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/src/main/java/shop/whitedns/client/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class MainActivity : ComponentActivity() {
}
ConnectionStatus.CONNECTING,
ConnectionStatus.CONNECTED -> viewModel.disconnect()
ConnectionStatus.DISCONNECTING -> Unit
}
},
onSettingsChange = viewModel::updateSettings,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ enum class ConnectionStatus {
DISCONNECTED,
CONNECTING,
CONNECTED,
DISCONNECTING,
}

data class Choice<T>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package shop.whitedns.client.proxy
import java.util.concurrent.CopyOnWriteArraySet

sealed class WhiteDnsProxyEvent {
data class Log(val message: String) : WhiteDnsProxyEvent()
data class Ready(val message: String) : WhiteDnsProxyEvent()
data class Failed(val message: String) : WhiteDnsProxyEvent()
data class Log(val sessionId: String, val message: String) : WhiteDnsProxyEvent()
data class Ready(val sessionId: String, val message: String) : WhiteDnsProxyEvent()
data class Failed(val sessionId: String, val message: String) : WhiteDnsProxyEvent()
}

object WhiteDnsProxyEvents {
Expand All @@ -19,16 +19,16 @@ object WhiteDnsProxyEvents {
listeners.remove(listener)
}

fun log(message: String) {
emit(WhiteDnsProxyEvent.Log(message))
fun log(sessionId: String, message: String) {
emit(WhiteDnsProxyEvent.Log(sessionId, message))
}

fun ready(message: String) {
emit(WhiteDnsProxyEvent.Ready(message))
fun ready(sessionId: String, message: String) {
emit(WhiteDnsProxyEvent.Ready(sessionId, message))
}

fun failed(message: String) {
emit(WhiteDnsProxyEvent.Failed(message))
fun failed(sessionId: String, message: String) {
emit(WhiteDnsProxyEvent.Failed(sessionId, message))
}

private fun emit(event: WhiteDnsProxyEvent) {
Expand Down
244 changes: 135 additions & 109 deletions app/src/main/java/shop/whitedns/client/proxy/WhiteDnsProxyService.kt

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.os.Build
import android.service.quicksettings.Tile
import android.service.quicksettings.TileService
import androidx.core.app.NotificationManagerCompat
import java.util.UUID
import shop.whitedns.client.MainActivity
import shop.whitedns.client.model.StormDnsServerProfile
import shop.whitedns.client.model.WhiteDnsSettings
Expand Down Expand Up @@ -48,6 +49,7 @@ class WhiteDnsTileService : TileService() {
openApp()
return
}
val sessionId = UUID.randomUUID().toString()

when (resolvedSettings.connectionMode) {
WhiteDnsRuntimeStateStore.ModeVpn -> {
Expand All @@ -61,6 +63,7 @@ class WhiteDnsTileService : TileService() {
}
WhiteDnsVpnService.start(
context = applicationContext,
sessionId = sessionId,
serverProfile = serverProfile,
settings = settings,
)
Expand All @@ -69,6 +72,7 @@ class WhiteDnsTileService : TileService() {
else -> {
WhiteDnsProxyService.start(
context = applicationContext,
sessionId = sessionId,
serverProfile = serverProfile,
settings = settings,
)
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package shop.whitedns.client.runtime

class RuntimeReconnectGuard(
private val maxFailures: Int,
private val windowMillis: Long,
) {
private val failureTimes = ArrayDeque<Long>()

fun recordFailure(nowMillis: Long = System.currentTimeMillis()): Boolean {
prune(nowMillis)
failureTimes.addLast(nowMillis)
return failureTimes.size <= maxFailures
}

fun reset() {
failureTimes.clear()
}

fun failureCount(nowMillis: Long = System.currentTimeMillis()): Int {
prune(nowMillis)
return failureTimes.size
}

private fun prune(nowMillis: Long) {
while (failureTimes.isNotEmpty() && nowMillis - failureTimes.first() > windowMillis) {
failureTimes.removeFirst()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import shop.whitedns.client.model.resolve
import shop.whitedns.client.model.selectedConnectionProfile

data class WhiteDnsRuntimeState(
val sessionId: String,
val mode: String,
val status: String,
val connectionProfileId: String,
Expand All @@ -25,23 +26,28 @@ object WhiteDnsRuntimeStateStore {
const val ModeVpn = "vpn"
const val StatusStarting = "starting"
const val StatusReady = "ready"
const val StatusDisconnecting = "disconnecting"
const val StatusStopped = "stopped"
const val StatusFailed = "failed"

fun markStarting(context: Context, settings: WhiteDnsSettings, message: String = "") {
writeSettingsState(context, settings, StatusStarting, message)
fun markStarting(context: Context, settings: WhiteDnsSettings, sessionId: String, message: String = "") {
writeSettingsState(context, settings, sessionId, StatusStarting, message)
}

fun markReady(context: Context, settings: WhiteDnsSettings, message: String = "") {
writeSettingsState(context, settings, StatusReady, message)
fun markReady(context: Context, settings: WhiteDnsSettings, sessionId: String, message: String = "") {
writeSettingsState(context, settings, sessionId, StatusReady, message)
}

fun markStopped(context: Context, mode: String, message: String = "") {
writeModeState(context, mode, StatusStopped, message)
fun markDisconnecting(context: Context, mode: String, sessionId: String = "", message: String = "") {
writeModeState(context, mode, sessionId, StatusDisconnecting, message)
}

fun markFailed(context: Context, mode: String, message: String) {
writeModeState(context, mode, StatusFailed, message)
fun markStopped(context: Context, mode: String, sessionId: String = "", message: String = "") {
writeModeState(context, mode, sessionId, StatusStopped, message)
}

fun markFailed(context: Context, mode: String, sessionId: String = "", message: String) {
writeModeState(context, mode, sessionId, StatusFailed, message)
}

fun read(context: Context, mode: String): WhiteDnsRuntimeState? {
Expand All @@ -66,6 +72,7 @@ object WhiteDnsRuntimeStateStore {
private fun writeSettingsState(
context: Context,
settings: WhiteDnsSettings,
sessionId: String,
status: String,
message: String,
) {
Expand All @@ -74,6 +81,7 @@ object WhiteDnsRuntimeStateStore {
writeState(
context = context,
state = WhiteDnsRuntimeState(
sessionId = sessionId,
mode = resolvedSettings.connectionMode,
status = status,
connectionProfileId = connectionProfile.id,
Expand All @@ -88,13 +96,15 @@ object WhiteDnsRuntimeStateStore {
private fun writeModeState(
context: Context,
mode: String,
sessionId: String,
status: String,
message: String,
) {
val previous = read(context, mode)
writeState(
context = context,
state = WhiteDnsRuntimeState(
sessionId = sessionId.ifBlank { previous?.sessionId.orEmpty() },
mode = mode,
status = status,
connectionProfileId = previous?.connectionProfileId.orEmpty(),
Expand Down Expand Up @@ -129,6 +139,7 @@ object WhiteDnsRuntimeStateStore {

private fun encode(state: WhiteDnsRuntimeState): JSONObject {
return JSONObject()
.put("sessionId", state.sessionId)
.put("mode", state.mode)
.put("status", state.status)
.put("connectionProfileId", state.connectionProfileId)
Expand All @@ -140,6 +151,7 @@ object WhiteDnsRuntimeStateStore {

private fun decode(json: JSONObject): WhiteDnsRuntimeState {
return WhiteDnsRuntimeState(
sessionId = json.optString("sessionId"),
mode = json.optString("mode"),
status = json.optString("status"),
connectionProfileId = json.optString("connectionProfileId"),
Expand Down
Loading