]> sjero.net Git - linphone/blobdiff - coreapi/help/doxygen.dox
add IOS section in doxygen
[linphone] / coreapi / help / doxygen.dox
index 32ed3da1af9e009d71548af61d6252cfc8b7c121..8217eaf6b9a29fe5b9c510ffb8976f9095f21240 100644 (file)
@@ -25,7 +25,7 @@
 
 /**
  * @page liblinphone_license COPYING 
- * @verbinclude COPYING
+ * @include COPYING
  */
 
 /**
@@ -196,5 +196,150 @@ void text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddre
  *
 **/
 
+/**
+ * @defgroup port Portability: 
+ *
+**/
+/**
+ * @defgroup IOS IOS
+ * @ingroup port
+ *<br>
+ <b>Multitasking</b>
+ <br> liblinphone for IOS natively supports multitasking assuming application follows multitasking guides provided by Apple. First step is to declare application as multitasked. It means adding background mode for both audio and voip to Info.plist file.
+ <br>
+ \code
+       <key>UIBackgroundModes</key>
+       <array>
+               <string>voip</string>
+               <string>audio</string>
+       </array>
+\endcode
+<br>
+<ul>
+<li><b>SIP socket </b> Recommanded mode is TCP, because UDP requires keep alives for maintaining NAT association at the IP router level. 
+Unfortunnatly, UDP keep alives are not possible on IOS. For TCP, liblinphone automatically configures SIP socket for voip  (I.E kCFStreamNetworkServiceType set to kCFStreamNetworkServiceTypeVoIP). 
+For UDP, it is the responsability of application to set this property of the UDP SIP socket before entering in background. For UDP, the application can access the SIP socket from method #linphone_core_get_sip_socket(). Note this property is only settable on a connected socket. As liblinphone UDP socket are not connected, application willing to enable UDP bacground mode  must first  connect the UDP sip socket before configuring the voip mode. Pseudo code belows show the different steps:
+\code
+       //get sip socket
+       CFReadStreamRef mReadStream
+       int sipsock = linphone_core_get_sip_socket(theLinphoneCore);    
+       //get address port of the sip proxy in order to connect the udp socket to this proxy
+       const char *port;
+       addr=linphone_address_new(linphone_proxy_config_get_addr(proxyCfg));
+       memset(&hints,0,sizeof(hints));
+       hints.ai_family=linphone_core_ipv6_enabled(theLinphoneCore) ? AF_INET6 : AF_INET;
+       port=linphone_address_get_port(addr);
+       if (port==NULL) port="5060";
+       err=getaddrinfo(linphone_address_get_domain(addr),port,&hints,&res);
+       if (err!=0){
+               ms_error("getaddrinfo() failed for %s: %s",linphone_address_get_domain(addr),gai_strerror(err));
+               linphone_address_destroy(addr);
+               return;
+       }
+       //connect the udp socket
+       err=connect(sipsock,res->ai_addr,res->ai_addrlen);
+       if (err==-1){
+               ms_error("Connect failed: %s",strerror(errno));
+       }
+       freeaddrinfo(res);
+       //create CFRead stream from the sip socket id
+       CFStreamCreatePairWithSocket(NULL, (CFSocketNativeHandle)sipsock, &mReadStream,nil);
+       //configure for persistante connection
+       if (!CFReadStreamSetProperty(mReadStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP)) {
+               ms_error("cannot set service type to voip for read stream");
+       }
+       if (!CFReadStreamOpen(mReadStream)) {
+               ms_error("cannot open read stream");
+       }               
 
+\endcode
+<br> Note this operation has to be performed every time the application enters in background mode.
+<br> Anyway, for battery saving, UDP background mode is not recomnmanded
+<li><b>Entering bacground mode</b>
+<br> Before entering in background mode  \code - (void)applicationDidEnterBackground:(UIApplication *)application \endcode    The application must first refresh sip registration using function #linphone_core_refresh_registers();
+and register a Keep alive handler for periodically refreshing registration. The speudo code below show how to register a keep alive handler:
+\code
+       //First refresh registration
+       linphone_core_refresh_registers(theLinphoneCore);
+       //wait for registration answer
+       int i=0;
+       while (!linphone_proxy_config_is_registered(proxyCfg) && i++<40 ) {
+               linphone_core_iterate(theLinphoneCore);
+               usleep(100000);
+       }
+       //register keepalive handler
+       [[UIApplication sharedApplication] setKeepAliveTimeout:600/*minimal interval is 600 s*/ 
+                                                       handler:^{
+                                                                //refresh sip registration
+                                                                linphone_core_refresh_registers(theLinphoneCore);
+                                                                //make sure sip REGISTER 
+                                                                linphone_core_iterate(theLinphoneCore);
+                                                                 }];
+\endcode
+<li><b>Incoming call notification while in background mode</b>
+<br>Assuming application using liblinphone is well configured for multitasking, incoming calls arriving while liblinphone is in background mode will simply wakeup  liblinphone thread but not resume GUI. To wakeup GUI, it is recommanded  to send a Local Notification to the user from the #LinphoneCallStateCb. Here under a speudo code for this operation:
+\code
+       if ([UIApplication sharedApplication].applicationState ==  UIApplicationStateBackground) {
+               // Create a new notification
+               UILocalNotification* notif = [[[UILocalNotification alloc] init] autorelease];
+               if (notif) {
+                       notif.repeatInterval = 0;
+                       notif.alertBody =@"New incoming call";
+                       notif.alertAction = @"Answer";
+                       notif.soundName = @"oldphone-mono-30s.caf";
+                       
+                       [[UIApplication sharedApplication]  presentLocalNotificationNow:notif];
+               }
+\endcode
+</ul>
+<b>Networking</b>
+<br>
+<ul><li><b>WWAN connection</b>
+<br>liblinphone relies on bsd socket for sip/rtp networking. On IOS, WWAN connection is supposed to automatically setup on any networking resquest issued by an application. At least on iPhone OS 3.x, BSD sockets do not automaticaly bring up the WWAN interface. So it is recommanded to add a special code to make sure the WWAN connection is properly setup. Speudo code belows describe a way to force WWAN connection.
+\code
+/*start a new thread to avoid blocking the main ui in case of peer host failure*/
+[NSThread detachNewThreadSelector:@selector(runNetworkConnection) toTarget:self withObject:nil];
+-(void) runNetworkConnection {
+       CFWriteStreamRef writeStream;
+       //create a dummy socket
+       CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.0.200", 15000, nil, &writeStream);
+       CFWriteStreamOpen (writeStream);
+       const char* buff="hello";
+       //try to write on this socket
+       CFWriteStreamWrite (writeStream,(const UInt8*)buff,strlen(buff));
+       CFWriteStreamClose (writeStream);
+}      
+\endcode  
+It is recommanded to perform this task each time the application is waked up, including keep alive handler.
+<li><b>Managing IP connection state</b>
+<br>liblinphone for IOS relies on the application to be informed of network changes. Network state change when the IP connection move from DOWN to UP, or from WIFI to WWAN. Applications using liblinphone must inform libliblinphone of this changes using function #linphone_core_set_network_reachable(). Usually this method is called from the IOS NetworkReachability callback. Here under a sample code:
+\code
+//typical reachability callback
+void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void * info) {
+       if ((flags == 0) | (flags & (kSCNetworkReachabilityFlagsConnectionRequired |kSCNetworkReachabilityFlagsConnectionOnTraffic))) {
+               //network state is off
+               linphone_core_set_network_reachable(lc,false);
+               ((LinphoneManager*)info).connectivity = none;
+       } else {
+               Connectivity  newConnectivity = flags & kSCNetworkReachabilityFlagsIsWWAN ? wwan:wifi;
+               if (lLinphoneMgr.connectivity == none) {
+                       //notify new network state
+                       linphone_core_set_network_reachable(lc,true);
+               } else if (lLinphoneMgr.connectivity != newConnectivity) {
+                       // connectivity has changed
+                       linphone_core_set_network_reachable(lc,false);
+                       linphone_core_set_network_reachable(lc,true);
+               }
+               //store new connectivity status
+               lLinphoneMgr.connectivity=newConnectivity;
+       }
+}
+}
+       
+\endcode  
+</ul>
+<b>DTMF feebacks</b>
+<br>liblinphone provides  functions \link #linphone_core_play_dtmf() to play dtmf \endlink . Usually this is used to play a sound when the a user type a digit.  On IOS, libLinphone relies on Audio unit for interfacing with the audio system. Audio unit initialization is a quit long operation that may trigger a bad user experience if performed each time a DTMF is played. On IOS, liblinphone introduce 2 functions for \link linphone_core_start_dtmf_stream() preloading \endlink \link #linphone_core_start_dtmf_stream() unloading \endlink underlying  audio graph responsible of playing DTMFs.  
+<br> For application using function  #linphone_core_play_dtmf() , it is recommanded to call #linphone_core_start_dtmf_stream() when entering in foreground and #linphone_core_stop_dtmf_stream() upon entering background mode. 
+*/