Revision: 6c0c4d7dd521
Author:   Alexandre Mendonça <ammendonca>
Date:     Wed Jan  2 08:30:17 2013
Log:      Improvements to Charging Server Core SBB and ABMF SBB

http://code.google.com/p/charging-server/source/detail?r=6c0c4d7dd521

Added:
 /sbb/src/main/resources/users.properties
Modified:
/sbb/src/main/java/org/mobicents/charging/server/DiameterChargingServerSbb.java /sbb/src/main/java/org/mobicents/charging/server/account/AccountBalanceManagement.java /sbb/src/main/java/org/mobicents/charging/server/account/AccountBalanceManagementSbb.java
 /sbb/src/main/resources/META-INF/sbb-jar.xml

=======================================
--- /dev/null
+++ /sbb/src/main/resources/users.properties    Wed Jan  2 08:30:17 2013
@@ -0,0 +1,11 @@
+# MSISDN = Balance (octets)
+351910000000 = 1073741824
+351911111111 = 1073741824
+351912222222 = 1073741824
+351913333333 = 1073741824
+351914444444 = 1073741824
+351915555555 = 1073741824
+351916666666 = 1073741824
+351917777777 = 1073741824
+351918888888 = 1073741824
+351919999999 = 1073741824
=======================================
--- /sbb/src/main/java/org/mobicents/charging/server/DiameterChargingServerSbb.java Wed Dec 5 09:26:03 2012 +++ /sbb/src/main/java/org/mobicents/charging/server/DiameterChargingServerSbb.java Wed Jan 2 08:30:17 2013
@@ -24,7 +24,9 @@

 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
+import java.util.Properties;

 import javax.slee.ActivityContextInterface;
 import javax.slee.ChildRelation;
@@ -42,14 +44,13 @@
 import javax.slee.resource.ResourceAdaptorTypeID;
 import javax.slee.serviceactivity.ServiceStartedEvent;

-import net.java.slee.resource.diameter.base.events.avp.DiameterAvp;
 import net.java.slee.resource.diameter.base.events.avp.DiameterResultCode;
 import net.java.slee.resource.diameter.cca.events.avp.CcRequestType;
import net.java.slee.resource.diameter.cca.events.avp.CreditControlResultCode; import net.java.slee.resource.diameter.cca.events.avp.GrantedServiceUnitAvp; import net.java.slee.resource.diameter.cca.events.avp.MultipleServicesCreditControlAvp; +import net.java.slee.resource.diameter.cca.events.avp.RequestedServiceUnitAvp;
 import net.java.slee.resource.diameter.cca.events.avp.SubscriptionIdAvp;
-import net.java.slee.resource.diameter.cca.events.avp.SubscriptionIdType;
 import net.java.slee.resource.diameter.cca.events.avp.UsedServiceUnitAvp;
import net.java.slee.resource.diameter.ro.RoActivityContextInterfaceFactory;
 import net.java.slee.resource.diameter.ro.RoAvpFactory;
@@ -57,10 +58,7 @@
 import net.java.slee.resource.diameter.ro.RoServerSessionActivity;
 import net.java.slee.resource.diameter.ro.events.RoCreditControlAnswer;
 import net.java.slee.resource.diameter.ro.events.RoCreditControlRequest;
-import net.java.slee.resource.diameter.ro.events.avp.PsInformation;
-import net.java.slee.resource.diameter.ro.events.avp.ServiceInformation;

-import org.jdiameter.api.ResultCode;
 import org.mobicents.charging.server.account.AccountBalanceManagement;
 import org.mobicents.charging.server.account.UnitReservation;
 import org.mobicents.charging.server.account.UnitReservation.ErrorCodeType;
@@ -132,19 +130,11 @@

// --------------------------------- IES ---------------------------------- public InitialEventSelector onCreditControlRequestInitialEventSelect(InitialEventSelector ies) {
-               //TODO: verify if this is correct.
                RoCreditControlRequest event = (RoCreditControlRequest) 
ies.getEvent();
- String endUserE164 = null; // FIXME: Use as number instead of String for better perf... if needed.
-               for (SubscriptionIdAvp subscriptionId : 
event.getSubscriptionIds()) {
- if (subscriptionId.getSubscriptionIdType() == SubscriptionIdType.END_USER_E164) {
-                               endUserE164 = 
subscriptionId.getSubscriptionIdData();
-                       }
-               }
+               RoCreditControlRequest ccr = event;

