package org.mobicents.slee.resources.diameter.tests.framework.validator; import static org.jdiameter.client.impl.helpers.Parameters.AcctApplId; import static org.jdiameter.client.impl.helpers.Parameters.ApplicationId; import static org.jdiameter.client.impl.helpers.Parameters.Assembler; import static org.jdiameter.client.impl.helpers.Parameters.AuthApplId; import static org.jdiameter.client.impl.helpers.Parameters.OwnDiameterURI; import static org.jdiameter.client.impl.helpers.Parameters.OwnRealm; import static org.jdiameter.client.impl.helpers.Parameters.OwnVendorID; import static org.jdiameter.client.impl.helpers.Parameters.PeerName; import static org.jdiameter.client.impl.helpers.Parameters.PeerRating; import static org.jdiameter.client.impl.helpers.Parameters.PeerTable; import static org.jdiameter.client.impl.helpers.Parameters.RealmEntry; import static org.jdiameter.client.impl.helpers.Parameters.RealmTable; import static org.jdiameter.client.impl.helpers.Parameters.VendorId; import static org.junit.Assert.fail; import java.util.HashMap; import java.util.Map; import net.java.slee.resource.diameter.base.events.avp.AvpNotAllowedException; import net.java.slee.resource.diameter.base.events.avp.AvpUtilities; import net.java.slee.resource.diameter.base.events.avp.DiameterAvpType; import org.jdiameter.api.Avp; import org.jdiameter.api.AvpSet; import org.jdiameter.api.Session; import org.jdiameter.api.Stack; import org.jdiameter.client.impl.helpers.EmptyConfiguration; import org.jdiameter.common.impl.validation.DiameterMessageValidator; import org.jdiameter.common.impl.validation.JAvpNotAllowedException; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mobicents.diameter.dictionary.AvpDictionary; import org.mobicents.slee.resource.diameter.base.DiameterMessageFactoryImpl; import org.mobicents.slee.resource.diameter.base.events.AccountingRequestImpl; import org.mobicents.slee.resource.diameter.base.events.avp.DiameterAvpImpl; /** * Start time:14:15:19 2009-05-27<br> * Project: 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 AvpUtilitiesTest { private static String clientHost = "99.99.99.99"; private static String clientPort = "21812"; private static String clientURI = "aaa://" + clientHost + ":" + clientPort; private static String serverHost = "99.99.99.99"; private static String serverPort = "1812"; private static String serverURI = "aaa://" + serverHost + ":" + serverPort; private static String realmName = "mobicentsXYZ.org"; private static DiameterMessageFactoryImpl baseFactory; private DiameterMessageValidator instance = null; private static Stack stack = null; private final static String validatorOnFile = "validator.xml"; private final static String validatorOffFile = "validatorOff.xml"; @Before public void setUp() { this.instance = DiameterMessageValidator.getInstance(); } @After public void tearDown() { this.instance = null; } @Test public void testOperationsAddWithValidatorOnAndRemovalAllowed() { AvpUtilities.allowRemove(true); instance.parseConfiguration(this.getClass().getClassLoader().getResourceAsStream(validatorOnFile),true); // It has session id AccountingRequestImpl request = (AccountingRequestImpl) baseFactory.createAccountingRequest(); // <avp name="Session-Id" code="263" vendor="0" multiplicity="1" // index="0"/> AvpUtilities.setAvpAsUTF8String(request.getGenericData(), 263, request.getGenericData().getAvps(), "1346ferg5y"); // <avp name="Origin-Host" code="264" vendor="0" multiplicity="1" // index="-1"/> AvpUtilities.setAvpAsOctetString(request.getGenericData(), 264, request.getGenericData().getAvps(), clientURI); // <avp name="Origin-Realm" code="296" vendor="0" multiplicity="1" // index="-1"/> AvpUtilities.setAvpAsOctetString(request.getGenericData(), 296, request.getGenericData().getAvps(), realmName); AvpUtilities.setAvpAsOctetString(request.getGenericData(), 296, request.getGenericData().getAvps(), realmName); // <avp name="Destination-Realm" code="283" vendor="0" multiplicity="1" // index="-1"/> AvpUtilities.setAvpAsOctetString(request.getGenericData(), 283, request.getGenericData().getAvps(), realmName); // <avp name="Accounting-Record-Type" code="480" vendor="0" // multiplicity="1" index="-1"/> AvpUtilities.setAvpAsUnsigned32(request.getGenericData(), 480, request.getGenericData().getAvps(), 1); String sessionId = AvpUtilities.getAvpAsUTF8String(263, request.getGenericData().getAvps()); Session localSession = null; try { localSession = stack.getSessionFactory().getNewSession(sessionId); localSession.send(request.getGenericData()); // this should fail eve so, but just in case fail("We should not send this message."); } catch (JAvpNotAllowedException e) { if (e.getAvpCode() != 485 && e.getVendorId() != 0) { fail("Wrong AVP code and vendorId in exception."); } } catch (Exception e) { e.printStackTrace(); fail("Failed to create Diam session"); } // <avp name="Accounting-Record-Number" code="485" vendor="0" // multiplicity="1" index="-1"/> AvpUtilities.setAvpAsUnsigned32(request.getGenericData(), 485, request.getGenericData().getAvps(), 1); // Here it should be ok. since we are here, validation works, try { localSession.send(request.getGenericData()); // this will fail, as there is no route fail("Should not allow to send"); } catch (org.jdiameter.api.RouteException e) { // its ok :) } catch (Exception e) { // this includes validation error e.printStackTrace(); fail("Received wrong exception...: " + e); } // <avp name="Acct-Application-Id" code="259" vendor="0" // multiplicity="0-1" index="-1"/> AvpUtilities.setAvpAsUnsigned32(request.getGenericData(), 259, request.getGenericData().getAvps(), 1); // Here it should be ok. since we are here, validation works, try { localSession.send(request.getGenericData()); // this will fail, as there is no route fail("Should not allow to send"); } catch (org.jdiameter.api.RouteException e) { // its ok :) } catch (Exception e) { // this includes validation error e.printStackTrace(); fail("Received wrong exception...: " + e); } // <!-- FORBBIDEN --> // <avp name="Auth-Application-Id" code="258" vendor="0" // multiplicity="0" index="-1"/> try { AvpUtilities.setAvpAsUnsigned32(request.getGenericData(), 258, request.getGenericData().getAvps(), 1); // this should fail eve so, but just in case fail("We should not get here."); } catch (AvpNotAllowedException e) { if (e.getAvpCode() != 258 && e.getVendorId() != 0) { fail("Wrong AVP code and vendorId in exception."); } } catch (Exception e) { e.printStackTrace(); fail("Faield, we should get AvpNotAllowedException, not: " + e); } //This is just in case Map<ExpectedAvp,ExpectedAvp> expectedAvps = new HashMap<ExpectedAvp, ExpectedAvp>(); ExpectedAvp a = new ExpectedAvp(); a.code = 263; a.count = 1; expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 264; a.count = 1; expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 296; a.count = 1; expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 283; a.count = 1; expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 480; a.count = 1; expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 485; a.count = 1; expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 259; a.count = 1; expectedAvps.put(a, a); testPresentAvps(request.getGenericData().getAvps(),expectedAvps); } @Test public void testOperationsAddWithValidatorOnAndRemovalNotAllowed() { AvpUtilities.allowRemove(false); instance.parseConfiguration(this.getClass().getClassLoader().getResourceAsStream(validatorOnFile),true); // It has session id AccountingRequestImpl request = (AccountingRequestImpl) baseFactory.createAccountingRequest(new DiameterAvpImpl[]{new DiameterAvpImpl(263, 0L, 0, 1, "xxx".getBytes(), DiameterAvpType.UTF8_STRING)}); // <avp name="Session-Id" code="263" vendor="0" multiplicity="1" // index="0"/> try { AvpUtilities.setAvpAsUTF8String(request.getGenericData(), 263, request.getGenericData().getAvps(), "1346ferg5y"); fail("We should not get here: Session-Id can not be set twice if remove is off."); } catch (AvpNotAllowedException e) { if (e.getAvpCode() != 258 && e.getVendorId() != 0) { fail("Wrong AVP code and vendorId in exception."); } } catch (Exception e) { e.printStackTrace(); fail("Failed, add operation should fail with AvpNotAllowedException, not with: " + e); } // <avp name="Origin-Host" code="264" vendor="0" multiplicity="1" // index="-1"/> if(!request.hasOriginHost()) AvpUtilities.setAvpAsOctetString(request.getGenericData(), 264, request.getGenericData().getAvps(), clientURI); // <avp name="Origin-Realm" code="296" vendor="0" multiplicity="1" // index="-1"/> if(!request.hasOriginRealm()) AvpUtilities.setAvpAsOctetString(request.getGenericData(), 296, request.getGenericData().getAvps(), realmName); // <avp name="Destination-Realm" code="283" vendor="0" multiplicity="1" // index="-1"/> AvpUtilities.setAvpAsOctetString(request.getGenericData(), 283, request.getGenericData().getAvps(), realmName); // <avp name="Accounting-Record-Type" code="480" vendor="0" // multiplicity="1" index="-1"/> AvpUtilities.setAvpAsUnsigned32(request.getGenericData(), 480, request.getGenericData().getAvps(), 1); String sessionId = AvpUtilities.getAvpAsUTF8String(263, request.getGenericData().getAvps()); Session localSession = null; try { localSession = stack.getSessionFactory().getNewSession(sessionId); localSession.send(request.getGenericData()); // this should fail eve so, but just in case fail("We should nto send this message."); } catch (JAvpNotAllowedException e) { if (e.getAvpCode() != 485 && e.getVendorId() != 0) { fail("Wrong AVP code and vendorId in exception."); } } catch (Exception e) { e.printStackTrace(); fail("Failed to create Diam session"); } // <avp name="Accounting-Record-Number" code="485" vendor="0" // multiplicity="1" index="-1"/> AvpUtilities.setAvpAsUnsigned32(request.getGenericData(), 485, request.getGenericData().getAvps(), 1); // Here it should be ok. since we are here, validation works, try { localSession.send(request.getGenericData()); // this will fail, as there is no route fail("Should not allow to send"); } catch (org.jdiameter.api.RouteException e) { // its ok :) } catch (Exception e) { // this includes validation error e.printStackTrace(); fail("Received wrong exception...: " + e); } // <avp name="Acct-Application-Id" code="259" vendor="0" // multiplicity="0-1" index="-1"/> AvpUtilities.setAvpAsUnsigned32(request.getGenericData(), 259, request.getGenericData().getAvps(), 1); // Here it should be ok. since we are here, validation works, try { localSession.send(request.getGenericData()); // this will fail, as there is no route fail("Should not allow to send"); } catch (org.jdiameter.api.RouteException e) { // its ok :) } catch (Exception e) { // this includes validation error e.printStackTrace(); fail("Received wrong exception...: " + e); } // <!-- FORBBIDEN --> // <avp name="Auth-Application-Id" code="258" vendor="0" // multiplicity="0" index="-1"/> try { AvpUtilities.setAvpAsUnsigned32(request.getGenericData(), 258, request.getGenericData().getAvps(), 1); // this should fail eve so, but just in case fail("We should nto get here."); } catch (AvpNotAllowedException e) { if (e.getAvpCode() != 258 && e.getVendorId() != 0) { fail("Wrong AVP code and vendorId in exception."); } } catch (Exception e) { e.printStackTrace(); fail("Failed, add operation should fail with AvpNotAllowedException, not with: " + e); } //Just in case. Map<ExpectedAvp,ExpectedAvp> expectedAvps = new HashMap<ExpectedAvp, ExpectedAvp>(); ExpectedAvp a = new ExpectedAvp(); a.code = 263; a.count = 1; expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 264; a.count = 1; expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 296; a.count = 1; expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 283; a.count = 1; expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 480; a.count = 1; expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 485; a.count = 1; expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 259; a.count = 1; expectedAvps.put(a, a); testPresentAvps(request.getGenericData().getAvps(),expectedAvps); } @Test public void testOperationsAddWithValidatorOffAndRemovalAllowed() { AvpUtilities.allowRemove(true); instance.parseConfiguration(this.getClass().getClassLoader().getResourceAsStream(validatorOffFile),true); // It has session id AccountingRequestImpl request = (AccountingRequestImpl) baseFactory.createAccountingRequest(new DiameterAvpImpl[]{new DiameterAvpImpl(263, 0L, 0, 1, "xxx".getBytes(), DiameterAvpType.UTF8_STRING)}); // <avp name="Session-Id" code="263" vendor="0" multiplicity="1" // index="0"/> AvpUtilities.setAvpAsUTF8String(request.getGenericData(), 263, request.getGenericData().getAvps(), "1346ferg5y"); // <avp name="Origin-Host" code="264" vendor="0" multiplicity="1" // index="-1"/> AvpUtilities.setAvpAsOctetString(request.getGenericData(), 264, request.getGenericData().getAvps(), clientURI); // <avp name="Origin-Realm" code="296" vendor="0" multiplicity="1" // index="-1"/> AvpUtilities.setAvpAsOctetString(request.getGenericData(), 296, request.getGenericData().getAvps(), realmName); AvpUtilities.setAvpAsOctetString(request.getGenericData(), 296, request.getGenericData().getAvps(), realmName); // <avp name="Destination-Realm" code="283" vendor="0" multiplicity="1" // index="-1"/> AvpUtilities.setAvpAsOctetString(request.getGenericData(), 283, request.getGenericData().getAvps(), realmName); // <avp name="Accounting-Record-Type" code="480" vendor="0" // multiplicity="1" index="-1"/> AvpUtilities.setAvpAsUnsigned32(request.getGenericData(), 480, request.getGenericData().getAvps(), 1); String sessionId = AvpUtilities.getAvpAsUTF8String(263, request.getGenericData().getAvps()); Session localSession = null; try { localSession = stack.getSessionFactory().getNewSession(sessionId); localSession.send(request.getGenericData()); // this should fail eve so, but just in case fail("We should not send this message."); } catch (org.jdiameter.api.RouteException e) { } catch (Exception e) { e.printStackTrace(); fail("Failed to create session/send request due to wrong reason: "+e); } // <avp name="Accounting-Record-Number" code="485" vendor="0" // multiplicity="1" index="-1"/> AvpUtilities.setAvpAsUnsigned32(request.getGenericData(), 485, request.getGenericData().getAvps(), 1); // Here it should be ok. since we are here, validation works, try { localSession.send(request.getGenericData()); // this will fail, as there is no route fail("Should not allow to send"); } catch (org.jdiameter.api.RouteException e) { // its ok :) } catch (Exception e) { // this includes validation error e.printStackTrace(); fail("Failed to create session/send request due to wrong reason: "+e); } // <avp name="Acct-Application-Id" code="259" vendor="0" // multiplicity="0-1" index="-1"/> AvpUtilities.setAvpAsUnsigned32(request.getGenericData(), 259, request.getGenericData().getAvps(), 1); // Here it should be ok. since we are here, validation works, try { localSession.send(request.getGenericData()); // this will fail, as there is no route fail("Should not allow to send"); } catch (org.jdiameter.api.RouteException e) { // its ok :) } catch (Exception e) { // this includes validation error e.printStackTrace(); fail("Received wrong exception...: " + e); } // <!-- FORBBIDEN --> // <avp name="Auth-Application-Id" code="258" vendor="0" // multiplicity="0" index="-1"/> try { AvpUtilities.setAvpAsUnsigned32(request.getGenericData(), 258, request.getGenericData().getAvps(), 1); // this should fail eve so, but just in case } catch (AvpNotAllowedException e) { fail("We should not get here."); } catch (Exception e) { e.printStackTrace(); fail("Faield, we should get AvpNotAllowedException, not: " + e); } //This is just in case Map<ExpectedAvp,ExpectedAvp> expectedAvps = new HashMap<ExpectedAvp, ExpectedAvp>(); ExpectedAvp a = new ExpectedAvp(); a.code = 263; a.count = 2; expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 264; a.count = 2; // was 1 but request comes with one already... expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 296; //cause its legal in this case. a.count = 3; // was 2 but request comes with one already... expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 283; a.count = 1; expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 480; a.count = 1; expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 485; a.count = 1; expectedAvps.put(a, a); a = new ExpectedAvp(); a.code = 259; a.count = 1; expectedAvps.put(a, a); // yes, its legal also. we dont check a = new ExpectedAvp(); a.code = 258; a.count = 1; expectedAvps.put(a, a); testPresentAvps(request.getGenericData().getAvps(),expectedAvps); } static { stack = new org.jdiameter.client.impl.StackImpl(); try { stack.init(new MyConfiguration()); stack.start(); } catch (Exception e) { throw new RuntimeException("Failed to initialize the stack."); } baseFactory = new DiameterMessageFactoryImpl(stack); // DiameterAvpFactoryImpl baseAvpFactory = new DiameterAvpFactoryImpl(); try { AvpDictionary.INSTANCE.parseDictionary(AvpUtilitiesTest.class.getClassLoader().getResourceAsStream("dictionary.xml")); } catch (Exception e) { throw new RuntimeException("Failed to parse dictionary file."); } } private void testPresentAvps(AvpSet set,Map<ExpectedAvp,ExpectedAvp> expected) { for(ExpectedAvp e: expected.values()) { AvpSet innerSet = set.removeAvp(e.code); if(innerSet.size()!=e.count) { fail("Wrong count of avps, code: "+e.code+", vendor:"+e.vendor+". Expected: "+e.count+", present: "+innerSet.size()); } if(e.count>0) { Avp avp = innerSet.getAvpByIndex(0); if(avp.getVendorId()!=e.vendor) { fail("Wrong vendor of avp, code: "+e.code+". Expected: "+e.vendor+", present: "+avp.getVendorId()); } } } if(set.size()>0) { String s=""; for(Avp a: set) { s+="Code["+a.getCode()+"] Vendor["+a.getVendorId()+"],"; } fail("Wrong count of avps, removed all expected, left overs: "+set.size()+" -- "+s); } } /** * Class representing the Diameter Configuration */ public static class MyConfiguration extends EmptyConfiguration { public MyConfiguration() { super(); add(Assembler, Assembler.defValue()); add(OwnDiameterURI, clientURI); add(OwnRealm, realmName); add(OwnVendorID, 193L); // Set Ericsson SDK feature // add(UseUriAsFqdn, true); // Set Common Applications add(ApplicationId, // AppId 1 getInstance().add(VendorId, 193L).add(AuthApplId, 0L).add(AcctApplId, 19302L)); // Set peer table add(PeerTable, // Peer 1 getInstance().add(PeerRating, 1).add(PeerName, serverURI)); // Set realm table add(RealmTable, // Realm 1 getInstance().add(RealmEntry, realmName + ":" + clientHost + "," + serverHost)); } } } class ExpectedAvp { int code = 0; long vendor = 0; int count = 0; @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + code; result = prime * result + (int) (vendor ^ (vendor >>> 32)); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ExpectedAvp other = (ExpectedAvp) obj; if (code != other.code) return false; if (vendor != other.vendor) return false; return true; } }