joffrey-bion / krossbow

A Kotlin multiplatform coroutine-based STOMP client over websockets, with built-in conversions.
MIT License
202 stars 15 forks source link

KMM iOS websocket connection refused #241

Closed hyangilam closed 2 years ago

hyangilam commented 2 years ago

These days, trying to connect websocket session to local docker ws server with krossbow but still failing. I wonder why the connection is refused. Could you check the attached sample KMM iosApp project? also, console log

Will it be configuration problem? How did you test & verify iOS? I am curious

default 15:17:25.543029+0900 iosApp nw_socket_handle_socket_event [C1:2] Socket received CONNRESET event default 15:17:25.543194+0900 iosApp nw_socket_handle_socket_event [C1:2] Socket received DISCONNECTED event error 15:17:25.543364+0900 iosApp nw_socket_handle_socket_event [C1:2] Socket SO_ERROR [61: Connection refused] default 15:17:25.544306+0900 iosApp nw_flow_disconnected [C1 127.0.0.1:12020 in_progress socket-flow (satisfied (Path is satisfied), viable, interface: lo0)] Output protocol disconnected default 15:17:25.544478+0900 iosApp [C1 127.0.0.1:12020 failed socket-flow (satisfied (Path is satisfied), viable, interface: lo0)] event: flow:failed_connect @0.038s, error Connection refused

iosApp-Console.log krossbowkmmios.zip iosApp-ConsoleApp-detail.log

joffrey-bion commented 2 years ago

Hi, thank you for reporting this, and thanks a lot for the attached logs and project! I don't have a mac unfortunately so I can't reproduce locally, but logs are helpful.

How did you test & verify iOS? I am curious

I test the iOS client on GitHub Actions's macOS runner, on all darwin platforms, using a local websocket server (running in docker) which handles various error and success cases (the Autobahn Test Suite). But all tests are on simulator, I do not have real devices to test on.

I see the following root cause in the attached logs:

Caused by: org.hildan.krossbow.websocket.darwin.DarwinWebSocketException:
Error
    Domain=NSURLErrorDomain
    Code=-1004 "Could not connect to the server."
UserInfo={
    NSErrorFailingURLStringKey=http://127.0.0.1:12020/ngp,
    NSErrorFailingURLKey=http://127.0.0.1:12020/ngp,
    _NSURLErrorRelatedURLSessionTaskErrorKey=(
        "LocalWebSocketTask <34CC3AFC-B82D-4882-B134-63896752E15A>.<1>"
    ),
    _NSURLErrorFailingURLSessionTaskErrorKey=LocalWebSocketTask <34CC3AFC-B82D-4882-B134-63896752E15A>.<1>, 
    NSLocalizedDescription=Could not connect to the server.
}

The Apple documentation specifies that error -1004 of the NSURLErrorDomain is NSURLErrorCannotConnectToHost:

This can occur when a host name resolves, but the host is down or may not be accepting connections on a certain port.

The issue is likely the port here, are you sure port 12020 is correct? Did you expose that port from your server's container?

joffrey-bion commented 2 years ago

Oh, another idea, maybe you need a URL starting with ws:// scheme and not http:// scheme to connect to the websocket on your server. Could you please try that?

hyangilam commented 2 years ago

Oh, another idea, maybe you need a URL starting with ws:// scheme and not http:// scheme to connect to the websocket on your server. Could you please try that?

Thank you for this quick response. Seeing the attached sample project, server url is set to "ws://127.0.0.1:12020" Using other tool ( postman), Websocket connection is confirmed using that address and port.

Screen Shot 2022-06-14 at 5 14 44 PM
hyangilam commented 2 years ago

Actually, I tried several ways which you explained from https://joffrey-bion.github.io/krossbow/websocket/ktor/ but it all failed γ…œγ…œ One more thing, compared to real device, Simulator shows a little bit different logs.

