Problem in communication with SwiftNIO when server is in a background app

For some reason, I want to connect to a websocket server from web browser. It means I have implemented websocket server in an ios app with SwiftNIO and then connect to it from javascript in browser.
I can connect to the websocket server successfuly from javascript when I open it in webview, but when I open web page in browser, the websocket server doesn't respond until the ios app comes to the front.
I implemented this solution successfully in android, but I faced such problem in IOS. I will appreciate if anyone can guid me to solve my problem.
I used this code as my server:
https://github.com/apple/swift-nio/blob/main/Sources/NIOWebSocketServer/main.swift

You can’t run networking in the background, except for limited time if you take a background task assertion or using a background URLSession, which doesn’t support websockets.

1 Like

Thank you Jon for your answer. I want to make sure that I understand your answer correctly. Did you say, it doesn't have any solution for websocket (both background task assertion and using a background URLSession don't support websocket)?

1 Like

On iOS only very specific apps (e.g. VoIP) are allowed to run in the background, and for very specific purposes only.

I.e. regular apps are stopped when they enter the background.
If you have server components in the app, that usually means that you have to stop the server when entering the background and restart them when going to foreground again.

The answers on this thread are spot on. There are very limited situations where iOS apps can run background networking. The most common case would be via background URLSession, but that would not apply in this case because it sounds like you are using SwiftNIO:

I have implemented websocket server in an ios app with SwiftNIO and then connect to it from javascript in browser.

Regarding:

I want to make sure that I understand your answer correctly. Did you say, it doesn't have any solution for websocket (both background task assertion and using a background URLSession don't support websocket)?

In URLSession the only supported background tasks are URLSessionUploadTask and URLSessionDownloadTask.

Thanks @meaton! Given that their app's a WebSocket server, I assume URLSession won't work here (your answer pretty much implies that).

That means that unless the application is a VoIP app and gets the appropriate entitlement (for background networking), the app will not be allowed to carry out its work in the background. Correct? Any other exceptions apart from VoIP apps?

E.g. tunnel providers, which often tend to use SwiftNIO and be proxy servers ;-)

1 Like

Thanks @meaton! Given that their app's a WebSocket server , I assume URLSession won't work here (your answer pretty much implies that).

Yes, that is correct.

That means that unless the application is a VoIP app and gets the appropriate entitlement (for background networking), the app will not be allowed to carry out its work in the background. Correct?
Any other exceptions apart from VoIP apps?

and

E.g. tunnel providers, which often tend to use SwiftNIO and be proxy servers ;-)

Regarding the VoIP and CallKit workflows; I'm not the best to answer the background capabilities there as I do not work with these APIs or entitlements on a day to day basis. One thing I can mention is that a lot of that functionality changed here with iOS 13+.

Now, regarding Network Extension on iOS, that is something I can speak to. While this may be technically possible there are a few things that need to be considered about this type of workflow:

  1. Using a Network Extension to gain background runtime for a server is not the intended use of that API. Specifically if you try and deploy this to the App Store I suspect you will need to explain this to App Review.
  2. There is a memory limit of 15 mb in a Network Extension on iOS. If you exceed this your extension will get terminated. This would mean that you need to build out a functional Network Extension and a WebSocket server in SwiftNIO, and so while I'm not sure where this would put you memory wise, it could lead to issues very quickly.
  3. Why build a server on iOS to consume traffic from another app? What is the use case here? I understand there are use cases for building a server inside an iOS app and serving local connections, but what is the use case outside of the app?

For completeness, I also believe that the background audio entitlement can keep your app alive while you are playing audio.

1 Like

Yes, all those backgrounding approaches are very likely a no-go for most apps.

This has been done by multiple people already, I also wrote one myself, but in plain Network.framework. 15 MB is a lot for a streaming protocol.

I can't speak for the original poster, but there are plenty of scenarios, e.g. in P2P setups.
An actual use case I have is with the home automation system I have deployed. It can push live updates to an HTTP server. Works well, but is quite some infra to pull the servers up and down (unfortunately NW doesn't deal with that automagically, which would be quite nice).