I am developing a VoIP based iOS (7.1) application. It's underlying socket programming is written in C++ rather than objective C. The app runs fine in foreground but while putting in sleep/background mode it can't receive any communication from server. According to apple document we have to configure one of the app socket for VoIP usage. I am unable to figure out how to configure C++ sockets (Because there are many sockets; i.e. SSL, SIP, RESTful).
The intention is to run the app in sleep mode until it's killed. Tried few links and even couple of them from SO, but since I am novice I would want to have a step by step procedure for this configuration. [Note: In somewhere I found CoreFoudation framework, do I need to use that?]
Edit: begin from iOS8, apple introduces PushKit framework to release the work we need to do to config VoIP application and it also reduces energy usage. You really need to migrate to it
There are tips for developing a VoIP App, reference from Apple
A Voice over Internet Protocol (VoIP) app allows the user to make phone calls using an Internet connection instead of the device’s cellular service. Such an app needs to maintain a persistent network connection to its associated service so that it can receive incoming calls and other relevant data. Rather than keep VoIP apps awake all the time, the system allows them to be suspended and provides facilities for monitoring their sockets for them. When incoming traffic is detected, the system wakes up the VoIP app and returns control of its sockets to it.
There are several requirements for implementing a VoIP app:
Enabling the VoIP background mode lets the system know that it should allow the app to run in the background as needed to manage its network sockets. This key also permits your app to play background audio (although enabling the Audio and AirPlay mode is still encouraged). An app that supports this mode is also relaunched in the background immediately after system boot to ensure that the VoIP services are always available.
The code below shows that how to configure app's socket for VoIP usage.
Step 1: Connect to server
uint16_t port ;
NSString *strIp ;
char ip[20] = {0} ;
memset(ip, 0, sizeof(ip)) ;
memcpy(ip, [strIp UTF8String], [strIp length]) ;
clientSocket = socket(AF_INET, SOCK_STREAM, 0) ;
struct sockaddr_in server_addr ;
bzero(&server_addr, sizeof(server_addr)) ;
server_addr.sin_port = htons(port) ;
server_addr.sin_addr.s_addr = inet_addr(ip) ;
server_addr.sin_family = AF_INET ;
int i = connect(clientSocket, (const struct sockaddr *)&server_addr, sizeof(server_addr)) ;
if (i >= 0) {
}
The server side code may be in C++ environment, but you can pass the clientSocket
to the Objective-C instance, it is a int
value.
Step 2: Create and config read and write stream
After connected to the server, you need to create a read & write stream based on clientSocket
using CFStreamCreatePairWithSocket()
and set the property of streams with NSStreamNetworkServiceTypeVoIP
.
Define read and write streams and keep the strong reference them. Close and release them when the connection is lost.
@property (nonatomic, strong) NSInputStream *inputStream ;
@property (nonatomic, strong) NSOutputStream *outputStream ;
Then config streams:
CFReadStreamRef readStreamRef = nil ;
CFWriteStreamRef writeStreamRef = nil ;
CFStreamCreatePairWithSocket(NULL, clientSocket, &readStreamRef, &writeStreamRef) ; // the socket must have already been connected.
_inputStream = (__bridge_transfer NSInputStream *)readStreamRef ;
_outputStream = (__bridge_transfer NSOutputStream *)writeStreamRef ;
[_inputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType] ;
[_outputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType] ;
[_inputStream open] ;
[_outputStream open] ;
Make sure the socket is already connected before connecting with read & write stream.
Step 3:keep the connection
[[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{
// the code to check if the socket is connected to server
// if not, reconnect to server
// and re-set the read stream and write stream in step2
}] ;
When your app enters background, the socket is managed by system and when the server sends packet to your app, system wakes it up, passes the packet to it. You only have a few seconds to handle the data, so don't do much work here. As it's a VoIP app, the socket should be used to notify user that a call is incoming and you can push a local notification to make user be aware of that.
Because VoIP apps need to stay running in order to receive incoming calls, the system automatically relaunches the app if it exits with a nonzero exit code. (This type of exit could happen when there is memory pressure and your app is terminated as a result.) However, terminating the app also releases all of its sockets, including the one used to maintain the VoIP service connection. Therefore, when the app is launched, it always needs to create its sockets from scratch.
I have created an example project here, the relevant server side code here.