package org.mobicents.slee.resource.diameter.base.handlers; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import net.java.slee.resource.diameter.base.events.AbortSessionAnswer; import net.java.slee.resource.diameter.base.events.AccountingAnswer; import net.java.slee.resource.diameter.base.events.CapabilitiesExchangeAnswer; import net.java.slee.resource.diameter.base.events.DeviceWatchdogAnswer; import net.java.slee.resource.diameter.base.events.DisconnectPeerAnswer; import net.java.slee.resource.diameter.base.events.ErrorAnswer; import net.java.slee.resource.diameter.base.events.ExtensionDiameterMessage; import net.java.slee.resource.diameter.base.events.ReAuthAnswer; import net.java.slee.resource.diameter.base.events.SessionTerminationAnswer; import org.apache.log4j.Logger; import org.jdiameter.api.Answer; import org.jdiameter.api.ApplicationId; import org.jdiameter.api.IllegalDiameterStateException; import org.jdiameter.api.InternalException; import org.jdiameter.api.OverloadException; import org.jdiameter.api.Request; import org.jdiameter.api.RouteException; import org.jdiameter.api.SessionFactory; import org.jdiameter.api.acc.ClientAccSession; import org.jdiameter.api.acc.ClientAccSessionListener; import org.jdiameter.api.acc.ServerAccSession; import org.jdiameter.api.acc.ServerAccSessionListener; import org.jdiameter.api.acc.events.AccountAnswer; import org.jdiameter.api.acc.events.AccountRequest; import org.jdiameter.api.app.AppAnswerEvent; import org.jdiameter.api.app.AppRequestEvent; import org.jdiameter.api.app.AppSession; import org.jdiameter.api.app.StateChangeListener; import org.jdiameter.client.impl.app.acc.ClientAccSessionImpl; import org.jdiameter.common.api.app.IAppSessionFactory; import org.jdiameter.server.impl.app.acc.ServerAccSessionImpl; import static org.mobicents.slee.resource.diameter.base.handlers.BaseSessionCreationListener.*; public class AccountingSessionFactory implements IAppSessionFactory, ServerAccSessionListener, StateChangeListener, ClientAccSessionListener { private static final Map<Integer, String> events; private static HashSet<Integer> accEventCodes = new HashSet<Integer>(); private static HashSet<Integer> authEventCodes = new HashSet<Integer>(); static { Map<Integer, String> eventsTemp = new HashMap<Integer, String>(); eventsTemp.put(AbortSessionAnswer.commandCode, "AbortSession"); eventsTemp.put(AccountingAnswer.commandCode, "Accounting"); eventsTemp.put(CapabilitiesExchangeAnswer.commandCode, "CapabilitiesExchange"); eventsTemp.put(DeviceWatchdogAnswer.commandCode, "DeviceWatchdog"); eventsTemp.put(DisconnectPeerAnswer.commandCode, "DisconnectPeer"); eventsTemp.put(ReAuthAnswer.commandCode, "ReAuth"); eventsTemp.put(SessionTerminationAnswer.commandCode, "SessionTermination"); eventsTemp.put(ErrorAnswer.commandCode, "Error"); // FIXME: baranowb - make sure its compilant with xml eventsTemp.put(ExtensionDiameterMessage.commandCode, "ExtensionDiameter"); events = Collections.unmodifiableMap(eventsTemp); authEventCodes.add(AbortSessionAnswer.commandCode); authEventCodes.add(ReAuthAnswer.commandCode); authEventCodes.add(SessionTerminationAnswer.commandCode); accEventCodes.add(AccountingAnswer.commandCode); } protected HashMap<ApplicationId, BaseSessionCreationListener> ras; protected long messageTimeout = 5000; protected SessionFactory sessionFactory = null; protected final static Logger logger = Logger.getLogger(AccountingSessionFactory.class); public static AccountingSessionFactory INSTANCE = new AccountingSessionFactory(); /* * public AccountingSessionFactory(BaseSessionCreationListener ra, long * messageTimeout, SessionFactory sessionFactory, ApplicationId appId) { * super(); this.ras.put(appId, ra); this.messageTimeout = messageTimeout; * this.sessionFactory = sessionFactory; } */ private AccountingSessionFactory() { this.ras = new HashMap<ApplicationId, BaseSessionCreationListener>(); } public void registerListener(BaseSessionCreationListener ra, long messageTimeout, SessionFactory sessionFactory) { for (ApplicationId appId : ra.getSupportedApplications()) this.ras.put(appId, ra); this.messageTimeout = messageTimeout; this.sessionFactory = sessionFactory; } public AppSession getNewSession(String sessionId, Class<? extends AppSession> aClass, ApplicationId applicationId, Object[] args) { try { if (aClass == ServerAccSession.class) { Request request = (Request) args[0]; ServerAccSessionImpl session = new ServerAccSessionImpl(sessionFactory.getNewSession(request.getSessionId()), request, this, messageTimeout, true, new StateChangeListener[] { this }); BaseSessionCreationListener ra = this.ras.get(applicationId) != null ? this.ras.get(applicationId) : this.ras.values().iterator().next(); ra.sessionCreated(session); return session; } else if (aClass == ClientAccSession.class) { ClientAccSessionImpl session = sessionId == null ? new ClientAccSessionImpl(sessionFactory, this, applicationId) : new ClientAccSessionImpl(sessionFactory, sessionId, this, applicationId); session.addStateChangeNotification(this); BaseSessionCreationListener ra = this.ras.get(applicationId) != null ? this.ras.get(applicationId) : this.ras.values().iterator().next(); ra.sessionCreated(session); return session; } } catch (Exception e) { logger.error("Failure to obtain new Accounting Session.", e); } return null; } public void doAccRequestEvent(ServerAccSession appSession, AccountRequest request) throws InternalException, IllegalDiameterStateException, RouteException, OverloadException { logger.info("Diameter Base AccountingSessionFactory :: doAccRequestEvent :: appSession[" + appSession + "], Request[" + request + "]"); ApplicationId appId = null; Iterator<ApplicationId> appIdIt = request.getMessage().getApplicationIdAvps().iterator(); while (appIdIt.hasNext() && appId == null) { appId = appIdIt.next(); appId = appId.getAcctAppId() != ApplicationId.UNDEFINED_VALUE && this.ras.containsKey(appId) ? appId : null; } BaseSessionCreationListener ra = appId != null ? this.ras.get(appId) : this.ras.values().iterator().next(); ra.fireEvent(appSession.getSessions().get(0).getSessionId(), _AccountingRequest, (Request) request.getMessage(), null); } public void doAccAnswerEvent(ClientAccSession appSession, AccountRequest request, AccountAnswer answer) throws InternalException, IllegalDiameterStateException, RouteException, OverloadException { logger.info("doAccAnswerEvent :: appSession[" + appSession + "], request[" + request + "], answer[" + answer + "]"); ApplicationId appId = null; Iterator<ApplicationId> appIdIt = request.getMessage().getApplicationIdAvps().iterator(); while (appIdIt.hasNext() && appId == null) { appId = appIdIt.next(); appId = appId.getAcctAppId() != ApplicationId.UNDEFINED_VALUE && this.ras.containsKey(appId) ? appId : null; } BaseSessionCreationListener ra = appId != null ? this.ras.get(appId) : this.ras.values().iterator().next(); if(answer.getMessage().isError()) { ra.fireEvent(appSession.getSessions().get(0).getSessionId(), _ErrorAnswer, null, (Answer) answer.getMessage()); }else { ra.fireEvent(appSession.getSessions().get(0).getSessionId(), _AccountingAnswer, null, (Answer) answer.getMessage()); } } public void doOtherEvent(AppSession appSession, AppRequestEvent request, AppAnswerEvent answer) throws InternalException, IllegalDiameterStateException, RouteException, OverloadException { logger.info("Diameter Base AccountingSessionFactory :: doOtherEvent :: appSession[" + appSession + "], Request[" + request + "], Answer[" + answer + "]"); ApplicationId appId = null; Iterator<ApplicationId> appIdIt = request.getMessage().getApplicationIdAvps().iterator(); while (appIdIt.hasNext() && appId == null) { appId = appIdIt.next(); appId = appId.getAcctAppId() != ApplicationId.UNDEFINED_VALUE && this.ras.containsKey(appId) ? appId : null; } BaseSessionCreationListener ra = appId != null ? this.ras.get(appId) : this.ras.values().iterator().next(); //FIXME: Alex validate :} if (answer != null) { if(answer.getMessage().isError()) { ra.fireEvent(appSession.getSessions().get(0).getSessionId(), _ErrorAnswer, null, (Answer) answer.getMessage()); }else { ra.fireEvent(appSession.getSessions().get(0).getSessionId(), _ExtensionDiameterMessage, null, (Answer) answer.getMessage()); } } else { ra.fireEvent(appSession.getSessions().get(0).getSessionId(), _ExtensionDiameterMessage, (Request) request.getMessage(), null); } } public void stateChanged(Enum oldState, Enum newState) { logger.info("Diameter Base AccountingSessionFactory :: stateChanged :: oldState[" + oldState + "], newState[" + newState + "]"); //FIXME: add code here. } }