Package org.jainslee.resources.diameter.base

The Diameter Base Resource Adaptor allows SLEE services to construct messages using the Diameter protocol, and send those requests to a Diameter server. The Base RA can also be used to construct and send extension messages.

SBBs obtain a DiameterProvider instance via JNDI by specifying an appropriate <resource-adaptor-entity-binding> entry in the SBB deployment descriptor.

The DiameterProvider provides a factory (DiameterMessageFactory) that is used to create Diameter AVPs and Diameter messages.

Client -- Sending Diameter requests

The DiameterProvider interface provides methods that allow SBBs to send synchronous Diameter requests, and a method to create a DiameterActivity to send requests asynchronously.

Diameter requests consist of a DiameterMessage containing the command code and Attribute Value Pair (AVP) data. Responses consist of a DiameterMessage with the result in appropriate AVPs as defined by the Diameter application being used. DiameterMessage implementations are either returned from synchronous method invocations or fired as events in the asynchronous case.

Asynchronous Requests

Asynchronous requests are sent by first creating an activity, attaching to the activity then invoking the sendMessage method on the activity. When the request completes, an event is fired on the activity.


The following code snippet demonstrates sending an "extension" Diameter command (i.e., one not defined by the base Diameter specification).
        DiameterMessageFactory messageFactory = diameterProvider.getDiameterMessageFactory();

        DiameterCommand command = messageFactory.createCommand(TEST_AUTH_COMMAND_CODE, 10000, "TAR", "Test-Auth-Request", true, true);
        DiameterAvp[] avps = new DiameterAvp[]{
            messageFactory.createAvp(DiameterAvpCodes.AUTH_APPLICATION_ID, 1),
            messageFactory.createAvp(DiameterAvpCodes.USER_NAME, "user@domain.com"),
            messageFactory.createAvp(DiameterAvpCodes.RE_AUTH_REQUEST_TYPE, ReAuthRequestType.AUTHORIZE_ONLY)
        };

        DiameterMessage message = messageFactory.createMessage(command, avps);

        message.setDestinationRealm(new DiameterIdentity("diameter-server"));
        message.setDestinationHost(new DiameterIdentity("opencloud"));

        DiameterActivity activity = diameterProvider.createActivity();
        ActivityContextInterface diameterACI = diameterACIFactory.getActivityContextInterface(activity);
        diameterACI.attach(getSbbLocalObject());
        activity.sendMessage(message);

    

The following code snippet demonstrates sending a Diameter Re-Auth-Request command on an existing activity. (The getDiameterActivity() method used here is simply a helper method that uses SbbContext.getActivities() to retrieve the Diameter activity that this SBB is attached to.) The Re-Auth-Request message is defined by Diameter, therefore the message factory provides a named constructor for this message, and the ReAuthRequest interface has set methods for each AVP it can contain.
        DiameterActivity activity = getDiameterActivity();
        if(activity == null) {
            trace(Level.SEVERE, "Could not get attached activity");
            return;
        }
        DiameterMessageFactory messageFactory = activity.getDiameterMessageFactory();
        
        ReAuthRequest reAuthRequest = messageFactory.createReAuthRequest();
        reAuthRequest.setAuthApplicationId(10000);
        reAuthRequest.setUserName("user@domain.com");
        reAuthRequest.setReAuthRequestType(ReAuthRequestType.AUTHORIZE_ONLY);
        activity.sendMessage(reAuthRequest);

    

Client -- Receiving Diameter responses


The following code snippet shows an event handler method for a Re-Auth-Answer message.
        public void onReAuthAnswer(ReAuthAnswer reAuthAnswer, ActivityContextInterface aci) {
            trace(Level.FINE, "ReAuthAnswer " + reAuthAnswer);
    
            String sessionID = reAuthAnswer.getSessionId();
            if(DiameterResultCode.DIAMETER_SUCCESS == reAuthAnswer.getResultCode()) {
                trace(Level.FINE, "ReAuth success for session " + sessionID);
            }
            else {
                trace(Level.FINE, "ReAuth failure for session " + sessionID);
                trace(Level.FINE, "Reason: " + reAuthAnswer.getErrorMessage());
            }
        }
    

The following code snippet shows an event handler method for an answer message not defined by the base Diameter specification. (Note this is a very simple implementation, an application that was handling multiple different "extension" messages would need something more sophisticated.)
    public void onExtensionMessage(ExtensionDiameterMessage event, ActivityContextInterface avi) {
        trace(Level.FINE, "ExtensionMessage " + event);
        DiameterCommand command = event.getCommand();
        if(TEST_AUTH_COMMAND_CODE == command.getCode()) {
            DiameterAvp[] avps = event.getAvps();
            for (int i = 0; i < avps.length; i++) {
                DiameterAvp avp = avps[i];
                int code = avp.getCode();
                switch(code) {
                    case DiameterAvpCodes.SESSION_ID:
                        trace(Level.FINE, "Session-Id " + avp.stringValue());
                        break;
                    case DiameterAvpCodes.RESULT_CODE:
                        trace(Level.FINE, "Result-Code  " + avp.longValue());
                        break;
                    /* ... etc ... */
                    default:
                        trace(Level.WARNING, "Unknown AVP code for TestAuth message: " + code);
                }
            }
        }
        else {
            trace(Level.WARNING, "Unknown command code: " + command.getCode());
        }
    }
    

Synchronous Requests

Synchronous requests are sent by calling DiameterProvider.sendSyncMessage(DiameterMessage)

Note: The synchronous API should only be used for simple test services that are not expected to run at high loads. The resource adaptor does not currently implement timeouts for synchronous requests, so SBBs may block indefinitely. Services that use the synchronous model also do not scale well.


The following code snippet demonstrates sending an extension Diameter command (i.e., one not defined by the base Diameter specification).
        
        DiameterMessageFactory messageFactory = diameterProvider.getDiameterMessageFactory();

        DiameterCommand command = messageFactory.createCommand(TEST_AUTH_COMMAND_CODE, 10000, "TAR", "Test-Auth-Request", true, true);
        DiameterAvp[] avps = new DiameterAvp[]{
            messageFactory.createAvp(DiameterAvpCodes.AUTH_APPLICATION_ID, 1),
            messageFactory.createAvp(DiameterAvpCodes.USER_NAME, "user@domain.com"),
            messageFactory.createAvp(DiameterAvpCodes.RE_AUTH_REQUEST_TYPE, ReAuthRequestType.AUTHORIZE_ONLY)
        };
    
        DiameterMessage message = messageFactory.createMessage(command, avps);
    
        message.setDestinationRealm(new DiameterIdentity("diameter-server"));
        message.setDestinationHost(new DiameterIdentity("opencloud"));
    
        DiameterMessage answer = diameterProvider.sendSyncMessage(message);
    
        // Process answer