android-ngn-stack/src/main/java/org/doubango/ngn/services/INgnSipService.java
c732d49e
 /*
74ca6d11
 * Copyright (C) 2020, University of the Basque Country (UPV/EHU)
c732d49e
 *  Contact for licensing options: <licensing-mcpttclient(at)mcopenplatform(dot)com>
 *
 * The original file was part of Open Source IMSDROID
 *  Copyright (C) 2010-2011, Mamadou Diop.
 *  Copyright (C) 2011, Doubango Telecom.
 *
 *
 * Contact: Mamadou Diop <diopmamadou(at)doubango(dot)org>
 *
 * This file is part of Open Source Doubango Framework.
 *
 * This is free software: you can redistribute it and/or modify it under the terms of
 * the GNU General Public License as published by the Free Software Foundation, either version 3
 * of the License, or (at your option) any later version.
 *
 * This is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 package org.doubango.ngn.services;
 
 import android.content.Context;
 
 import org.doubango.ngn.sip.NgnPresenceStatus;
 import org.doubango.ngn.sip.NgnSipSession.ConnectionState;
 import org.doubango.ngn.sip.NgnSipStack;
 
 /**@page NgnSipService_page SIP/IMS Service
  * This service is used to manage the SIP/IMS stack. You should never create or start this service by yourself. <br />
  * An instance of this service could be retrieved like this:
  * @code
  * final INgnSipService mSipService = NgnEngine.getInstance().getSipService();
  * @endcode
  * 
  * <h1>Audio/Video calls</h1>
  * <h2>Making audio call</h2>
  * To get notified about the audio/video call state please see @ref anchor_Listening_for_audio_video_call_state "here"<br/>
  * @code
  * final String remoteUri = "+33600000000";
  * final String validUri = NgnUriUtils.makeValidSipUri(remoteUri); // sip:+33600000000"@doubango.org
  * NgnAVSession avSession = NgnAVSession.createOutgoingSession(mSipService.getSipStack(), NgnMediaType.Audio);
  * if(avSession.makeCall(validUri)){
  * 	Log.d(TAG,"all is ok");
  * }
  * else{
  * Log.e(TAG,"Failed to place the call");
  * }
  * @endcode
  * <h2>Making video call</h2>
  * To get notified about the audio/video call state please see @ref anchor_Listening_for_audio_video_call_state "here"<br/>
  * @code
  * final String remoteUri = "+33600000000";
  * final String validUri = NgnUriUtils.makeValidSipUri(remoteUri); // sip:+33600000000"@doubango.org
  * NgnAVSession avSession = NgnAVSession.createOutgoingSession(mSipService.getSipStack(), NgnMediaType.AudioVideo);
  * if(avSession.makeCall(validUri)){
  * 	Log.d(TAG,"all is ok");
  * }
  * else{
  * Log.e(TAG,"Failed to place the call");
  * }
  * @endcode
  * 
  * <h1>SMS and Chat</h1>
  * <h2>3GPP Binary SMS</h2>
  * @code
  * final String SMSC = "sip:+3310000000@doubango.org"; // SMS Center
  * final String remotePartyUri = "sip:+336000000@doubango.org"; // remote party
  * final String textToSend = "hello world!";
  * final NgnMessagingSession imSession = NgnMessagingSession.createOutgoingSession(mSipService.getSipStack(), 
  * remotePartyUri);
  * if(!imSession.SendBinaryMessage(textToSend,SMSC)){
  * 	Log.e(TAG,"Failed to send");
  * }
  * else{
  * Log.d(TAG,"Message sent");
  * }
  * // release session
  * NgnMessagingSession.releaseSession(imSession);
  * @endcode
  * 
  * <h2>Pager Mode IM</h2>
  * @code
  * final String textToSend = "hello world!";
  * final String remotePartyUri = "sip:+336000000@doubango.org"; // remote party
  * final NgnMessagingSession imSession = NgnMessagingSession.createOutgoingSession(mSipService.getSipStack(), 
  * remotePartyUri);
  * if(!imSession.sendTextMessage(textToSend)){
  * 	Log.e(TAG,"Failed to send");
  * }
  * else{
  * Log.d(TAG,"Message sent");
  * }
  * // release session
  * NgnMessagingSession.releaseSession(imSession);
  * @endcode
  * 
  * <h1>Listening to events</h1>
  * The SIP/IMS service is responsible for all task related to the SIP protocol (Registration, audio/video calls, Pager mode IM, Presence, ...) and you can subscribe
  * to the event changed in order to get notified when the registration state change, new SIP MESSAGE is received, new incoming audio/video call, ...<br />
  * All notifications are sent to you in asynchronous way which mean that you don't need to query for them more than once.
  * 
  * <h2>Listening for registration state change</h2>
  * You can listen to the registration state change in order to get notified when you are logged in/out.
  * @code
  * final TextView mTvInfo = (TextView)findViewById(R.id.textViewInfo);
  * final BroadcastReceiver mSipBroadCastRecv = new BroadcastReceiver() {
  * 			@Override
  * 			public void onReceive(Context context, Intent intent) {
  * 				final String action = intent.getAction();
  * 				
  * 				// Registration Event
  * 				if(NgnRegistrationEventArgs.ACTION_REGISTRATION_EVENT.equals(action)){
  * 					NgnRegistrationEventArgs args = intent.getParcelableExtra(NgnEventArgs.EXTRA_EMBEDDED);
  * 					if(args == null){
  * 						Log.e(TAG, "Invalid event args");
  * 						return;
  * 					}
  * 					switch(args.getEventType()){
  * 						case REGISTRATION_NOK:
  * 							mTvInfo.setText("Failed to register :(");
  * 							break;
  * 						case UNREGISTRATION_OK:
  * 							mTvInfo.setText("You are now unregistered :)");
  * 							break;
  * 						case REGISTRATION_OK:
  * 							mTvInfo.setText("You are now registered :)");
  * 							break;
  * 						case REGISTRATION_INPROGRESS:
  * 							mTvInfo.setText("Trying to register...");
  * 							break;
  * 						case UNREGISTRATION_INPROGRESS:
  * 							mTvInfo.setText("Trying to unregister...");
  * 							break;
  * 						case UNREGISTRATION_NOK:
  * 							mTvInfo.setText("Failed to unregister :(");
  * 							break;
  * 					}
  * 				}
  * 			}
  * 		};
  * 		final IntentFilter intentFilter = new IntentFilter();
  * 		intentFilter.addAction(NgnRegistrationEventArgs.ACTION_REGISTRATION_EVENT);
  * 	    registerReceiver(mSipBroadCastRecv, intentFilter);
  * @endcode
  * 
  * <h2>Listening for audio/video call state change</h2>
  *  @anchor anchor_Listening_for_audio_video_call_state
  * You can listen to the audio/video call state change in order to get notified when the call state change (incoming, incall, outgoing, terminated, ...).
  * @code
  * final BroadcastReceiver mSipBroadCastRecv = new BroadcastReceiver() {
  * 		@Override
  * 		public void onReceive(Context context, Intent intent) {
  * 			InviteState state;
  * 			final String action = intent.getAction();
  * 			if(NgnInviteEventArgs.ACTION_INVITE_EVENT.equals(action)){
  * 				NgnInviteEventArgs args = intent.getParcelableExtra(NgnEventArgs.EXTRA_EMBEDDED);
  * 				if(args == null){
  * 					Log.e(TAG, "Invalid event args");
  * 					return;
  * 				}
  * 				Log.d(TAG, "This is an event for session number "+args.getSessionId());		
  * 				// Retrieve the session from the store
  * 				NgnAVSession avSession = NgnAVSession.getSession(args.getSessionId());
  * 				if(avSession == null){
  * 					Log.e(TAG, "Cannot find session");
  * 					return;
  * 				}
  * 				switch((state = avSession.getState())){
  * 					case NONE:
  * 					default:
  * 						break;
  * 						
  * 					case INCOMING:
  * 						Log.i(TAG, "Incoming call");
  * 						break;
  * 						
  * 					case INPROGRESS:
  * 						Log.i(TAG, "Call in progress");
  * 						break;
  * 						
  * 					case REMOTE_RINGING:
  * 						Log.i(TAG, "Remote party is ringing");
  * 						break;
  * 						
  * 					case EARLY_MEDIA:
  * 						Log.i(TAG, "Early media started");
  * 						break;
  * 						
  * 					case INCALL:
  * 						Log.i(TAG, "Call connected");
  * 						break;
  * 						
  * 					case TERMINATING:
  * 						Log.i(TAG, "Call terminating");
  * 						break;
  * 						
  * 					case TERMINATED:
  * 						Log.i(TAG, "Call terminated");
  * 						break;
  * 				}
  * 			}
  * 		}
  * 	};
  * @endcode
  * 
  * <h1>Configuration</h1>
  * Before trying to register to the SIP/IMS server you must configure the stack with your credentials.<br />
  * The configuration service is responsible of this task. <b>All preferences defined using the configuration service
  * are persistent which means that you can retrieve them when the application/device restarts</b>.
  * To configure the stack you must get an instance of the configuration service from the engine like this:
  * @code
  * final INgnConfigurationService mConfigurationService = NgnEngine.getInstance().getConfigurationService();
  * @endcode
  * 
  * <h3>Realm</h3>
  * The <b>realm</b> is the name of the domain to authenticate to. It should be a valid SIP URI (e.g.
  * <i>sip:open-ims.test</i> or <i>sip:10.0.0.1</i>). <br />
  * The <b>realm</b> is mandatory and should be set before the stack starts. You should never change its
  * value once the stack is started. If the address of the Proxy-CSCF is missing, then the stack will
  * automatically use DNS NAPTR+SRV and/or DHCP mechanisms for dynamic discovery. <br />
  * The value of the <b>realm</b> will be used as domain name for the DNS NAPTR query. For more information about
  * how to set the Proxy-CSCF IP address and port, please refer to section 22.1.8.
  * @code 
  * final String myRealm = "sip:doubango.org"; 
  * final boolean bSaveNow = true;
  * mConfigurationService(ConfigurationEntry.NETWORK_REALM, myRealm, bSaveNow);
  * @endcode
  * 
  * <h3>IMS Private Identity (IMPI)</h3>
  * The IMS Private Identity (a.k.a <b>IMPI</b>) is a unique identifier assigned to a user (or UE) by the home network. It could be either a
  * SIP URI (e.g. <i>sip:bob@open-ims.test</i>), a tel URI (e.g. <i>tel:+33100000</i>) or any alphanumeric string
  * (e.g. <i>bob@open-ims.test</i> or <i>bob</i>). It is used to authenticate the UE (username field in SIP Digest
  * Authorization/Proxy-Authorization header). <br />
  * In the real world, it should be stored in an UICC (Universal Integrated Circuit Card).
  * For those using this IMS stack as a basic (IETF) SIP stack, the IMPU should coincide with their
  * authentication name. <br />
  * The <b>IMPI is mandatory</b> and should be set before the stack starts. You should never change the
  * <b>IMPI</b> once the stack is started.
  * @code 
  * final String myIMPI = "33446677887"; 
  * final boolean bSaveNow = true;
  * mConfigurationService(ConfigurationEntry.IDENTITY_IMPI, myIMPI, bSaveNow);
  * @endcode
  * 
  * <h3>IMS Public Identity (IMPU)</h3>
  * As its name says, its you public visible identifier where you are willing to receive calls or any
  * demands. An IMPU could be either a SIP or tel URI (e.g. <i>tel:+33100000</i> or <i>sip:bob@open-ims.test</i>).
  * In IMS world, a user can have multiple IMPUs associated to its unique IMPI.<br />
  * For those using this IMS stack as basic SIP stack, the IMPU should coincide with their SIP URI (a.k.a
  * SIP address).<br />
  * The <b>IMPU is mandatory</b> and should be set before the stack starts. You should never change the
  * IMPU once the stack is started (instead, change the P-Preferred-Identity if you want to change your
  * default public identifier).
  * @code
  * final boolean bSaveNow = true; 
  * final String myIMPU = "sip:33446677887@doubango.org"; 
  * mConfigurationService(ConfigurationEntry.IDENTITY_IMPU, myIMPU, bSaveNow);
  * @endcode
  * 
  * <h3>Preferred Identity</h3>
  * As a user has multiple IMPUs, it can for each outgoing request, defines which IMPU to use by
  * setting the preferred identity. The user should check that this IPMU is not barred. An IMPU is
  * barred if it doesnt appear in the associated URIs returned in the 200 OK REGISTER. <br />
  * By default, the preferred identity is the first URI in the list of the associated identities. If the IMPU
  * used to REGISTER the user is barred, then the stack will use the default URI returned by the SCSCF. <br />
  * You should never manually set this SIP header (P-Preferred-Identity); its up to the stack.
  * 
  * <h3>Proxy-CSCF Host address </h3>
  * The Proxy-CSCF Host is the IP address (192.168.0.1) or FQDN (doubango.org) of the SIP registrar. <br />
  * You should set the Proxy-CSCF address and IP only if required. Dynamic discovery mechanisms
  * (DNS NAPTR and/or DHCPv4/v6) should be used.
  * The code below shows how to set the Proxy-CSCF IP address and Port. If the port is missing, then
  * its default value will be 5060.
  * @code
  * // Sets IP address
  * final String proxyHost = "192.168.0.1";
  * mConfigurationService(ConfigurationEntry.NETWORK_PCSCF_HOST, proxyHost);
  * // Sets port 
  * final int proxyPort = 5060;
  * mConfigurationService.putInt(ConfigurationEntry.NETWORK_PCSCF_PORT, proxyPort);
  * Save changes
  * mConfigurationService.commit();
  * @endcode
  */
 public interface INgnSipService extends INgnBaseService {
 	String getDefaultIdentity();
 	void setDefaultIdentity(String identity);
 	/**
 	 * Gets the underlaying SIP/IMS stack managed by this service. This function should only be called after
 	 * successful registration.
 	 * @return a valid SIP/IMS stack if succeed and null otherwise
 	 * @sa @ref register()
 	 */
     NgnSipStack getSipStack();
     /**
      * Checks whether we are already registered or not.
      * @return
      */
     boolean isRegistered();
175b478c
 
 
c732d49e
     /**
      * Gets the registration state
      * @return the registration state
      */
     ConnectionState getRegistrationState();
     boolean isXcapEnabled();
     boolean isPublicationEnabled();
     boolean isSubscriptionEnabled();
     boolean isSubscriptionToRLSEnabled();
     /**
      * Gets the list of all active codecs
      * @return the list of all active codecs
      */
     int getCodecs();
     /**
      * Sets the list of all active codecs
      * @param coddecs the new codecs to activate
      */
     void setCodecs(int coddecs);
 
     byte[] getSubRLSContent();
     byte[] getSubRegContent();
     byte[] getSubMwiContent();
     byte[] getSubWinfoContent();
 
     /**
      * Set the LocalIp for use in sip stack
      * @param ip is the address in formate String
      * @return
      */
     boolean setLocalIp(String ip);
 
     /**
      * Configure profile
175b478c
      * @param context,invalidProfile
      * @return
      */
     boolean configureProfile(boolean invalidProfile,Context context);
 
     /**
      * Configure profile
c732d49e
      * @param context
      * @return
      */
     boolean configureProfile(Context context);
 
     /**
      * Stops the SIP/IMS stack. Before stopping the stack we the engine will hangup all calls and 
      * shutdown all active sip sessions.
      * @return true if succeed and false otherwise
      */
     boolean stopStack();
175b478c
 
 
 
c732d49e
     /**
      * Sends a Sip REGISTER request to the Proxy-CSCF
      * @param context the context associated to this request. Could be null.
      * @return true if succeed and false otherwise
      * @sa @ref unRegister()
      */
     boolean register(Context context);
     /**
175b478c
      * Sends a Sip REGISTER request to the Proxy-CSCF
      * @param context the context associated to this request. Could be null.
      * @param   invalidProfile
c732d49e
      * @return true if succeed and false otherwise
175b478c
      * @sa @ref unRegister()
c732d49e
      */
175b478c
     boolean register(boolean invalidProfile,Context context);
 
 
 
         /**
          * Deregisters the user by sending a Sip REGISTER request with an expires value equal to zero
          * @return true if succeed and false otherwise
          * @sa register
          */
c732d49e
     boolean unRegister();
 
     boolean PresencePublish();
     boolean PresencePublish(NgnPresenceStatus status);
 
 
     public boolean isRegisterBefore();
 
     public void setRegisterBefore(boolean registerBefore);
 
 
     public  interface  OnAuthenticationListener{
         String onAuthRegister(String nonce);
     }
 
     public  void setOnAuthenticationListener(OnAuthenticationListener onAuthenticationListener);
 
 }