c732d49e |
/* |
175b478c |
|
74ca6d11 |
* Copyright (C) 2020, University of the Basque Country (UPV/EHU) |
c732d49e |
*
* Contact for licensing options: <licensing-mcpttclient(at)mcopenplatform(dot)com>
*
* This file is part of MCOP MCPTT Client
*
* 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.impl.affiliation;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import org.doubango.ngn.BuildConfig;
import org.doubango.ngn.NgnApplication;
import org.doubango.ngn.NgnEngine;
import org.doubango.ngn.datatype.affiliation.affiliationcommand.CommandList;
import org.doubango.ngn.datatype.affiliation.pidf.AffiliationType;
import org.doubango.ngn.datatype.affiliation.pidf.Presence;
import org.doubango.ngn.datatype.affiliation.pidf.Status;
import org.doubango.ngn.datatype.affiliation.pidf.StatusType;
import org.doubango.ngn.datatype.affiliation.pidf.Tuple;
import org.doubango.ngn.services.affiliation.IMyAffiliationService;
import org.doubango.ngn.sip.MyPublicationAffiliationSession;
import org.doubango.ngn.sip.MySubscriptionAffiliationSession;
import org.doubango.ngn.sip.NgnSipPrefrences;
import org.doubango.utils.Utils;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class MyAffiliationService implements IMyAffiliationService {
private final static String TAG = Utils.getTAG(MyAffiliationService.class.getCanonicalName());
private static boolean isStart; |
175b478c |
private BroadcastReceiver broadcastReceiverAffiliationMessage; |
c732d49e |
private MySubscriptionAffiliationSession mSessionSuscription=null;
private static final boolean USE_VERSION_OLD_AFFILIATION= false;
public static final String AFFILIATION_REGISTER=TAG +".AFFILIATION_REGISTER";
private Presence presenceNow=null;
private Map<String,Presence> stringPresenceMap;
private Map<Long,String> longStringMap;
private OnAffiliationServiceListener onAffiliationServiceListener;
private MyPublicationAffiliationSession mSessionPublication;
private Map<String, Long> mGroupsMap;
private TreeMap<Long, Map<String,String>> mExpiresMap;
private Handler handlerService;
private static final boolean checkExpiredActive=false;
private Presence presenceNowDelay;
private String pidNowDelay;
private Map<String, String> expiresNowDelay;
private CommandList commandListNowDelay;
private Handler handlerStartAffiliation;
private Runnable runnableStartAffiliation;
private ArrayList affiliationGroupDelay;
private boolean isSubscribed=false;
@Override
public boolean start() {
Log.d(TAG,"Start "+"AffiliationService");
stringPresenceMap=new HashMap<>();
isStart=true;
isSubscribed=false;
broadcastReceiverAffiliationMessage=new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(AFFILIATION_ACTION_MESSAGE)) {
Log.d(TAG,"New message received");
byte[] messageAffiliation=intent.getByteArrayExtra(AFFILIATION_NEWAFFILIATION_MESSAGE);
if(messageAffiliation==null || messageAffiliation.length==0){
Log.e(TAG,"Affiliation message not valid.");
}else{
Log.d(TAG,"Received new affiliation message.");
try {
CommandList commandList=AffiliationUtils.getCommandList(messageAffiliation);
receiveNewSelfAffiliation(commandList);
} catch (Exception e) {
Log.e(TAG,"Error parsing new message: "+e.toString()+" "+e.getMessage());
}
}
}else if (intent.getAction().equals(AFFILIATION_ACTION_NOTIFY)) {
Log.d(TAG,"New notify received.");
boolean sendAccound=false;
byte[] messageAffiliation=intent.getByteArrayExtra(AFFILIATION_NEWAFFILIATION_NOTIFY);
Log.d(TAG,"New notify affiliation received.");
//try { |
175b478c |
Presence presence=null;
if(messageAffiliation==null || messageAffiliation.length==0){
Log.w(TAG,"Affiliation notify not valid or empty.");
presence=new Presence();
}else{
Log.d(TAG,"Valid affiliation notify.");
try {
if(BuildConfig.DEBUG)Log.d(TAG,"new notify: "+new String(messageAffiliation));
presence=AffiliationUtils.getPresence(messageAffiliation);
} catch (Exception e) {
Log.e(TAG,"Error proccess new affiliation:"+e.getMessage()); |
c732d49e |
} |
175b478c |
}
String mcpttID=null;
NgnSipPrefrences profile=NgnEngine.getInstance().getProfilesService().getProfileNow(context);
if(profile!=null)mcpttID=profile.getMcpttId();
if((presence!=null) && (mcpttID!=null) &&
(presence.getEntity()!=null) &&
(presence.getEntity().trim().compareTo(mcpttID.trim())==0)){
setPresenceNow(presence);
if(presence.getTuple()!=null && profile!=null){
if(!sendAccound){
if(presence.getPId()!=null &&
!presence.getPId().isEmpty() &&
stringPresenceMap!=null &&
stringPresenceMap.get(presence.getPId())!=null){
receiveNewPresenceResponse(presence,presence.getPId()); |
c732d49e |
}else{ |
175b478c |
receiveNewPresence(presence); |
c732d49e |
}
}else{ |
175b478c |
Log.d(TAG,"No listeners."); |
c732d49e |
} |
175b478c |
}else{
Log.e(TAG,"Error processing affiliation data.");
} |
c732d49e |
|
175b478c |
}else if(presence!=null && mcpttID!=null &&
presence.getEntity()==null){
setPresenceNow(presence);
receiveNewPresence(presence);
}else{
Log.e(TAG,"Invalid new notify.");
} |
c732d49e |
/*
} catch (Exception e) {
Log.e(TAG,"it isn´t possible to parse the info on sip notify "+e.toString());
}
*/
}else if (intent.getAction().equals(AFFILIATION_ACTION_SUBSCRIBE)) {
Log.d(TAG,"Receive response subscribe");
String error=intent.getStringExtra(AFFILIATION_RESPONSE_SUBSCRIBE_ERROR);
String responseOk=intent.getStringExtra(AFFILIATION_RESPONSE_SUBSCRIBE_OK);
if(error!=null){
//Error |
175b478c |
Log.e(TAG,"Error in subscribe for affiliation "+error); |
c732d49e |
isSubscribed=false;
}else if(responseOk!=null){
//Ok
Log.d(TAG,"Correct subscribe for affiliation");
isSubscribed=true;
if(affiliationGroupDelay!=null){
Log.d(TAG,"Affiliation now to groups");
affiliationGroups(context,affiliationGroupDelay);
affiliationGroupDelay=null;
}
}else
Log.w(TAG,"This situation isn´t logic");
}else if (intent.getAction().equals(AFFILIATION_ACTION_UNSUBSCRIBE)) {
Log.d(TAG,"UnSubscribe");
isSubscribed=false;
}
}
};
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(AFFILIATION_ACTION_MESSAGE);
intentFilter.addAction(AFFILIATION_ACTION_NOTIFY);
intentFilter.addAction(AFFILIATION_ACTION_SUBSCRIBE);
intentFilter.addAction(AFFILIATION_ACTION_UNSUBSCRIBE);
NgnApplication.getContext().registerReceiver(broadcastReceiverAffiliationMessage,intentFilter); |
175b478c |
return true;
}
@Override
public boolean stop() {
Log.d(TAG,"Stop "+"AffiliationService");
stringPresenceMap=null;
isSubscribed=false;
unRegister();
try{
if(handlerService!=null && runnableStartAffiliation!=null){
handlerService.removeCallbacks(runnableStartAffiliation);
runnableStartAffiliation=null;
handlerService=null;
}
}catch (Exception e){
Log.e(TAG,"Error in stop affiliation");
e.printStackTrace();
}
isStart=false;
return true;
}
public MyAffiliationService() {
|
c732d49e |
}
private void affilitionChange(boolean isRegister){
if(!isRegister){
if(mSessionSuscription!=null){
Log.d(TAG,"Unsubscribe affiliation");
mSessionSuscription.unSubscribeAffiliation();
mSessionSuscription=null;
}
}else{
mSessionSuscription= MySubscriptionAffiliationSession.createOutgoingSession(NgnEngine.getInstance().getSipService().getSipStack());
if(mSessionSuscription.subscribeAffiliation()){
Log.d(TAG,"Subscribe sent.");
}
}
}
//INIT Publication
public String unAffiliationGroup(Context context,String groupSusbcribe){
if(context==null || groupSusbcribe==null)return null;
ArrayList<String> groups=new ArrayList<>();
groups.add(groupSusbcribe);
Log.d(TAG,"Group unaffiliation initialized: "+groupSusbcribe);
return unAffiliationGroups( context,groups);
}
public String unAffiliationGroups(Context context,List<String> groupsSusbcribe){
if(groupsSusbcribe==null || groupsSusbcribe.isEmpty()){
Log.e(TAG,"Invalid configuration.");
return null;
}
byte[] bytes=null;
Presence presence=null;
if(!USE_VERSION_OLD_AFFILIATION){
presence=generatePif(groupsSusbcribe,context,getPresenceNow(),false);
}else{
presence=generatePif(groupsSusbcribe,context);
} |
175b478c |
if(presence!=null) |
c732d49e |
try {
bytes=AffiliationUtils.getBytesOfPresenceForAffiliation(context,presence);
} catch (Exception e) {
Log.e(TAG,"Invalid pidf+xml.");
return null;
}
String impu=null;
NgnSipPrefrences profileNow=NgnEngine.getInstance().getProfilesService().getProfileNow(context);
if(profileNow!=null)impu=profileNow.getIMPU();
if(mSessionPublication==null && impu!=null){
mSessionPublication= MyPublicationAffiliationSession.createOutgoingSession(NgnEngine.getInstance().getSipService().getSipStack(),impu);
}else{
Log.d(TAG,"Publication is different than NULL.");
}
boolean result=false;
if(!USE_VERSION_OLD_AFFILIATION){
//use new version.
if(bytes==null){
result=mSessionPublication.unPublish(bytes,context);
}else{
result=mSessionPublication.publish(bytes,context);
}
}else{
result=mSessionPublication.unPublish(bytes,context);
}
if(result && stringPresenceMap!=null){
if(presence!=null){
stringPresenceMap.put(presence.getPId(),presence);
return presence.getPId();
}else{
return "";
}
}else{
Log.e(TAG,"Error sending publication.");
}
return null;
}
public String affiliationGroup(Context context,String groupSusbcribe){
if(context==null || groupSusbcribe==null)return null;
Log.d(TAG,"Init Affiliation->"+groupSusbcribe);
ArrayList<String> groups=new ArrayList<>();
groups.add(groupSusbcribe.trim());
return affiliationGroups( context,groups);
}
public String affiliationGroups(Context context,List<String> groupsSusbcribe){
if(groupsSusbcribe==null || groupsSusbcribe.isEmpty())return null;
if(!isSubscribed){
Log.d(TAG,"Now,it isn´t subcribe");
if(affiliationGroupDelay==null)affiliationGroupDelay=new ArrayList();
affiliationGroupDelay.addAll(groupsSusbcribe);
return null;
}
byte[] bytes=null;
Presence presence=generatePif(groupsSusbcribe,context,getPresenceNow(),true);
try {
bytes=AffiliationUtils.getBytesOfPresenceForAffiliation(context,presence);
} catch (Exception e) {
Log.e(TAG,"Invalid pidf+xml.");
return null;
}
String impu=null;
NgnSipPrefrences profileNow= NgnEngine.getInstance().getProfilesService().getProfileNow(context);
if(profileNow!=null)impu=profileNow.getIMPU();
if(bytes==null || bytes.length==0)return null;
if(mSessionPublication==null && impu!=null)
mSessionPublication= MyPublicationAffiliationSession.createOutgoingSession(NgnEngine.getInstance().getSipService().getSipStack(),impu);
boolean result=mSessionPublication.publish(bytes,context);
if(result){
stringPresenceMap.put(presence.getPId(),presence);
return presence.getPId();
}
return null;
}
/**
* @param groupsSusbcribe
* @param context
* @return
*/
private Presence generatePif(List<String> groupsSusbcribe,Context context){
return generatePif(groupsSusbcribe,context,null,true);
}
/**
* Function to create the PIF (generate new pif or use an old pif+xml).
* @param groupsSusbcribe
* @param context
* @param presence
* @return
*/
private Presence generatePif(List<String> groupsSusbcribe,Context context,Presence presence,boolean affiliate){
if(groupsSusbcribe==null || groupsSusbcribe.isEmpty())return null;
ArrayList<AffiliationType> affiliationTypes;
Tuple tuple;
Status status;
if(presence!=null && presence.getTuple()!=null &&
presence.getTuple().size()>0 &&
(tuple=presence.getTuple().get(0))!=null &&
(status=tuple.getStatus())!=null && |
175b478c |
(status.getAffiliations()!=null) && (new ArrayList<>(status.getAffiliations()))!=null |
c732d49e |
){
Log.d(TAG,"Using the old presence.");
}else{
if(presence==null){
Log.d(TAG,"Generating new presence for affiliation process.");
}else{
Log.e(TAG,"Invalid current presence. New one generated.");
}
}
String mcpttID=null;
Presence presence2=new Presence();
NgnSipPrefrences profileNow= NgnEngine.getInstance().getProfilesService().getProfileNow(context);
if(profileNow!=null)mcpttID=profileNow.getMcpttId();
presence2.setEntity(mcpttID);
tuple=new Tuple();
String mcpttClientID=null;
if(profileNow!=null)mcpttClientID=profileNow.getMcpttClientId();
tuple.setId(mcpttClientID);
status=new Status();
affiliationTypes=new ArrayList<>();
status.setAffiliations(affiliationTypes);
tuple.setStatus(status);
ArrayList<Tuple> tuples=new ArrayList<>();
tuples.add(tuple);
String pid=mcpttID+Calendar.getInstance().getTimeInMillis();
presence2.setPId(pid);
presence2.setTuple(tuples); |
175b478c |
Tuple tupleRemote=null; |
c732d49e |
if(affiliate){
if(presence!=null && presence.getTuple()!=null && |
175b478c |
presence.getTuple().size()>0)
for(Tuple tupleRemote2:presence.getTuple()){
if(profileNow.getMcpttClientId()!=null && tupleRemote2.getId()!=null && tupleRemote2.getId().compareTo(profileNow.getMcpttClientId())==0){
tupleRemote=tupleRemote2;
}
}
if((tupleRemote!=null &&
(status=tupleRemote.getStatus())!=null
&& status.getAffiliations()!=null
)){
affiliationTypes=new ArrayList<>(status.getAffiliations()); |
c732d49e |
}else{
affiliationTypes=new ArrayList<>();
}
for(String group:groupsSusbcribe){ |
175b478c |
if(/*AffiliationUtils.isValidURISIP(group) &&*/ checkGroupStatus(affiliationTypes,group)<0){ |
c732d49e |
AffiliationType affiliationType=new AffiliationType();
affiliationType.setGroup(group);
affiliationTypes.add(affiliationType);
}
}
presence2.getTuple().get(0).getStatus().setAffiliations(createListAffiliationType(affiliationTypes));
}else{
//unaffiliate |
175b478c |
if(presence!=null){
affiliationTypes=new ArrayList<>(presence.getTuple().get(0).getStatus().getAffiliations());
}else{
affiliationTypes=new ArrayList<>();
} |
c732d49e |
for(String group:groupsSusbcribe){
int index=-1;
if((index=checkGroupStatus(affiliationTypes,group))>=0 && affiliationTypes.size()>index){
Log.d(TAG,"unaffiliate");
affiliationTypes.remove(index);
}else{
Log.e(TAG,"Error unaffiliating "+index);
}
}
if(affiliationTypes.size()==0){
Log.d(TAG,"Device does not have any affiliation group.");
return null;
}
presence2.getTuple().get(0).getStatus().setAffiliations(createListAffiliationType(affiliationTypes));
if(affiliationTypes.size()==0){
presence2=null;
}
}
return presence2;
}
private int checkGroupStatus(ArrayList<AffiliationType> affiliationTypes,String group){
if(group==null && affiliationTypes==null){
Log.e(TAG, "Error checking group affiliations parameters.");
return -1;
}
if(affiliationTypes!=null){
for(int con=0;con<affiliationTypes.size();con++){
if(affiliationTypes.get(con).getGroup().compareTo(group)==0){
return con;
}
}
}
return -1;
}
private List<AffiliationType> createListAffiliationType( List<AffiliationType> affiliationTypes){
ArrayList<AffiliationType> result=new ArrayList<>();
for(AffiliationType affiliationType:affiliationTypes){
result.add(new AffiliationType(affiliationType.getGroup()));
}
return result;
}
//END Publication
//INIT service affiliation
/**
* Executed when the service starts
*/
public void startServiceAffiliation(Context context){
//Start Service
if(isAffiliation(context)){
affilitionChange(true);
}
}
/**
* Executed when the service starts
*/
public void startServiceAffiliation(){
//Start Service
Log.d(TAG,"Start affiliation service.");
handlerStartAffiliation = new Handler(Looper.getMainLooper());
runnableStartAffiliation=new Runnable() {
@Override
public void run() {
if(isAffiliation(NgnApplication.getContext())){
affilitionChange(true);
}
}
};
handlerStartAffiliation.postDelayed(runnableStartAffiliation, DELAY_ACTION_AFFILIATION_MSEC);
}
/**
* Executed when the service stops
*/
public void stopServiceAffiliation(){
//Stop Serveice
//affilitionChange(false);
}
private void unRegister(){
try { |
175b478c |
if(broadcastReceiverAffiliationMessage!=null){
NgnApplication.getContext().unregisterReceiver(broadcastReceiverAffiliationMessage);
broadcastReceiverAffiliationMessage=null;
}
if(BuildConfig.DEBUG)Log.d(TAG,"Unregisted: broadcastReceiverAffiliationMessage"); |
c732d49e |
}catch (Exception e){
Log.e(TAG,"Error1:"+e.getMessage());
}
}
public Presence getPresenceNow() {
return presenceNow;
}
public void setPresenceNow(Presence presenceNow) {
this.presenceNow = presenceNow;
}
public void setOnAffiliationServiceListener(OnAffiliationServiceListener onAffiliationServiceListener){
this.onAffiliationServiceListener=onAffiliationServiceListener;
}
//Init affiliation action
private void receiveNewPresence(Presence presence) {
if(BuildConfig.DEBUG)Log.d(TAG,"receiveNewPresence");
if(onAffiliationServiceListener!=null){
onAffiliationServiceListener.receiveNewPresence( presence);
}else{
if(BuildConfig.DEBUG)Log.d(TAG,"No define interface affiliation");
}
}
private void receiveNewPresenceResponse(Presence presence, String pid) {
if(BuildConfig.DEBUG)Log.d(TAG,"receiveNewPresence:"+pid);
presenceNowDelay=presence;
pidNowDelay=pid;
if(onAffiliationServiceListener!=null){
onAffiliationServiceListener.receiveNewPresenceResponse( presenceNowDelay, pidNowDelay);
}else{
if(BuildConfig.DEBUG)Log.d(TAG,"No define interface affiliation");
}
}
private void expireAffiliations(Map<String, String> expires) {
expiresNowDelay=expires;
if(onAffiliationServiceListener!=null)onAffiliationServiceListener.expireAffiliations(expiresNowDelay);
}
private void receiveNewSelfAffiliation(CommandList commandList) {
commandListNowDelay=commandList;
if(onAffiliationServiceListener!=null)onAffiliationServiceListener.receiveNewSelfAffiliation( commandListNowDelay);
}
private void startNewService() {
if(onAffiliationServiceListener!=null)onAffiliationServiceListener.startNewServiceAffiliation();
}
//end affiliation action
//END service affiliation
//INIT affiliation automatically
public void processingCommandList(Context context,CommandList commandList){
if(commandList==null || !AffiliationUtils.isSelfAffiliation(context)){
return;
}
//Send to GUI from the client.
//Affiliation
if(commandList.getAffiliate()!=null && commandList.getAffiliate().getGroup()!=null){
List<String> groups=AffiliationUtils.isValidURIsSIP(new ArrayList<String>(commandList.getAffiliate().getGroup()));
if(groups!=null)affiliationGroups(context,groups);
}
//Deaffiliation
if(commandList.getDeAffiliate()!=null && commandList.getDeAffiliate().getGroup()!=null){
List<String> groups=AffiliationUtils.isValidURIsSIP(new ArrayList<String>(commandList.getDeAffiliate().getGroup()));
if(groups!=null)unAffiliationGroups(context,groups);
}
}
//END affiliation automatically
//INIT checkExpire
private void checkExpire(){
if(isCheckExpiredActive()) {
handlerService = new Handler();
handlerService.postDelayed(new Runnable() {
@Override
public void run() {
if (isStart && mExpiresMap.size() > 0) {
checkExpire();
}
}
}, DEFAULT_SECOS_BETWEEN_CHECK_EXPIRES * 1000);
checkExpire(Calendar.getInstance().getTime());
}
}
private void checkExpire(Date date){
Map<String,String> expires=new HashMap<>();
expires=checkExpire(date,expires);
if(expires!=null && expires.size()>0){
expireAffiliations(expires);
}
}
private Map<String,String> checkExpire(Date date,Map<String,String> expires){
if(mExpiresMap==null)return null;
Map.Entry<Long, Map<String,String>> hashMapEntry= mExpiresMap.firstEntry();
if(hashMapEntry==null)return expires;
Long time=hashMapEntry.getKey();
if(date.getTime()>=time){
Map<String,String> arrayList=hashMapEntry.getValue();
if(arrayList!=null)arrayList.putAll(expires);
mExpiresMap.remove(time);
return checkExpire(date,arrayList);
}else{
return expires;
}
}
public void addNewOrChangeTimeExpire(List<AffiliationType> affiliationTypes){
mExpiresMap=new TreeMap<>();
if(affiliationTypes==null)return;
for(AffiliationType affiliationType:affiliationTypes){
if(affiliationType!=null && affiliationType.getStatus()== StatusType.affiliated){
String group=affiliationType.getGroup();
Date date=affiliationType.getExpiresDate();
if(group!=null && date!=null){
Map<String,String> strings=mExpiresMap.get(date.getTime());
if(strings==null){
strings=new HashMap<>();
mExpiresMap.put(date.getTime(),strings);
}
strings.put(group,group);
}
}
}
checkExpire();
}
//END checkExpire
private boolean isCheckExpiredActive() {
return checkExpiredActive;
}
public boolean isAffiliation(Context context){
NgnSipPrefrences profileNow=NgnEngine.getInstance().getProfilesService().getProfileNow(context);
if(profileNow==null || profileNow.isMcpttIsEnableAffiliation()==null)return false;
return profileNow.isMcpttIsEnableAffiliation();
}
@Override
public boolean clearService(){
Log.d(TAG,"Clear: "+"LocalizationService");
if(presenceNow!=null)presenceNow=null;
return true;
}
} |