Edoardo Luppi
08/01/2024, 6:51 PMval tcp = aSocket(SelectorManagerHolder.instance()).tcp()
socket = tcp.connect(address.host, address.port) {
noDelay = true
keepAlive = true
}
readChannel = socket.openReadChannel()
writeChannel = socket.openWriteChannel()
// This reads from the plain socket
val properties = deserialize(::ServerProperties)
if (properties.ssl) {
socket = socket.tls(currentCoroutineContext()) {
trustManager = NoopTrustManager
}
}
However I get the following exception:
reading channel has already been set
java.lang.IllegalStateException: reading channel has already been set
at io.ktor.network.sockets.NIOSocketImpl.attachFor(NIOSocketImpl.kt:90)
at io.ktor.network.sockets.NIOSocketImpl.attachForReading(NIOSocketImpl.kt:46)
at io.ktor.network.sockets.SocketsKt.openReadChannel(Sockets.kt:113)
What am I missing here?Aleksei Tirman [JB]
08/01/2024, 8:47 PMtls
method call opens the read and write channels, which are already opened explicitly in your code.Edoardo Luppi
08/01/2024, 9:05 PMEdoardo Luppi
08/01/2024, 9:07 PMval properties = deserialize(::ServerProperties)
uses readChannel
internally, so I need it.Aleksei Tirman [JB]
08/01/2024, 9:15 PMEdoardo Luppi
08/01/2024, 9:17 PMEdoardo Luppi
08/01/2024, 9:18 PMOleg Yukhnevich
08/01/2024, 9:29 PMConnection
in the beginning from socket
and then use tls
extension on `Connection`: https://github.com/ktorio/ktor/blob/b813aebb82b8c9c76dd575762250815b6b27e446/ktor-[…]ktor-network-tls/jvmAndNix/src/io/ktor/network/tls/TLSCommon.kt
AFAIK it doesn't open channels, as they are already opened and stored inside Connection
Oleg Yukhnevich
08/01/2024, 9:31 PMval tcp = aSocket(SelectorManagerHolder.instance()).tcp()
val connection = tcp.connect(address.host, address.port) {
noDelay = true
keepAlive = true
}
socket = connection.socket
readChannel = connection.input
writeChannel = connection.output
// This reads from the plain socket
val properties = deserialize(::ServerProperties)
if (properties.ssl) {
socket = connection.tls(currentCoroutineContext()) {
trustManager = NoopTrustManager
}
}
something like this
or you can even store connection
instead of socket
and it's channels, so to make sure that they are kept in syncEdoardo Luppi
08/01/2024, 9:35 PMOperation is already in progress
java.lang.IllegalStateException: Operation is already in progress
at io.ktor.utils.io.ByteBufferChannel.suspensionForSize(ByteBufferChannel.kt:3638)
at io.ktor.utils.io.ByteBufferChannel.readSuspendImpl(ByteBufferChannel.kt:2238)
at io.ktor.utils.io.ByteBufferChannel.readSuspendLoop(ByteBufferChannel.kt:2189)
at io.ktor.utils.io.ByteBufferChannel.readSuspend(ByteBufferChannel.kt:2173)
at io.ktor.utils.io.ByteBufferChannel.readInt(ByteBufferChannel.kt:2560)
at com.hcl.mainframe.proto.internal.JvmSocket$readUInt$uint$1.invokeSuspend(JvmSocket.kt:133)
at com.hcl.mainframe.proto.internal.JvmSocket$readUInt$uint$1.invoke(JvmSocket.kt)
at com.hcl.mainframe.proto.internal.JvmSocket$readUInt$uint$1.invoke(JvmSocket.kt)
at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturnIgnoreTimeout(Undispatched.kt:72)
at kotlinx.coroutines.TimeoutKt.setupTimeout(Timeout.kt:148)
at kotlinx.coroutines.TimeoutKt.withTimeoutOrNull(Timeout.kt:104)
at com.hcl.mainframe.proto.internal.JvmSocket.readUInt(JvmSocket.kt:132)
at com.hcl.mainframe.proto.internal.JvmSocket.deserialize(JvmSocket.kt:101)
Edoardo Luppi
08/01/2024, 9:56 PMval tlsSocket = this.connection.tls(currentCoroutineContext()) {
trustManager = NoopTrustManager
}
this.connection = tlsSocket.connection()
Basically the original plain socket channels are used for the TLS handshake, and then new channels need to be binded.Edoardo Luppi
08/01/2024, 9:57 PMEdoardo Luppi
08/01/2024, 10:03 PMEdoardo Luppi
08/01/2024, 11:04 PMif (sslSocket != null) {
// Closes the SSL socket before the second handshake
sslSocket.close();
}
SSLContext ctx = getSSLContext(hostDetails);
sslSocket = (SSLSocket) ctx.getSocketFactory().createSocket(plainSocket, this.hostName, this.portNumber, false);
Any way to do the same in Ktor? Basically I'd need to re-negotiate.
The plain socket is kept alive between all this.