-               if (endUserE164 != null) {
-                       ies.setCustomName(event.getSessionId());
-                       ies.setInitialEvent(true);
-               }
+               ies.setCustomName(event.getSessionId());
+               ies.setInitialEvent(true);

                return ies;
        }
@@ -200,15 +190,43 @@
tracer.info("== http://www.telestax.com/ =="); tracer.info("==============================================================================");
                }
+
+    AccountBalanceManagement am;
+    try {
+      am = getAccountManager();
+    }
+    catch (Exception e) {
+ tracer.severe(" [xx] Unable to fetch Account and Balance Management Child SBB .");
+      return;
+    }
+
+    try {
+      Properties props = new Properties();
+ props.load(this.getClass().getClassLoader().getResourceAsStream("users.properties"));
+      for (Object key : props.keySet()) {
+        String msisdn = (String) key;
+        am.addUser(msisdn, Long.valueOf(props.getProperty(msisdn)));
+      }
+ tracer.info(" [--] Loaded users from properties file. Dumping state.");
+      am.dump(".*");
+    }
+    catch(Exception e) {
+ tracer.warning(" [!!] Unable to load users from properties file. Allowing everything!");
+      am.setBypass(true);
+    }
        }

public void onCreditControlRequest(RoCreditControlRequest ccr, ActivityContextInterface aci) {
-
                String serviceContextId = "Some-Service-Context-Id";

                String sessionId = ccr.getSessionId();

- // Some common ops. may be moved to proper places to avoid unnecessary ops
+    if (tracer.isInfoEnabled()) {
+ tracer.info(" [<<] SID<" + ccr.getSessionId() + "> Received Credit-Control-Request [" + ccr.getCcRequestType().toString() + "]");
+      //tracer.info(event.toString());
+    }
+
+ // Some common ops. may be moved to proper places to avoid unnecessary ops RoServerSessionActivity ccServerActivity = (RoServerSessionActivity) aci.getActivity();

                String endUserId = null;
@@ -221,17 +239,18 @@
                        if (tracer.isInfoEnabled()) {
                                for (SubscriptionIdAvp subscriptionId : 
subscriptionIds) {
tracer.info(" [--] SID<" + sessionId + "> Received CCR has Subcription-Id with type '" + subscriptionId. - getSubscriptionIdType() + "' and data '" + subscriptionId.getSubscriptionIdData() + "'."); + getSubscriptionIdType() + "' and value '" + subscriptionId.getSubscriptionIdData() + "'.");
                                }
                        }
                }
                else {
tracer.severe(" [xx] SID<" + sessionId + "> Subscription-Id AVP missing in CCR. Rejecting CCR.");
-                       createCCA(ccServerActivity, ccr, null, 
ResultCode.MISSING_AVP);
+ createCCA(ccServerActivity, ccr, null, DiameterResultCode.DIAMETER_MISSING_AVP);
                }

                RoCreditControlAnswer cca = null;
                if (endUserId == null) {
+ tracer.severe(" [xx] SID<" + sessionId + "> Subscription-Id AVP is present but could not read it's data. Rejecting CCR."); cca = createCCA(ccServerActivity, ccr, null, DiameterResultCode.DIAMETER_MISSING_AVP); //TODO: include missing avp - its a "SHOULD"
                        try {
                                ccServerActivity.sendRoCreditControlAnswer(cca);
@@ -243,31 +262,39 @@
                        return;
                }

+               AccountBalanceManagement accountBalanceManagement = null;

                switch (ccr.getCcRequestType()) {
                // INITIAL_REQUEST 1
                case INITIAL_REQUEST:
                        // UPDATE_REQUEST 2
                case UPDATE_REQUEST:
-                       if (tracer.isInfoEnabled()) {
- tracer.info(" [<<] SID<" + sessionId + "> Received Credit-Control-Request [" + (ccr.getCcRequestType() == CcRequestType.INITIAL_REQUEST ? "INITIAL" : "UPDATE") + "]");
-                       }
-
-                       if (tracer.isFineEnabled()) {
-                               tracer.fine(ccr.toString());
-                       }

- timerFacility.setTimer(aci, null, System.currentTimeMillis() + 15000, DEFAULT_TIMER_OPTIONS); + timerFacility.setTimer(aci, null, System.currentTimeMillis() + 15000, DEFAULT_TIMER_OPTIONS);

-                       // In any case it will iterate only once.... WHY MSCC 
is used...
                        try {
+                               accountBalanceManagement = getAccountManager();
+
+                               // retrieve service information from AVPs
+                               serviceContextId = ccr.getServiceContextId();
+                               if (serviceContextId == null) {
+ tracer.severe(" [xx] SID<" + sessionId + "> Service-Context-Id AVP missing in CCR. Rejecting CCR."); + createCCA(ccServerActivity, ccr, null, DiameterResultCode.DIAMETER_MISSING_AVP);
+                               }
+                               else {
+                                 if (serviceContextId.equals("")) {
+ tracer.severe(" [xx] SID<" + sessionId + "> Service-Context-Id AVP is empty in CCR. Rejecting CCR."); + createCCA(ccServerActivity, ccr, null, DiameterResultCode.DIAMETER_INVALID_AVP_VALUE);
+                                 }
+                               }
+
+                               // TODO: For Ro, support Service-Information AVP

- AccountBalanceManagement accountBalanceManagement = getAccountManager();
-                               ServiceInformation serviceInformationAvp = 
ccr.getServiceInformation();
                                long reqNumber = ccr.getCcRequestNumber();
+                               List<UnitReservation> reservations = new 
ArrayList<UnitReservation>();
+                               long resultCode = 
DiameterResultCode.DIAMETER_SUCCESS;
+
MultipleServicesCreditControlAvp[] multipleServicesCreditControlAvps = ccr.getMultipleServicesCreditControls();
-                               List<UnitReservation> reservations = new 
ArrayList<UnitReservation>();
-                               long resultCode = 2001;
for (MultipleServicesCreditControlAvp mscc : multipleServicesCreditControlAvps) { long requestedUnits = mscc.getRequestedServiceUnit().getCreditControlTotalOctets(); // FIXME: No diff between IN/OUT, from docs it seems

@@ -286,58 +313,24 @@
unitReservation = accountBalanceManagement.updateRequest(sessionId, endUserId, requestedUnits, usedUnitsCount, (int)ccr.getCcRequestNumber()); //...
                                        }
                                        else {
-                                               //its initial
- if (serviceInformationAvp == null || serviceInformationAvp.getPsInformation() == null) { - cca = createCCA(ccServerActivity, ccr, null,DiameterResultCode.DIAMETER_MISSING_AVP); //TODO: include this avp - its a "SHOULD"
-                                                       try {
-                                                               
ccServerActivity.sendRoCreditControlAnswer(cca);
-                                                       }
-                                                       catch (IOException e) {
-                                                               // TODO 
Auto-generated catch block
-                                                               
e.printStackTrace();
-                                                       }
-                                                       
aci.detach(this.getSbbContext().getSbbLocalObject());
-                                                       return;
-                                               }
- PsInformation psInformation = serviceInformationAvp.getPsInformation();
-                                               String tgppSgsnMccMnc = 
psInformation.getTgppSgsnMccMnc();
-                                               String calledStationId = null;
-                                               //rel 7... no called-station-Id
-                                               DiameterAvp[] avps = 
psInformation.getExtensionAvps();
-                                               for (DiameterAvp avp : avps) {
-                                                       if (avp.getCode() == 
30) {
-                                                               calledStationId 
= avp.octetStringValue();
-                                                       }
-                                               }
-                                               if (calledStationId == null || 
tgppSgsnMccMnc == null) {
- cca = createCCA(ccServerActivity, ccr, null,DiameterResultCode.DIAMETER_MISSING_AVP); //TODO: include this avp - its a "SHOULD"
-                                                       try {
-                                                               
ccServerActivity.sendRoCreditControlAnswer(cca);
-                                                       }
-                                                       catch (IOException e) {
-                                                               // TODO 
Auto-generated catch block
-                                                               
e.printStackTrace();
-                                                       }
-                                                       
aci.detach(this.getSbbContext().getSbbLocalObject());
-                                                       return;
-                                               }
+                                               // Initial Request
unitReservation = accountBalanceManagement.initialRequest(sessionId, endUserId, requestedUnits/*, tgppSgsnMccMnc, calledStationId, ccr.getDestinationHost().toString()*/);
                                        }

                                        //if its update
                                        if (tracer.isInfoEnabled()) {
- tracer.info(" [>>] SID<" + ccr.getSessionId() + "> '" + endUserId + "' REQUESTED " + requestedUnits + " octets for '" + serviceIds + "'."); + tracer.info(" [>>] SID<" + ccr.getSessionId() + "> '" + endUserId + "' REQUESTED " + requestedUnits + " octets for '" + Arrays.toString(serviceIds) + "'.");
                                        }

                                        reservations.add(unitReservation);

                                        if (unitReservation.isSuccess()) {
- tracer.info(" [>>] SID<" + ccr.getSessionId() + "> '" + endUserId + "' GRANTED " + requestedUnits + " octets for '" + serviceIds + "'."); + tracer.info(" [>>] SID<" + ccr.getSessionId() + "> '" + endUserId + "' GRANTED " + requestedUnits + " octets for '" + Arrays.toString(serviceIds) + "'.");
                                        }
                                        else {
- tracer.info(" [>>] SID<" + ccr.getSessionId() + "> '" + endUserId + "' DENIED " + requestedUnits + " octets for '" + serviceIds + "'."); + tracer.info(" [>>] SID<" + ccr.getSessionId() + "> '" + endUserId + "' DENIED " + requestedUnits + " octets for '" + Arrays.toString(serviceIds) + "'.");
                                                if 
(CcRequestType.UPDATE_REQUEST == ccr.getCcRequestType()) {
- accountBalanceManagement.terminateRequest(sessionId, endUserId, 0L,usedUnitsCount , (int)ccr.getCcRequestNumber()); + accountBalanceManagement.updateRequest(sessionId, endUserId, 0L,usedUnitsCount , (int)ccr.getCcRequestNumber());
                                                }
                                                resultCode = 
getResultCode(unitReservation.getErrorCodeType());
                                        }
@@ -358,25 +351,22 @@
                        break;
                        // TERMINATION_REQUEST 3
                case TERMINATION_REQUEST:
-                       if (tracer.isInfoEnabled()) {
- tracer.info(" [<<] SID<" + ccr.getSessionId() + "> Received Credit-Control-Request [TERMINATION]");
-                               //tracer.info(event.toString());
-                       }
                        try {

                                if (tracer.isInfoEnabled()) {
tracer.info(" [>>] SID<" + ccr.getSessionId() + "> '" + endUserId + "' requested service termination for '" + serviceContextId + "'.");
                                }
- AccountBalanceManagement accountBalanceManagement = getAccountManager();
+                               accountBalanceManagement = getAccountManager();
                                List<UnitReservation> reservations = new 
ArrayList<UnitReservation>();

for (MultipleServicesCreditControlAvp mscc : ccr.getMultipleServicesCreditControls()) { - long requestedUnits = mscc.getRequestedServiceUnit().getCreditControlTotalOctets(); // FIXME: No diff between IN/OUT, from docs it seems
+                                 RequestedServiceUnitAvp rsu = 
mscc.getRequestedServiceUnit();
+ long requestedUnits = rsu != null ? rsu.getCreditControlTotalOctets() : 0; // FIXME: No diff between IN/OUT, from docs it seems

                                        long[] serviceIds = 
mscc.getServiceIdentifiers();

                                        if (tracer.isInfoEnabled()) {
- tracer.info(" [>>] SID<" + ccr.getSessionId() + "> '" + endUserId + "' requested " + requestedUnits + " octets for '" + serviceIds + "'."); + tracer.info(" [>>] SID<" + ccr.getSessionId() + "> '" + endUserId + "' requested " + requestedUnits + " octets for '" + Arrays.toString(serviceIds) + "'.");
                                        }

                                        // TODO: update used units.
@@ -448,7 +438,7 @@
                                // We use no money notion ... maybe later.
                                // AvpSet costInformation = 
ccaAvps.addGroupedAvp(423);
//always 2001 - 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, 
2001);
+ cca = createCCA(ccServerActivity, ccr, null, DiameterResultCode.DIAMETER_SUCCESS);
                                ccServerActivity.sendRoCreditControlAnswer(cca);
                        }
                        catch (Exception e) {
@@ -469,6 +459,9 @@
                default:
                        break;
                }
+
+               // dump user status
+               accountBalanceManagement.dump(endUserId);
        }

        public void onTimerEvent(TimerEvent timer, ActivityContextInterface 
aci) {
@@ -551,7 +544,7 @@
                                        GrantedServiceUnitAvp gsu = 
avpFactory.createGrantedServiceUnit();
                                        
gsu.setCreditControlTotalOctets(unitReservation.getUnits());
                                        ansMscc.setGrantedServiceUnit(gsu);
-                                       ansMscc.setResultCode(2001);
+                                       
ansMscc.setResultCode(DiameterResultCode.DIAMETER_SUCCESS);
                                }
                                else {
ansMscc.setResultCode(getResultCode(unitReservation.getErrorCodeType()));
=======================================
--- /sbb/src/main/java/org/mobicents/charging/server/account/AccountBalanceManagement.java Wed Dec 5 09:26:03 2012 +++ /sbb/src/main/java/org/mobicents/charging/server/account/AccountBalanceManagement.java Wed Jan 2 08:30:17 2013
@@ -36,7 +36,10 @@

UnitReservation terminateRequest(String sessionId, String userId, long requestedAmount, long usedAmount, int requestNumber);

-       void dump();
+       void dump(String usersRegExp);

-       boolean addUser(String userId, long balance);
+       boolean addUser(String userId, long balance);
+
+       void setBypass(boolean bypass);
+
 }
=======================================
--- /sbb/src/main/java/org/mobicents/charging/server/account/AccountBalanceManagementSbb.java Wed Dec 5 09:26:03 2012 +++ /sbb/src/main/java/org/mobicents/charging/server/account/AccountBalanceManagementSbb.java Wed Jan 2 08:30:17 2013
@@ -22,6 +22,7 @@

 package org.mobicents.charging.server.account;

+import java.util.Properties;
 import java.util.concurrent.ConcurrentHashMap;

 import javax.slee.Sbb;
@@ -42,12 +43,15 @@
        private Tracer tracer;
        private SbbContextExt sbbContext;

-       private static ConcurrentHashMap<String, Long> userBalance;
+       // If set to true, no balance is verified for any user.
+       private boolean bypass = false;
+
+ private static ConcurrentHashMap<String, Long> userBalance = new ConcurrentHashMap<String, Long>();

private static ConcurrentHashMap<String, Long> userUsedUnits = new ConcurrentHashMap<String, Long>(); private static ConcurrentHashMap<String, Long> userReservedUnits = new ConcurrentHashMap<String, Long>();

- // --------------------------- SBB LO callbacks --------------------------- + // --------------------------- SBB LO callbacks ---------------------------

        /*
         * Initial Request Handling
@@ -65,6 +69,10 @@
        {
tracer.info(" [>>] Received an Initial Request to Account and Balance Management SBB.");

+               if (bypass) {
+ return reserveUnits(sessionId, userId, requestedAmount, Long.MAX_VALUE);
+               }
+
                // get user current balance
                Long units = userBalance.get(userId);

@@ -106,7 +114,11 @@

                checkUsedUnits(userId, usedAmount, units);

-               if (units <= 0) {
+    if (bypass) {
+ return reserveUnits(sessionId, userId, requestedAmount, Long.MAX_VALUE);
+    }
+
+    if (units <= 0) {
return new UnitReservation(503L, "No Units Available", sessionId, System.currentTimeMillis());
                }
                else {
@@ -148,7 +160,7 @@
        public void setSbbContext(SbbContext context) {
                this.tracer = context.getTracer("CS-ABMF");
                this.sbbContext = (SbbContextExt) context;
-       }
+  }

        /*
         * (non-Javadoc)
@@ -160,12 +172,14 @@
                this.tracer = null;
        }

-       public void dump() {
+       public void dump(String usersRegExp) {
tracer.info(String.format("%20s | %10s | %10s | %10s |", "User ID", "Balance", "Reserved", "Used")); tracer.info("---------------------+------------+------------+------------+");
                for (String user : userBalance.keySet()) {
- tracer.info(String.format("%20s | %10s | %10s | %10s |", user, userBalance.get(user), userReservedUnits.get(user),
-                                       userUsedUnits.get(user)));
+                 if(user.matches(usersRegExp)) {
+ tracer.info(String.format("%20s | %10s | %10s | %10s |", user, userBalance.get(user), userReservedUnits.get(user),
+                       userUsedUnits.get(user)));
+                 }
                }
        }

@@ -198,9 +212,9 @@
        }

private void checkUsedUnits(String userId, long usedAmount, long availableAmount) {
-               Long reservedUnits = userReservedUnits.get(userId);
+               Long reservedUnits = userReservedUnits.remove(userId);

-               Long nonUsedUnits = reservedUnits - usedAmount;
+ Long nonUsedUnits = (reservedUnits == null ? 0 : reservedUnits)- usedAmount;

                if (nonUsedUnits < 0) {
                        tracer.warning(" [!!] User used more than granted 
units.");
@@ -216,5 +230,9 @@
                Long oldUsedUnits = userUsedUnits.get(userId);
userUsedUnits.put(userId, oldUsedUnits != null ? oldUsedUnits + usedAmount : usedAmount);
        }
+
+       public void setBypass(boolean bypass) {
+    this.bypass = bypass;
+  }

 }
=======================================
--- /sbb/src/main/resources/META-INF/sbb-jar.xml        Wed Dec  5 09:26:03 2012
+++ /sbb/src/main/resources/META-INF/sbb-jar.xml        Wed Jan  2 08:30:17 2013
@@ -70,6 +70,48 @@
                                
<resource-adaptor-entity-link>DiameterRo</resource-adaptor-entity-link>
                        </resource-adaptor-entity-binding>
                </resource-adaptor-type-binding>
+
+               <!-- event event-direction="Receive" initial-event="True">
+                       <event-name>ServiceStartedEvent</event-name>
+                       <event-type-ref>
+ <event-type-name>javax.slee.serviceactivity.ServiceStartedEvent</event-type-name>
+                               
<event-type-vendor>javax.slee</event-type-vendor>
+                               <event-type-version>1.1</event-type-version>
+                       </event-type-ref>
+                       <initial-event-select variable="ActivityContext" />
+               </event>
+               <event event-direction="Receive" initial-event="True">
+                       <event-name>CreditControlRequest</event-name>
+                       <event-type-ref>
+ <event-type-name>net.java.slee.resource.diameter.cca.events.CreditControlRequest</event-type-name>
+                               <event-type-vendor>java.net</event-type-vendor>
+                               <event-type-version>0.8</event-type-version>
+                       </event-type-ref>
+ <initial-event-selector-method-name>onCreditControlRequestInitialEventSelect</initial-event-selector-method-name>
+               </event>
+        <event event-direction="Receive" initial-event="False">
+            <event-name>TimerEvent</event-name>
+            <event-type-ref>
+ <event-type-name>javax.slee.facilities.TimerEvent</event-type-name>
+                <event-type-vendor>javax.slee</event-type-vendor>
+                <event-type-version>1.0</event-type-version>
+            </event-type-ref>
+        </event>
+
+               <resource-adaptor-type-binding>
+                       <resource-adaptor-type-ref>
+                               <resource-adaptor-type-name>Diameter 
CCA</resource-adaptor-type-name>
+                               
<resource-adaptor-type-vendor>java.net</resource-adaptor-type-vendor>
+                               
<resource-adaptor-type-version>0.8.1</resource-adaptor-type-version>
+                       </resource-adaptor-type-ref>
+
+ <activity-context-interface-factory-name>slee/resources/DiameterCCAResourceAdaptor/java.net/0.8.1/acif</activity-context-interface-factory-name>
+
+                       <resource-adaptor-entity-binding>
+ <resource-adaptor-object-name>slee/resources/diameter-cca-client-ra-interface</resource-adaptor-object-name> + <resource-adaptor-entity-link>DiameterCCA</resource-adaptor-entity-link>
+                       </resource-adaptor-entity-binding>
+               </resource-adaptor-type-binding -->
        </sbb>

        <sbb>

Reply via email to