"/Users/spring/AndroidStudioProjects/krossbowkmmios 2/build/ios/Debug-iphonesimulator/iosApp.app" krossbow websocket connect requestStompConnect 2022-06-14 17:38:33.652026+0900 iosApp[32533:746329] [connection] nw_read_request_report [C1] Receive failed with error "Socket is not connected" 2022-06-14 17:38:33.652129+0900 iosApp[32533:746329] [connection] nw_flow_service_reads [C1 127.0.0.1:12020 failed socket-flow (satisfied (Path is satisfied), interface: lo0)] No output handler 2022-06-14 17:38:33.652453+0900 iosApp[32533:746329] Connection 1: received failure notification 2022-06-14 17:38:33.652593+0900 iosApp[32533:746327] [connection] nw_flow_add_write_request [C1 127.0.0.1:12020 failed socket-flow (satisfied (Path is satisfied), interface: lo0)] cannot accept write requests 2022-06-14 17:38:33.652745+0900 iosApp[32533:746327] [connection] nw_write_request_report [C1] Send failed with error "Socket is not connected" Uncaught Kotlin exception: org.hildan.krossbow.stomp.StompConnectionException: Failed to connect at STOMP protocol level to host '127.0.0.1' at 0 iosApp 0x103dd5cf7 kfun:kotlin.Exception#(kotlin.String?;kotlin.Throwable?){} + 119 at 1 iosApp 0x104190df8 kfun:org.hildan.krossbow.stomp.ConnectionException#(kotlin.String;kotlin.String;kotlin.Throwable?){} + 152 at 2 iosApp 0x104191283 kfun:org.hildan.krossbow.stomp.StompConnectionException#(kotlin.String?;kotlin.Throwable?){} + 643 at 3 iosApp 0x10419969b kfun:org.hildan.krossbow.stomp.$stompCOROUTINE$50#invokeSuspend(kotlin.Result<kotlin.Any?>){}kotlin.Any? + 2235 at 4 iosApp 0x103de0c86 kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#resumeWith(kotlin.Result<kotlin.Any?>){} + 758 at 5 iosApp 0x103fb61d7 kfun:kotlinx.coroutines.internal.ShareableContinuation#resumeWith(kotlin.Result<1:0>){} + 583 at 6 iosApp 0x103f92c96 kfun:kotlinx.coroutines.internal.ScopeCoroutine#afterResume(kotlin.Any?){} + 374 at 7 iosApp 0x103ef72ae kfun:kotlinx.coroutines.AbstractCoroutine#resumeWith(kotlin.Result<1:0>){} + 414 at 8 iosApp 0x103de0fc7 kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#resumeWith(kotlin.Result<kotlin.Any?>){} + 1591 at 9 iosApp 0x103fb61d7 kfun:kotlinx.coroutines.internal.ShareableContinuation#resumeWith(kotlin.Result<1:0>){} + 583 at 10 iosApp 0x103f92c96 kfun:kotlinx.coroutines.internal.ScopeCoroutine#afterResume(kotlin.Any?){} + 374 at 11 iosApp 0x103ef72ae kfun:kotlinx.coroutines.AbstractCoroutine#resumeWith(kotlin.Result<1:0>){} + 414 at 12 iosApp 0x103de0fc7 kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#resumeWith(kotlin.Result<kotlin.Any?>){} + 1591 at 13 iosApp 0x103f87cea kfun:kotlinx.coroutines.DispatchedTask#run(){} + 2938 at 14 iosApp 0x103f0f06a kfun:kotlinx.coroutines.EventLoopImplBase#processNextEvent(){}kotlin.Long + 858 at 15 iosApp 0x103fabe27 kfun:kotlinx.coroutines#runEventLoop(kotlinx.coroutines.EventLoop?;kotlin.Function0){} + 967 at 16 iosApp 0x103fb2d46 kfun:kotlinx.coroutines.WorkerCoroutineDispatcherImpl.start$lambda-1#internal + 390 at 17 iosApp 0x103fb2e7f kfun:kotlinx.coroutines.WorkerCoroutineDispatcherImpl.$start$lambda-1$FUNCTION_REFERENCE$230.invoke#internal + 63 at 18 iosApp 0x103fb2f5f kfun:kotlinx.coroutines.WorkerCoroutineDispatcherImpl.$start$lambda-1$FUNCTION_REFERENCE$230.$invoke(){}#internal + 63 at 19 iosApp 0x103dec0af WorkerLaunchpad + 175 at 20 iosApp 0x10427e270 _ZN6Worker19processQueueElementEb + 2368 at 21 iosApp 0x10427d8cd _ZN12_GLOBAL__N_113workerRoutineEPv + 77 at 22 libsystem_pthread.dylib 0x7fff6da334e0 _pthread_start + 124 at 23 libsystem_pthread.dylib 0x7fff6da2ef6a thread_start + 14 Caused by: org.hildan.krossbow.stomp.StompErrorFrameReceived: Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]; nested exception is java.lang.NullPointerException: null cannot be cast to non-null type kotlin.String at 0 iosApp 0x103ddc25d kfun:kotlin.Throwable#(kotlin.String?){} + 93 at 1 iosApp 0x103dd5c69 kfun:kotlin.Exception#(kotlin.String?){} + 89 at 2 iosApp 0x1041913cf kfun:org.hildan.krossbow.stomp.StompErrorFrameReceived#(org.hildan.krossbow.stomp.frame.StompFrame.Error){} + 191 at 3 iosApp 0x1041938a6 kfun:org.hildan.krossbow.stomp.StompSocket.$decodeStompCOROUTINE$45.invokeSuspend#internal + 1686 at 4 iosApp 0x10419407c kfun:org.hildan.krossbow.stomp.StompSocket.decodeStomp#internal + 316 at 5 iosApp 0x1041979fe kfun:org.hildan.krossbow.stomp.StompSocket.object-1.$collect$lambda-0COROUTINE$43.invokeSuspend#internal + 622 at 6 iosApp 0x104197fdc kfun:org.hildan.krossbow.stomp.StompSocket.object-1.collect$lambda-0#internal + 396 at 7 iosApp 0x104198094 kfun:org.hildan.krossbow.stomp.StompSocket.object-1.$collect$lambda-0$FUNCTION_REFERENCE$9.emit#internal + 116 at 8 iosApp 0x103f79349 kfun:kotlinx.coroutines.flow.$catchImpl$lambda-0COROUTINE$204.invokeSuspend#internal + 681 at 9 iosApp 0x103f796ec kfun:kotlinx.coroutines.flow.catchImpl$lambda-0#internal + 396 at 10 iosApp 0x103f7a274 kfun:kotlinx.coroutines.flow.$catchImpl$lambda-0$FUNCTION_REFERENCE$220.emit#internal + 116 at 11 iosApp 0x103f5de37 kfun:kotlinx.coroutines.flow.$emitAllImplCOROUTINE$192.invokeSuspend#internal + 2391 at 12 iosApp 0x103de0c86 kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#resumeWith(kotlin.Result<kotlin.Any?>){} + 758 at 13 iosApp 0x103f87e93 kfun:kotlinx.coroutines.DispatchedTask#run(){} + 3363 at 14 iosApp 0x103f0f06a kfun:kotlinx.coroutines.EventLoopImplBase#processNextEvent(){}kotlin.Long + 858 ... and 9 more common stack frames skipped

