/* * Mobicents, Communications Middleware * * Copyright (c) 2008, Red Hat Middleware LLC or third-party * contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors. All third-party contributions are * distributed under license by Red Hat Middleware LLC. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program 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 Lesser General Public License * for more details. * * * You should have received a copy of the GNU Lesser General Public License * along with this distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * * Boston, MA 02110-1301 USA */ package org.mobicents.slee.resource.diameter.sh.client; import java.io.IOException; import java.util.ArrayList; import javax.slee.resource.SleeEndpoint; import net.java.slee.resource.diameter.base.events.DiameterMessage; import net.java.slee.resource.diameter.base.events.avp.AuthSessionStateType; import net.java.slee.resource.diameter.base.events.avp.AvpNotAllowedException; import net.java.slee.resource.diameter.base.events.avp.AvpUtilities; import net.java.slee.resource.diameter.base.events.avp.DiameterIdentity; import net.java.slee.resource.diameter.sh.client.DiameterShAvpFactory; import net.java.slee.resource.diameter.sh.client.ShClientMessageFactory; import net.java.slee.resource.diameter.sh.client.ShClientSubscriptionActivity; import net.java.slee.resource.diameter.sh.client.ShSessionState; import net.java.slee.resource.diameter.sh.client.events.PushNotificationRequest; import net.java.slee.resource.diameter.sh.client.events.avp.DataReferenceType; import net.java.slee.resource.diameter.sh.client.events.avp.DiameterShAvpCodes; import net.java.slee.resource.diameter.sh.client.events.avp.SubsReqType; import net.java.slee.resource.diameter.sh.client.events.avp.UserIdentityAvp; import net.java.slee.resource.diameter.sh.server.events.ProfileUpdateRequest; import net.java.slee.resource.diameter.sh.server.events.PushNotificationAnswer; import net.java.slee.resource.diameter.sh.server.events.SubscribeNotificationsRequest; import net.java.slee.resource.diameter.sh.server.events.UserDataRequest; import org.jdiameter.api.Answer; import org.jdiameter.api.EventListener; import org.jdiameter.api.Request; import org.jdiameter.api.app.StateChangeListener; import org.jdiameter.api.sh.ClientShSession; import org.jdiameter.common.impl.app.sh.ProfileUpdateRequestImpl; import org.jdiameter.common.impl.app.sh.PushNotificationAnswerImpl; import org.jdiameter.common.impl.app.sh.SubscribeNotificationsRequestImpl; import org.jdiameter.common.impl.app.sh.UserDataRequestImpl; import org.jdiameter.common.impl.validation.JAvpNotAllowedException; import org.mobicents.diameter.dictionary.AvpDictionary; import org.mobicents.diameter.dictionary.AvpRepresentation; import org.mobicents.slee.resource.diameter.base.DiameterActivityImpl; import org.mobicents.slee.resource.diameter.base.DiameterAvpFactoryImpl; import org.mobicents.slee.resource.diameter.base.DiameterMessageFactoryImpl; import org.mobicents.slee.resource.diameter.base.events.DiameterMessageImpl; import org.mobicents.slee.resource.diameter.sh.client.events.DiameterShMessageImpl; import org.mobicents.slee.resource.diameter.sh.client.events.avp.UserIdentityAvpImpl; import org.mobicents.slee.resource.diameter.sh.client.handlers.ShClientSessionListener; /** * * Sh Client activity created for subscription cases * * @author <a href="mailto:baranowb@gmail.com"> Bartosz Baranowski </a> * @author <a href="mailto:brainslog@gmail.com"> Alexandre Mendonca </a> * @see ShClientSubscriptionActivity */ public class ShClientSubscriptionActivityImpl extends DiameterActivityImpl implements ShClientSubscriptionActivity, StateChangeListener { protected ClientShSession clientSession = null; protected ShSessionState state = ShSessionState.NOTSUBSCRIBED; protected ShClientSessionListener listener = null; protected DiameterShAvpFactory shAvpFactory = null; protected ShClientMessageFactory messageFactory = null; //FIXME: add more protected UserIdentityAvp userIdentity; protected DataReferenceType[] dataReferenceType; protected AuthSessionStateType authSessionState; protected DiameterIdentity remoteRealm; // Last received message protected ArrayList<DiameterMessageImpl> stateMessages = new ArrayList<DiameterMessageImpl>(); public ShClientSubscriptionActivityImpl(DiameterMessageFactoryImpl messageFactory, ShClientMessageFactory shClientMessageFactory, DiameterAvpFactoryImpl avpFactory, DiameterShAvpFactory diameterShAvpFactory, ClientShSession session, long timeout, DiameterIdentity destinationHost, DiameterIdentity destinationRealm, SleeEndpoint endpoint) { super(messageFactory, avpFactory, null, (EventListener<Request, Answer>) session, timeout, destinationHost, destinationRealm, endpoint); this.clientSession = session; this.clientSession.addStateChangeNotification(this); super.setCurrentWorkingSession(this.clientSession.getSessions().get(0)); this.shAvpFactory = diameterShAvpFactory; this.messageFactory = shClientMessageFactory; } /* * (non-Javadoc) * @see net.java.slee.resource.diameter.sh.client.ShClientSubscriptionActivity#getSubscribedUserIdendity() */ public UserIdentityAvp getSubscribedUserIdendity() { return this.userIdentity; } public PushNotificationAnswer createPushNotificationAnswer() { PushNotificationAnswer answer = null; for (int index = 0; index < stateMessages.size(); index++) { if (stateMessages.get(index).getCommand().getCode() == PushNotificationAnswer.commandCode) { PushNotificationRequest msg = (PushNotificationRequest) stateMessages.get(index); answer = this.messageFactory.createPushNotificationAnswer(msg); if (answer.getAuthSessionState() == null && this.authSessionState != null) { answer.setAuthSessionState(this.authSessionState); } if (answer.getDestinationRealm() == null && remoteRealm != null) { // FIXME: answer.setDestinationRealm(remoteRealm); } ((DiameterShMessageImpl) answer).setData(msg); break; } } return answer; } public PushNotificationAnswer createPushNotificationAnswer(long resultCode, boolean isExperimaental) { PushNotificationAnswer answer = null; for(int index =0 ;index<stateMessages.size();index++) { if(stateMessages.get(index).getCommand().getCode() == PushNotificationAnswer.commandCode) { PushNotificationRequest msg = (PushNotificationRequest) stateMessages.get(index); answer = this.messageFactory.createPushNotificationAnswer(msg, resultCode, isExperimaental); if(answer.getAuthSessionState() == null && this.authSessionState!=null) { answer.setAuthSessionState(this.authSessionState); } if(answer.getDestinationRealm()== null && remoteRealm!=null) { //FIXME: answer.setDestinationRealm(remoteRealm); } ((DiameterShMessageImpl)answer).setData(msg); break; } } return answer; } // public UserDataRequest createUserDataRequest() // { // UserDataRequest uda = this.messageFactory.createUserDataRequest(); // if(userIdentity!=null) // uda.setUserIdentity(this.userIdentity); // if(dataReferenceType!=null) // uda.setDataReferences(dataReferenceType); // if(remoteRealm!=null) // uda.setDestinationRealm(remoteRealm); // if(authSessionState!=null) // uda.setAuthSessionState(authSessionState); // return uda; // // } // // public ProfileUpdateRequest createProfileUpdateRequest() // { // ProfileUpdateRequest pur = this.messageFactory.createProfileUpdateRequest(); // if(userIdentity!=null) // pur.setUserIdentity(this.userIdentity); // if(authSessionState!=null) // pur.setAuthSessionState(authSessionState); // if(remoteRealm!=null) // pur.setDestinationRealm(remoteRealm); // // // return pur; // } public void sendUserDataRequest(UserDataRequest message) throws IOException { try { DiameterMessageImpl msg = (DiameterMessageImpl) message; this.clientSession.sendUserDataRequest(new UserDataRequestImpl((Request) msg.getGenericData())); } catch (JAvpNotAllowedException e) { AvpNotAllowedException anae = new AvpNotAllowedException("Message validation failed.", e, e.getAvpCode(), e.getVendorId()); throw anae; } catch (Exception e) { e.printStackTrace(); IOException ioe = new IOException("Failed to send message, due to: " + e); throw ioe; } } public void sendProfileUpdateRequest(ProfileUpdateRequest message) throws IOException { try { DiameterMessageImpl msg = (DiameterMessageImpl) message; clientSession.sendProfileUpdateRequest(new ProfileUpdateRequestImpl((Request) msg.getGenericData())); } catch (JAvpNotAllowedException e) { AvpNotAllowedException anae = new AvpNotAllowedException("Message validation failed.", e, e.getAvpCode(), e.getVendorId()); throw anae; } catch (Exception e) { e.printStackTrace(); IOException ioe = new IOException("Failed to send message, due to: " + e); throw ioe; } } /* * (non-Javadoc) * @see net.java.slee.resource.diameter.sh.client.ShClientSubscriptionActivity#sendPushNotificationAnswer(net.java.slee.resource.diameter.sh.server.events.PushNotificationAnswer) */ public void sendPushNotificationAnswer(PushNotificationAnswer answer) throws IOException { try { DiameterMessageImpl msg = (DiameterMessageImpl) answer; this.clientSession.sendPushNotificationAnswer(new PushNotificationAnswerImpl((Answer) msg.getGenericData())); clean((DiameterShMessageImpl)answer); fetchSessionData(answer, false); } catch (JAvpNotAllowedException e) { AvpNotAllowedException anae = new AvpNotAllowedException("Message validation failed.", e, e.getAvpCode(), e.getVendorId()); throw anae; } catch (Exception e) { e.printStackTrace(); IOException ioe = new IOException("Failed to send message, due to: " + e); throw ioe; } } /* * (non-Javadoc) * * @see * net.java.slee.resource.diameter.sh.client.ShClientSubscriptionActivity * #sendPushNotificationAnswer(long, boolean) */ public void sendPushNotificationAnswer(long resultCode, boolean isExperimentalResultCode) throws IOException { PushNotificationAnswer answer= this.createPushNotificationAnswer(resultCode, isExperimentalResultCode); if(answer!=null) { this.sendPushNotificationAnswer(answer); }else { throw new IOException("Could not create PNA, there is no PNR?"); } } /* * (non-Javadoc) * * @see * net.java.slee.resource.diameter.sh.client.ShClientSubscriptionActivity * #sendSubscriptionNotificationRequest * (net.java.slee.resource.diameter.sh.server * .events.SubscribeNotificationsRequest) */ public void sendSubscriptionNotificationRequest(SubscribeNotificationsRequest request) throws IOException { try { DiameterMessageImpl msg = (DiameterMessageImpl) request; this.clientSession.sendSubscribeNotificationsRequest(new SubscribeNotificationsRequestImpl((Request) msg.getGenericData())); fetchSessionData(msg, false); } catch (JAvpNotAllowedException e) { AvpNotAllowedException anae = new AvpNotAllowedException("Message validation failed.", e, e.getAvpCode(), e.getVendorId()); throw anae; } catch (Exception e) { e.printStackTrace(); IOException ioe = new IOException("Failed to send message, due to: " + e); throw ioe; } } /* * (non-Javadoc) * * @see * net.java.slee.resource.diameter.sh.client.ShClientSubscriptionActivity * #sendUnsubscribeRequest() */ public void sendUnsubscribeRequest() throws IOException { try { // FIXME: Alexandre: How do we know DataReferenceType? SubscribeNotificationsRequest snr = this.messageFactory.createSubscribeNotificationsRequest(getSubscribedUserIdendity(), DataReferenceType.REPOSITORY_DATA, SubsReqType.UNSUBSCRIBE); snr.setDataReferences(this.dataReferenceType); snr.setDestinationRealm(remoteRealm); snr.setAuthSessionState(authSessionState); DiameterMessageImpl msg = (DiameterMessageImpl) snr; this.clientSession.sendSubscribeNotificationsRequest(new SubscribeNotificationsRequestImpl((Request) msg.getGenericData())); } catch (JAvpNotAllowedException e) { AvpNotAllowedException anae = new AvpNotAllowedException("Message validation failed.", e, e.getAvpCode(), e.getVendorId()); throw anae; } catch (Exception e) { e.printStackTrace(); IOException ioe = new IOException("Failed to send message, due to: " + e); throw ioe; } } private void clean(DiameterShMessageImpl msg) { if(msg.getData()!=null) { this.stateMessages.remove(msg.removeData()); } } /* * (non-Javadoc) * @see org.jdiameter.api.app.StateChangeListener#stateChanged(java.lang.Enum, java.lang.Enum) */ public void stateChanged(Enum oldState, Enum newState) { org.jdiameter.common.api.app.sh.ShSessionState shNewState = (org.jdiameter.common.api.app.sh.ShSessionState) newState; switch (shNewState) { case NOTSUBSCRIBED: break; case SUBSCRIBED: state = ShSessionState.SUBSCRIBED; // FIXME: error? break; case TERMINATED: state = ShSessionState.TERMINATED; listener.sessionDestroyed(getSessionId(), clientSession); this.clientSession.removeStateChangeNotification(this); break; } } /* * (non-Javadoc) * @see org.mobicents.slee.resource.diameter.base.DiameterActivityImpl#getSessionListener() */ public Object getSessionListener() { return this.listener; } /* * (non-Javadoc) * @see org.mobicents.slee.resource.diameter.base.DiameterActivityImpl#setSessionListener(java.lang.Object) */ public void setSessionListener(Object ra) { this.listener = (ShClientSessionListener) ra; } /* * (non-Javadoc) * @see org.mobicents.slee.resource.diameter.base.DiameterActivityImpl#endActivity() */ public void endActivity() { this.clientSession.release(); } /* * (non-Javadoc) * @see org.mobicents.slee.resource.diameter.base.DiameterActivityImpl#getDiameterAvpFactory() */ public Object getDiameterAvpFactory() { return this.shAvpFactory; } /* * (non-Javadoc) * @see org.mobicents.slee.resource.diameter.base.DiameterActivityImpl#getDiameterMessageFactory() */ public Object getDiameterMessageFactory() { return this.messageFactory; } /** * * @return */ ClientShSession getClientSession() { return this.clientSession; } /** * * @param request */ public void fetchSessionData(DiameterMessage msg, boolean incoming) { if(msg.getHeader().isRequest()) { //Well it should always be getting this on request and only once ? if(incoming) { if(this.userIdentity == null) { try{ //FIXME: make this diff. AvpRepresentation rep = AvpDictionary.INSTANCE.getAvp(DiameterShAvpCodes.USER_IDENTITY, DiameterShAvpCodes.SH_VENDOR_ID); this.userIdentity = new UserIdentityAvpImpl(DiameterShAvpCodes.USER_IDENTITY, DiameterShAvpCodes.SH_VENDOR_ID,rep.getRuleMandatoryAsInt(),rep.getRuleProtectedAsInt(),AvpUtilities.getAvpAsGrouped(DiameterShAvpCodes.USER_IDENTITY, DiameterShAvpCodes.SH_VENDOR_ID, ((DiameterMessageImpl)msg).getGenericData().getAvps())); }catch(Exception e) { e.printStackTrace(); } } if(this.authSessionState == null) { try{ this.authSessionState = AuthSessionStateType.fromInt(AvpUtilities.getAvpAsInteger32(277, ((DiameterMessageImpl)msg).getGenericData().getAvps())); }catch(Exception e) { e.printStackTrace(); } } stateMessages.add((DiameterMessageImpl) msg); } else { if(destinationRealm == null) { this.remoteRealm = msg.getDestinationRealm(); } //FIXME, do more :) if(msg instanceof SubscribeNotificationsRequest) { SubscribeNotificationsRequest snr = (SubscribeNotificationsRequest) msg; if(dataReferenceType==null && snr.hasDataReferenceType()) { dataReferenceType = snr.getDataReferences(); } if(authSessionState==null && snr.hasAuthSessionState()) { authSessionState = snr.getAuthSessionState(); } if(userIdentity == null && snr.hasUserIdentity()) { userIdentity = snr.getUserIdentity(); } } } } } }