0

I'm using Kotlin coroutines to manage a TLS socket connection. In my minimal version of sendMessageToServerTest, I call connectTest() when the socket is not connected, then log the result. However, although connectTest() logs "connectTest: OK" and returns successfully, the log immediately following the call in sendMessageToServerTest never appears. Here’s the minimal code:

    Log.d(TAG, "sendMessageToServer: START")
    if (TcpSocketSSL.socketState.get() != TcpSocketSSL.SocketState.CONNECTED) {
        Log.d(TAG, "sendMessageToServer: connect")
        val res = TcpSocketSSL.connectTest()
        Log.d(TAG, "sendMessageToServer: connect 2 $res")
    }
    Log.d(TAG, "sendMessageToServer: XXX  $message")
}

and function connectTest

    suspend fun connectTest(): Result<Unit> = withContext(Dispatchers.IO) {
        Log.d(TAG, "connectTest: START")
        mutexConnect.withLock {
            if (socketState.get() == SocketState.DISCONNECTED) {
                try {
                    socketState.set(SocketState.CONNECTING)
                    _socketStateFlow.emit(SocketState.CONNECTING)
                    selectorManager.close()
                    selectorManager = SelectorManager(Dispatchers.IO)
                    val tcpSocket = withTimeout(SOCKET_TIMEOUT) {
                        aSocket(selectorManager).tcp().connect(hostname = DNS, port = PORT)
                    }
                    socket = tcpSocket.tls(coroutineContext)
                    receiveChannel = socket?.openReadChannel()
                    sendChannel = socket?.openWriteChannel(autoFlush = true)
                    socketState.set(SocketState.CONNECTED)
                    _socketStateFlow.emit(SocketState.CONNECTED)
                    Log.d(TAG, "connectTest: OK")
                    return@withLock Result.success(Unit)
                } catch (e: Exception) {
                    disconnect(who = "connect", cancelSocketJob = false)
                    return@withLock Result.failure(exception = e)
                }
            } else {
                return@withLock if (socketState.get() == SocketState.CONNECTED) {
                    Result.success(Unit)
                } else {
                    Result.failure(Exception("Unexpected Socket State. Socket state is ${socketState.get()}"))
                }
            }
        }
    }
}

Logcat
2025-03-03 08:57:14.660 18642-18682 TcpSocketManager D sendMessageToServer: START
2025-03-03 08:57:14.660 18642-18682 TcpSocketManager D sendMessageToServer: connect
2025-03-03 08:57:14.661 18642-18682 TcpSocketSSL D connectTest: START
2025-03-03 08:57:14.941 18642-18696 TcpSocketSSL D connectTest: OK
But log Log.d(TAG, "sendMessageToServer: connect 2 $res") never shows. Why? UPDATE: if I use TCP connection without TLS, it works okay

socket = withTimeout(SOCKET_TIMEOUT) {
   aSocket(selectorManager).tcp().connect(hostname = DNS, port = PORT)
}

It seems Ktor TLS handshake is problem in this case. Why?

1

1 Answer 1

0

Try changing this:

_socketStateFlow.emit(SocketState.CONNECTED)

to this:

_socketStateFlow.tryEmit(SocketState.CONNECTED)

The emit function suspends while tryEmit does not and this can sometimes cause you to infinitely suspend if you are not careful.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.