package org.jdiameter.client.impl.controller;
/*
* Copyright (c) 2006 jDiameter.
* https://jdiameter.dev.java.net/
*
* License: GPL v3
*
* e-mail: erick.svenson@yahoo.com
*
*/
import static org.jdiameter.api.Avp.ACCT_APPLICATION_ID;
import static org.jdiameter.api.Avp.AUTH_APPLICATION_ID;
import static org.jdiameter.api.Avp.DESTINATION_HOST;
import static org.jdiameter.api.Avp.DESTINATION_REALM;
import static org.jdiameter.api.Avp.DISCONNECT_CAUSE;
import static org.jdiameter.api.Avp.ERROR_MESSAGE;
import static org.jdiameter.api.Avp.FIRMWARE_REVISION;
import static org.jdiameter.api.Avp.HOST_IP_ADDRESS;
import static org.jdiameter.api.Avp.ORIGIN_HOST;
import static org.jdiameter.api.Avp.ORIGIN_REALM;
import static org.jdiameter.api.Avp.ORIGIN_STATE_ID;
import static org.jdiameter.api.Avp.PRODUCT_NAME;
import static org.jdiameter.api.Avp.RESULT_CODE;
import static org.jdiameter.api.Avp.SUPPORTED_VENDOR_ID;
import static org.jdiameter.api.Avp.VENDOR_ID;
import static org.jdiameter.api.Avp.VENDOR_SPECIFIC_APPLICATION_ID;
import static org.jdiameter.api.Message.CAPABILITIES_EXCHANGE_REQUEST;
import static org.jdiameter.api.Message.DEVICE_WATCHDOG_REQUEST;
import static org.jdiameter.api.Message.DISCONNECT_PEER_REQUEST;
import static org.jdiameter.client.api.fsm.EventTypes.CEA_EVENT;
import static org.jdiameter.client.api.fsm.EventTypes.CER_EVENT;
import static org.jdiameter.client.api.fsm.EventTypes.CONNECT_EVENT;
import static org.jdiameter.client.api.fsm.EventTypes.DISCONNECT_EVENT;
import static org.jdiameter.client.api.fsm.EventTypes.DPA_EVENT;
import static org.jdiameter.client.api.fsm.EventTypes.DPR_EVENT;
import static org.jdiameter.client.api.fsm.EventTypes.DWA_EVENT;
import static org.jdiameter.client.api.fsm.EventTypes.DWR_EVENT;
import static org.jdiameter.client.api.fsm.EventTypes.INTERNAL_ERROR;
import static org.jdiameter.client.api.fsm.EventTypes.RECEIVE_MSG_EVENT;
import static org.jdiameter.client.api.fsm.EventTypes.STOP_EVENT;
import static org.jdiameter.client.impl.helpers.Parameters.SecurityRef;
import static org.jdiameter.client.impl.helpers.Parameters.UseUriAsFqdn;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import org.jdiameter.api.ApplicationId;
import org.jdiameter.api.Avp;
import org.jdiameter.api.AvpDataException;
import org.jdiameter.api.AvpSet;
import org.jdiameter.api.Configuration;
import org.jdiameter.api.IllegalDiameterStateException;
import org.jdiameter.api.InternalException;
import org.jdiameter.api.Message;
import org.jdiameter.api.NetworkReqListener;
import org.jdiameter.api.OverloadException;
import org.jdiameter.api.Peer;
import org.jdiameter.api.PeerState;
import org.jdiameter.api.PeerStateListener;
import org.jdiameter.api.ResultCode;
import org.jdiameter.api.RouteException;
import org.jdiameter.api.URI;
import org.jdiameter.api.app.StateChangeListener;
import org.jdiameter.client.api.IMessage;
import org.jdiameter.client.api.IMetaData;
import org.jdiameter.client.api.controller.IPeer;
import org.jdiameter.client.api.fsm.EventTypes;
import org.jdiameter.client.api.fsm.ExecutorFactory;
import org.jdiameter.client.api.fsm.FsmEvent;
import org.jdiameter.client.api.fsm.IContext;
import org.jdiameter.client.api.fsm.IFsmFactory;
import org.jdiameter.client.api.fsm.IStateMachine;
import org.jdiameter.client.api.io.IConnection;
import org.jdiameter.client.api.io.IConnectionListener;
import org.jdiameter.client.api.io.ITransportLayerFactory;
import org.jdiameter.client.api.io.TransportError;
import org.jdiameter.client.api.io.TransportException;
import org.jdiameter.client.api.parser.IMessageParser;
import org.jdiameter.client.api.router.IRouter;
import org.jdiameter.client.impl.helpers.UIDGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PeerImpl implements IPeer, Comparable<Peer> {
public static final int INT_COMMON_APP_ID = 0xffffffff;
protected static UIDGenerator uid = new UIDGenerator();
// Logger
protected Logger logger = LoggerFactory.getLogger(PeerImpl.class);
// Properties
protected URI uri;
protected InetAddress[] addresses;
protected String realmName;
protected long vendorID;
protected String productName;
protected int firmWare;
protected Set<ApplicationId> commonApplications = new HashSet<ApplicationId>();
protected long hopByHopId = uid.nextInt();
protected int rating;
protected boolean stopping = false;
// Members
protected IMetaData metaData;
protected PeerTableImpl table;
// Facilities
protected IRouter router;
protected Map<String, NetworkReqListener> slc;
protected Map<Long, IMessage> peerRequests = new ConcurrentHashMap<Long, IMessage>();
// FSM layer
protected IStateMachine fsm;
protected IMessageParser parser;
// Feature
protected boolean useUriAsFQDN = false; // Use URI as orign host name into CER command
// Transport layer
protected IConnection connection;
protected IConnectionListener connListener = new IConnectionListener() {
public void connectionOpened(String connKey) {
logger.debug("Connection to {} is opened", uri);
try {
fsm.handleEvent( new FsmEvent(CONNECT_EVENT, connKey) );
}
catch (Exception e) {
logger.warn( "Can not run start procedure", e);
}
}
public void connectionClosed(String connKey, List notSended) {
logger.debug("Connection from {} is closed", uri);
for (IMessage request: peerRequests.values()) {
if (request.getState() == IMessage.STATE_SENT) {
request.setReTransmitted(true);
request.setState(IMessage.STATE_NOT_SENT);
try {
peerRequests.remove(request.getHopByHopIdentifier());
table.sendMessage(request);
}
catch(Throwable exc) {
request.setReTransmitted(false);
}
}
}
try {
fsm.handleEvent( new FsmEvent(DISCONNECT_EVENT, connKey) );
}
catch (Exception e) {
logger.warn( "Can not run stopping procedure", e);
}
}
public void messageReceived(String connKey, IMessage message) {
boolean req = message.isRequest();
try {
int type = message.getCommandCode();
logger.debug("Receive message type {}", type);
switch(type) {
case CAPABILITIES_EXCHANGE_REQUEST:
fsm.handleEvent( new FsmEvent(req ? CER_EVENT : CEA_EVENT, message, connKey) );
break;
case DEVICE_WATCHDOG_REQUEST:
fsm.handleEvent( new FsmEvent(req ? DWR_EVENT : DWA_EVENT, message, connKey) );
break;
case DISCONNECT_PEER_REQUEST:
fsm.handleEvent( new FsmEvent(req ? DPR_EVENT : DPA_EVENT, message) );
break;
default:
fsm.handleEvent( new FsmEvent(RECEIVE_MSG_EVENT, message) );
}
}
catch (Exception e) {
logger.debug("Error during processing incomming message", e);
if (req) {
try {
message.setRequest(false);
message.setError(true);
message.getAvps().addAvp(Avp.RESULT_CODE, ResultCode.TOO_BUSY, true);
connection.sendMessage(message);
}
catch (Exception exc) {
logger.debug("Can not send error answer", exc);
}
}
}
}
public void internalError(String connKey, IMessage message, TransportException cause) {
try {
logger.debug("internalError ", cause);
fsm.handleEvent( new FsmEvent(INTERNAL_ERROR, message));
}
catch (Exception e) {
logger.debug( "Can not run internalError procedure", e);
}
}
};
public PeerImpl(PeerTableImpl table, int rating, URI remotePeer, String ip, String portRange, IMetaData metaData, Configuration config,
Configuration peerConfig, IFsmFactory fsmFactory, ITransportLayerFactory trFactory, IMessageParser parser) throws InternalException, TransportException {
this(table, rating, remotePeer, ip, portRange, metaData, config, peerConfig, fsmFactory, trFactory, parser, null);
}
protected PeerImpl(final PeerTableImpl table, int rating, URI remotePeer, String ip, String portRange, IMetaData metaData, Configuration config,
Configuration peerConfig, IFsmFactory fsmFactory, ITransportLayerFactory trFactory, IMessageParser parser,
IConnection connection) throws InternalException, TransportException {
this.table = table;
this.rating = rating;
this.router = table.router;
this.metaData = metaData;
this.slc = table.getSessionReqListeners();
this.uri = remotePeer;
int port = remotePeer.getPort();
InetAddress remoteAddress;
try {
remoteAddress = InetAddress.getByName( ip != null ? ip : remotePeer.getFQDN());
}
catch (UnknownHostException e) {
throw new TransportException("Can not found host", TransportError.Internal, e);
}
IContext actionContext = getContext();
this.fsm = fsmFactory.createInstanceFsm(actionContext, new ExecutorFactory() {
public ExecutorService getExecutor() {
return table.getPeerTaskExecutor();
}
}, config);
this.fsm.addStateChangeNotification(
new StateChangeListener() {
public void stateChanged(Enum oldState, Enum newState) {
PeerState s = (PeerState) newState;
if (PeerState.DOWN.equals(s)) {
stopping = false;
}
}
}
);
if (connection == null) {
String ref = peerConfig.getStringValue(SecurityRef.ordinal(), null);
InetAddress localAddress = null;
int localPort = 0;
if (portRange != null) {
try {
Peer local = metaData.getLocalPeer();
if (local.getIPAddresses() != null && local.getIPAddresses().length > 0) {
localAddress = local.getIPAddresses()[0];
}
else {
localAddress = InetAddress.getByName(metaData.getLocalPeer().getUri().getFQDN());
}
}
catch (Exception e) {
logger.debug("Can not get local address", e);
}
try {
String[] rng = portRange.trim().split("-");
int strRange = Integer.parseInt(rng[0]);
int endRange = Integer.parseInt(rng[1]);
localPort = strRange + new Random().nextInt(endRange - strRange + 1);
}
catch (Exception exc) {
logger.debug("Can not get local port", exc);
}
logger.debug("Create conn with localAddress={}; localPort={}", localAddress, localPort);
}
this.connection = trFactory.createConnection(remoteAddress, port, localAddress, localPort, connListener, ref);
}
else {
this.connection = connection;
this.connection.addConnectionListener(connListener);
}
this.parser = parser;
this.addresses = new InetAddress[] {remoteAddress};
this.useUriAsFQDN = config.getBooleanValue(UseUriAsFqdn.ordinal(), (Boolean) UseUriAsFqdn.defValue());
}
public IContext getContext() {
return new ActionContext();
}
private boolean isRedirectAnswer(Avp avpResCode, IMessage answer) {
try {
return (answer.getFlags() & 0x20) != 0 && avpResCode != null && avpResCode.getInteger32() == ResultCode.REDIRECT_INDICATION;
}
catch (AvpDataException e) {
return false;
}
}
public void addPeerStateListener(final PeerStateListener listener) {
fsm.addStateChangeNotification(new StateChangeListener() {
public void stateChanged(Enum oldState, Enum newState) {
listener.stateChanged((PeerState) oldState, (PeerState) newState);
}
public int hashCode() {
return listener.hashCode();
}
public boolean equals(Object obj) {
return listener.equals(obj);
}
});
}
public void removePeerStateListener(final PeerStateListener listener) {
if (listener != null) {
fsm.remStateChangeNotification(new StateChangeListener() {
public void stateChanged(Enum oldState, Enum newState) {
listener.stateChanged((PeerState) oldState, (PeerState) newState);
}
public int hashCode() {
return listener.hashCode();
}
public boolean equals(Object obj) {
return listener.equals(obj);
}
});
}
}
private IMessage processRedirectAnswer(IMessage answer) {
int resultCode = 0;
// Update redirect information
try {
router.updateRedirectInformation(answer);
}
catch (RouteException exc) {
// Loop detected (may be stack must send error response to redirect host)
resultCode = ResultCode.LOOP_DETECTED;
}
catch(Throwable exc) {
// Incorrect redirect message
resultCode = ResultCode.UNABLE_TO_DELIVER;
}
// Update destination avps
if (resultCode == 0) {
// Clear avps
answer.getAvps().removeAvp(RESULT_CODE);
// Update flags
answer.setRequest(true);
answer.setError(false);
try {
table.sendMessage(answer);
answer = null;
}
catch (Exception e) {
logger.debug("Unable to deliver due to error", e);
resultCode = ResultCode.UNABLE_TO_DELIVER;
}
}
if (resultCode != 0) {
// Restore answer flag
answer.setRequest(false);
answer.setError(true);
answer.getAvps().removeAvp(RESULT_CODE);
answer.getAvps().addAvp(RESULT_CODE, resultCode, true, false, true);
}
return answer;
}
public void connect() throws InternalException, IOException, IllegalDiameterStateException {
if (getState(PeerState.class) != PeerState.DOWN) {
throw new IllegalDiameterStateException("Invalid state:" + getState(PeerState.class));
}
try {
fsm.handleEvent( new FsmEvent(EventTypes.START_EVENT) );
}
catch (Exception e) {
throw new InternalException(e);
}
}
public void disconnect() throws InternalException, IllegalDiameterStateException {
if (getState(PeerState.class) != PeerState.DOWN) {
stopping = true;
try {
fsm.handleEvent( new FsmEvent(STOP_EVENT) );
}
catch (OverloadException e) {
stopping = false;
logger.debug("Error during stopping procedure", e);
}
}
}
public <E> E getState(Class<E> enumc) {
return fsm.getState(enumc);
}
public URI getUri() {
return uri;
}
public InetAddress[] getIPAddresses() {
return addresses;
}
public String getRealmName() {
return realmName;
}
public long getVendorId() {
return vendorID;
}
public String getProductName() {
return productName;
}
public long getFirmware() {
return firmWare;
}
public Set<ApplicationId> getCommonApplications() {
return commonApplications;
}
public long getHopByHopIdentifier() {
return hopByHopId++;
}
public void addMessage(IMessage message) {
peerRequests.put(message.getHopByHopIdentifier(), message);
}
public void remMessage(IMessage message) {
peerRequests.remove(message.getHopByHopIdentifier());
}
public IMessage[] remAllMessage() {
IMessage[] m = peerRequests.values().toArray(new IMessage[0]);
peerRequests.clear();
return m;
}
public boolean handleMessage(EventTypes type, IMessage message, String key) throws TransportException, OverloadException, InternalException {
return !stopping && fsm.handleEvent( new FsmEvent(type, message, key) );
}
public boolean sendMessage(IMessage message) throws TransportException, OverloadException, InternalException {
return !stopping && fsm.handleEvent( new FsmEvent(EventTypes.SEND_MSG_EVENT, message) );
}
public boolean hasValidConnection() {
return connection != null && connection.isConnected();
}
public void setRealm(String realm) {
realmName = realm;
}
public void addStateChangeListener(StateChangeListener listener) {
fsm.addStateChangeNotification(listener);
}
public void remStateChangeListener(StateChangeListener listener) {
fsm.remStateChangeNotification(listener);
}
public void addConnectionListener(IConnectionListener listener) {
if (connection != null) {
connection.addConnectionListener(listener);
}
}
public void remConnectionListener(IConnectionListener listener) {
if (connection != null) {
connection.remConnectionListener(listener);
}
}
public int getRaiting() {
return rating;
}
public int compareTo(Peer o) {
return uri.compareTo(o.getUri());
}
public String toString() {
return "Peer{" + "Uri=" + uri + "; State="+fsm.getState(PeerState.class).toString() + '}';
}
protected void fillIPAddressTable(IMessage message) {
AvpSet avps = message.getAvps().getAvps(HOST_IP_ADDRESS);
if (avps != null) {
ArrayList<InetAddress> t = new ArrayList<InetAddress>();
for (int i=0; i < avps.size(); i++) {
try {
t.add( avps.getAvpByIndex(i).getAddress() );
}
catch (AvpDataException e) {
logger.debug("Can not get ip address from HOST_IP_ADDRESS avp");
}
}
addresses = t.toArray(new InetAddress[t.size()]);
}
}
protected Set<ApplicationId> getCommonApplicationIds(IMessage message) {
Set<ApplicationId> newAppId = new HashSet<ApplicationId>();
Set<ApplicationId> locAppId = metaData.getLocalPeer().getCommonApplications();
Set<ApplicationId> remAppId = message.getApplicationIdAvps();
// check common application
for (ApplicationId l : locAppId) {
for (ApplicationId r : remAppId) {
if (l.equals(r)) {
newAppId.add(l);
}
else if (r.getAcctAppId() == INT_COMMON_APP_ID || r.getAuthAppId() == INT_COMMON_APP_ID ||
l.getAcctAppId() == INT_COMMON_APP_ID || l.getAuthAppId() == INT_COMMON_APP_ID) {
newAppId.add(r);
}
}
}
return newAppId;
}
protected void preProcessRequest(IMessage answer) {
}
protected class ActionContext implements IContext {
public void connect() throws InternalException, IOException, IllegalDiameterStateException {
try {
connection.connect();
logger.debug("Connected to peer {}", PeerImpl.this.getUri());
}
catch (TransportException e) {
switch(e.getCode()) {
case NetWorkError:
throw new IOException("Can not connect to " + connection.getKey() + " - " + e.getMessage());
case FailedSendMessage:
throw new IllegalDiameterStateException(e);
default:
throw new InternalException(e);
}
}
}
public void disconnect() throws InternalException, IllegalDiameterStateException {
if (connection != null) {
connection.disconnect();
logger.debug("Disconnected from peer {}", PeerImpl.this.getUri());
}
}
public String getPeerDescription() {
return PeerImpl.this.toString();
}
public boolean isConnected() {
return (connection != null) && connection.isConnected();
}
public boolean sendMessage(IMessage message) throws TransportException, OverloadException {
// Check message
if (message.isTimeOut()) {
logger.debug( "Message {} skipped (timeout)", message);
return false;
}
if (message.getState() == IMessage.STATE_SENT) {
logger.debug( "Message {} already sent", message);
return false;
}
// Remove destionation information from answer messages
if ( !message.isRequest() ) {
message.getAvps().removeAvp(DESTINATION_HOST);
message.getAvps().removeAvp(DESTINATION_REALM);
}
// Send to network
message.setState(IMessage.STATE_SENT);
connection.sendMessage(message);
logger.debug("Send message {} to peer {}", message, PeerImpl.this.getUri());
return true;
}
public void sendCerMessage() throws TransportException, OverloadException {
logger.debug("Send CER message");
IMessage message = parser.createEmptyMessage(CAPABILITIES_EXCHANGE_REQUEST, 0);
message.setRequest(true);
message.setHopByHopIdentifier(getHopByHopIdentifier());
if (useUriAsFQDN) {
message.getAvps().addAvp(ORIGIN_HOST, metaData.getLocalPeer().getUri().toString(), true, false, true);
}
else {
message.getAvps().addAvp(ORIGIN_HOST, metaData.getLocalPeer().getUri().getFQDN(), true, false, true);
}
message.getAvps().addAvp(ORIGIN_REALM, metaData.getLocalPeer().getRealmName(), true, false, true);
for (InetAddress ia : metaData.getLocalPeer().getIPAddresses()) {
message.getAvps().addAvp(HOST_IP_ADDRESS, ia, true, false);
}
message.getAvps().addAvp(VENDOR_ID, metaData.getLocalPeer().getVendorId(), true, false, true);
message.getAvps().addAvp(PRODUCT_NAME, metaData.getLocalPeer().getProductName(), false);
for (ApplicationId appId: metaData.getLocalPeer().getCommonApplications()) {
addAppId(appId, message);
}
message.getAvps().addAvp(FIRMWARE_REVISION, metaData.getLocalPeer().getFirmware(), true );
message.getAvps().addAvp(ORIGIN_STATE_ID, metaData.getLocalHostStateId(), true, false, true);
sendMessage(message);
}
public void sendCeaMessage(int resultCode, Message cer, String errMessage) throws TransportException, OverloadException {
}
public void sendDwrMessage() throws TransportException, OverloadException {
logger.debug("Send DWR message");
IMessage message = parser.createEmptyMessage( DEVICE_WATCHDOG_REQUEST, 0 );
message.setRequest(true);
message.setHopByHopIdentifier(getHopByHopIdentifier());
// Set content
message.getAvps().addAvp(ORIGIN_HOST, metaData.getLocalPeer().getUri().getFQDN(), true, false, true);
message.getAvps().addAvp(ORIGIN_REALM, metaData.getLocalPeer().getRealmName(), true, false, true);
message.getAvps().addAvp(ORIGIN_STATE_ID, metaData.getLocalHostStateId(), true, false, true);
// Remove trash avp
message.getAvps().removeAvp(DESTINATION_HOST);
message.getAvps().removeAvp(DESTINATION_REALM);
// Send
sendMessage(message);
}
public void sendDwaMessage(IMessage dwr, int resultCode, String errorMessage) throws TransportException, OverloadException {
logger.debug("Send DWA message");
IMessage message = parser.createEmptyMessage(dwr);
message.setRequest(false);
message.setHopByHopIdentifier(dwr.getHopByHopIdentifier());
message.setEndToEndIdentifier(dwr.getEndToEndIdentifier());
// Set content
message.getAvps().addAvp(RESULT_CODE, resultCode, true, false, true);
if (errorMessage != null) {
message.getAvps().addAvp(ERROR_MESSAGE, errorMessage, false);
}
// Remove trash avp
message.getAvps().removeAvp(DESTINATION_HOST);
message.getAvps().removeAvp(DESTINATION_REALM);
// Send
sendMessage(message);
}
public boolean isRestoreConnection() {
return true;
}
public void sendDprMessage(int disconnectCause) throws TransportException, OverloadException {
logger.debug("Send DPR message");
IMessage message = parser.createEmptyMessage(DISCONNECT_PEER_REQUEST, 0 );
message.setRequest(true);
message.setHopByHopIdentifier(getHopByHopIdentifier());
message.getAvps().addAvp(ORIGIN_HOST, metaData.getLocalPeer().getUri().getFQDN(), true, false, true);
message.getAvps().addAvp(ORIGIN_REALM, metaData.getLocalPeer().getRealmName(), true, false, true);
message.getAvps().addAvp(DISCONNECT_CAUSE, disconnectCause, true, false );
sendMessage(message);
}
public void sendDpaMessage(IMessage dpr, int resultCode, String errorMessage) throws TransportException, OverloadException {
logger.debug("Send DPA message");
IMessage message = parser.createEmptyMessage(dpr);
message.setRequest(false);
message.setHopByHopIdentifier(dpr.getHopByHopIdentifier());
message.setEndToEndIdentifier(dpr.getEndToEndIdentifier());
message.getAvps().addAvp(RESULT_CODE, resultCode, true, false, true);
if (errorMessage != null) {
message.getAvps().addAvp(ERROR_MESSAGE, errorMessage, false);
}
sendMessage(message);
}
public int processCerMessage(String key, IMessage message) {
return 0;
}
public boolean processCeaMessage(String key, IMessage message) {
boolean rc = true;
try {
Avp origHost = message.getAvps().getAvp(ORIGIN_HOST);
Avp origRealm = message.getAvps().getAvp(ORIGIN_REALM);
Avp vendorId = message.getAvps().getAvp(VENDOR_ID);
Avp prdName = message.getAvps().getAvp(PRODUCT_NAME);
Avp resCode = message.getAvps().getAvp(RESULT_CODE);
Avp frmId = message.getAvps().getAvp(FIRMWARE_REVISION);
if (origHost == null || origRealm == null || vendorId == null) {
logger.debug("Incorrect CEA message (missing mandatory AVPs)");
}
else {
if (realmName == null) {
realmName = origRealm.getOctetString();
}
if (vendorID == 0) {
vendorID = vendorId.getUnsigned32();
}
fillIPAddressTable(message);
if (productName == null && prdName != null) {
productName = prdName.getUTF8String();
}
if (resCode != null) {
int mrc = resCode.getInteger32();
if (mrc != ResultCode.SUCCESS) {
logger.debug("Result code value {}", mrc);
return false;
}
}
Set<ApplicationId> cai = getCommonApplicationIds(message);
if (cai.size() > 0) {
commonApplications.clear();
commonApplications.addAll(cai);
} else {
logger.debug("CEA did not containe appId, therefore set local appids to common-appid field");
commonApplications.clear();
commonApplications.addAll(metaData.getLocalPeer().getCommonApplications());
}
if (firmWare == 0 && frmId != null) {
firmWare = frmId.getInteger32();
}
}
}
catch(Exception exc) {
logger.debug("Incorrect CEA message", exc);
rc = false;
}
return rc;
}
public boolean receiveMessage(IMessage message) {
boolean isProcessed = false;
if ( !message.isRequest() ) {
IMessage request = peerRequests.remove( message.getHopByHopIdentifier() );
if ( request != null && !request.isTimeOut()) {
request.clearTimer();
request.setState(IMessage.STATE_ANSWERED);
Avp avpResCode = message.getAvps().getAvp( RESULT_CODE );
if (isRedirectAnswer(avpResCode, message)) {
message.setListener(request.getEventListener());
message = processRedirectAnswer( message );
isProcessed = message == null;
}
if (message != null) {
request.getEventListener().receivedSuccessMessage( request, message );
isProcessed = true;
}
}
} else {
// Server request
String avpSessionId = message.getSessionId();
if (avpSessionId != null) {
NetworkReqListener listener = slc.get(avpSessionId);
if (listener != null) {
router.registerRequestRouteInfo( message );
preProcessRequest(message);
IMessage answer = (IMessage) listener.processRequest(message);
if (answer != null) {
try {
sendMessage(answer);
} catch (Exception e) {
logger.warn("Can not send immediate answer {}", answer);
}
}
isProcessed = true;
}
}
}
return isProcessed;
}
public int processDwrMessage(IMessage iMessage) {
return ResultCode.SUCCESS;
}
public int processDprMessage(IMessage iMessage) {
return ResultCode.SUCCESS;
}
protected void addAppId(ApplicationId appId, IMessage message) { // todo duplicate code look SessionImpl 225 line
if (appId.getVendorId() == 0) {
if (appId.getAuthAppId() != 0) {
message.getAvps().addAvp( AUTH_APPLICATION_ID, appId.getAuthAppId(), true, false, true );
}
else if (appId.getAcctAppId() != 0) {
message.getAvps().addAvp( ACCT_APPLICATION_ID, appId.getAcctAppId(), true, false, true );
}
}
else {
message.getAvps().addAvp( SUPPORTED_VENDOR_ID, appId.getVendorId(), true, false, true);
AvpSet vendorApp = message.getAvps().addGroupedAvp(VENDOR_SPECIFIC_APPLICATION_ID, true, false );
vendorApp.addAvp(VENDOR_ID, appId.getVendorId(), true, false, true );
if (appId.getAuthAppId() != 0) {
vendorApp.addAvp( AUTH_APPLICATION_ID, appId.getAuthAppId(), true, false, true );
}
if (appId.getAcctAppId() != 0) {
vendorApp.addAvp( ACCT_APPLICATION_ID, appId.getAcctAppId(), true, false, true );
}
}
}
}
}