/*
* 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.server;
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.ShSessionState;
import net.java.slee.resource.diameter.sh.client.events.ProfileUpdateAnswer;
import net.java.slee.resource.diameter.sh.client.events.SubscribeNotificationsAnswer;
import net.java.slee.resource.diameter.sh.client.events.UserDataAnswer;
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.UserIdentityAvp;
import net.java.slee.resource.diameter.sh.server.ShServerActivity;
import net.java.slee.resource.diameter.sh.server.ShServerMessageFactory;
import net.java.slee.resource.diameter.sh.server.events.ProfileUpdateRequest;
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.ServerShSession;
import org.jdiameter.common.impl.app.sh.ProfileUpdateAnswerImpl;
import org.jdiameter.common.impl.app.sh.SubscribeNotificationsAnswerImpl;
import org.jdiameter.common.impl.app.sh.UserDataAnswerImpl;
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.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.server.handlers.ShServerSessionListener;
/**
* Start time:16:43:18 2009-01-06<br>
* Project: mobicents-diameter-parent<br>
* Implementation of stateles Sh Server activity whihc recieves. It ends after resposne is sent.
* @author <a href = "mailto:baranowb@gmail.com"> Bartosz Baranowski </a>
* @author <a href = "mailto:brainslog@gmail.com"> Alexandre Mendonca </a>
* @see ShServerActivity
*/
public class ShServerActivityImpl extends DiameterActivityImpl implements ShServerActivity, StateChangeListener {
protected ServerShSession serverSession = null;
protected ShSessionState state = ShSessionState.NOTSUBSCRIBED;
protected ShServerSessionListener listener = null;
// Factories
protected DiameterShAvpFactory shAvpFactory = null;
protected ShServerMessageFactoryImpl messageFactory = null;
//FIXME: add more
protected UserIdentityAvp userIdentity;
protected DataReferenceType[] dataReferenceType;
protected AuthSessionStateType authSessionState;
protected DiameterIdentity remoteRealm;
protected DiameterIdentity remoteHost;
// THIS IS BAD, we need to come up with something.
/**
* Should contina requests, so we can create answer.
*/
protected ArrayList<DiameterMessageImpl> stateMessages = new ArrayList<DiameterMessageImpl>();
public ShServerActivityImpl(ShServerMessageFactory shServerMessageFactory, DiameterShAvpFactory diameterShAvpFactory, ServerShSession session, long timeout, DiameterIdentity destinationHost, DiameterIdentity destinationRealm, SleeEndpoint endpoint)
{
super(null, null, null, (EventListener<Request, Answer>) session, timeout, destinationHost, destinationRealm, endpoint);
this.serverSession = session;
this.serverSession.addStateChangeNotification(this);
super.setCurrentWorkingSession(this.serverSession.getSessions().get(0));
this.shAvpFactory = diameterShAvpFactory;
this.messageFactory = (ShServerMessageFactoryImpl) shServerMessageFactory;
}
public ProfileUpdateAnswer createProfileUpdateAnswer(long resultCode, boolean isExperimentalResult)
{
ProfileUpdateAnswer answer = null;
for(int index =0 ;index<stateMessages.size();index++)
{
if(stateMessages.get(index).getCommand().getCode() == ProfileUpdateRequest.commandCode)
{
ProfileUpdateRequest msg = (ProfileUpdateRequest) stateMessages.get(index);
answer = this.messageFactory.createProfileUpdateAnswer(msg, resultCode, isExperimentalResult);
if(answer.getAuthSessionState() == null && this.authSessionState!=null)
{
answer.setAuthSessionState(this.authSessionState);
}
((DiameterShMessageImpl)answer).setData(msg);
break;
}
}
//answer.setSessionId(super.session.getSessionId());
return answer;
}
/*
* (non-Javadoc)
* @see net.java.slee.resource.diameter.sh.server.ShServerSubscriptionActivity#createSubscribeNotificationsAnswer()
*/
public ProfileUpdateAnswer createProfileUpdateAnswer()
{
ProfileUpdateAnswer answer = null;
for(int index =0 ;index<stateMessages.size();index++)
{
if(stateMessages.get(index).getCommand().getCode() == ProfileUpdateRequest.commandCode)
{
ProfileUpdateRequest msg = (ProfileUpdateRequest) stateMessages.get(index);
answer = this.messageFactory.createProfileUpdateAnswer(msg);
if(answer.getAuthSessionState() == null && this.authSessionState!=null)
{
answer.setAuthSessionState(this.authSessionState);
}
((DiameterShMessageImpl)answer).setData(msg);
break;
}
}
//answer.setSessionId(super.session.getSessionId());
return answer;
}
public UserDataAnswer createUserDataAnswer(byte[] userData)
{
UserDataAnswer answer = null;
for(int index =0 ;index<stateMessages.size();index++)
{
if(stateMessages.get(index).getCommand().getCode() == UserDataRequest.commandCode)
{
UserDataRequest msg = (UserDataRequest) stateMessages.get(index);
answer = this.messageFactory.createUserDataAnswer(msg,userData);
if(answer.getAuthSessionState() == null && this.authSessionState!=null)
{
answer.setAuthSessionState(this.authSessionState);
}
((DiameterShMessageImpl)answer).setData(msg);
break;
}
}
//answer.setSessionId(super.session.getSessionId());
return answer;
}
public UserDataAnswer createUserDataAnswer(long resultCode, boolean isExperimentalResult)
{
UserDataAnswer answer = null;
for(int index =0 ;index<stateMessages.size();index++)
{
if(stateMessages.get(index).getCommand().getCode() == UserDataRequest.commandCode)
{
UserDataRequest msg = (UserDataRequest) stateMessages.get(index);
answer = this.messageFactory.createUserDataAnswer(msg,resultCode,isExperimentalResult);
if(answer.getAuthSessionState() == null && this.authSessionState!=null)
{
answer.setAuthSessionState(this.authSessionState);
}
((DiameterShMessageImpl)answer).setData(msg);
break;
}
}
//answer.setSessionId(super.session.getSessionId());
return answer;
}
public UserDataAnswer createUserDataAnswer()
{
UserDataAnswer answer = null;
for(int index =0 ;index<stateMessages.size();index++)
{
if(stateMessages.get(index).getCommand().getCode() == UserDataRequest.commandCode)
{
UserDataRequest msg = (UserDataRequest) stateMessages.get(index);
answer = this.messageFactory.createUserDataAnswer(msg);
if(answer.getAuthSessionState() == null && this.authSessionState!=null)
{
answer.setAuthSessionState(this.authSessionState);
}
((DiameterShMessageImpl)answer).setData(msg);
break;
}
}
//answer.setSessionId(super.session.getSessionId());
return answer;
}
public SubscribeNotificationsAnswer createSubscribeNotificationsAnswer(long resultCode, boolean isExperimentalResult)
{
SubscribeNotificationsAnswer answer = null;
for(int index =0 ;index<stateMessages.size();index++)
{
if(stateMessages.get(index).getCommand().getCode() == SubscribeNotificationsRequest.commandCode)
{
SubscribeNotificationsRequest msg = (SubscribeNotificationsRequest) stateMessages.get(index);
answer = this.messageFactory.createSubscribeNotificationsAnswer(msg, resultCode, isExperimentalResult);
if(answer.getAuthSessionState() == null && this.authSessionState!=null)
{
answer.setAuthSessionState(this.authSessionState);
}
((DiameterShMessageImpl)answer).setData(msg);
break;
}
}
//answer.setSessionId(super.session.getSessionId());
return answer;
}
/*
* (non-Javadoc)
* @see net.java.slee.resource.diameter.sh.server.ShServerSubscriptionActivity#createSubscribeNotificationsAnswer()
*/
public SubscribeNotificationsAnswer createSubscribeNotificationsAnswer()
{
SubscribeNotificationsAnswer answer = null;
for(int index =0 ;index<stateMessages.size();index++)
{
if(stateMessages.get(index).getCommand().getCode() == SubscribeNotificationsRequest.commandCode)
{
SubscribeNotificationsRequest msg = (SubscribeNotificationsRequest) stateMessages.get(index);
answer = this.messageFactory.createSubscribeNotificationsAnswer(msg);
if(answer.getAuthSessionState() == null && this.authSessionState!=null)
{
answer.setAuthSessionState(this.authSessionState);
}
((DiameterShMessageImpl)answer).setData(msg);
break;
}
}
//answer.setSessionId(super.session.getSessionId());
return answer;
}
public void sendSubscribeNotificationsAnswer(SubscribeNotificationsAnswer message) throws IOException {
DiameterShMessageImpl msg = (DiameterShMessageImpl) message;
fetchSessionData(msg, false);
try {
this.serverSession.sendSubscribeNotificationsAnswer(new SubscribeNotificationsAnswerImpl((Answer) msg.getGenericData()));
clean(msg);
} 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 sendUserDataAnswer(UserDataAnswer message) throws IOException {
try {
DiameterShMessageImpl msg = (DiameterShMessageImpl) message;
this.serverSession.sendUserDataAnswer(new UserDataAnswerImpl((Answer) msg.getGenericData()));
clean(msg);
} 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 sendProfileUpdateAnswer(ProfileUpdateAnswer message) throws IOException {
DiameterShMessageImpl msg = (DiameterShMessageImpl) message;
fetchSessionData(msg, false);
try {
this.serverSession.sendProfileUpdateAnswer(new ProfileUpdateAnswerImpl((Answer) msg.getGenericData()));
clean(msg);
} 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;
}
}
@Override
public Object getDiameterAvpFactory()
{
return this.avpFactory;
}
@Override
public Object getDiameterMessageFactory()
{
return this.messageFactory;
}
// #########################
// # StateChangeListener
// #########################
public void stateChanged(Enum oldState, Enum newState)
{
org.jdiameter.common.api.app.sh.ShSessionState _state = (org.jdiameter.common.api.app.sh.ShSessionState) newState;
switch(_state)
{
case NOTSUBSCRIBED:
break;
case SUBSCRIBED:
//FIXME: error?
//This should not happen!!!
break;
case TERMINATED:
state = ShSessionState.TERMINATED;
this.listener.sessionDestroyed(getSessionId(), serverSession);
this.serverSession.removeStateChangeNotification(this);
this.messageFactory.clean();
this.messageFactory = null;
this.serverSession = null;
super.session = null;
this.shAvpFactory = null;
this.stateMessages.clear();
this.listener = null;
super.clean();
break;
}
}
// #########################
// # DiameterActivityImpl
// #########################
@Override
public Object getSessionListener()
{
return this.listener;
}
@Override
public void setSessionListener(Object ra)
{
this.listener = (ShServerSessionListener) ra;
}
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(remoteRealm == null )
remoteRealm = msg.getOriginRealm();
if(remoteHost == null)
remoteHost = msg.getOriginHost();
if(this.userIdentity == null)
{
try{
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
{
//FIXME, do more :)
}
}
}
private void clean(DiameterShMessageImpl msg)
{
if(msg.getData()!=null)
{
this.stateMessages.remove(msg.removeData());
}
}
}