package org.mobicents.slee.resource.diameter.cca;
import java.io.IOException;
import java.util.ArrayList;
import javax.slee.resource.SleeEndpoint;
import net.java.slee.resource.diameter.base.DiameterException;
import net.java.slee.resource.diameter.base.events.ReAuthAnswer;
import net.java.slee.resource.diameter.base.events.avp.AvpNotAllowedException;
import net.java.slee.resource.diameter.base.events.avp.DiameterAvp;
import net.java.slee.resource.diameter.base.events.avp.DiameterIdentity;
import net.java.slee.resource.diameter.cca.CreditControlAVPFactory;
import net.java.slee.resource.diameter.cca.CreditControlClientSession;
import net.java.slee.resource.diameter.cca.CreditControlMessageFactory;
import net.java.slee.resource.diameter.cca.CreditControlSessionState;
import net.java.slee.resource.diameter.cca.events.CreditControlRequest;
import net.java.slee.resource.diameter.cca.events.avp.CcRequestType;
import org.jdiameter.api.Answer;
import org.jdiameter.api.EventListener;
import org.jdiameter.api.Request;
import org.jdiameter.api.cca.ClientCCASession;
import org.jdiameter.common.api.app.cca.ClientCCASessionState;
import org.jdiameter.common.impl.app.auth.ReAuthAnswerImpl;
import org.jdiameter.common.impl.app.cca.JCreditControlRequestImpl;
import org.jdiameter.common.impl.validation.JAvpNotAllowedException;
import org.mobicents.slee.resource.diameter.base.events.DiameterMessageImpl;
import org.mobicents.slee.resource.diameter.cca.handlers.CCASessionCreationListener;
/**
* Start time:15:00:53 2008-12-08<br>
* Project: mobicents-diameter-parent<br>
*
* @author <a href="mailto:baranowb@gmail.com"> Bartosz Baranowski </a>
* @author <a href="mailto:brainslog@gmail.com"> Alexandre Mendonca </a>
*/
public class CreditControlClientSessionImpl extends CreditControlSessionImpl implements CreditControlClientSession {
protected ClientCCASession session = null;
protected ArrayList<DiameterAvp> sessionAvps = new ArrayList<DiameterAvp>();
boolean terminateAfterAnswer = false;
/**
* @param messageFactory
* @param avpFactory
* @param session
* @param raEventListener
* @param timeout
* @param destinationHost
* @param destinationRealm
* @param endpoint
*/
public CreditControlClientSessionImpl(CreditControlMessageFactory messageFactory, CreditControlAVPFactory avpFactory, ClientCCASession session, long timeout, DiameterIdentity destinationHost,
DiameterIdentity destinationRealm, SleeEndpoint endpoint) {
super(messageFactory, avpFactory, null, (EventListener<Request, Answer>) session, timeout, destinationHost, destinationRealm, endpoint);
this.session = session;
this.session.addStateChangeNotification(this);
super.setCurrentWorkingSession(this.session.getSessions().get(0));
}
public void endActivity() {
//this.listener.sessionDestroyed(this.sessionId, this);
this.session.release();
}
public Object getDiameterAvpFactory() {
return this.ccaAvpFactory;
}
public Object getDiameterMessageFactory() {
return this.ccaMessageFactory;
}
/*
* (non-Javadoc)
*
* @seenet.java.slee.resource.diameter.cca.CreditControlClientSession#
* createCreditControlRequest()
*/
public CreditControlRequest createCreditControlRequest() {
// Create the request
CreditControlRequest request = super.ccaMessageFactory.createCreditControlRequest(super.getSessionId());
// If there's a Destination-Host, add the AVP
if (destinationHost != null) {
request.setDestinationHost(destinationHost);
}
if (destinationRealm != null) {
request.setDestinationRealm(destinationRealm);
}
// Fill extension avps if present
if (sessionAvps.size() > 0) {
try {
request.setExtensionAvps(sessionAvps.toArray(new DiameterAvp[sessionAvps.size()]));
} catch (AvpNotAllowedException e) {
logger.error("Failed to add Session AVPs to request.", e);
}
}
return request;
}
/*
* (non-Javadoc)
*
* @seenet.java.slee.resource.diameter.cca.CreditControlClientSession#
* sendCreditControlRequest
* (net.java.slee.resource.diameter.cca.events.CreditControlRequest)
*/
public void sendCreditControlRequest(CreditControlRequest ccr) throws IOException {
// fetchCurrentState(ccr);
DiameterMessageImpl msg = (DiameterMessageImpl) ccr;
validateState(ccr);
try {
session.sendCreditControlRequest(new JCreditControlRequestImpl((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)
*
* @seenet.java.slee.resource.diameter.cca.CreditControlClientSession#
* sendInitialCreditControlRequest
* (net.java.slee.resource.diameter.cca.events.CreditControlRequest)
*/
public void sendInitialCreditControlRequest(CreditControlRequest ccr) throws IOException {
// FIXME: should this affect FSM ?
ccr.setCcRequestType(CcRequestType.INITIAL_REQUEST);
validateState(ccr);
DiameterMessageImpl msg = (DiameterMessageImpl) ccr;
try {
session.sendCreditControlRequest(new JCreditControlRequestImpl((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)
*
* @seenet.java.slee.resource.diameter.cca.CreditControlClientSession#
* sendUpdateCreditControlRequest
* (net.java.slee.resource.diameter.cca.events.CreditControlRequest)
*/
public void sendUpdateCreditControlRequest(CreditControlRequest ccr) throws IOException {
// FIXME: Should this come already in the CCR?
ccr.setCcRequestType(CcRequestType.UPDATE_REQUEST);
validateState(ccr);
DiameterMessageImpl msg = (DiameterMessageImpl) ccr;
try {
session.sendCreditControlRequest(new JCreditControlRequestImpl((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)
*
* @seenet.java.slee.resource.diameter.cca.CreditControlClientSession#
* sendTerminationCreditControlRequest
* (net.java.slee.resource.diameter.cca.events.CreditControlRequest)
*/
public void sendTerminationCreditControlRequest(CreditControlRequest ccr) throws IOException {
// This should not be used to terminate sub-sessions!
// FIXME: Should this come already in the CCR?
ccr.setCcRequestType(CcRequestType.TERMINATION_REQUEST);
validateState(ccr);
DiameterMessageImpl msg = (DiameterMessageImpl) ccr;
try {
session.sendCreditControlRequest(new JCreditControlRequestImpl((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)
*
* @seenet.java.slee.resource.diameter.cca.CreditControlClientSession#
* sendReAuthAnswer
* (net.java.slee.resource.diameter.base.events.ReAuthAnswer)
*/
public void sendReAuthAnswer(ReAuthAnswer rar) throws IOException {
DiameterMessageImpl msg = (DiameterMessageImpl) rar;
try {
session.sendReAuthAnswer(new ReAuthAnswerImpl((Answer) 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
* org.jdiameter.api.app.StateChangeListener#stateChanged(java.lang.Enum,
* java.lang.Enum)
*/
public void stateChanged(Enum oldState, Enum newState) {
ClientCCASessionState s = (ClientCCASessionState) newState;
// IDLE(0), PENDING_EVENT(1), PENDING_INITIAL(2), PENDING_UPDATE(3),
// PENDING_TERMINATION(4), PENDING_BUFFERED(5), OPEN(6);
switch (s) {
case PENDING_EVENT:
this.state = CreditControlSessionState.PENDING_EVENT;
break;
case PENDING_BUFFERED:
this.state = CreditControlSessionState.PENDING_BUFFERED;
break;
case PENDING_TERMINATION:
this.state = CreditControlSessionState.PENDING_TERMINATION;
break;
case PENDING_UPDATE:
this.state = CreditControlSessionState.PENDING_UPDATE;
break;
case OPEN:
// FIXME: this should not happen?
this.state = CreditControlSessionState.OPEN;
break;
case PENDING_INITIAL:
this.state = CreditControlSessionState.PENDING_INITIAL;
break;
case IDLE:
this.state = CreditControlSessionState.IDLE;
ClientCCASessionState old = (ClientCCASessionState) oldState;
if (old == ClientCCASessionState.PENDING_EVENT) {
terminateAfterAnswer = true;
} else {
((CCASessionCreationListener) this.getSessionListener()).sessionDestroyed(sessionId, this);
this.session.release();
}
break;
default:
logger.error("Unexpected state in Credit-Control Client FSM: " + s);
}
}
private void validateState(CreditControlRequest ccr) {
//this is used for methods that send specific messages. should be done in jdiam, but there is not hook for it now.
if(ccr.getCcRequestType()==null)
{
throw new DiameterException("No request type is present!!");
}
int t = ccr.getCcRequestType().getValue();
CreditControlSessionState currentState = this.getState();
if(t == CcRequestType._INITIAL_REQUEST)
{
if(currentState!=CreditControlSessionState.IDLE )
{
//FIXME: change all exception to DiameterException
throw new DiameterException("Failed to validate, intial event, wrong state: "+currentState);
}
}else if(t == CcRequestType._UPDATE_REQUEST)
{
if(currentState!=CreditControlSessionState.OPEN )
{
//FIXME: change all exception to DiameterException
throw new DiameterException("Failed to validate, intial event, wrong state: "+currentState);
}
}else if(t == CcRequestType._TERMINATION_REQUEST)
{
if(currentState!=CreditControlSessionState.OPEN )
{
//FIXME: change all exception to DiameterException
throw new DiameterException("Failed to validate, intial event, wrong state: "+currentState);
}
}else if(t == CcRequestType._EVENT_REQUEST)
{
if(currentState!=CreditControlSessionState.IDLE )
{
//FIXME: change all exception to DiameterException
throw new DiameterException("Failed to validate, intial event, wrong state: "+currentState);
}
}
}
public boolean getTerminateAfterAnswer() {
return this.terminateAfterAnswer;
}
}