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 | ||||
| 
 | ||||
| @Suppress("unused") | ||||
| class InetProxyDevice( | ||||
| class InetTransportDevice( | ||||
|     inputChannel: Channel<UByteArray?>, | ||||
|     outputChannel: Channel<UByteArray>, | ||||
|     val remoteAddress: NetworkAddress, | ||||
| @ -2,7 +2,6 @@ package net.sergeych.kiloparsec.adapter | ||||
| 
 | ||||
| import kotlinx.coroutines.channels.ReceiveChannel | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| import net.sergeych.kiloparsec.Transport | ||||
| 
 | ||||
| /** | ||||
|  * 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 | ||||
| 
 | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| import net.sergeych.kiloparsec.Transport | ||||
| 
 | ||||
| actual fun NetworkAddress(host: String, port: Int): NetworkAddress { | ||||
|     TODO("Not yet implemented") | ||||
| } | ||||
| 
 | ||||
| actual fun acceptTcpDevice(port: Int): Flow<Transport.Device> { | ||||
| actual fun acceptTcpDevice(port: Int): Flow<InetTransportDevice> { | ||||
|     TODO("Not yet implemented") | ||||
| } | ||||
| 
 | ||||
| actual suspend fun connectTcpDevice(address: NetworkAddress): Transport.Device { | ||||
| actual suspend fun connectTcpDevice(address: NetworkAddress): InetTransportDevice { | ||||
|     TODO("Not yet implemented") | ||||
| } | ||||
| @ -1,12 +1,10 @@ | ||||
| package net.sergeych.kiloparsec.adapter | ||||
| 
 | ||||
| import kotlinx.coroutines.Dispatchers | ||||
| import kotlinx.coroutines.channels.SendChannel | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| import kotlinx.coroutines.flow.flow | ||||
| import kotlinx.coroutines.suspendCancellableCoroutine | ||||
| import kotlinx.coroutines.withContext | ||||
| import net.sergeych.kiloparsec.Transport | ||||
| import java.net.InetAddress | ||||
| import java.net.InetSocketAddress | ||||
| import java.nio.channels.AsynchronousServerSocketChannel | ||||
| @ -16,7 +14,7 @@ import kotlin.coroutines.suspendCoroutine | ||||
| actual fun NetworkAddress(host: String, port: Int): NetworkAddress = | ||||
|     JvmNetworkAddress(InetAddress.getByName(host), port) | ||||
| 
 | ||||
| actual fun acceptTcpDevice(port: Int): Flow<Transport.Device> { | ||||
| actual fun acceptTcpDevice(port: Int): Flow<InetTransportDevice> { | ||||
|     return flow { | ||||
|         val socket = withContext(Dispatchers.IO) { | ||||
|             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 | ||||
|     val socket = withContext(Dispatchers.IO) { | ||||
|         AsynchronousSocketChannel.open() | ||||
| @ -45,7 +43,3 @@ actual suspend fun connectTcpDevice(address: NetworkAddress): Transport.Device { | ||||
|     } | ||||
|     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 | ||||
|  *  or the socket is closed, for example, by network failure. | ||||
|  */ | ||||
| suspend fun asyncSocketToDevice(socket: AsynchronousSocketChannel): InetProxyDevice { | ||||
|     val deferredDevice = CompletableDeferred<InetProxyDevice>() | ||||
| suspend fun asyncSocketToDevice(socket: AsynchronousSocketChannel): InetTransportDevice { | ||||
|     val deferredDevice = CompletableDeferred<InetTransportDevice>() | ||||
|     globalLaunch { | ||||
|         coroutineScope { | ||||
|             fun stop() { | ||||
| @ -109,7 +109,7 @@ suspend fun asyncSocketToDevice(socket: AsynchronousSocketChannel): InetProxyDev | ||||
| //            SocketAddress. | ||||
|             val addr = socket.remoteAddress as InetSocketAddress | ||||
|             deferredDevice.complete( | ||||
|                 InetProxyDevice(inputBlocks, outputBlocks, JvmNetworkAddress(addr.address,addr.port)) { stop() } | ||||
|                 InetTransportDevice(inputBlocks, outputBlocks, JvmNetworkAddress(addr.address,addr.port)) { stop() } | ||||
|             ) | ||||
|         } | ||||
|         globalLaunch { socket.close() } | ||||
|  | ||||
| @ -38,7 +38,6 @@ class NetworkTest { | ||||
|             val j = launch { | ||||
|                 serverFlow.collect { device -> | ||||
|                     launch { | ||||
|                         println("connected!") | ||||
|                         device.output.send("Hello, world!".encodeToUByteArray()) | ||||
|                         device.output.send("Great".encodeToUByteArray()) | ||||
|                         while (true) { | ||||
| @ -56,29 +55,18 @@ class NetworkTest { | ||||
|             } | ||||
|             yield() | ||||
|             run { | ||||
|                 println("x0") | ||||
|                 val s = connectTcpDevice("127.0.1.1:17171".toNetworkAddress()) | ||||
|                 println("x1") | ||||
|                 assertEquals("Hello, world!", s.input.receive()!!.decodeFromUByteArray()) | ||||
|                 println("x2") | ||||
|                 assertEquals("Great", s.input.receive()!!.decodeFromUByteArray()) | ||||
|                 println("x3") | ||||
|                 s.output.send("Goodbye".encodeToUByteArray()) | ||||
|                 println("pre1") | ||||
|                 s.close() | ||||
|                 println("pre2") | ||||
|             } | ||||
|             val s1 = connectTcpDevice("127.0.1.1:17171".toNetworkAddress()) | ||||
|             println("conn-0-1") | ||||
|             assertEquals("Hello, world!", s1.input.receive()!!.decodeFromUByteArray()) | ||||
|             println("conn-0-2") | ||||
|             assertEquals("Great", s1.input.receive()!!.decodeFromUByteArray()) | ||||
|             println("1") | ||||
|             s1.output.send("die".encodeToUByteArray()) | ||||
|             println("2") | ||||
|             delay(200) | ||||
|             s1.close() | ||||
|             println("3 -- the -- end") | ||||
|             j.cancelAndJoin() | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -1,16 +1,15 @@ | ||||
| package net.sergeych.kiloparsec.adapter | ||||
| 
 | ||||
| import kotlinx.coroutines.flow.Flow | ||||
| import net.sergeych.kiloparsec.Transport | ||||
| 
 | ||||
| actual fun NetworkAddress(host: String, port: Int): NetworkAddress { | ||||
|     TODO("Not yet implemented") | ||||
| } | ||||
| 
 | ||||
| actual fun acceptTcpDevice(port: Int): Flow<Transport.Device> { | ||||
| actual fun acceptTcpDevice(port: Int): Flow<InetTransportDevice> { | ||||
|     TODO("Not yet implemented") | ||||
| } | ||||
| 
 | ||||
| actual suspend fun connectTcpDevice(address: NetworkAddress): Transport.Device { | ||||
| actual suspend fun connectTcpDevice(address: NetworkAddress): InetTransportDevice { | ||||
|     TODO("Not yet implemented") | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user