Process finished with exit code 0

iosApp_simulator.log

hyangilam commented 2 years ago

If you can run iOS simulator, how about executing the sample project?

joffrey-bion commented 2 years ago

Thank you for this quick response

Same to you πŸ™‚

Seeing the attached sample project, server url is set to "ws://127.0.0.1:12020"

Sorry I missed this, I had only looked at build files so far. I'm surprised iOS reports an http:// URL then πŸ€”

Here are a few questions, just to make sure I understand the situation better:

  1. Where exactly are you running this client code from? Are you running from a simulator? A device?
  2. What is your server? And where does it run?
  3. Given the commented line above, I'm assuming you already tried with the docker gateway host name host.docker.internal, right? Did you get the same result or was the host name not even found in that case? (this gateway should be helpful when trying to call a local service from a docker container AFAIK, but if your client is not dockerized it shouldn't be necessary)
  4. DId you get the same error with the Ktor websocket client? (I see you made an attempt with it, but it's commented out). Which engine did you use? I don't see an engine dependency in your build files, but for iOS you should probably add the ktor-client-darwin engine.

If you can run iOS simulator, how about executing the sample project?

The simulator is automatically run by Gradle during Kotlin/Native tests for iOS targets, it's only done from the CI. I have no way to run this locally (yes, it was a painfully long feedback loop for me when developing the iOS client! πŸ˜†)

joffrey-bion commented 2 years ago

compared to real device

Wait, the Connection refused is on a real device? How is the client on the device supposed to connect to the server on your computer via 127.0.0.1 (localhost) in your setup? Are you somehow bridging 127.0.0.1 from the device to your computer where you run the server? (at least port 12020?) Or are you running the server on the device as well?

If you're not bridging anything, and not running the server on the device, it seems normal to me that the client cannot connect to the server using a localhost IP, so that would explain your issue on device.

joffrey-bion commented 2 years ago

The simulator logs are more promising now, it means it manages to connect the web socket, but then the STOMP connection fails. This failure is the server sending an ERROR STOMP frame, meaning something went wrong. The exact error is:

Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]; nested exception is java.lang.NullPointerException: null cannot be cast to non-null type kotlin.String

