network transport with remote address, universal server
This commit is contained in:
parent
96edbb2040
commit
f92431a281
27
src/commonMain/kotlin/net/sergeych/kiloparsec/KiloServer.kt
Normal file
27
src/commonMain/kotlin/net/sergeych/kiloparsec/KiloServer.kt
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package net.sergeych.kiloparsec
|
||||||
|
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import net.sergeych.crypto.Key
|
||||||
|
import net.sergeych.mp_tools.globalLaunch
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
class KiloServer<S>(
|
||||||
|
private val clientInterface: KiloInterface<S>,
|
||||||
|
private val connections: Flow<Transport.Device>,
|
||||||
|
private val serverSigningKey: Key.Signing? = null,
|
||||||
|
private val sessionBuilder: ()->S,
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val job = globalLaunch {
|
||||||
|
connections.collect { device ->
|
||||||
|
launch {
|
||||||
|
KiloServerConnection(clientInterface,device,sessionBuilder(), serverSigningKey).run()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun close() {
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@ package net.sergeych.kiloparsec.adapter
|
|||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
class InetProxyDevice(
|
class InetTransportDevice(
|
||||||
inputChannel: Channel<UByteArray?>,
|
inputChannel: Channel<UByteArray?>,
|
||||||
outputChannel: Channel<UByteArray>,
|
outputChannel: Channel<UByteArray>,
|
||||||
val remoteAddress: NetworkAddress,
|
val remoteAddress: NetworkAddress,
|
@ -2,7 +2,6 @@ package net.sergeych.kiloparsec.adapter
|
|||||||
|
|
||||||
import kotlinx.coroutines.channels.ReceiveChannel
|
import kotlinx.coroutines.channels.ReceiveChannel
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import net.sergeych.kiloparsec.Transport
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Multiplatform implementation of an internet address.
|
* Multiplatform implementation of an internet address.
|
||||||
@ -51,6 +50,6 @@ fun CharSequence.toNetworkAddress() : NetworkAddress {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
expect fun acceptTcpDevice(port: Int): Flow<Transport.Device>
|
expect fun acceptTcpDevice(port: Int): Flow<InetTransportDevice>
|
||||||
|
|
||||||
expect suspend fun connectTcpDevice(address: NetworkAddress): Transport.Device
|
expect suspend fun connectTcpDevice(address: NetworkAddress): InetTransportDevice
|
@ -1,16 +1,15 @@
|
|||||||
package net.sergeych.kiloparsec.adapter
|
package net.sergeych.kiloparsec.adapter
|
||||||
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import net.sergeych.kiloparsec.Transport
|
|
||||||
|
|
||||||
actual fun NetworkAddress(host: String, port: Int): NetworkAddress {
|
actual fun NetworkAddress(host: String, port: Int): NetworkAddress {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun acceptTcpDevice(port: Int): Flow<Transport.Device> {
|
actual fun acceptTcpDevice(port: Int): Flow<InetTransportDevice> {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
actual suspend fun connectTcpDevice(address: NetworkAddress): Transport.Device {
|
actual suspend fun connectTcpDevice(address: NetworkAddress): InetTransportDevice {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
@ -1,12 +1,10 @@
|
|||||||
package net.sergeych.kiloparsec.adapter
|
package net.sergeych.kiloparsec.adapter
|
||||||
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.channels.SendChannel
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import net.sergeych.kiloparsec.Transport
|
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
import java.net.InetSocketAddress
|
import java.net.InetSocketAddress
|
||||||
import java.nio.channels.AsynchronousServerSocketChannel
|
import java.nio.channels.AsynchronousServerSocketChannel
|
||||||
@ -16,7 +14,7 @@ import kotlin.coroutines.suspendCoroutine
|
|||||||
actual fun NetworkAddress(host: String, port: Int): NetworkAddress =
|
actual fun NetworkAddress(host: String, port: Int): NetworkAddress =
|
||||||
JvmNetworkAddress(InetAddress.getByName(host), port)
|
JvmNetworkAddress(InetAddress.getByName(host), port)
|
||||||
|
|
||||||
actual fun acceptTcpDevice(port: Int): Flow<Transport.Device> {
|
actual fun acceptTcpDevice(port: Int): Flow<InetTransportDevice> {
|
||||||
return flow {
|
return flow {
|
||||||
val socket = withContext(Dispatchers.IO) {
|
val socket = withContext(Dispatchers.IO) {
|
||||||
AsynchronousServerSocketChannel.open().also {
|
AsynchronousServerSocketChannel.open().also {
|
||||||
@ -35,7 +33,7 @@ actual fun acceptTcpDevice(port: Int): Flow<Transport.Device> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual suspend fun connectTcpDevice(address: NetworkAddress): Transport.Device {
|
actual suspend fun connectTcpDevice(address: NetworkAddress): InetTransportDevice {
|
||||||
address as JvmNetworkAddress
|
address as JvmNetworkAddress
|
||||||
val socket = withContext(Dispatchers.IO) {
|
val socket = withContext(Dispatchers.IO) {
|
||||||
AsynchronousSocketChannel.open()
|
AsynchronousSocketChannel.open()
|
||||||
@ -45,7 +43,3 @@ actual suspend fun connectTcpDevice(address: NetworkAddress): Transport.Device {
|
|||||||
}
|
}
|
||||||
return asyncSocketToDevice(socket)
|
return asyncSocketToDevice(socket)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun SendChannel<UByte>.sendAll(bytes: Collection<UByte>) {
|
|
||||||
for (b in bytes) send(b)
|
|
||||||
}
|
|
@ -31,8 +31,8 @@ private fun encode(block: UByteArray): ByteArray
|
|||||||
* to the socket in a global scope.These are closed when transport is closed
|
* to the socket in a global scope.These are closed when transport is closed
|
||||||
* or the socket is closed, for example, by network failure.
|
* or the socket is closed, for example, by network failure.
|
||||||
*/
|
*/
|
||||||
suspend fun asyncSocketToDevice(socket: AsynchronousSocketChannel): InetProxyDevice {
|
suspend fun asyncSocketToDevice(socket: AsynchronousSocketChannel): InetTransportDevice {
|
||||||
val deferredDevice = CompletableDeferred<InetProxyDevice>()
|
val deferredDevice = CompletableDeferred<InetTransportDevice>()
|
||||||
globalLaunch {
|
globalLaunch {
|
||||||
coroutineScope {
|
coroutineScope {
|
||||||
fun stop() {
|
fun stop() {
|
||||||
@ -109,7 +109,7 @@ suspend fun asyncSocketToDevice(socket: AsynchronousSocketChannel): InetProxyDev
|
|||||||
// SocketAddress.
|
// SocketAddress.
|
||||||
val addr = socket.remoteAddress as InetSocketAddress
|
val addr = socket.remoteAddress as InetSocketAddress
|
||||||
deferredDevice.complete(
|
deferredDevice.complete(
|
||||||
InetProxyDevice(inputBlocks, outputBlocks, JvmNetworkAddress(addr.address,addr.port)) { stop() }
|
InetTransportDevice(inputBlocks, outputBlocks, JvmNetworkAddress(addr.address,addr.port)) { stop() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
globalLaunch { socket.close() }
|
globalLaunch { socket.close() }
|
||||||
|
@ -38,7 +38,6 @@ class NetworkTest {
|
|||||||
val j = launch {
|
val j = launch {
|
||||||
serverFlow.collect { device ->
|
serverFlow.collect { device ->
|
||||||
launch {
|
launch {
|
||||||
println("connected!")
|
|
||||||
device.output.send("Hello, world!".encodeToUByteArray())
|
device.output.send("Hello, world!".encodeToUByteArray())
|
||||||
device.output.send("Great".encodeToUByteArray())
|
device.output.send("Great".encodeToUByteArray())
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -56,29 +55,18 @@ class NetworkTest {
|
|||||||
}
|
}
|
||||||
yield()
|
yield()
|
||||||
run {
|
run {
|
||||||
println("x0")
|
|
||||||
val s = connectTcpDevice("127.0.1.1:17171".toNetworkAddress())
|
val s = connectTcpDevice("127.0.1.1:17171".toNetworkAddress())
|
||||||
println("x1")
|
|
||||||
assertEquals("Hello, world!", s.input.receive()!!.decodeFromUByteArray())
|
assertEquals("Hello, world!", s.input.receive()!!.decodeFromUByteArray())
|
||||||
println("x2")
|
|
||||||
assertEquals("Great", s.input.receive()!!.decodeFromUByteArray())
|
assertEquals("Great", s.input.receive()!!.decodeFromUByteArray())
|
||||||
println("x3")
|
|
||||||
s.output.send("Goodbye".encodeToUByteArray())
|
s.output.send("Goodbye".encodeToUByteArray())
|
||||||
println("pre1")
|
|
||||||
s.close()
|
s.close()
|
||||||
println("pre2")
|
|
||||||
}
|
}
|
||||||
val s1 = connectTcpDevice("127.0.1.1:17171".toNetworkAddress())
|
val s1 = connectTcpDevice("127.0.1.1:17171".toNetworkAddress())
|
||||||
println("conn-0-1")
|
|
||||||
assertEquals("Hello, world!", s1.input.receive()!!.decodeFromUByteArray())
|
assertEquals("Hello, world!", s1.input.receive()!!.decodeFromUByteArray())
|
||||||
println("conn-0-2")
|
|
||||||
assertEquals("Great", s1.input.receive()!!.decodeFromUByteArray())
|
assertEquals("Great", s1.input.receive()!!.decodeFromUByteArray())
|
||||||
println("1")
|
|
||||||
s1.output.send("die".encodeToUByteArray())
|
s1.output.send("die".encodeToUByteArray())
|
||||||
println("2")
|
|
||||||
delay(200)
|
delay(200)
|
||||||
s1.close()
|
s1.close()
|
||||||
println("3 -- the -- end")
|
|
||||||
j.cancelAndJoin()
|
j.cancelAndJoin()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
package net.sergeych.kiloparsec.adapter
|
package net.sergeych.kiloparsec.adapter
|
||||||
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import net.sergeych.kiloparsec.Transport
|
|
||||||
|
|
||||||
actual fun NetworkAddress(host: String, port: Int): NetworkAddress {
|
actual fun NetworkAddress(host: String, port: Int): NetworkAddress {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun acceptTcpDevice(port: Int): Flow<Transport.Device> {
|
actual fun acceptTcpDevice(port: Int): Flow<InetTransportDevice> {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
actual suspend fun connectTcpDevice(address: NetworkAddress): Transport.Device {
|
actual suspend fun connectTcpDevice(address: NetworkAddress): InetTransportDevice {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user