diff --git a/.idea/artifacts/kiloparsec_js_0_1_2_SNAPSHOT.xml b/.idea/artifacts/kiloparsec_js_0_1_2_SNAPSHOT.xml new file mode 100644 index 0000000..f9b38cf --- /dev/null +++ b/.idea/artifacts/kiloparsec_js_0_1_2_SNAPSHOT.xml @@ -0,0 +1,6 @@ + + + $PROJECT_DIR$/build/libs + + + \ No newline at end of file diff --git a/.idea/artifacts/kiloparsec_js_0_2_2_SNAPSHOT.xml b/.idea/artifacts/kiloparsec_js_0_2_2_SNAPSHOT.xml new file mode 100644 index 0000000..5df380c --- /dev/null +++ b/.idea/artifacts/kiloparsec_js_0_2_2_SNAPSHOT.xml @@ -0,0 +1,8 @@ + + + $PROJECT_DIR$/build/libs + + + + + \ No newline at end of file diff --git a/.idea/artifacts/kiloparsec_js_0_2_3.xml b/.idea/artifacts/kiloparsec_js_0_2_3.xml new file mode 100644 index 0000000..b53b884 --- /dev/null +++ b/.idea/artifacts/kiloparsec_js_0_2_3.xml @@ -0,0 +1,8 @@ + + + $PROJECT_DIR$/build/libs + + + + + \ No newline at end of file diff --git a/.idea/artifacts/kiloparsec_jvm_0_1_2_SNAPSHOT.xml b/.idea/artifacts/kiloparsec_jvm_0_1_2_SNAPSHOT.xml new file mode 100644 index 0000000..7a15b72 --- /dev/null +++ b/.idea/artifacts/kiloparsec_jvm_0_1_2_SNAPSHOT.xml @@ -0,0 +1,6 @@ + + + $PROJECT_DIR$/build/libs + + + \ No newline at end of file diff --git a/.idea/artifacts/kiloparsec_jvm_0_2_2_SNAPSHOT.xml b/.idea/artifacts/kiloparsec_jvm_0_2_2_SNAPSHOT.xml new file mode 100644 index 0000000..d47f5d9 --- /dev/null +++ b/.idea/artifacts/kiloparsec_jvm_0_2_2_SNAPSHOT.xml @@ -0,0 +1,8 @@ + + + $PROJECT_DIR$/build/libs + + + + + \ No newline at end of file diff --git a/.idea/artifacts/kiloparsec_jvm_0_2_3.xml b/.idea/artifacts/kiloparsec_jvm_0_2_3.xml new file mode 100644 index 0000000..dff5778 --- /dev/null +++ b/.idea/artifacts/kiloparsec_jvm_0_2_3.xml @@ -0,0 +1,8 @@ + + + $PROJECT_DIR$/build/libs + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index eec43a0..76d6398 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,7 +1,10 @@ + - + + + \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index c4d2605..157162c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ plugins { } group = "net.sergeych" -version = "0.2.2-SNAPSHOT" +version = "0.2.4" repositories { mavenCentral() @@ -17,13 +17,8 @@ repositories { kotlin { jvm() - js(IR) { + js { browser { -// commonWebpackConfig { -// cssSupport { -// enabled.set(true) -// } -// } } } // val hostOs = System.getProperty("os.name") @@ -39,16 +34,15 @@ kotlin { // else -> throw GradleException("Host OS is not supported in Kotlin/Native.") // } -// macosArm64() -// iosX64() -// iosArm64() -// iosSimulatorArm64() + macosArm64() + iosX64() + iosArm64() + iosSimulatorArm64() linuxX64() linuxArm64() -// macosX64() + macosX64() - - val ktor_version = "2.3.6" + val ktor_version = "2.3.12" sourceSets { all { @@ -64,17 +58,20 @@ kotlin { // api("com.ionspin.kotlin:bignum:0.3.9") api("io.ktor:ktor-client-core:$ktor_version") - -// api("net.sergeych:mp_bintools:0.1.1") -// api("net.sergeych:mp_stools:1.4.7") - api("net.sergeych:crypto2:0.4.1-SNAPSHOT") + api("net.sergeych:crypto2:0.4.2") } } +// val ktorSocketMain by creating { +// dependsOn(commonMain) +// dependencies { +// implementation("io.ktor:ktor-network:$ktor_version") +// } +// } val commonTest by getting { dependencies { implementation(kotlin("test")) implementation("org.slf4j:slf4j-simple:2.0.9") - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1") } } val jvmMain by getting { @@ -85,6 +82,7 @@ kotlin { implementation("io.ktor:ktor-server-netty:$ktor_version") api("io.ktor:ktor-client-cio:$ktor_version") } +// dependsOn(ktorSocketMain) } val jvmTest by getting val jsMain by getting { @@ -93,12 +91,10 @@ kotlin { } } val jsTest by getting -// val nativeMain by getting { -// dependencies { -// implementation("io.ktor:ktor-client-cio:$ktor_version") -// } -// } -// val nativeTest by getting + +// for (pm in listOf(linuxMain, macosMain, iosMain, mingwMain)) +// pm { dependsOn(ktorSocketMain) } + } publishing { diff --git a/src/commonMain/kotlin/net/sergeych/kiloparsec/AsyncVarint.kt b/src/commonMain/kotlin/net/sergeych/kiloparsec/AsyncVarint.kt new file mode 100644 index 0000000..c50b58b --- /dev/null +++ b/src/commonMain/kotlin/net/sergeych/kiloparsec/AsyncVarint.kt @@ -0,0 +1,37 @@ +package net.sergeych.kiloparsec + +import io.ktor.utils.io.* + +object AsyncVarint { + suspend fun encodeUnsigned(value: ULong, output: ByteWriteChannel) { + var rest = value + do { + val x = (rest and 127u).toInt() + rest = rest shr 7 + if (rest > 0u) + output.writeByte(x or 0x80) + else + output.writeByte(x) + + } while (rest > 0u) + } + + suspend fun decodeUnsigned(source: ByteReadChannel): ULong { + var result: ULong = 0u + var count = 0 + while (true) { + val x = source.readUByte().toInt() + result = result or ((x and 0x7F).toULong() shl count) + if ((x and 0x80) == 0) + break + count += 7 + } + return result + } +} + +suspend fun ByteReadChannel.readUByte(): UByte = this.readByte().toUByte() + +suspend fun ByteWriteChannel.writeByte(byte: Int) { + this.writeByte(byte.toByte()) +} diff --git a/src/commonMain/kotlin/net/sergeych/kiloparsec/KiloInterface.kt b/src/commonMain/kotlin/net/sergeych/kiloparsec/KiloInterface.kt index aac9e82..25fb03a 100644 --- a/src/commonMain/kotlin/net/sergeych/kiloparsec/KiloInterface.kt +++ b/src/commonMain/kotlin/net/sergeych/kiloparsec/KiloInterface.kt @@ -1,7 +1,7 @@ package net.sergeych.kiloparsec /** - * The local interface to provice functions, register errors for Kiloparsec users. Use it + * The local interface to provide functions, register errors for Kiloparsec users. Use it * with [KiloClient], [KiloClientConnection], [KiloServerConnection], etc. * * BAse implementation registers relevant exceptions. diff --git a/src/jvmMain/kotlin/net/sergeych/kiloparsec/adapter/NetworkProvider.jvm.kt b/src/jvmMain/kotlin/net/sergeych/kiloparsec/adapter/NetworkProvider.jvm.kt index 4fb4bfe..ccc682c 100644 --- a/src/jvmMain/kotlin/net/sergeych/kiloparsec/adapter/NetworkProvider.jvm.kt +++ b/src/jvmMain/kotlin/net/sergeych/kiloparsec/adapter/NetworkProvider.jvm.kt @@ -22,12 +22,14 @@ actual fun acceptTcpDevice(port: Int): Flow { } } while (true) { + println("0 --- $port") val connectedSocket = suspendCancellableCoroutine { continuation -> continuation.invokeOnCancellation { socket.close() } socket.accept(continuation, ContinuationHandler()) } + println("1 ---") emit(asyncSocketToDevice(connectedSocket)) } } diff --git a/src/jvmTest/kotlin/net/sergeych/kiloparsec/ClientTest.kt b/src/jvmTest/kotlin/net/sergeych/kiloparsec/ClientTest.kt index 1343bba..e66ea1a 100644 --- a/src/jvmTest/kotlin/net/sergeych/kiloparsec/ClientTest.kt +++ b/src/jvmTest/kotlin/net/sergeych/kiloparsec/ClientTest.kt @@ -100,16 +100,9 @@ class ClientTest { on(cmdCheckConnected) { connectedCalled } on(cmdClose) { throw LocalInterface.BreakConnectionException() -// if( closeCounter < 2 ) { -// println("-------------------------- call close!") -// throw RemoteInterface.ClosedException() -// } -// else { -// println("close counter $closeCounter, ignoring") -// } } } -// val server = setupWebsoketServer() + val ns: NettyApplicationEngine = embeddedServer(Netty, port = 8080, host = "0.0.0.0", module = { setupWebsocketServer(serverInterface) { Session() } }).start(wait = false) diff --git a/src/jvmTest/kotlin/net/sergeych/kiloparsec/adapters/NetworkTest.kt b/src/jvmTest/kotlin/net/sergeych/kiloparsec/adapters/NetworkTest.kt index 8ebb77f..43dd531 100644 --- a/src/jvmTest/kotlin/net/sergeych/kiloparsec/adapters/NetworkTest.kt +++ b/src/jvmTest/kotlin/net/sergeych/kiloparsec/adapters/NetworkTest.kt @@ -10,6 +10,7 @@ import net.sergeych.kiloparsec.adapter.toNetworkAddress import net.sergeych.kiloparsec.decodeFromUByteArray import net.sergeych.kiloparsec.encodeToUByteArray import net.sergeych.mp_logger.Log +import net.sergeych.mp_logger.LogTag import net.sergeych.synctools.ProtectedOp import net.sergeych.synctools.invoke import kotlin.test.Test @@ -43,8 +44,11 @@ class NetworkTest { val op = ProtectedOp() var pills = setOf() val j = launch { + println("serf") serverFlow.collect { device -> + println("serf 0") launch { + println("serf 1") device.output.send("Hello, world!".encodeToUByteArray()) device.output.send("Great".encodeToUByteArray()) while (true) { @@ -63,13 +67,22 @@ class NetworkTest { } yield() run { - val s = connectTcpDevice("127.0.1.1:17171".toNetworkAddress()) - assertEquals("Hello, world!", s.input.receive().decodeFromUByteArray()) - assertEquals("Great", s.input.receive().decodeFromUByteArray()) - s.output.send("Goodbye".encodeToUByteArray()) - s.output.send("die1".encodeToUByteArray()) - s.close() + try { + println("pre-con") + val s = connectTcpDevice("127.0.1.1:17171".toNetworkAddress()) + println("2") + assertEquals("Hello, world!", s.input.receive().decodeFromUByteArray()) + assertEquals("Great", s.input.receive().decodeFromUByteArray()) + s.output.send("Goodbye".encodeToUByteArray()) + s.output.send("die1".encodeToUByteArray()) + s.close() + } + catch(t: Throwable) { + t.printStackTrace() + throw t + } } + println("pre-con2") val s1 = connectTcpDevice("127.0.1.1:17171".toNetworkAddress()) assertEquals("Hello, world!", s1.input.receive().decodeFromUByteArray()) assertEquals("Great", s1.input.receive().decodeFromUByteArray()) diff --git a/src/ktorSocketMain/kotlin/adapter/socketClient.kt b/src/ktorSocketMain/kotlin/adapter/socketClient.kt new file mode 100644 index 0000000..48214fc --- /dev/null +++ b/src/ktorSocketMain/kotlin/adapter/socketClient.kt @@ -0,0 +1,43 @@ +package net.sergeych.kiloparsec.adapter + +import io.ktor.network.selector.* +import io.ktor.network.sockets.* +import io.ktor.util.network.* +import io.ktor.utils.io.* +import io.ktor.utils.io.core.* +import kotlinx.coroutines.* +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import net.sergeych.kiloparsec.AsyncVarint +import net.sergeych.mp_logger.LogTag +import kotlin.io.use + +//class SocketNetworkAddress(override val host: String, override val port: Int) : NetworkAddress +// +//actual fun NetworkAddress(host: String, port: Int): NetworkAddress = SocketNetworkAddress(host, port) +// +//fun acceptTcpSocketDevice(port: Int): Flow { +// val selectorManager = SelectorManager(Dispatchers.IO) +// val serverSocket = aSocket(selectorManager).tcp().bind("127.0.0.1", port) +// val log = LogTag("TCPS${}") +// return flow { +// serverSocket.accept().use { sock -> +// val closed = CompletableDeferred() +// val scope = coroutineScope { +// val networkAddress = sock.remoteAddress.toJavaAddress().let { NetworkAddress(it.hostname, it.port) } +// val inputBlocks = Channel(4096) +// sock.launch { +// val sockInput = sock.openReadChannel() +// while (isActive && sock.isActive) { +// try { +// val size = AsyncVarint.decodeUnsigned(sockInput) +// } catch (e: Exception) { +// +// } +// } +// } +// } +// } +// } +//}