This should be from your server, so maybe there is something in the server logs that you could check for further investigation (like a more informative stack trace on this error).

hyangilam commented 2 years ago

Thank you!. I will check server side first

hyangilam commented 2 years ago

Sorry for this delayed check. Actually, WS server was implemented by other guy and he confirmed that custom header is needed to WS connect.

So I have added that custom header to stomp connect api but it does not work. Could you check StompClient connect api?

Screen Shot 2022-06-16 at 11 48 34 AM Screen Shot 2022-06-16 at 11 55 41 AM
hyangilam commented 2 years ago

Sorry for this delayed check. Actually, WS server was implemented by other guy and he confirmed that custom header is needed to WS connect.

So I have added that custom header to stomp connect api but it does not work. Could you check StompClient connect api?

Screen Shot 2022-06-16 at 11 48 34 AM Screen Shot 2022-06-16 at 11 55 41 AM

Please Ignore previous my query. It seems that there is another reason. I will check further with server guy. (custom header works!!)

joffrey-bion commented 2 years ago

Thanks a lot for keeping me updated on this! Good to hear that custom STOMP connect headers work fine :)

joffrey-bion commented 2 years ago

Hey @hyangilam, just checking up on this topic. Did you manage to resolve your issue eventually?

hyangilam commented 2 years ago

Sorry joffrey, forgot to share progress. There was issue when connecting rabbitmq from ws server side. Server guy handled it! :)

2022λ…„ 6μ›” 24일 (금) μ˜€ν›„ 6:45, Joffrey Bion @.***>λ‹˜μ΄ μž‘μ„±:

Hey @hyangilam https://github.com/hyangilam, just checking up on this topic. Did you manage to resolve your issue eventually?

β€” Reply to this email directly, view it on GitHub https://github.com/joffrey-bion/krossbow/issues/241#issuecomment-1165401708, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA6OLRUIEET7VQ6JI44O2NTVQV7VLANCNFSM5YWQRXMQ . You are receiving this because you were mentioned.Message ID: @.***>

joffrey-bion commented 2 years ago

Good to hear! I'll close this issue then. Feel free to open other issues if you have any other problem.