Skip to content

Commit

Permalink
perf: ktor http server
Browse files Browse the repository at this point in the history
  • Loading branch information
lisonge committed Nov 18, 2024
1 parent 8f3a085 commit 7838d23
Show file tree
Hide file tree
Showing 12 changed files with 72 additions and 66 deletions.
20 changes: 10 additions & 10 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import java.io.ByteArrayOutputStream

fun String.runCommand(currentWorkingDir: File = file("./")): String {
val byteOut = ByteArrayOutputStream()
project.exec {
workingDir = currentWorkingDir
commandLine = this@runCommand.split("\\s".toRegex())
standardOutput = byteOut
errorOutput = ByteArrayOutputStream()
fun String.runCommand(): String {
val process = ProcessBuilder(split(" "))
.redirectErrorStream(true)
.start()
val output = process.inputStream.bufferedReader().readText().trim()
val exitCode = process.waitFor()
if (exitCode != 0) {
error("Command failed with exit code $exitCode: $output")
}
return String(byteOut.toByteArray()).trim()
return output
}

data class GitInfo(
Expand Down Expand Up @@ -191,6 +190,7 @@ composeCompiler {
}

dependencies {
implementation(libs.kotlin.stdlib)

implementation(project(mapOf("path" to ":selector")))

Expand Down
4 changes: 4 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
-keep class li.songe.**{*;}
-keep interface li.songe.**{*;}

# fix ktor error https://youtrack.jetbrains.com/issue/KTOR-7298
# it should the bug of agp
-keep class com.hjq.toast.** {*;}

-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod

-keep, allowobfuscation, allowoptimization @kotlinx.serialization.Serializable class * {*;}
Expand Down
23 changes: 16 additions & 7 deletions app/src/main/kotlin/li/songe/gkd/debug/HttpService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import li.songe.gkd.util.OnCreate
import li.songe.gkd.util.OnDestroy
import li.songe.gkd.util.SERVER_SCRIPT_URL
import li.songe.gkd.util.getIpAddressInLocalNetwork
import li.songe.gkd.util.isPortAvailable
import li.songe.gkd.util.keepNullJson
import li.songe.gkd.util.launchTry
import li.songe.gkd.util.map
Expand Down Expand Up @@ -78,9 +79,6 @@ class HttpService : Service(), OnCreate, OnDestroy {

private val httpServerPortFlow = storeFlow.map(scope) { s -> s.httpServerPort }

private var server: EmbeddedServer<CIOApplicationEngine, CIOApplicationEngine.Configuration>? =
null

init {
useLogLifecycle()
useAliveFlow(isRunning)
Expand All @@ -92,21 +90,28 @@ class HttpService : Service(), OnCreate, OnDestroy {
if (storeFlow.value.autoClearMemorySubs) {
deleteSubscription(LOCAL_HTTP_SUBS_ID)
}
httpServerFlow.value = null
}

onCreated {
httpNotif.notifyService(this)
scope.launchTry(Dispatchers.IO) {
httpServerPortFlow.collect { port ->
server?.stop()
server = try {
httpServerFlow.value?.stop()
httpServerFlow.value = null
if (!isPortAvailable(port)) {
toast("端口 $port 被占用, 请更换后重试")
stopSelf()
return@collect
}
httpServerFlow.value = try {
scope.createServer(port).apply { start() }
} catch (e: Exception) {
toast("HTTP服务启动失败:${e.stackTraceToString()}")
LogUtils.d("HTTP服务启动失败", e)
null
}
if (server == null) {
toast("HTTP服务启动失败,您可以尝试切换端口后重新启动")
if (httpServerFlow.value == null) {
stopSelf()
return@collect
}
Expand All @@ -117,6 +122,7 @@ class HttpService : Service(), OnCreate, OnDestroy {
}

companion object {
val httpServerFlow = MutableStateFlow<ServerType?>(null)
val isRunning = MutableStateFlow(false)
val localNetworkIpsFlow = MutableStateFlow(emptyList<String>())
fun stop() {
Expand All @@ -130,6 +136,9 @@ class HttpService : Service(), OnCreate, OnDestroy {
}
}

typealias ServerType = EmbeddedServer<CIOApplicationEngine, CIOApplicationEngine.Configuration>


@Serializable
data class RpcOk(
val message: String? = null,
Expand Down
12 changes: 9 additions & 3 deletions app/src/main/kotlin/li/songe/gkd/ui/AdvancedPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ fun AdvancedPage() {
httpServerPort = newPort
)
showEditPortDlg = false
if (HttpService.httpServerFlow.value != null) {
toast("已更新, 重启服务")
} else {
toast("已更新")
}
}
) {
Text(
Expand Down Expand Up @@ -196,7 +201,8 @@ fun AdvancedPage() {
ShizukuFragment()
}

val httpServerRunning by HttpService.isRunning.collectAsState()
val server by HttpService.httpServerFlow.collectAsState()
val httpServerRunning = server != null
val localNetworkIps by HttpService.localNetworkIpsFlow.collectAsState()

Text(
Expand Down Expand Up @@ -252,14 +258,14 @@ fun AdvancedPage() {
}
Switch(
checked = httpServerRunning,
onCheckedChange = vm.viewModelScope.launchAsFn<Boolean> {
onCheckedChange = throttle(fn = vm.viewModelScope.launchAsFn<Boolean> {
if (it) {
requiredPermission(context, notificationState)
HttpService.start()
} else {
HttpService.stop()
}
}
})
)
}

Expand Down
16 changes: 16 additions & 0 deletions app/src/main/kotlin/li/songe/gkd/util/NetworkExt.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package li.songe.gkd.util

import java.net.NetworkInterface
import java.net.ServerSocket

fun getIpAddressInLocalNetwork(): List<String> {
val networkInterfaces = try {
Expand All @@ -18,3 +19,18 @@ fun getIpAddressInLocalNetwork(): List<String> {
}
return localAddresses.toList()
}


fun isPortAvailable(port: Int): Boolean {
var serverSocket: ServerSocket? = null
return try {
serverSocket = ServerSocket(port)
serverSocket.reuseAddress = true
true
} catch (e: Exception) {
e.printStackTrace()
false
} finally {
serverSocket?.close()
}
}
31 changes: 0 additions & 31 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,18 +1,3 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
mavenLocal()
mavenCentral()
google()
maven("https://jitpack.io")
}
dependencies {
classpath(libs.android.gradle)
classpath(libs.kotlin.gradle.plugin)
classpath(libs.kotlin.serialization)
}
}

plugins {
alias(libs.plugins.google.ksp) apply false

Expand All @@ -30,22 +15,6 @@ plugins {
alias(libs.plugins.rikka.refine) apply false
}

// can not work with Kotlin Multiplatform
// https://youtrack.jetbrains.com/issue/KT-33191/
//tasks.register<Delete>("clean").configure {
// delete(rootProject.buildDir)
//}

project.gradle.taskGraph.whenReady {
allTasks.forEach { task ->
// error: The binary version of its metadata is 1.8.0, expected version is 1.6.0.
// I don't know how to solve it, so just disable these tasks
if (task.name.contains("lintAnalyzeDebug") || task.name.contains("lintVitalAnalyzeRelease")) {
task.enabled = false
}
}
}

// https://kotlinlang.org/docs/js-project-setup.html#use-pre-installed-node-js
rootProject.plugins.withType<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin> {
rootProject.the<org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension>().download =
Expand Down
2 changes: 0 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ android.useAndroidX=true
android.enableJetifier=true
android.debug.obsoleteApi=true
kotlin.code.style=official
# https://youtrack.jetbrains.com/issue/KTOR-7298
android.suppressUnsupportedCompileSdk=35
android_compileSdk=35
android_targetSdk=35
android_buildToolsVersion=35.0.0
Expand Down
7 changes: 2 additions & 5 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[versions]
kotlin = "2.0.21"
ksp = "2.0.21-1.0.25"
android = "8.5.2"
android = "8.7.2"
compose = "1.7.5"
rikka = "4.4.0"
room = "2.6.1"
Expand All @@ -12,9 +12,7 @@ coil = "2.7.0"
shizuku = "13.1.5"

[libraries]
kotlin_gradle_plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
kotlin_serialization = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kotlin" }
kotlin_stdlib_common = { module = "org.jetbrains.kotlin:kotlin-stdlib-common", version.ref = "kotlin" }
kotlin_stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
kotlin_test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
kotlinx_serialization_json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version = "1.7.3" }
ktor_server_core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }
Expand All @@ -24,7 +22,6 @@ ktor_client_core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
ktor_client_okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
ktor_client_content_negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" }
ktor_serialization_kotlinx_json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
android_gradle = { module = "com.android.tools.build:gradle", version.ref = "android" }
compose_ui = { module = "androidx.compose.ui:ui", version.ref = "compose" }
compose_ui_graphics = { module = "androidx.compose.ui:ui-graphics", version.ref = "compose" }
compose_animation = { module = "androidx.compose.animation:animation", version.ref = "compose" }
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
5 changes: 1 addition & 4 deletions selector/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.kotlin.serialization)
Expand All @@ -21,7 +18,7 @@ kotlin {
}
commonMain {
dependencies {
implementation(libs.kotlin.stdlib.common)
implementation(libs.kotlin.stdlib)
}
}
jvmTest {
Expand Down
10 changes: 8 additions & 2 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ pluginManagement {
repositories {
mavenLocal()
mavenCentral()
google()
google {
content {
includeGroupByRegex("com\\.android.*")
includeGroupByRegex("com\\.google.*")
includeGroupByRegex("androidx.*")
}
}
maven("https://jitpack.io")
maven("https://plugins.gradle.org/m2/")
gradlePluginPortal()
}
}

Expand Down
6 changes: 5 additions & 1 deletion wasm_matches/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
@file:OptIn(ExperimentalKotlinGradlePluginApi::class, ExperimentalWasmDsl::class)

import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
Expand All @@ -22,7 +26,7 @@ kotlin {
}
commonMain {
dependencies {
implementation(libs.kotlin.stdlib.common)
implementation(libs.kotlin.stdlib)
}
}
}
Expand Down

0 comments on commit 7838d23

Please sign in to comment.