use of org.mobicents.charging.server.account.CreditControlUnit in project charging-server by RestComm.
the class DiameterChargingServerSbb method getRequestedUnits.
private ArrayList<CreditControlUnit> getRequestedUnits(RoCreditControlRequest ccr, RequestedServiceUnitAvp rsu, long[] serviceIds) {
ArrayList<CreditControlUnit> ccRequestedUnits = new ArrayList<CreditControlUnit>();
long requestedUnits = 0;
for (int i = 0; i < CcUnitType.values().length; i++) {
CcUnitType type = CcUnitType.fromInt(i);
// MONEY is not supported by 3GPP. TODO: Add support for non 3GPP ?
if (type == CcUnitType.MONEY) {
continue;
}
String methodName = "getCreditControl" + toCamelCase(type.toString());
try {
Method m = rsu.getClass().getMethod(methodName, new Class[0]);
requestedUnits = (Long) m.invoke(rsu, new Object[0]);
if (tracer.isInfoEnabled() && requestedUnits != Long.MIN_VALUE) {
tracer.info("[><] " + sidString + " Requested Units of type '" + type + "' in CCR = " + requestedUnits);
}
if (requestedUnits >= 0) {
CreditControlUnit ccUnit = new CreditControlUnit();
ccUnit.setUnitType(type);
if (performRating) {
double rateForService = getRateForService(ccr, serviceIds[0], type.getValue(), requestedUnits);
ccUnit.setRateForService(rateForService);
// FIXME: This is not right. Rating should convert to monetary units...
ccUnit.setRequestedAmount((long) Math.ceil(requestedUnits * rateForService));
} else {
ccUnit.setRequestedAmount(requestedUnits);
}
ccUnit.setRequestedUnits(requestedUnits);
ccRequestedUnits.add(ccUnit);
}
} catch (Exception e) {
tracer.severe("[xx] " + sidString + " Unable to retrieve/invoke '" + methodName + "' for extracting Requested Units of type " + type, e);
}
}
return ccRequestedUnits;
}
use of org.mobicents.charging.server.account.CreditControlUnit in project charging-server by RestComm.
the class DiameterChargingServerSbb method createCCA.
/**
* @param ccServerActivity
* @param request
* @param reservations
* @param resultCode
* @return
*/
private RoCreditControlAnswer createCCA(RoServerSessionActivity ccServerActivity, RoCreditControlRequest request, List<CreditControlInfo> reservations, long resultCode) {
RoCreditControlAnswer answer = ccServerActivity.createRoCreditControlAnswer();
// <Credit-Control-Answer> ::= < Diameter Header: 272, PXY >
// < Session-Id >
// { Result-Code }
answer.setResultCode(resultCode);
// *[ AVP ]
if (reservations != null && reservations.size() > 0) {
MultipleServicesCreditControlAvp[] reqMSCCs = request.getMultipleServicesCreditControls();
List<MultipleServicesCreditControlAvp> ansMSCCs = new ArrayList<MultipleServicesCreditControlAvp>();
for (int index = 0; index < reqMSCCs.length; index++) {
MultipleServicesCreditControlAvp reqMSCC = reqMSCCs[index];
MultipleServicesCreditControlAvp ansMscc = avpFactory.createMultipleServicesCreditControl();
ansMscc.setRatingGroup(reqMSCC.getRatingGroup());
ansMscc.setServiceIdentifiers(reqMSCC.getServiceIdentifiers());
// FIXME: Check how to handle this in case of MSCC if anything different is needed
CreditControlInfo ccInfo = reservations.get(reservations.size() - 1);
if (ccInfo.isSuccessful()) {
GrantedServiceUnitAvp gsu = avpFactory.createGrantedServiceUnit();
ArrayList<CreditControlUnit> ccUnits = ccInfo.getCcUnits();
for (int i = 0; i < ccUnits.size(); i++) {
CreditControlUnit ccUnit = ccUnits.get(i);
if (ccUnit.getUnitType() == CcUnitType.INPUT_OCTETS) {
gsu.setCreditControlInputOctets(ccUnit.getReservedUnits());
}
// TODO: Add CC-Money support if not 3GPP ?
if (ccUnit.getUnitType() == CcUnitType.OUTPUT_OCTETS) {
gsu.setCreditControlOutputOctets(ccUnit.getReservedUnits());
}
if (ccUnit.getUnitType() == CcUnitType.SERVICE_SPECIFIC_UNITS) {
gsu.setCreditControlServiceSpecificUnits(ccUnit.getReservedUnits());
}
if (ccUnit.getUnitType() == CcUnitType.TIME) {
gsu.setCreditControlTime(ccUnit.getReservedUnits());
}
if (ccUnit.getUnitType() == CcUnitType.TOTAL_OCTETS) {
gsu.setCreditControlTotalOctets(ccUnit.getReservedUnits());
}
}
ansMscc.setGrantedServiceUnit(gsu);
ansMscc.setResultCode(DiameterResultCode.DIAMETER_SUCCESS);
// If we are terminating gracefully we MAY include the Final-Unit-Indication
if (answer.getCcRequestType() == CcRequestType.TERMINATION_REQUEST) {
FinalUnitIndicationAvp fuiAvp = avpFactory.createFinalUnitIndication();
fuiAvp.setFinalUnitAction(FinalUnitActionType.TERMINATE);
ansMscc.setFinalUnitIndication(fuiAvp);
}
} else {
// In case it's not successful we want to have Final-Unit-Indication
FinalUnitIndicationAvp fuiAvp = avpFactory.createFinalUnitIndication();
fuiAvp.setFinalUnitAction(FinalUnitActionType.TERMINATE);
ansMscc.setFinalUnitIndication(fuiAvp);
ansMscc.setResultCode(resultCode);
}
ansMSCCs.add(ansMscc);
ansMscc.setValidityTime(DEFAULT_VALIDITY_TIME);
}
answer.setMultipleServicesCreditControls(ansMSCCs.toArray(new MultipleServicesCreditControlAvp[ansMSCCs.size()]));
}
if (tracer.isInfoEnabled()) {
tracer.info("[>>] " + sidString + " Created Credit-Control-Answer with Result-Code = " + answer.getResultCode() + ".");
if (tracer.isFineEnabled()) {
tracer.fine(answer.toString());
}
}
return answer;
}
use of org.mobicents.charging.server.account.CreditControlUnit in project charging-server by RestComm.
the class CDRGeneratorSbb method writeCDR.
public void writeCDR(UserSessionInfo sessionInfo) {
// Let's sum up the total used units and total used amount for the CDR.
ArrayList<CreditControlInfo> reserv = sessionInfo.getReservations();
long balanceBefore = 0;
long balanceAfter = 0;
long totalUsedUnitsInput = 0;
long totalUsedUnitsMoney = 0;
long totalUsedUnitsOutput = 0;
long totalUsedUnitsServiceSpecific = 0;
long totalUsedUnitsTime = 0;
long totalUsedUnitsTotal = 0;
long totalUsedAmountInput = 0;
long totalUsedAmountMoney = 0;
long totalUsedAmountOutput = 0;
long totalUsedAmountServiceSpecific = 0;
long totalUsedAmountTime = 0;
long totalUsedAmountTotal = 0;
for (int i = 0; i < reserv.size(); i++) {
CreditControlInfo ccI = reserv.get(i);
ArrayList<CreditControlUnit> ccUnits = ccI.getCcUnits();
for (int j = 0; j < ccUnits.size(); j++) {
CreditControlUnit ccUnit = ccUnits.get(j);
if (ccUnit.getUnitType() == CcUnitType.INPUT_OCTETS) {
totalUsedUnitsInput += ccUnit.getUsedUnits();
totalUsedAmountInput += ccUnit.getUsedAmount();
}
if (ccUnit.getUnitType() == CcUnitType.MONEY) {
totalUsedUnitsMoney += ccUnit.getUsedUnits();
totalUsedAmountMoney += ccUnit.getUsedAmount();
}
if (ccUnit.getUnitType() == CcUnitType.OUTPUT_OCTETS) {
totalUsedUnitsOutput += ccUnit.getUsedUnits();
totalUsedAmountOutput += ccUnit.getUsedAmount();
}
if (ccUnit.getUnitType() == CcUnitType.SERVICE_SPECIFIC_UNITS) {
totalUsedUnitsServiceSpecific += ccUnit.getUsedUnits();
totalUsedAmountServiceSpecific += ccUnit.getUsedAmount();
}
if (ccUnit.getUnitType() == CcUnitType.TIME) {
totalUsedUnitsTime += ccUnit.getUsedUnits();
totalUsedAmountTime += ccUnit.getUsedAmount();
}
if (ccUnit.getUnitType() == CcUnitType.TOTAL_OCTETS) {
totalUsedUnitsTotal += ccUnit.getUsedUnits();
totalUsedAmountTotal += ccUnit.getUsedAmount();
}
}
if (i == 0) {
balanceBefore = ccI.getBalanceBefore();
}
if (i == reserv.size() - 1) {
balanceAfter = ccI.getBalanceAfter();
}
}
/**
* Date Time of record (Format: yyyy-MM-dd'T'HH:mm:ss.SSSZ)
* Diameter Origin Host
* Diameter Origin Realm
* Diameter Destination Host
* Diameter Destination Realm
* Service IDs
* Session Start Time
* Current Time in milliseconds
* Session Duration
* SessionID
* Calling party type
* Calling party info
* Called party type
* Called party info
* Balance Before
* Balance After
* Total Input Octets Units Used
* Total Input Octets Amount Charged
* Total Money Units Used
* Total Money Amount Charged
* Total Output Octets Units Used
* Total Output Octets Amount Charged
* Total Service Specific Units Used
* Total Service Specific Amount Charged
* Total Time Units Used
* Total Time Amount Charged
* Total Total Octets Units Used
* Total Total Octets Amount Charged
* Event Type - Create/Interim/Terminate/Event (CDR's are only generated at Terminate for now)
* Number of events in this session
* Termination Cause
*/
StringBuffer cdr = new StringBuffer();
String DELIMITER = ";";
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
long elapsed = System.currentTimeMillis() - sessionInfo.getSessionStartTime();
try {
cdr.append(df.format(new Date())).append(DELIMITER);
cdr.append(sessionInfo.getCcr().getOriginHost()).append(DELIMITER);
cdr.append(sessionInfo.getCcr().getOriginRealm()).append(DELIMITER);
cdr.append(sessionInfo.getCcr().getDestinationHost()).append(DELIMITER);
cdr.append(sessionInfo.getCcr().getDestinationRealm()).append(DELIMITER);
cdr.append(Arrays.toString(sessionInfo.getServiceIds())).append(DELIMITER);
cdr.append(sessionInfo.getSessionStartTime()).append(DELIMITER);
cdr.append(System.currentTimeMillis()).append(DELIMITER);
cdr.append(elapsed).append(DELIMITER);
cdr.append(sessionInfo.getCcr().getSessionId()).append(DELIMITER);
cdr.append(sessionInfo.getEndUserType().getValue()).append(DELIMITER);
cdr.append(sessionInfo.getEndUserId()).append(DELIMITER);
// TODO: Get Destination Subscription ID Type and Value if available
cdr.append(sessionInfo.getEndUserType().getValue()).append(DELIMITER);
cdr.append(sessionInfo.getEndUserId()).append(DELIMITER);
cdr.append(balanceBefore).append(DELIMITER);
cdr.append(balanceAfter).append(DELIMITER);
cdr.append(totalUsedUnitsInput).append(DELIMITER);
cdr.append(totalUsedAmountInput).append(DELIMITER);
cdr.append(totalUsedUnitsMoney).append(DELIMITER);
cdr.append(totalUsedAmountMoney).append(DELIMITER);
cdr.append(totalUsedUnitsOutput).append(DELIMITER);
cdr.append(totalUsedAmountOutput).append(DELIMITER);
cdr.append(totalUsedUnitsServiceSpecific).append(DELIMITER);
cdr.append(totalUsedAmountServiceSpecific).append(DELIMITER);
cdr.append(totalUsedUnitsTime).append(DELIMITER);
cdr.append(totalUsedAmountTime).append(DELIMITER);
cdr.append(totalUsedUnitsTotal).append(DELIMITER);
cdr.append(totalUsedAmountTotal).append(DELIMITER);
// FIXME? cdr.append(storedCCR.getCcRequestType().getValue()).append(DELIMITER);
cdr.append(sessionInfo.getReservations().size()).append(DELIMITER);
// FIXME? cdr.append(storedCCR.getTerminationCause()).append(DELIMITER);
} catch (Exception e) {
tracer.warning("Failure while trying to generate CDR");
}
// TODO: Use a different logger.
if (tracer.isInfoEnabled()) {
tracer.info(cdr.toString());
}
}
use of org.mobicents.charging.server.account.CreditControlUnit in project charging-server by RestComm.
the class DirectDebitUnitsJdbcTask method executeSimple.
@Override
public Object executeSimple(JdbcTaskContext taskContext) {
try {
long balance = 0;
// get Balance Before (can this be made more efficient?)
PreparedStatement preparedStatement = taskContext.getConnection().prepareStatement(DataSourceSchemaInfo._QUERY_SELECT);
preparedStatement.setString(1, msisdn);
preparedStatement.execute();
ResultSet resultSet = preparedStatement.getResultSet();
while (resultSet.next()) {
balance = resultSet.getLong(DataSourceSchemaInfo._COL_BALANCE);
ccInfo.setBalanceBefore(balance);
}
for (CreditControlUnit ccUnit : ccUnits) {
long reservedAmount = ccUnit.getReservedAmount();
long usedAmount = ccUnit.getUsedAmount();
long requestedAmount = ccUnit.getRequestedAmount();
long requestedUnits = ccUnit.getRequestedUnits();
if (balance < requestedAmount) {
accountData = new UserAccountData();
accountData.setMsisdn(msisdn);
accountData.setBalance(0);
accountData.setFailure(true);
ccUnit.setReservedUnits(0);
ccUnit.setReservedAmount(0);
if (tracer.isInfoEnabled()) {
tracer.info("[//] User does not have sufficient balance for reservation. Balance available: " + balance + ".");
}
break;
} else if (balance > requestedAmount) {
int n = 1;
tracer.info(("[//] Executing DB Statement '" + DataSourceSchemaInfo._QUERY_DEBIT).replaceFirst("\\?", String.valueOf(requestedAmount)).replaceFirst("\\?", msisdn));
preparedStatement = taskContext.getConnection().prepareStatement(DataSourceSchemaInfo._QUERY_DEBIT);
preparedStatement.setLong(n++, requestedAmount);
preparedStatement.setString(n++, msisdn);
accountData = new UserAccountData();
accountData.setMsisdn(msisdn);
if (preparedStatement.executeUpdate() == 1) {
// ok great, we have successfully reserved the units
preparedStatement = taskContext.getConnection().prepareStatement(DataSourceSchemaInfo._QUERY_SELECT);
preparedStatement.setString(1, msisdn);
// tracer.info(("[//] Executing DB Statement '" + DataSourceSchemaInfo._QUERY_SELECT).replaceFirst("\\?", msisdn));
preparedStatement.execute();
resultSet = preparedStatement.getResultSet();
while (resultSet.next()) {
balance = resultSet.getLong(DataSourceSchemaInfo._COL_BALANCE);
accountData.setBalance(balance);
accountData.setFailure(false);
ccUnit.setReservedUnits(requestedUnits);
ccUnit.setReservedAmount(requestedAmount);
ccInfo.setBalanceAfter(balance);
}
} else {
// check what kind of error happened
accountData.setBalance(0);
accountData.setFailure(true);
ccUnit.setReservedUnits(0);
ccUnit.setReservedAmount(0);
}
}
}
} catch (Exception e) {
tracer.severe("[xx] Failed to execute task to Reserve Units for MSISDN '" + msisdn + "'", e);
}
return this;
}
use of org.mobicents.charging.server.account.CreditControlUnit in project charging-server by RestComm.
the class DiameterChargingServerSbb method onCreditControlRequest.
public void onCreditControlRequest(RoCreditControlRequest ccr, ActivityContextInterface aci) {
String serviceContextId = "Some-Service-Context-Id";
String sessionId = ccr.getSessionId();
UserSessionInfo sessionInfo = getSessionInfo();
if (sessionInfo == null) {
sessionInfo = new UserSessionInfo();
sessionInfo.setSessionStartTime(System.currentTimeMillis());
}
sessionInfo.setCcr(ccr);
sessionInfo.setSessionId(sessionId);
setSessionInfo(sessionInfo);
String reqType = ccr.getCcRequestType().toString();
long reqNumber = ccr.getCcRequestNumber();
sidString = "SID<" + limitString(sessionId, 9, 9, "..") + "/" + reqType.substring(0, 3) + "#" + reqNumber + ">";
if (tracer.isInfoEnabled()) {
tracer.info("[<<] " + sidString + " Received Credit-Control-Request [" + reqType + "]");
if (tracer.isFineEnabled()) {
tracer.fine(ccr.toString());
}
}
// Some common ops. may be moved to proper places to avoid unnecessary ops
RoServerSessionActivity ccServerActivity = (RoServerSessionActivity) aci.getActivity();
SubscriptionIdType endUserType = null;
String endUserId = null;
// Get the Subscription-Id and it's Type .. for now we only care for first, still we log all
SubscriptionIdAvp[] subscriptionIds = ccr.getSubscriptionIds();
RoCreditControlAnswer cca = null;
if (subscriptionIds != null && subscriptionIds.length > 0) {
endUserType = subscriptionIds[0].getSubscriptionIdType();
endUserId = subscriptionIds[0].getSubscriptionIdData();
if (tracer.isFineEnabled()) {
String subsIdsStr = "";
for (SubscriptionIdAvp subscriptionId : subscriptionIds) {
subsIdsStr += subscriptionId.getSubscriptionIdType() + "=" + subscriptionId.getSubscriptionIdData() + " ";
}
tracer.fine("[--] " + sidString + " Received CCR has Subcription-Id(s): " + subsIdsStr.substring(0, subsIdsStr.length() - 1));
}
} else {
tracer.severe("[xx] " + sidString + " Subscription-Id AVP missing in CCR. Rejecting CCR.");
cca = createCCA(ccServerActivity, ccr, null, DiameterResultCode.DIAMETER_MISSING_AVP);
sendCCA(cca, aci, true);
return;
}
if (endUserId == null) {
tracer.severe("[xx] " + sidString + " Subscription-Id AVP is present but could not read it's data. Rejecting CCR.");
cca = createCCA(ccServerActivity, ccr, null, DiameterResultCode.DIAMETER_MISSING_AVP);
sendCCA(cca, aci, true);
return;
}
// Retrieve child SBBs
try {
accountBalanceManagement = getAccountManager();
ratingEngineManagement = getRatingEngineManager();
cdrGenerator = getCDRGenerator();
} catch (Exception e) {
// TODO: By configuration it should be possible to proceed
tracer.severe("[xx] " + sidString + " Unable to retrieve Account & Balance Management or Rating Child SBB. Unable to continue.", e);
cca = createCCA(ccServerActivity, ccr, new ArrayList<CreditControlInfo>(), DiameterResultCode.DIAMETER_UNABLE_TO_COMPLY);
sendCCA(cca, aci, true);
}
switch(ccr.getCcRequestType()) {
// INITIAL_REQUEST 1
case INITIAL_REQUEST:
// UPDATE_REQUEST 2
case UPDATE_REQUEST:
try {
// retrieve service information from AVPs
serviceContextId = ccr.getServiceContextId();
if (serviceContextId == null) {
tracer.severe("[xx] " + sidString + " Service-Context-Id AVP missing in CCR. Rejecting CCR.");
// TODO: include missing avp - its a "SHOULD"
cca = createCCA(ccServerActivity, ccr, null, DiameterResultCode.DIAMETER_MISSING_AVP);
sendCCA(cca, aci, true);
} else {
if (serviceContextId.equals("")) {
tracer.severe("[xx] " + sidString + " Service-Context-Id AVP is empty in CCR. Rejecting CCR.");
cca = createCCA(ccServerActivity, ccr, null, DiameterResultCode.DIAMETER_INVALID_AVP_VALUE);
sendCCA(cca, aci, true);
}
}
// TODO: For Ro, support Service-Information AVP
List<CreditControlInfo> reservations = new ArrayList<CreditControlInfo>();
long resultCode = DiameterResultCode.DIAMETER_SUCCESS;
MultipleServicesCreditControlAvp[] multipleServicesCreditControlAvps = ccr.getMultipleServicesCreditControls();
if (multipleServicesCreditControlAvps != null && tracer.isFineEnabled()) {
tracer.fine("[--] " + sidString + " Received CCR has Multiple-Services-Credit-Control AVP with length = " + multipleServicesCreditControlAvps.length);
}
// If there's no MSCC AVP, we'll create one, just to go inside the for and have it processed..
if (multipleServicesCreditControlAvps.length == 0) {
MultipleServicesCreditControlAvp fakeMSCC = avpFactory.createMultipleServicesCreditControl();
fakeMSCC.setServiceIdentifier(0);
RequestedServiceUnitAvp rsu = avpFactory.createRequestedServiceUnit();
rsu.setCreditControlTotalOctets(0);
fakeMSCC.setRequestedServiceUnit(rsu);
multipleServicesCreditControlAvps = new MultipleServicesCreditControlAvp[] { fakeMSCC };
}
// single rating group.
for (MultipleServicesCreditControlAvp mscc : multipleServicesCreditControlAvps) {
// The Service-Identifier and the Rating-Group AVPs are used to associate the granted units to a
// given service or rating group. If both the Service-Identifier and the Rating-Group AVPs are
// included, the target of the service units is always the service(s) indicated by the value of the
// Service-Identifier AVP(s). If only the Rating-Group-Id AVP is present, the Multiple-Services-
// -Credit-Control AVP relates to all the services that belong to the specified rating group.
long ratingGroup = mscc.getRatingGroup();
long[] serviceIds = mscc.getServiceIdentifiers();
// The Requested-Service-Unit AVP MAY contain the amount of requested service units [...]. It MUST
// be present in the initial interrogation and within the intermediate interrogations in which new
// quota is requested. If the credit-control client does not include the Requested-Service-Unit AVP
// in a request command, because for instance, it has determined that the end-user terminated the
// service, the server MUST debit the used amount from the user's account but MUST NOT return a new
// quota in the corresponding answer.
RequestedServiceUnitAvp rsu = mscc.getRequestedServiceUnit();
ArrayList<CreditControlUnit> ccUnits = getRequestedUnits(ccr, rsu, serviceIds);
// if its UPDATE, lets first update data
if (ccr.getCcRequestType() == CcRequestType.UPDATE_REQUEST) {
// update used units for each CC-Type.
UsedServiceUnitAvp[] usedUnitsAvps = mscc.getUsedServiceUnits();
sessionInfo = getSessionInfo();
CreditControlInfo reservedInfo = sessionInfo.getReservations().get(sessionInfo.getReservations().size() - 1);
ArrayList<CreditControlUnit> usedCCUnits = collectUsedUnits(usedUnitsAvps, reservedInfo.getCcUnits());
// Merge Requested with Used/Reserved CC Units into a single CCUnits
ccUnits.addAll(usedCCUnits);
// Call ABMF with this Credit Control Info
CreditControlInfo ccInfo = buildCCInfo(ccr, endUserId, endUserType, ccUnits);
accountBalanceManagement.updateRequest(ccInfo);
} else {
// Initial Request
// Call ABMF with this Credit Control Info
CreditControlInfo ccInfo = buildCCInfo(ccr, endUserId, endUserType, ccUnits);
accountBalanceManagement.initialRequest(ccInfo);
}
// Store Credit Control Info in CMP
sessionInfo = getSessionInfo();
sessionInfo.setCcr(ccr);
sessionInfo.setServiceIds(serviceIds);
sessionInfo.setEndUserId(endUserId);
sessionInfo.setEndUserType(endUserType);
setSessionInfo(sessionInfo);
// we'll continue @ resumeOnCreditControlRequest(..)
return;
}
if (reservations.size() > 0) {
cca = createCCA(ccServerActivity, ccr, reservations, resultCode);
} else {
cca = createCCA(ccServerActivity, ccr, null, DiameterResultCode.DIAMETER_MISSING_AVP);
}
sendCCA(cca, aci, false);
} catch (Exception e) {
tracer.severe("[xx] " + sidString + " Failure processing Credit-Control-Request [" + (ccr.getCcRequestType() == CcRequestType.INITIAL_REQUEST ? "INITIAL" : "UPDATE") + "]", e);
}
break;
// TERMINATION_REQUEST 3
case TERMINATION_REQUEST:
try {
if (tracer.isInfoEnabled()) {
tracer.info("[>>] " + sidString + " '" + endUserId + "' requested service termination for '" + serviceContextId + "'.");
}
for (MultipleServicesCreditControlAvp mscc : ccr.getMultipleServicesCreditControls()) {
UsedServiceUnitAvp[] usedUnitsAvps = mscc.getUsedServiceUnits();
sessionInfo = getSessionInfo();
CreditControlInfo reservedInfo = sessionInfo.getReservations().get(sessionInfo.getReservations().size() - 1);
ArrayList<CreditControlUnit> ccUnits = collectUsedUnits(usedUnitsAvps, reservedInfo.getCcUnits());
// Call ABMF with this Credit Control Info
CreditControlInfo ccInfo = buildCCInfo(ccr, endUserId, endUserType, ccUnits);
accountBalanceManagement.terminateRequest(ccInfo);
// we'll continue @ resumeOnCreditControlRequest(..)
return;
}
// 8.7. Cost-Information AVP
//
// The Cost-Information AVP (AVP Code 423) is of type Grouped, and it is
// used to return the cost information of a service, which the credit-
// control client can transfer transparently to the end user. The
// included Unit-Value AVP contains the cost estimate (always type of
// money) of the service, in the case of price enquiry, or the
// accumulated cost estimation, in the case of credit-control session.
//
// The Currency-Code specifies in which currency the cost was given.
// The Cost-Unit specifies the unit when the service cost is a cost per
// unit (e.g., cost for the service is $1 per minute).
//
// When the Requested-Action AVP with value PRICE_ENQUIRY is included in
// the Credit-Control-Request command, the Cost-Information AVP sent in
// the succeeding Credit-Control-Answer command contains the cost
// estimation of the requested service, without any reservation being
// made.
//
// The Cost-Information AVP included in the Credit-Control-Answer
// command with the CC-Request-Type set to UPDATE_REQUEST contains the
// accumulated cost estimation for the session, without taking any
// credit reservation into account.
//
// The Cost-Information AVP included in the Credit-Control-Answer
// command with the CC-Request-Type set to EVENT_REQUEST or
// TERMINATION_REQUEST contains the estimated total cost for the
// requested service.
//
// It is defined as follows (per the grouped-avp-def of
// RFC 3588 [DIAMBASE]):
//
// Cost-Information ::= < AVP Header: 423 >
// { Unit-Value }
// { Currency-Code }
// [ Cost-Unit ]
// 7.2.133 Remaining-Balance AVP
//
// The Remaining-Balance AVP (AVPcode 2021) is of type Grouped and
// provides information about the remaining account balance of the
// subscriber.
//
// It has the following ABNF grammar:
// Remaining-Balance :: = < AVP Header: 2021 >
// { Unit-Value }
// { Currency-Code }
// We use no money notion ... maybe later.
// AvpSet costInformation = ccaAvps.addGroupedAvp(423);
// Answer with DIAMETER_SUCCESS, since "4) The default action for failed operations should be to terminate the data session"
// its terminated, we cant do much here...
cca = createCCA(ccServerActivity, ccr, null, DiameterResultCode.DIAMETER_SUCCESS);
sendCCA(cca, aci, true);
} catch (Exception e) {
tracer.severe("[xx] " + sidString + " Failure processing Credit-Control-Request [TERMINATION]", e);
}
break;
// EVENT_REQUEST 4
case EVENT_REQUEST:
try {
RequestedActionType reqAction = ccr.getRequestedAction();
if (tracer.isInfoEnabled()) {
tracer.info("[<<] " + sidString + " Received Credit-Control-Request [EVENT] with Requested-Action [" + reqAction + "]");
if (tracer.isFineEnabled()) {
tracer.fine(ccr.toString());
}
}
if (reqAction == null) {
tracer.severe("[xx] " + sidString + " Unable to retrieve Requested-Action AVP. Replying with MISSING_AVP.");
createCCA(ccServerActivity, ccr, new ArrayList<CreditControlInfo>(), DiameterResultCode.DIAMETER_MISSING_AVP);
sendCCA(cca, aci, true);
} else if (reqAction == RequestedActionType.DIRECT_DEBITING) {
for (MultipleServicesCreditControlAvp mscc : ccr.getMultipleServicesCreditControls()) {
RequestedServiceUnitAvp rsu = mscc.getRequestedServiceUnit();
long[] serviceIds = mscc.getServiceIdentifiers();
ArrayList<CreditControlUnit> ccUnits = getRequestedUnits(ccr, rsu, serviceIds);
// Call ABMF with this Credit Control Info
CreditControlInfo ccInfo = buildCCInfo(ccr, endUserId, endUserType, ccUnits);
accountBalanceManagement.eventRequest(ccInfo);
// Store Credit Control Info in CMP
sessionInfo = getSessionInfo();
sessionInfo.setCcr(ccr);
sessionInfo.setEndUserId(endUserId);
// sessionInfo.getReservations().add(ccInfo);
setSessionInfo(sessionInfo);
if (tracer.isInfoEnabled()) {
tracer.info(sessionInfo.toString());
}
// we'll continue @ resumeOnCreditControlRequest(..)
return;
}
} else {
tracer.severe("[xx] " + sidString + " Unsupported Requested-Action AVP (" + reqAction + "). Replying with DIAMETER_UNABLE_TO_COMPLY.");
createCCA(ccServerActivity, ccr, new ArrayList<CreditControlInfo>(), DiameterResultCode.DIAMETER_UNABLE_TO_COMPLY);
sendCCA(cca, aci, true);
}
} catch (Exception e) {
tracer.severe("[xx] " + sidString + " Failure processing Credit-Control-Request [EVENT]", e);
}
break;
default:
tracer.warning("[xx] " + sidString + " Unknown request type found!");
break;
}
}
Aggregations