KServerSocketImpl.kt
package org.knio.core.net
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import org.knio.core.context.getKnioContext
import org.knio.core.nio.acceptSuspend
import java.net.*
import java.nio.channels.AsynchronousServerSocketChannel
internal class KServerSocketImpl(
private val channel: AsynchronousServerSocketChannel
): KServerSocket {
private val acceptMutex = Mutex()
override suspend fun accept(): KSocket {
acceptMutex.withLock {
return accept0()
}
}
private suspend fun accept0(): KSocket {
val acceptChannel = channel.acceptSuspend()
return KSocketImpl(acceptChannel, getKnioContext())
}
override suspend fun bind(endpoint: SocketAddress, backlog: Int): Unit = withContext(Dispatchers.IO) {
channel.bind(endpoint, backlog)
}
override suspend fun close(): Unit {
channel.close()
}
override suspend fun getInetAddress(): InetAddress? {
val address = channel.localAddress ?: return null
return if(address is InetSocketAddress) {
address.address
} else {
null
}
}
override suspend fun getLocalPort(): Int {
val address = channel.localAddress ?: return -1
return if(address is InetSocketAddress) {
address.port
} else {
-1
}
}
override suspend fun getLocalSocketAddress(): SocketAddress? = channel.localAddress
override suspend fun getReceiveBufferSize(): Int = withContext(Dispatchers.IO) {
channel.getOption(StandardSocketOptions.SO_RCVBUF)
}
override suspend fun getReuseAddress(): Boolean = withContext(Dispatchers.IO) {
channel.getOption(StandardSocketOptions.SO_REUSEADDR)
}
override suspend fun isBound(): Boolean = channel.localAddress != null
override suspend fun isClosed(): Boolean = !channel.isOpen
override suspend fun setReceiveBufferSize(size: Int): Unit = withContext(Dispatchers.IO) {
channel.setOption(StandardSocketOptions.SO_RCVBUF, size)
}
override suspend fun setReuseAddress(on: Boolean): Unit = withContext(Dispatchers.IO) {
channel.setOption(StandardSocketOptions.SO_REUSEADDR, on)
}
}