Ktor: Support websockets in kotlin-native

Created on 8 Jun 2020  路  4Comments  路  Source: ktorio/ktor

Ktor Version and Engine Used (client or server and name)
kotlin: 1.3.72
io.ktor:ktor-client-curl: 1.3.2
io.ktor:ktor-client-websockets-native: 1.3.2

Describe the bug
I am trying to create a client for a websocket using ktor for ios and js. I don't have a mac machine so i want to test on linux(linuxX64) but it fails with an iOS error.

To Reproduce
Steps to reproduce the behavior:

  1. Use runBlocking{ } to start a websocket
  2. Run using curl
  3. See error
kotlin.IllegalStateException: [generateNonce] is not supported on iOS
        at kfun:kotlin.Throwable.<init>(kotlin.String?)kotlin.Throwable (0x2fe9b7)
        at kfun:kotlin.Exception.<init>(kotlin.String?)kotlin.Exception (0x2f82c5)
        at kfun:kotlin.RuntimeException.<init>(kotlin.String?)kotlin.RuntimeException (0x2f7e85)
        at kfun:kotlin.IllegalStateException.<init>(kotlin.String?)kotlin.IllegalStateException (0x2f8465)
        at kfun:io.ktor.util.generateNonce()kotlin.String (0x57749b)
        at kfun:io.ktor.util.generateNonce(kotlin.Int)kotlin.ByteArray (0x5615b4)
        at kfun:io.ktor.client.features.websocket.WebSocketContent.<init>()io.ktor.client.features.websocket.WebSocketContent (0x5f47b3)
        at kfun:io.ktor.client.features.websocket.WebSockets.Feature.$install$lambda-0COROUTINE$36.invokeSuspend#internal (0x5f6372)
        at kfun:io.ktor.client.features.websocket.WebSockets.Feature.$install$lambda-0COROUTINE$36.invoke#internal (0x5f692f)
        at kfun:io.ktor.util.pipeline.SuspendFunctionGun.loop#internal (0x5731fd)
        at kfun:io.ktor.util.pipeline.SuspendFunctionGun.proceed#internal (0x57287e)
        at kfun:io.ktor.util.pipeline.SuspendFunctionGun.proceedWith#internal (0x572a57)
        at kfun:io.ktor.client.features.HttpCallValidator.Companion.$install$lambda-0COROUTINE$22.invokeSuspend#internal (0x5e0014)
        at kfun:io.ktor.client.features.HttpCallValidator.Companion.$install$lambda-0COROUTINE$22.invoke#internal (0x5e082f)
        at kfun:io.ktor.util.pipeline.SuspendFunctionGun.loop#internal (0x5731fd)
        at kfun:io.ktor.util.pipeline.SuspendFunctionGun.proceed#internal (0x57287e)
        at kfun:io.ktor.client.features.HttpRequestLifecycle.Feature.$install$lambda-0COROUTINE$30.invokeSuspend#internal (0x5ea8b6)
        at kfun:io.ktor.client.features.HttpRequestLifecycle.Feature.$install$lambda-0COROUTINE$30.invoke#internal (0x5eaf7f)
        at kfun:io.ktor.util.pipeline.SuspendFunctionGun.loop#internal (0x5731fd)
        at kfun:io.ktor.util.pipeline.SuspendFunctionGun.proceed#internal (0x57287e)
        at kfun:io.ktor.util.pipeline.SuspendFunctionGun.execute#internal (0x572c81)
        at kfun:io.ktor.util.pipeline.Pipeline.execute(TContext;TSubject)TSubject (0x56da50)
        at kfun:io.ktor.client.HttpClient.$executeCOROUTINE$10.invokeSuspend(kotlin.Result<kotlin.Any?>)kotlin.Any? (0x5c1f82)
        at kfun:io.ktor.client.HttpClient.execute(io.ktor.client.request.HttpRequestBuilder)io.ktor.client.call.HttpClientCall (0x5c22a6)
        at kfun:io.ktor.client.statement.HttpStatement.$executeUnsafeCOROUTINE$45.invokeSuspend(kotlin.Result<kotlin.Any?>)kotlin.Any? (0x607384)
        at kfun:io.ktor.client.statement.HttpStatement.executeUnsafe$ktor-client-core()io.ktor.client.statement.HttpResponse (0x60766a)
        at kfun:io.ktor.client.features.websocket.$webSocketCOROUTINE$38.invokeSuspend(kotlin.Result<kotlin.Any?>)kotlin.Any? (0x5f9a99)
        at kfun:io.ktor.client.features.websocket.webSocket@io.ktor.client.HttpClient.(kotlin.Function1<io.ktor.client.request.HttpRequestBuilder,kotlin.Unit>;kotlin.coroutines.SuspendFunction1<io.ktor.client.features.websocket.DefaultClientWebSocketSession,kotlin.Unit>) (0x5fbd21)
        at kfun:io.ktor.client.features.websocket.webSocket@io.ktor.client.HttpClient.(io.ktor.http.HttpMethod;kotlin.String;kotlin.Int;kotlin.String;kotlin.Function1<io.ktor.client.request.HttpRequestBuilder,kotlin.Unit>;kotlin.coroutines.SuspendFunction1<io.ktor.client.features.websocket.DefaultClientWebSocketSession,kotlin.Unit>) (0x5f85af)
        at kfun:[email protected].(io.ktor.http.HttpMethod;kotlin.String;kotlin.Int;kotlin.String;kotlin.Function1<io.ktor.client.request.HttpRequestBuilder,kotlin.Unit>;kotlin.coroutines.SuspendFunction1<io.ktor.client.features.websocket.DefaultClientWebSocketSession,kotlin.Unit>) (0x5f82c9)
        at kfun:ro.sevens.client.SevensSocketImpl.connect() (0x622083)
        at kfun:ro.sevens.client.LinuxSocketTest.$test$lambda-1COROUTINE$0.invokeSuspend#internal (0x625767)
        at kfun:kotlin.coroutines.native.internal.BaseContinuationImpl.resumeWith(kotlin.Result<kotlin.Any?>) (0x31a818)
        at kfun:kotlinx.coroutines.DispatchedTask.run() (0x48baba)
        at kfun:kotlinx.coroutines.EventLoopImplBase.processNextEvent()kotlin.Long (0x467367)
        at kfun:kotlinx.coroutines.BlockingCoroutine.joinBlocking#internal (0x498b4e)
        at kfun:kotlinx.coroutines.runBlocking(kotlin.coroutines.CoroutineContext;kotlin.coroutines.SuspendFunction1<kotlinx.coroutines.CoroutineScope,T>){0<kotlin.Any?>}Generic (0x497c38)
        at kfun:kotlinx.coroutines.runBlocking$default(kotlin.coroutines.CoroutineContext?;kotlin.coroutines.SuspendFunction1<kotlinx.coroutines.CoroutineScope,T>;kotlin.Int){0<kotlin.Any?>}Generic (0x498171)
        at kfun:ro.sevens.client.LinuxSocketTest.test() (0x625118)
        at kfun:ro.sevens.client.$LinuxSocketTest$test$0.$test$FUNCTION_REFERENCE$1.invoke#internal (0x6260a3)
        at kfun:ro.sevens.client.$LinuxSocketTest$test$0.$test$FUNCTION_REFERENCE$1.$<bridge-UNNN>invoke(P1)#internal (0x626119)
        at kfun:kotlin.native.internal.test.BaseClassSuite.TestCase.run() (0x3510e7)
        at kfun:kotlin.native.internal.test.TestRunner.run#internal (0x34b1a6)
        at kfun:kotlin.native.internal.test.TestRunner.runIteration#internal (0x34c334)
        at kfun:kotlin.native.internal.test.TestRunner.run()kotlin.Int (0x34cc4d)
        at kfun:kotlin.native.internal.test.testLauncherEntryPoint(kotlin.Array<kotlin.String>)kotlin.Int (0x340a9c)
        at kfun:kotlin.native.internal.test.main(kotlin.Array<kotlin.String>) (0x340967)
        at Konan_start (0x340bcb)
        at Init_and_run_start (0x64c33b)
        at __libc_start_main (0x7f46ed52f002)
        at  (0x2b3029)
        at  ((nil))

Example:

@Test
    fun test() {
        runBlocking {
            //creates an object that initiates the 
            val sevensSocket = LinuxSevensSocket(
                    "127.0.0.1",
                    3333,
                    tokenProvider = { token },
                    listener = AbsSevensSocketListener() //this is for callbacks, does nothing right now
            )
            // starts a client.ws(...) session
            sevensSocket.connect()
        }
        println("asdfg")
    }
duplicate feature

Most helpful comment

Btw we have #ktor channel in kotlin slack: https://surveys.jetbrains.com/s3/kotlin-slack-sign-up
You can always ask any question there :)

All 4 comments

Yep. Native websockets have not supported yet.
Will be fixed in https://github.com/ktorio/ktor/issues/1215

Thank you for your quick response.

Is it ok the way I started the coroutine? I keep searching how to do it and this is the only way i had in mind.

Hi @dragossusi, thanks for the report.
As mentioned before, the WebSockets support is on the roadmap. Yep, you can start coroutine with runBlocking or use launch with Dispatchers.IO for background tasks.

Closed

Btw we have #ktor channel in kotlin slack: https://surveys.jetbrains.com/s3/kotlin-slack-sign-up
You can always ask any question there :)

Was this page helpful?
0 / 5 - 0 ratings