package org.mobicents.slee.resource.diameter.cxdx;
import static org.jdiameter.client.impl.helpers.Parameters.MessageTimeOut;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.management.ObjectName;
import javax.naming.NamingException;
import javax.naming.OperationNotSupportedException;
import javax.slee.Address;
import javax.slee.facilities.EventLookupFacility;
import javax.slee.management.UnrecognizedResourceAdaptorEntityException;
import javax.slee.resource.ActivityHandle;
import javax.slee.resource.BootstrapContext;
import javax.slee.resource.FailureReason;
import javax.slee.resource.Marshaler;
import javax.slee.resource.ResourceAdaptor;
import javax.slee.resource.ResourceAdaptorTypeID;
import javax.slee.resource.ResourceException;
import javax.slee.resource.SleeEndpoint;
import net.java.slee.resource.diameter.base.CreateActivityException;
import net.java.slee.resource.diameter.base.DiameterActivity;
import net.java.slee.resource.diameter.base.DiameterMessageFactory;
import net.java.slee.resource.diameter.base.events.AccountingAnswer;
import net.java.slee.resource.diameter.base.events.DiameterMessage;
import net.java.slee.resource.diameter.base.events.avp.DiameterIdentity;
import net.java.slee.resource.diameter.cxdx.CxDxAVPFactory;
import net.java.slee.resource.diameter.cxdx.CxDxActivityContextInterfaceFactory;
import net.java.slee.resource.diameter.cxdx.CxDxClientSession;
import net.java.slee.resource.diameter.cxdx.CxDxMessageFactory;
import net.java.slee.resource.diameter.cxdx.CxDxProvider;
import net.java.slee.resource.diameter.cxdx.CxDxServerSession;
import net.java.slee.resource.diameter.cxdx.events.LocationInfoRequest;
import net.java.slee.resource.diameter.cxdx.events.MultimediaAuthenticationRequest;
import net.java.slee.resource.diameter.cxdx.events.PushProfileRequest;
import net.java.slee.resource.diameter.cxdx.events.RegistrationTerminationRequest;
import net.java.slee.resource.diameter.cxdx.events.ServerAssignmentRequest;
import net.java.slee.resource.diameter.cxdx.events.UserAuthorizationRequest;
import org.apache.log4j.Logger;
import org.jdiameter.api.Answer;
import org.jdiameter.api.ApplicationId;
import org.jdiameter.api.Avp;
import org.jdiameter.api.AvpDataException;
import org.jdiameter.api.AvpSet;
import org.jdiameter.api.EventListener;
import org.jdiameter.api.IllegalDiameterStateException;
import org.jdiameter.api.InternalException;
import org.jdiameter.api.Message;
import org.jdiameter.api.Peer;
import org.jdiameter.api.PeerTable;
import org.jdiameter.api.Request;
import org.jdiameter.api.Session;
import org.jdiameter.api.SessionFactory;
import org.jdiameter.api.Stack;
import org.jdiameter.api.acc.ClientAccSession;
import org.jdiameter.api.acc.ServerAccSession;
import org.jdiameter.api.cxdx.ClientCxDxSession;
import org.jdiameter.api.cxdx.ServerCxDxSession;
import org.jdiameter.client.api.ISessionFactory;
import org.jdiameter.client.impl.app.acc.ClientAccSessionImpl;
import org.jdiameter.server.impl.app.acc.ServerAccSessionImpl;
import org.mobicents.diameter.stack.DiameterListener;
import org.mobicents.diameter.stack.DiameterStackMultiplexerMBean;
import org.mobicents.slee.container.SleeContainer;
import org.mobicents.slee.resource.ResourceAdaptorActivityContextInterfaceFactory;
import org.mobicents.slee.resource.ResourceAdaptorEntity;
import org.mobicents.slee.resource.ResourceAdaptorState;
import org.mobicents.slee.resource.diameter.base.DiameterActivityHandle;
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.AccountingAnswerImpl;
import org.mobicents.slee.resource.diameter.base.events.AccountingRequestImpl;
import org.mobicents.slee.resource.diameter.base.events.ErrorAnswerImpl;
import org.mobicents.slee.resource.diameter.base.events.ExtensionDiameterMessageImpl;
import org.mobicents.slee.resource.diameter.base.handlers.AccountingSessionFactory;
import org.mobicents.slee.resource.diameter.cxdx.events.LocationInfoAnswerImpl;
import org.mobicents.slee.resource.diameter.cxdx.events.LocationInfoRequestImpl;
import org.mobicents.slee.resource.diameter.cxdx.events.MultimediaAuthenticationAnswerImpl;
import org.mobicents.slee.resource.diameter.cxdx.events.MultimediaAuthenticationRequestImpl;
import org.mobicents.slee.resource.diameter.cxdx.events.PushProfileAnswerImpl;
import org.mobicents.slee.resource.diameter.cxdx.events.PushProfileRequestImpl;
import org.mobicents.slee.resource.diameter.cxdx.events.RegistrationTerminationAnswerImpl;
import org.mobicents.slee.resource.diameter.cxdx.events.RegistrationTerminationRequestImpl;
import org.mobicents.slee.resource.diameter.cxdx.events.ServerAssignmentAnswerImpl;
import org.mobicents.slee.resource.diameter.cxdx.events.ServerAssignmentRequestImpl;
import org.mobicents.slee.resource.diameter.cxdx.events.UserAuthorizationAnswerImpl;
import org.mobicents.slee.resource.diameter.cxdx.events.UserAuthorizationRequestImpl;
import org.mobicents.slee.resource.diameter.cxdx.handlers.CxDxSessionCreationListener;
import org.mobicents.slee.resource.diameter.cxdx.handlers.CxDxSessionFactory;
/**
*
* CxDxResourceAdaptor.java
*
* @author <a href="mailto:brainslog@gmail.com"> Alexandre Mendonca </a>
* @author <a href="mailto:baranowb@gmail.com"> Bartosz Baranowski </a>
*/
public class CxDxResourceAdaptor implements ResourceAdaptor, DiameterListener , CxDxSessionCreationListener{
private static final long serialVersionUID = 1L;
private static transient Logger logger = Logger.getLogger(CxDxResourceAdaptor.class);
@SuppressWarnings("unused")
private ResourceAdaptorState state;
private Stack stack;
private SessionFactory sessionFactory = null;
private DiameterStackMultiplexerMBean diameterMux = null;
/**
* The BootstrapContext provides the resource adaptor with the required
* capabilities in the SLEE to execute its work. The bootstrap context is
* implemented by the SLEE. The BootstrapContext object holds references to
* a number of objects that are of interest to many resource adaptors. For
* further information see JSLEE v1.1 Specification Page 305. The
* bootstrapContext will be set in entityCreated() method.
*/
private transient BootstrapContext bootstrapContext = null;
/**
* The SLEE endpoint defines the contract between the SLEE and the resource
* adaptor that enables the resource adaptor to deliver events
* asynchronously to SLEE endpoints residing in the SLEE. This contract
* serves as a generic contract that allows a wide range of resources to be
* plugged into a SLEE environment via the resource adaptor architecture.
* For further information see JSLEE v1.1 Specification Page 307 The
* sleeEndpoint will be initialized in entityCreated() method.
*/
private transient SleeEndpoint sleeEndpoint = null;
/**
* the EventLookupFacility is used to look up the event id of incoming
* events
*/
private transient EventLookupFacility eventLookup = null;
/**
* The list of activites stored in this resource adaptor. If this resource
* adaptor were a distributed and highly available solution, this storage
* were one of the candidates for distribution.
*/
private transient ConcurrentHashMap<ActivityHandle, DiameterActivity> activities = null;
// Diameter Base Factories
private DiameterMessageFactoryImpl baseMessageFactory;
private DiameterAvpFactoryImpl baseAvpFactory;
// Cx/Dx Specific Factories
private CxDxMessageFactory cxdxMessageFactory;
private CxDxAVPFactory cxdxAvpFactory;
// ACI Factory
protected CxDxActivityContextInterfaceFactory acif = null;
// Provisioning
private long messageTimeout = 5000;
private CxDxSessionFactory cxdxSessionFactory;
private CxDxProviderImpl raProvider;
/**
*
*/
public CxDxResourceAdaptor() {
logger.debug("Diameter Cx/Dx RA :: Constructor called.");
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#activityEnded(javax.slee.resource.ActivityHandle)
*/
public void activityEnded(ActivityHandle handle) {
logger.info("Diameter Cx/Dx RA :: activityEnded :: handle[" + handle + ".");
if(this.activities != null)
{
synchronized (this.activities)
{
this.activities.remove(handle);
}
}
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#activityUnreferenced(javax.slee.resource.ActivityHandle)
*/
public void activityUnreferenced(ActivityHandle handle) {
logger.info("Diameter Cx/Dx RA :: activityUnreferenced :: handle[" + handle + "].");
this.activityEnded(handle);
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#entityActivated()
*/
public void entityActivated() throws ResourceException {
logger.info("Diameter Cx/Dx RA :: entityActivated.");
try
{
logger.info("Activating Diameter Cx/Dx RA Entity");
Object[] params = new Object[]{};
String[] signature = new String[]{};
String operation = "getMultiplexerMBean";
ObjectName diameterMultiplexerObjectName = new ObjectName("diameter.mobicents:service=DiameterStackMultiplexer");
Object object = SleeContainer.lookupFromJndi().getMBeanServer().invoke( diameterMultiplexerObjectName, operation, params, signature );
if(object instanceof DiameterStackMultiplexerMBean) {
this.diameterMux = (DiameterStackMultiplexerMBean) object;
}
this.raProvider = new CxDxProviderImpl(this);
initializeNamingContext();
this.activities = new ConcurrentHashMap();
this.state = ResourceAdaptorState.CONFIGURED;
// Initialize the protocol stack
initStack();
// Resource Adaptor ready to rumble!
this.state = ResourceAdaptorState.ACTIVE;
this.sessionFactory = this.stack.getSessionFactory();
this.baseMessageFactory = new DiameterMessageFactoryImpl(stack);
this.cxdxMessageFactory = new CxDxMessageFactoryImpl(stack);
this.baseAvpFactory = new DiameterAvpFactoryImpl();
this.cxdxAvpFactory = new CxDxAVPFactoryImpl();
//this.accSessionFactory = AccountingSessionFactory.INSTANCE;
//this.accSessionFactory.registerListener(this,messageTimeout,sessionFactory);
this.cxdxSessionFactory = new CxDxSessionFactory(this,messageTimeout,sessionFactory);
//this.cxdxSessionFactory.registerListener(this,messageTimeout,sessionFactory);
((ISessionFactory) sessionFactory).registerAppFacory(ServerCxDxSession.class, cxdxSessionFactory);
((ISessionFactory) sessionFactory).registerAppFacory(ClientCxDxSession.class, cxdxSessionFactory);
}
catch (Exception e) {
logger.error("Error Activating Diameter Cx/Dx RA Entity", e);
}
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#entityCreated(javax.slee.resource.BootstrapContext)
*/
public void entityCreated(BootstrapContext bootstrapContext) throws ResourceException {
logger.info("Diameter Cx/Dx RA :: entityCreated :: bootstrapContext[" + bootstrapContext + "].");
this.bootstrapContext = bootstrapContext;
this.sleeEndpoint = bootstrapContext.getSleeEndpoint();
this.eventLookup = bootstrapContext.getEventLookupFacility();
this.state = ResourceAdaptorState.UNCONFIGURED;
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#entityDeactivated()
*/
public void entityDeactivated() {
logger.info("Diameter Cx/Dx RA :: entityDeactivated.");
logger.info("Diameter Cx/Dx RA :: Cleaning RA Activities.");
synchronized (this.activities) {
activities.clear();
}
((ISessionFactory) sessionFactory).unRegisterAppFacory(ServerCxDxSession.class);
((ISessionFactory) sessionFactory).unRegisterAppFacory(ClientCxDxSession.class);
activities = null;
logger.info("Diameter Cx/Dx RA :: Cleaning naming context.");
try {
cleanNamingContext();
}
catch (NamingException e) {
logger.error("Diameter Cx/Dx RA :: Cannot unbind naming context.");
}
logger.info("Diameter Cx/Dx RA :: RA Stopped.");
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#entityDeactivating()
*/
public void entityDeactivating() {
logger.info("Diameter Cx/Dx RA :: entityDeactivating.");
this.state = ResourceAdaptorState.STOPPING;
try {
diameterMux.unregisterListener(this);
}
catch (Exception e) {
logger.error("Failure while unregistering Cx/Dx Resource Adaptor from Mux.", e);
}
synchronized (this.activities) {
for (ActivityHandle activityHandle : activities.keySet()) {
try {
logger.info("Ending activity [" + activityHandle + "]");
activities.get(activityHandle).endActivity();
}
catch (Exception e) {
logger.error("Error Deactivating Activity", e);
}
}
}
logger.info("Diameter Cx/Dx RA :: entityDeactivating completed.");
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#entityRemoved()
*/
public void entityRemoved() {
// Clean up!
this.acif = null;
this.activities = null;
this.bootstrapContext = null;
this.eventLookup = null;
this.raProvider = null;
this.sleeEndpoint = null;
this.stack = null;
logger.info("Diameter Cx/Dx RA :: entityRemoved.");
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#eventProcessingFailed(javax.slee.resource.ActivityHandle, java.lang.Object, int, javax.slee.Address, int, javax.slee.resource.FailureReason)
*/
public void eventProcessingFailed(ActivityHandle handle, Object event, int eventID, Address address, int flags, FailureReason reason) {
logger.info("Diameter Cx/Dx RA :: eventProcessingFailed :: handle[" + handle + "], event[" + event + "], eventID[" + eventID + "], address[" + address + "], flags[" + flags + "], reason[" + reason + "].");
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#eventProcessingSuccessful(javax.slee.resource.ActivityHandle, java.lang.Object, int, javax.slee.Address, int)
*/
public void eventProcessingSuccessful(ActivityHandle handle, Object event, int eventID, Address address, int flags) {
logger.info("Diameter Cx/Dx RA :: eventProcessingSuccessful :: handle[" + handle + "], event[" + event + "], eventID[" + eventID + "], address[" + address + "], flags[" + flags + "].");
// FIXME: Alexandre: Check if needed
//DiameterActivity activity = activities.get(handle);
//
//if(activity instanceof RfClientSessionImpl)
//{
// RfClientSessionImpl rfClientActivity = (RfClientSessionImpl) activity;
//
// FIXME: Alexandre: Check if needed to implement this method
// if(rfClientActivity..getTerminateAfterAnswer())
// {
// rfClientActivity.endActivity();
// }
//}
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#getActivity(javax.slee.resource.ActivityHandle)
*/
public Object getActivity(ActivityHandle handle) {
logger.info("Diameter Cx/Dx RA :: getActivity :: handle[" + handle + "].");
return this.activities.get(handle);
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#getActivityHandle(java.lang.Object)
*/
public ActivityHandle getActivityHandle(Object activity) {
logger.info("Diameter Cx/Dx RA :: getActivityHandle :: activity[" + activity + "].");
if (!(activity instanceof DiameterActivity)) {
logger.warn( "Trying to get activity handle for non-Diameter Activity. Returning null." );
return null;
}
DiameterActivity inActivity = (DiameterActivity) activity;
for (Map.Entry<ActivityHandle, DiameterActivity> activityInfo : this.activities.entrySet()) {
Object curActivity = activityInfo.getValue();
if (curActivity.equals(inActivity)) {
return activityInfo.getKey();
}
}
return null;
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#getMarshaler()
*/
public Marshaler getMarshaler() {
logger.info("Diameter Cx/Dx RA :: getMarshaler");
return null;
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#getSBBResourceAdaptorInterface(java.lang.String)
*/
public Object getSBBResourceAdaptorInterface(String className) {
logger.info("Diameter Cx/Dx RA :: getSBBResourceAdaptorInterface :: className[" + className + "].");
return this.raProvider;
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#queryLiveness(javax.slee.resource.ActivityHandle)
*/
public void queryLiveness(ActivityHandle handle) {
logger.info("Diameter Cx/Dx RA :: queryLiveness :: handle[" + handle + "].");
DiameterActivityImpl activity = (DiameterActivityImpl) activities.get(handle);
if (activity != null && !activity.isValid()) {
try {
sleeEndpoint.activityEnding(handle);
}
catch (Exception e) {
logger.error("Failure while ending non-live activity.", e);
}
}
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#serviceActivated(java.lang.String)
*/
public void serviceActivated(String serviceKey) {
logger.info("Diameter Cx/Dx RA :: serviceActivated :: serviceKey[" + serviceKey + "].");
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#serviceDeactivated(java.lang.String)
*/
public void serviceDeactivated(String serviceKey) {
logger.info("Diameter Cx/Dx RA :: serviceDeactivated :: serviceKey[" + serviceKey + "].");
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#serviceInstalled(java.lang.String, int[], java.lang.String[])
*/
public void serviceInstalled(String serviceKey, int[] eventIDs, String[] resourceOptions) {
logger.info("Diameter Cx/Dx RA :: serviceInstalled :: serviceKey[" + serviceKey + "], eventIDs[" + eventIDs + "], resourceOptions[" + resourceOptions + "].");
}
/* (non-Javadoc)
* @see javax.slee.resource.ResourceAdaptor#serviceUninstalled(java.lang.String)
*/
public void serviceUninstalled(String serviceKey) {
logger.info("Diameter Cx/Dx RA :: serviceUninstalled :: serviceKey[" + serviceKey + "].");
}
// ###################
// # PRIVATE METHODS #
// ###################
/**
* Set up the JNDI naming context.
*
* @throws NamingException
*/
private void initializeNamingContext() throws NamingException
{
// get the reference to the SLEE container from JNDI
SleeContainer container = SleeContainer.lookupFromJndi();
// get the entities name
String entityName = bootstrapContext.getEntityName();
ResourceAdaptorEntity resourceAdaptorEntity;
try
{
resourceAdaptorEntity = ((ResourceAdaptorEntity) container.getResourceAdaptorEntity(entityName));
}
catch (UnrecognizedResourceAdaptorEntityException uraee) {
throw new NamingException("Failure setting up Naming Context. RA Entity not found.");
}
ResourceAdaptorTypeID raTypeId = resourceAdaptorEntity.getInstalledResourceAdaptor().getRaType().getResourceAdaptorTypeID();
// create the ActivityContextInterfaceFactory
acif = new CxDxActivityContextInterfaceFactoryImpl(resourceAdaptorEntity.getServiceContainer(), entityName);
// set the ActivityContextInterfaceFactory
resourceAdaptorEntity.getServiceContainer().getActivityContextInterfaceFactories().put(raTypeId, acif);
try
{
if (this.acif != null)
{
// parse the string = java:slee/resources/RAFrameRA/raframeacif
String jndiName = ((ResourceAdaptorActivityContextInterfaceFactory) acif).getJndiName();
int begind = jndiName.indexOf(':');
int toind = jndiName.lastIndexOf('/');
String prefix = jndiName.substring(begind + 1, toind);
String name = jndiName.substring(toind + 1);
logger.info("Diameter Cx/Dx RA :: Registering in JNDI :: Prefix[" + prefix + "], Name[" + name + "].");
SleeContainer.registerWithJndi(prefix, name, this.acif);
logger.info("Diameter Cx/Dx RA :: Registered in JNDI successfully.");
}
}
catch (IndexOutOfBoundsException iobe) {
logger.info("Failure initializing name context.", iobe);
}
}
/**
* Clean the JNDI naming context.
*
* @throws NamingException
*/
private void cleanNamingContext() throws NamingException
{
try
{
if (this.acif != null)
{
// parse the string = java:slee/resources/RAFrameRA/raframeacif
String jndiName = ((ResourceAdaptorActivityContextInterfaceFactory) this.acif).getJndiName();
// remove "java:" prefix
int begind = jndiName.indexOf(':');
String javaJNDIName = jndiName.substring(begind + 1);
logger.info("Diameter Cx/Dx RA :: Unregistering from JNDI :: Name[" + javaJNDIName + "].");
SleeContainer.unregisterWithJndi(javaJNDIName);
logger.info("Diameter Cx/Dx RA :: Unregistered from JNDI successfully.");
}
}
catch (IndexOutOfBoundsException iobe) {
logger.error("Failure cleaning name context.", iobe);
}
}
/**
* Initializes the RA Diameter Stack.
*
* @throws Exception
*/
private synchronized void initStack() throws Exception
{
// Register the RA as a listener to Cx/Dx Application (Vendor-Id(10415), Acct-App-Id(16777216))
this.diameterMux.registerListener(this, new ApplicationId[]{ApplicationId.createByAuthAppId(10415L, 16777216L)});
this.stack = this.diameterMux.getStack();
this.messageTimeout = this.stack.getMetaData().getConfiguration().getLongValue(MessageTimeOut.ordinal(), (Long) MessageTimeOut.defValue());
logger.info("Diameter Cx/Dx RA :: Successfully initialized stack.");
}
/**
* Create the Diameter Activity Handle for an given session id
*
* @param sessionId the session identifier to create the activity handle from
* @return a DiameterActivityHandle for the provided sessionId
*/
protected DiameterActivityHandle getActivityHandle(String sessionId) {
return new DiameterActivityHandle(sessionId);
}
/**
* Method for performing tasks when activity is created, such as informing
* SLEE about it and storing into internal map.
*
* @param ac
* the activity that has been created
*/
private void activityCreated(DiameterActivity ac) {
logger.info( "Diameter Cx/Dx RA :: activityCreated :: activity[" + ac + "]" );
try {
// Inform SLEE that Activity Started
DiameterActivityImpl activity = (DiameterActivityImpl) ac;
activity.setSessionListener(this);
sleeEndpoint.activityStarted(activity.getActivityHandle());
// Put it into our activites map
activities.put(activity.getActivityHandle(), activity);
logger.info("Activity started [" + activity.getActivityHandle() + "]");
}
catch (Exception e) {
logger.error("Error creating activity", e);
throw new RuntimeException("Error creating activity", e);
}
}
/**
* Create Event object from request/answer
*
* @param request
* the request to create the event from, if any.
* @param answer
* the answer to create the event from, if any.
* @return a DiameterMessage object wrapping the request/answer
* @throws OperationNotSupportedException
*/
private DiameterMessage createEvent(Request request, Answer answer) throws OperationNotSupportedException {
if (request == null && answer == null) {
return null;
}
int commandCode = (request != null ? request.getCommandCode() : answer.getCommandCode());
if (answer != null && answer.isError()) {
return new ErrorAnswerImpl(answer);
}
// FIXME: baranowb: we might need here more.
switch (commandCode) {
case UserAuthorizationRequest.COMMAND_CODE: // UAR/UAA
return request != null ? new UserAuthorizationRequestImpl(request) : new UserAuthorizationAnswerImpl(answer);
case ServerAssignmentRequest.COMMAND_CODE: // SAR/SAA
return request != null ? new ServerAssignmentRequestImpl(request) : new ServerAssignmentAnswerImpl(answer);
case LocationInfoRequest.COMMAND_CODE: // LIR/LIA
return request != null ? new LocationInfoRequestImpl(request) : new LocationInfoAnswerImpl(answer);
case MultimediaAuthenticationRequest.COMMAND_CODE: // MAR/MAA
return request != null ? new MultimediaAuthenticationRequestImpl(request) : new MultimediaAuthenticationAnswerImpl(answer);
case RegistrationTerminationRequest.COMMAND_CODE: // RTR/RTA
return request != null ? new RegistrationTerminationRequestImpl(request) : new RegistrationTerminationAnswerImpl(answer);
case PushProfileRequest.COMMAND_CODE: // PPR/PPA
return request != null ? new PushProfileRequestImpl(request) : new PushProfileAnswerImpl(answer);
default:
// throw new OperationNotSupportedException("Not supported message code:" + commandCode + "\n" + (request != null ? request : answer));
return new ExtensionDiameterMessageImpl(request != null ? request : answer);
}
}
/* (non-Javadoc)
* @see org.mobicents.slee.resource.diameter.cxdx.handlers.CxDxSessionCreationListener#fireEvent(java.lang.String, java.lang.String, org.jdiameter.api.Request, org.jdiameter.api.Answer)
*/
public void fireEvent(String sessionId, String name, Request request, Answer answer) {
this.fireEvent(getActivityHandle(sessionId), name, request, answer);
}
/**
* Method for firing event to SLEE
*
* @param handle
* the handle for the activity where event will be fired on
* @param name
* the unqualified Event name
* @param request
* the request that will be wrapped in the event, if any
* @param answer
* the answer that will be wrapped in the event, if any
*/
private void fireEvent(ActivityHandle handle, String name, Request request, Answer answer)
{
try {
int eventID = eventLookup.getEventID(name, "java.net", "0.8");
DiameterMessage event = (DiameterMessage) createEvent(request, answer);
//perf looser, bu we need it.
Object _activity = this.activities.get(handle);
if(_activity != null && _activity instanceof CxDxSessionImpl) {
CxDxSessionImpl cxdxSession = (CxDxSessionImpl)_activity;
cxdxSession.fetchSessionData(event);
}
sleeEndpoint.fireEvent(handle, event, eventID, null);
}
catch (Exception e) {
logger.warn("Can not send event", e);
}
}
// ######################################
// ## DIAMETER LISTENER IMPLEMENTATION ##
// ######################################
/* (non-Javadoc)
* @see org.jdiameter.api.NetworkReqListener#processRequest(org.jdiameter.api.Request)
*/
public Answer processRequest(Request request) {
DiameterActivityImpl activity;
try {
activity = (DiameterActivityImpl) raProvider.createActivity(request);
/*if(activity instanceof RfServerSessionImpl) {
RfServerSessionImpl assai = (RfServerSessionImpl)activity;
((ServerAccSessionImpl)assai.getSession()).processRequest(request);
}
else if(activity instanceof RfClientSessionImpl) {
RfClientSessionImpl assai = (RfClientSessionImpl)activity;
((ClientAccSession)assai.getSession()).processRequest(request);
}*/
}
catch (CreateActivityException e) {
logger.error("", e);
}
// returning null so we can answer later
return null;
}
/* (non-Javadoc)
* @see org.jdiameter.api.EventListener#receivedSuccessMessage(org.jdiameter.api.Message, org.jdiameter.api.Message)
*/
public void receivedSuccessMessage(Request request, Answer answer) {
logger.info("Diameter Cx/Dx RA :: receivedSuccessMessage :: " + "Request[" + request + "], Answer[" + answer + "].");
try {
logger.info( "Received Message Result-Code: " + answer.getResultCode().getUnsigned32() );
}
catch ( AvpDataException ignore ) {
// ignore, this was just for informational purposes...
}
}
/* (non-Javadoc)
* @see org.jdiameter.api.EventListener#timeoutExpired(org.jdiameter.api.Message)
*/
public void timeoutExpired(Request request) {
logger.info("Diameter Cx/Dx RA :: timeoutExpired :: " + "Request[" + request + "].");
// Message delivery timed out - we have to remove activity
DiameterActivityHandle ah = new DiameterActivityHandle(request.getSessionId());
try {
activities.get(ah).endActivity();
}
catch (Exception e) {
logger.error("Failure processing timeout message.", e);
}
}
// #############################
// ## PROVIDER IMPLEMENTATION ##
// #############################
private class CxDxProviderImpl implements CxDxProvider {
protected final Logger logger = Logger.getLogger(CxDxProviderImpl.class);
protected CxDxResourceAdaptor ra;
protected CxDxAVPFactory avpFactory = null;
protected DiameterMessageFactory messageFactory = null;
/**
* Constructor.
*
* @param cxdxResourceAdaptor The resource adaptor for this Provider.
*/
public CxDxProviderImpl(CxDxResourceAdaptor cxdxResourceAdaptor) {
this.ra = cxdxResourceAdaptor;
}
private DiameterActivity createActivity(Message message) throws CreateActivityException {
String sessionId = message.getSessionId();
DiameterActivityHandle handle = new DiameterActivityHandle(sessionId);
if (activities.keySet().contains(handle)) {
return activities.get(handle);
}
else {
if (message.isRequest()) {
if(message.getCommandCode() == PushProfileRequest.COMMAND_CODE || message.getCommandCode() == RegistrationTerminationRequest.COMMAND_CODE) {
return createCxDxClientSessionActivity((Request) message);
}
else {
return createCxDxServerSessionActivity((Request) message);
}
}
else {
throw new IllegalStateException("Got answer, there should already be activity.");
// AvpSet avps = message.getAvps();
// Avp avp = null;
//
// DiameterIdentity destinationHost = null;
// DiameterIdentity destinationRealm = null;
//
// if ((avp = avps.getAvp(Avp.DESTINATION_HOST)) != null) {
// try {
// destinationHost = new DiameterIdentity(avp.getDiameterIdentity());
// }
// catch (AvpDataException e) {
// logger.error("Failed to extract Destination-Host from Message.", e);
// }
// }
//
// if ((avp = avps.getAvp(Avp.DESTINATION_REALM)) != null) {
// try {
// destinationRealm = new DiameterIdentity(avp.getDiameterIdentity());
// }
// catch (AvpDataException e) {
// logger.error("Failed to extract Destination-Realm from Message.", e);
// }
// }
//
// return createCxDxClientSessionActivity( destinationHost, destinationRealm );
}
}
}
private DiameterActivity createCxDxServerSessionActivity(Request request) throws CreateActivityException
{
ServerCxDxSession session = null;
try {
String sessionId = request == null? null: request.getSessionId();
ApplicationId appId = request.getApplicationIdAvps().isEmpty() ? null : request.getApplicationIdAvps().iterator().next();
session = ((ISessionFactory) stack.getSessionFactory()).getNewAppSession(sessionId, appId, ServerCxDxSession.class, request);
if (session == null) {
throw new CreateActivityException("Got NULL Session while creating Server Accounting Activity");
}
}
catch (InternalException e) {
throw new CreateActivityException("Internal exception while creating Server Accounting Activity", e);
}
catch (IllegalDiameterStateException e) {
throw new CreateActivityException("Illegal Diameter State exception while creating Server Accounting Activity", e);
}
org.mobicents.slee.resource.diameter.cxdx.CxDxServerSessionImpl activity = new org.mobicents.slee.resource.diameter.cxdx.CxDxServerSessionImpl(ra.cxdxMessageFactory, ra.cxdxAvpFactory, session, (EventListener<Request, Answer>) session, ra.messageTimeout, (DiameterIdentity)null, (DiameterIdentity)null, ra.sleeEndpoint,stack);
activityCreated(activity);
if(request!=null)
{
((org.jdiameter.server.impl.app.cxdx.CxDxServerSessionImpl)session).processRequest(request);
}
return activity;
}
// Actual Provider Methods
public CxDxClientSession createCxDxClientSessionActivity() throws CreateActivityException {
//return createCxDxClientSessionActivity( null, null );
//FIXME: I dony know why YOu push those methods :)
return createCxDxClientSessionActivity( null);
}
//public CxDxClientSession createCxDxClientSessionActivity( DiameterIdentity destinationHost, DiameterIdentity destinationRealm ) throws CreateActivityException
public CxDxClientSession createCxDxClientSessionActivity( Request req ) throws CreateActivityException
{
try {
String sessionId = req == null? null: req.getSessionId();
ClientCxDxSession session = ((ISessionFactory) stack.getSessionFactory()).getNewAppSession(sessionId, ApplicationId.createByAuthAppId(10415L, 16777216L), ClientCxDxSession.class);
//return new org.mobicents.slee.resource.diameter.cxdx.CxDxClientSessionImpl(ra.cxdxMessageFactory, ra.cxdxAvpFactory, session, (EventListener<Request, Answer>) session, ra.messageTimeout, destinationHost, destinationRealm, ra.sleeEndpoint);
org.mobicents.slee.resource.diameter.cxdx.CxDxClientSessionImpl activity = new org.mobicents.slee.resource.diameter.cxdx.CxDxClientSessionImpl(ra.cxdxMessageFactory, ra.cxdxAvpFactory, session, (EventListener<Request, Answer>) session, ra.messageTimeout, null, null, ra.sleeEndpoint);
activityCreated(activity);
if(req!=null)
{
((org.jdiameter.client.impl.app.cxdx.CxDxClientSessionImpl)session).processRequest(req);
}
return activity;
}
catch (Exception e) {
throw new CreateActivityException("Internal exception while creating Client Accounting Activity", e);
}
}
/* (non-Javadoc)
* @see net.java.slee.resource.diameter.cxdx.CxDxProvider#createCxDxClientSessionActivity(net.java.slee.resource.diameter.base.events.avp.DiameterIdentity, net.java.slee.resource.diameter.base.events.avp.DiameterIdentity)
*/
public CxDxClientSession createCxDxClientSessionActivity(DiameterIdentity destinationHost, DiameterIdentity destinationRealm) throws CreateActivityException {
try {
ClientCxDxSession session = ((ISessionFactory) stack.getSessionFactory()).getNewAppSession(null, ApplicationId.createByAuthAppId(10415L, 16777216L), ClientCxDxSession.class);
//return new org.mobicents.slee.resource.diameter.cxdx.CxDxClientSessionImpl(ra.cxdxMessageFactory, ra.cxdxAvpFactory, session, (EventListener<Request, Answer>) session, ra.messageTimeout, destinationHost, destinationRealm, ra.sleeEndpoint);
org.mobicents.slee.resource.diameter.cxdx.CxDxClientSessionImpl activity = new org.mobicents.slee.resource.diameter.cxdx.CxDxClientSessionImpl(ra.cxdxMessageFactory, ra.cxdxAvpFactory, session, (EventListener<Request, Answer>) session, ra.messageTimeout, destinationHost, destinationRealm, ra.sleeEndpoint);
activityCreated(activity);
return activity;
}
catch (Exception e) {
throw new CreateActivityException("Internal exception while creating Client Accounting Activity", e);
}
}
public CxDxMessageFactory getCxDxMessageFactory() {
return ra.cxdxMessageFactory;
}
public CxDxAVPFactory getCxDxAVPFactory() {
return ra.cxdxAvpFactory;
}
public DiameterIdentity[] getConnectedPeers() {
return ra.getConnectedPeers();
}
public int getPeerCount() {
return ra.getConnectedPeers().length;
}
public CxDxServerSession createCxDxServerSessionActivity() throws CreateActivityException {
return createCxDxServerSessionActivity(null, null);
}
public CxDxServerSession createCxDxServerSessionActivity(DiameterIdentity destinationHost, DiameterIdentity destinationRealm) throws CreateActivityException {
try {
ServerCxDxSession session = ((ISessionFactory) stack.getSessionFactory()).getNewAppSession(null, ApplicationId.createByAuthAppId(10415L, 16777216L), ServerCxDxSession.class);
org.mobicents.slee.resource.diameter.cxdx.CxDxServerSessionImpl activity = new org.mobicents.slee.resource.diameter.cxdx.CxDxServerSessionImpl(ra.cxdxMessageFactory,
ra.cxdxAvpFactory, session, (EventListener<Request, Answer>) session, ra.messageTimeout, destinationHost, destinationRealm, ra.sleeEndpoint, stack);
activityCreated(activity);
return activity;
} catch (Exception e) {
throw new CreateActivityException("Internal exception while creating Client Accounting Activity", e);
}
}
}
public DiameterIdentity[] getConnectedPeers() {
if (this.stack != null) {
try {
// Get the list of peers from the stack
List<Peer> peers = stack.unwrap(PeerTable.class).getPeerTable();
DiameterIdentity[] result = new DiameterIdentity[peers.size()];
int i = 0;
// Get each peer from the list and make a DiameterIdentity
for (Peer peer : peers) {
DiameterIdentity identity = new DiameterIdentity(peer.getUri().toString());
result[i++] = identity;
}
return result;
}
catch (Exception e) {
logger.error("Failure getting peer list.", e);
}
}
return new DiameterIdentity[0];
}
/* (non-Javadoc)
* @see org.mobicents.slee.resource.diameter.cxdx.handlers.CxDxSessionCreationListener#getSupportedApplications()
*/
public ApplicationId[] getSupportedApplications() {
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see org.mobicents.slee.resource.diameter.cxdx.handlers.CxDxSessionCreationListener#sessionCreated(org.jdiameter.api.cxdx.ServerCxDxSession)
*/
public void sessionCreated(ServerCxDxSession session) {
//FIXME: here we should create Activity!!!!!!!!!!!!!
}
/* (non-Javadoc)
* @see org.mobicents.slee.resource.diameter.cxdx.handlers.CxDxSessionCreationListener#sessionCreated(org.jdiameter.api.cxdx.ClientCxDxSession)
*/
public void sessionCreated(ClientCxDxSession session) {
//FIXME: here we should create Activity!!!!!!!!!!!!!
}
/* (non-Javadoc)
* @see org.mobicents.slee.resource.diameter.cxdx.handlers.CxDxSessionCreationListener#sessionCreated(org.jdiameter.api.Session)
*/
public void sessionCreated(Session session) {
//FIXME: here we should create Activity!!!!!!!!!!!!!
}
/* (non-Javadoc)
* @see org.mobicents.slee.resource.diameter.cxdx.handlers.CxDxSessionCreationListener#sessionDestroyed(java.lang.String, java.lang.Object)
*/
public void sessionDestroyed(String sessionId, Object appSession) {
try
{
this.sleeEndpoint.activityEnding(getActivityHandle(sessionId));
}
catch (Exception e) {
logger.error( "Failure Ending Activity with Session-Id[" + sessionId + "]", e );
}
}
/* (non-Javadoc)
* @see org.mobicents.slee.resource.diameter.cxdx.handlers.CxDxSessionCreationListener#sessionExists(java.lang.String)
*/
public boolean sessionExists(String sessionId) {
return this.activities.contains(new DiameterActivityHandle(sessionId));
}
}