diff --git a/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/client/slg/ClientSLgSessionDataReplicatedImpl.java b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/client/slg/ClientSLgSessionDataReplicatedImpl.java
new file mode 100644
index 000000000..d11876c4a
--- /dev/null
+++ b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/client/slg/ClientSLgSessionDataReplicatedImpl.java
@@ -0,0 +1,64 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, Telestax Inc and individual contributors
+ * by the @authors tag.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.mobicents.diameter.impl.ha.client.slg;
+
+import org.restcomm.cache.FqnWrapper;
+import org.jdiameter.api.slg.ClientSLgSession;
+import org.jdiameter.client.api.IContainer;
+import org.jdiameter.client.impl.app.slg.IClientSLgSessionData;
+import org.jdiameter.common.api.app.slg.SLgSessionState;
+import org.restcomm.cluster.MobicentsCluster;
+import org.mobicents.diameter.impl.ha.common.slg.SLgSessionDataReplicatedImpl;
+import org.mobicents.diameter.impl.ha.data.ReplicatedSessionDatasource;
+
+/**
+ *
+ * @author Fernando Mendioroz
+ *
+ */
+public class ClientSLgSessionDataReplicatedImpl extends SLgSessionDataReplicatedImpl implements IClientSLgSessionData {
+
+ /**
+ * @param nodeFqnWrapper
+ * @param mobicentsCluster
+ * @param container
+ */
+ public ClientSLgSessionDataReplicatedImpl(FqnWrapper nodeFqnWrapper, MobicentsCluster mobicentsCluster, IContainer container) {
+ super(nodeFqnWrapper, mobicentsCluster, container);
+
+ if (super.create()) {
+ setAppSessionIface(this, ClientSLgSession.class);
+ setSLgSessionState(SLgSessionState.IDLE);
+ }
+ }
+
+ /**
+ * @param sessionId
+ * @param mobicentsCluster
+ * @param container
+ */
+ public ClientSLgSessionDataReplicatedImpl(String sessionId, MobicentsCluster mobicentsCluster, IContainer container) {
+ this(
+ FqnWrapper.fromRelativeElementsWrapper(ReplicatedSessionDatasource.SESSIONS_FQN, sessionId), mobicentsCluster, container);
+ }
+
+}
diff --git a/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/client/slh/ClientSLhSessionDataReplicatedImpl.java b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/client/slh/ClientSLhSessionDataReplicatedImpl.java
new file mode 100644
index 000000000..016b09fa9
--- /dev/null
+++ b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/client/slh/ClientSLhSessionDataReplicatedImpl.java
@@ -0,0 +1,64 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, Telestax Inc and individual contributors
+ * by the @authors tag.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.mobicents.diameter.impl.ha.client.slh;
+
+import org.restcomm.cache.FqnWrapper;
+import org.jdiameter.api.slh.ClientSLhSession;
+import org.jdiameter.client.api.IContainer;
+import org.jdiameter.client.impl.app.slh.IClientSLhSessionData;
+import org.jdiameter.common.api.app.slh.SLhSessionState;
+import org.restcomm.cluster.MobicentsCluster;
+import org.mobicents.diameter.impl.ha.common.slh.SLhSessionDataReplicatedImpl;
+import org.mobicents.diameter.impl.ha.data.ReplicatedSessionDatasource;
+
+/**
+ *
+ * @author Fernando Mendioroz
+ *
+ */
+public class ClientSLhSessionDataReplicatedImpl extends SLhSessionDataReplicatedImpl implements IClientSLhSessionData {
+
+ /**
+ * @param nodeFqnWrapper
+ * @param mobicentsCluster
+ * @param container
+ */
+ public ClientSLhSessionDataReplicatedImpl(FqnWrapper nodeFqnWrapper, MobicentsCluster mobicentsCluster, IContainer container) {
+ super(nodeFqnWrapper, mobicentsCluster, container);
+
+ if (super.create()) {
+ setAppSessionIface(this, ClientSLhSession.class);
+ setSLhSessionState(SLhSessionState.IDLE);
+ }
+ }
+
+ /**
+ * @param sessionId
+ * @param mobicentsCluster
+ * @param container
+ */
+ public ClientSLhSessionDataReplicatedImpl(String sessionId, MobicentsCluster mobicentsCluster, IContainer container) {
+ this(
+ FqnWrapper.fromRelativeElementsWrapper(ReplicatedSessionDatasource.SESSIONS_FQN, sessionId), mobicentsCluster, container);
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/common/slg/SLgReplicatedSessionDataFactory.java b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/common/slg/SLgReplicatedSessionDataFactory.java
new file mode 100644
index 000000000..c54544bb6
--- /dev/null
+++ b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/common/slg/SLgReplicatedSessionDataFactory.java
@@ -0,0 +1,72 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, Telestax Inc and individual contributors
+ * by the @authors tag.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.mobicents.diameter.impl.ha.common.slg;
+
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.slg.ClientSLgSession;
+import org.jdiameter.api.slg.ServerSLgSession;
+import org.jdiameter.common.api.app.IAppSessionDataFactory;
+import org.jdiameter.common.api.app.slg.ISLgSessionData;
+import org.jdiameter.common.api.data.ISessionDatasource;
+import org.restcomm.cluster.MobicentsCluster;
+import org.mobicents.diameter.impl.ha.client.slg.ClientSLgSessionDataReplicatedImpl;
+import org.mobicents.diameter.impl.ha.data.ReplicatedSessionDatasource;
+import org.mobicents.diameter.impl.ha.server.slg.ServerSLgSessionDataReplicatedImpl;
+
+/**
+ *
+ * @author Fernando Mendioroz
+ *
+ */
+public class SLgReplicatedSessionDataFactory implements IAppSessionDataFactory {
+
+ private ReplicatedSessionDatasource replicatedSessionDataSource;
+ private MobicentsCluster mobicentsCluster;
+
+ /**
+ * @param replicatedSessionDataSource
+ */
+ public SLgReplicatedSessionDataFactory(ISessionDatasource replicatedSessionDataSource) { // Is this ok?
+ super();
+ this.replicatedSessionDataSource = (ReplicatedSessionDatasource) replicatedSessionDataSource;
+ this.mobicentsCluster = this.replicatedSessionDataSource.getMobicentsCluster();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jdiameter.common.api.app.IAppSessionDataFactory#getAppSessionData(java.lang.Class, java.lang.String)
+ */
+ public ISLgSessionData getAppSessionData(Class extends AppSession> clazz, String sessionId) {
+ if (clazz.equals(ClientSLgSession.class)) {
+ ClientSLgSessionDataReplicatedImpl data = new ClientSLgSessionDataReplicatedImpl(sessionId, this.mobicentsCluster,
+ this.replicatedSessionDataSource.getContainer());
+ return data;
+ } else if (clazz.equals(ServerSLgSession.class)) {
+ ServerSLgSessionDataReplicatedImpl data = new ServerSLgSessionDataReplicatedImpl(sessionId, this.mobicentsCluster,
+ this.replicatedSessionDataSource.getContainer());
+ return data;
+ }
+ throw new IllegalArgumentException();
+ }
+
+}
diff --git a/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/common/slg/SLgSessionDataReplicatedImpl.java b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/common/slg/SLgSessionDataReplicatedImpl.java
new file mode 100644
index 000000000..cc69afa49
--- /dev/null
+++ b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/common/slg/SLgSessionDataReplicatedImpl.java
@@ -0,0 +1,150 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, Telestax Inc and individual contributors
+ * by the @authors tag.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.mobicents.diameter.impl.ha.common.slg;
+
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+
+import org.restcomm.cache.FqnWrapper;
+import org.jdiameter.api.AvpDataException;
+import org.jdiameter.api.Request;
+import org.jdiameter.client.api.IContainer;
+import org.jdiameter.client.api.IMessage;
+import org.jdiameter.client.api.parser.IMessageParser;
+import org.jdiameter.client.api.parser.ParseException;
+import org.jdiameter.common.api.app.slg.SLgSessionState;
+import org.jdiameter.common.api.app.slg.ISLgSessionData;
+import org.restcomm.cluster.MobicentsCluster;
+import org.mobicents.diameter.impl.ha.common.AppSessionDataReplicatedImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author Fernando Mendioroz
+ *
+ */
+public abstract class SLgSessionDataReplicatedImpl extends AppSessionDataReplicatedImpl implements ISLgSessionData {
+
+ private static final Logger logger = LoggerFactory.getLogger(SLgSessionDataReplicatedImpl.class);
+
+ private static final String STATE = "STATE";
+ private static final String BUFFER = "BUFFER";
+ private static final String TS_TIMERID = "TS_TIMERID";
+
+ private IMessageParser messageParser;
+
+ /**
+ * @param nodeFqnWrapper
+ * @param mobicentsCluster
+ * @param container
+ */
+ public SLgSessionDataReplicatedImpl(FqnWrapper nodeFqnWrapper, MobicentsCluster mobicentsCluster, IContainer container) {
+ super(nodeFqnWrapper, mobicentsCluster);
+ this.messageParser = container.getAssemblerFacility().getComponentInstance(IMessageParser.class);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jdiameter.common.api.app.slg.ISLgSessionData#setSLgSessionState(org.jdiameter.common.api.app.slg.SLgSessionState)
+ */
+ public void setSLgSessionState(SLgSessionState state) {
+ if (exists()) {
+ getNode().put(STATE, state);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jdiameter.common.api.app.slg.ISLgSessionData#getSLgSessionState()
+ */
+ public SLgSessionState getSLgSessionState() {
+ if (exists()) {
+ return (SLgSessionState) getNode().get(STATE);
+ }
+ else {
+ throw new IllegalStateException();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jdiameter.common.api.app.slg.ISLgSessionData#getTsTimerId()
+ */
+ public Serializable getTsTimerId() {
+ if (exists()) {
+ return (Serializable) getNode().get(TS_TIMERID);
+ }
+ else {
+ throw new IllegalStateException();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jdiameter.common.api.app.slg.ISLgSessionData#setTsTimerId(java.io.Serializable)
+ */
+ public void setTsTimerId(Serializable tid) {
+ if (exists()) {
+ getNode().put(TS_TIMERID, tid);
+ }
+ else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public Request getBuffer() {
+ byte[] data = (byte[]) getNode().get(BUFFER);
+ if (data != null) {
+ try {
+ return (Request) this.messageParser.createMessage(ByteBuffer.wrap(data));
+ } catch (AvpDataException e) {
+ logger.error("Unable to recreate message from buffer.");
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ public void setBuffer(Request buffer) {
+ if (buffer != null) {
+ try {
+ byte[] data = this.messageParser.encodeMessage((IMessage) buffer).array();
+ getNode().put(BUFFER, data);
+ }
+ catch (ParseException e) {
+ logger.error("Unable to encode message to buffer.");
+ }
+ }
+ else {
+ getNode().remove(BUFFER);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/common/slh/SLhReplicatedSessionDataFactory.java b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/common/slh/SLhReplicatedSessionDataFactory.java
new file mode 100644
index 000000000..2f337ce45
--- /dev/null
+++ b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/common/slh/SLhReplicatedSessionDataFactory.java
@@ -0,0 +1,72 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, Telestax Inc and individual contributors
+ * by the @authors tag.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.mobicents.diameter.impl.ha.common.slh;
+
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.slh.ClientSLhSession;
+import org.jdiameter.api.slh.ServerSLhSession;
+import org.jdiameter.common.api.app.IAppSessionDataFactory;
+import org.jdiameter.common.api.app.slh.ISLhSessionData;
+import org.jdiameter.common.api.data.ISessionDatasource;
+import org.restcomm.cluster.MobicentsCluster;
+import org.mobicents.diameter.impl.ha.client.slh.ClientSLhSessionDataReplicatedImpl;
+import org.mobicents.diameter.impl.ha.data.ReplicatedSessionDatasource;
+import org.mobicents.diameter.impl.ha.server.slh.ServerSLhSessionDataReplicatedImpl;
+
+/**
+ *
+ * @author Fernando Mendioroz
+ *
+ */
+public class SLhReplicatedSessionDataFactory implements IAppSessionDataFactory {
+
+ private ReplicatedSessionDatasource replicatedSessionDataSource;
+ private MobicentsCluster mobicentsCluster;
+
+ /**
+ * @param replicatedSessionDataSource
+ */
+ public SLhReplicatedSessionDataFactory(ISessionDatasource replicatedSessionDataSource) { // Is this ok?
+ // super();
+ this.replicatedSessionDataSource = (ReplicatedSessionDatasource) replicatedSessionDataSource;
+ this.mobicentsCluster = this.replicatedSessionDataSource.getMobicentsCluster();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jdiameter.common.api.app.IAppSessionDataFactory#getAppSessionData(java.lang.Class, java.lang.String)
+ */
+ public ISLhSessionData getAppSessionData(Class extends AppSession> clazz, String sessionId) {
+ if (clazz.equals(ClientSLhSession.class)) {
+ ClientSLhSessionDataReplicatedImpl data = new ClientSLhSessionDataReplicatedImpl(sessionId, this.mobicentsCluster,
+ this.replicatedSessionDataSource.getContainer());
+ return data;
+ } else if (clazz.equals(ServerSLhSession.class)) {
+ ServerSLhSessionDataReplicatedImpl data = new ServerSLhSessionDataReplicatedImpl(sessionId, this.mobicentsCluster,
+ this.replicatedSessionDataSource.getContainer());
+ return data;
+ }
+ throw new IllegalArgumentException();
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/common/slh/SLhSessionDataReplicatedImpl.java b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/common/slh/SLhSessionDataReplicatedImpl.java
new file mode 100644
index 000000000..a8058ab0a
--- /dev/null
+++ b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/common/slh/SLhSessionDataReplicatedImpl.java
@@ -0,0 +1,146 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, Telestax Inc and individual contributors
+ * by the @authors tag.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.mobicents.diameter.impl.ha.common.slh;
+
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+
+import org.restcomm.cache.FqnWrapper;
+import org.jdiameter.api.AvpDataException;
+import org.jdiameter.api.Request;
+import org.jdiameter.client.api.IContainer;
+import org.jdiameter.client.api.IMessage;
+import org.jdiameter.client.api.parser.IMessageParser;
+import org.jdiameter.client.api.parser.ParseException;
+import org.jdiameter.common.api.app.slh.SLhSessionState;
+import org.jdiameter.common.api.app.slh.ISLhSessionData;
+import org.restcomm.cluster.MobicentsCluster;
+import org.mobicents.diameter.impl.ha.common.AppSessionDataReplicatedImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author Fernando Mendioroz
+ *
+ */
+public abstract class SLhSessionDataReplicatedImpl extends AppSessionDataReplicatedImpl implements ISLhSessionData {
+
+ private static final Logger logger = LoggerFactory.getLogger(SLhSessionDataReplicatedImpl.class);
+
+ private static final String STATE = "STATE";
+ private static final String BUFFER = "BUFFER";
+ private static final String TS_TIMERID = "TS_TIMERID";
+
+ private IMessageParser messageParser;
+
+ /**
+ * @param nodeFqnWrapper
+ * @param mobicentsCluster
+ * @param container
+ */
+ public SLhSessionDataReplicatedImpl(FqnWrapper nodeFqnWrapper, MobicentsCluster mobicentsCluster, IContainer container) {
+ super(nodeFqnWrapper, mobicentsCluster);
+ this.messageParser = container.getAssemblerFacility().getComponentInstance(IMessageParser.class);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jdiameter.common.api.app.slh.ISLhSessionData#setSLhSessionState(org.jdiameter.common.api.app.slh.SLhSessionState)
+ */
+ public void setSLhSessionState(SLhSessionState state) {
+ if (exists()) {
+ getNode().put(STATE, state);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jdiameter.common.api.app.slh.ISLhSessionData#getSLhSessionState()
+ */
+ public SLhSessionState getSLhSessionState() {
+ if (exists()) {
+ return (SLhSessionState) getNode().get(STATE);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jdiameter.common.api.app.slh.ISLhSessionData#getTsTimerId()
+ */
+ public Serializable getTsTimerId() {
+ if (exists()) {
+ return (Serializable) getNode().get(TS_TIMERID);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.jdiameter.common.api.app.slh.ISLhSessionData#setTsTimerId(java.io.Serializable)
+ */
+ public void setTsTimerId(Serializable tid) {
+ if (exists()) {
+ getNode().put(TS_TIMERID, tid);
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+
+ public Request getBuffer() {
+ byte[] data = (byte[]) getNode().get(BUFFER);
+ if (data != null) {
+ try {
+ return (Request) this.messageParser.createMessage(ByteBuffer.wrap(data));
+ } catch (AvpDataException e) {
+ logger.error("Unable to recreate message from buffer.");
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ public void setBuffer(Request buffer) {
+ if (buffer != null) {
+ try {
+ byte[] data = this.messageParser.encodeMessage((IMessage) buffer).array();
+ getNode().put(BUFFER, data);
+ }
+ catch (ParseException e) {
+ logger.error("Unable to encode message to buffer.");
+ }
+ } else {
+ getNode().remove(BUFFER);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/data/ReplicatedSessionDatasource.java b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/data/ReplicatedSessionDatasource.java
index 1ca5eb44a..d1158d540 100644
--- a/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/data/ReplicatedSessionDatasource.java
+++ b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/data/ReplicatedSessionDatasource.java
@@ -67,6 +67,8 @@
import org.jdiameter.common.api.app.sh.IShSessionData;
import org.jdiameter.common.api.data.ISessionDatasource;
import org.jdiameter.common.impl.data.LocalDataSource;
+import org.jdiameter.common.api.app.slh.ISLhSessionData;
+import org.jdiameter.common.api.app.slg.ISLgSessionData;
import org.restcomm.cache.FqnWrapper;
import org.restcomm.cache.MobicentsCache;
import org.restcomm.cluster.DataRemovalListener;
@@ -84,6 +86,8 @@
import org.mobicents.diameter.impl.ha.common.rx.RxReplicatedSessionDataFactory;
import org.mobicents.diameter.impl.ha.common.s13.S13ReplicatedSessionDataFactory;
import org.mobicents.diameter.impl.ha.common.sh.ShReplicatedSessionDataFactory;
+import org.mobicents.diameter.impl.ha.common.slh.SLhReplicatedSessionDataFactory;
+import org.mobicents.diameter.impl.ha.common.slg.SLgReplicatedSessionDataFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -137,7 +141,7 @@ public ReplicatedSessionDatasource(IContainer container, ISessionDatasource loca
this.mobicentsCluster.startCluster();
this.container = container;
- // this is coded, its tied to specific impl of SessionDatasource
+ // this is coded, it is tied to specific impl of SessionDatasource
appSessionDataFactories.put(IAuthSessionData.class, new AuthReplicatedSessionDataFactory(this));
appSessionDataFactories.put(IAccSessionData.class, new AccReplicatedSessionDataFactory(this));
appSessionDataFactories.put(ICCASessionData.class, new CCAReplicatedSessionDataFactory(this));
@@ -148,6 +152,8 @@ public ReplicatedSessionDatasource(IContainer container, ISessionDatasource loca
appSessionDataFactories.put(IGxSessionData.class, new GxReplicatedSessionDataFactory(this));
appSessionDataFactories.put(IRxSessionData.class, new RxReplicatedSessionDataFactory(this));
appSessionDataFactories.put(IS13SessionData.class, new S13ReplicatedSessionDataFactory(this));
+ appSessionDataFactories.put(ISLhSessionData.class, new SLhReplicatedSessionDataFactory(this));
+ appSessionDataFactories.put(ISLgSessionData.class, new SLgReplicatedSessionDataFactory(this));
}
diff --git a/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/server/slg/ServerSLgSessionDataReplicatedImpl.java b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/server/slg/ServerSLgSessionDataReplicatedImpl.java
new file mode 100644
index 000000000..62f1380c9
--- /dev/null
+++ b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/server/slg/ServerSLgSessionDataReplicatedImpl.java
@@ -0,0 +1,64 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, Telestax Inc and individual contributors
+ * by the @authors tag.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.mobicents.diameter.impl.ha.server.slg;
+
+import org.restcomm.cache.FqnWrapper;
+import org.jdiameter.api.slg.ServerSLgSession;
+import org.jdiameter.client.api.IContainer;
+import org.jdiameter.common.api.app.slg.SLgSessionState;
+import org.jdiameter.server.impl.app.slg.IServerSLgSessionData;
+import org.restcomm.cluster.MobicentsCluster;
+import org.mobicents.diameter.impl.ha.common.slg.SLgSessionDataReplicatedImpl;
+import org.mobicents.diameter.impl.ha.data.ReplicatedSessionDatasource;
+
+/**
+ *
+ * @author Fernando Mendioroz
+ *
+ */
+public class ServerSLgSessionDataReplicatedImpl extends SLgSessionDataReplicatedImpl implements IServerSLgSessionData {
+
+ /**
+ * @param nodeFqnWrapper
+ * @param mobicentsCluster
+ * @param container
+ */
+ public ServerSLgSessionDataReplicatedImpl(FqnWrapper nodeFqnWrapper, MobicentsCluster mobicentsCluster, IContainer container) {
+ super(nodeFqnWrapper, mobicentsCluster, container);
+
+ if (super.create()) {
+ setAppSessionIface(this, ServerSLgSession.class);
+ setSLgSessionState(SLgSessionState.IDLE);
+ }
+ }
+
+ /**
+ * @param sessionId
+ * @param mobicentsCluster
+ * @param container
+ */
+ public ServerSLgSessionDataReplicatedImpl(String sessionId, MobicentsCluster mobicentsCluster, IContainer container) {
+ this(
+ FqnWrapper.fromRelativeElementsWrapper(ReplicatedSessionDatasource.SESSIONS_FQN, sessionId), mobicentsCluster, container);
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/server/slh/ServerSLhSessionDataReplicatedImpl.java b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/server/slh/ServerSLhSessionDataReplicatedImpl.java
new file mode 100644
index 000000000..4af47f1bf
--- /dev/null
+++ b/core/jdiameter-ha/impl/src/main/java/org/mobicents/diameter/impl/ha/server/slh/ServerSLhSessionDataReplicatedImpl.java
@@ -0,0 +1,64 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, Telestax Inc and individual contributors
+ * by the @authors tag.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.mobicents.diameter.impl.ha.server.slh;
+
+import org.restcomm.cache.FqnWrapper;
+import org.jdiameter.api.slh.ServerSLhSession;
+import org.jdiameter.client.api.IContainer;
+import org.jdiameter.common.api.app.slh.SLhSessionState;
+import org.jdiameter.server.impl.app.slh.IServerSLhSessionData;
+import org.restcomm.cluster.MobicentsCluster;
+import org.mobicents.diameter.impl.ha.common.slh.SLhSessionDataReplicatedImpl;
+import org.mobicents.diameter.impl.ha.data.ReplicatedSessionDatasource;
+
+/**
+ *
+ * @author Fernando Mendioroz
+ *
+ */
+public class ServerSLhSessionDataReplicatedImpl extends SLhSessionDataReplicatedImpl implements IServerSLhSessionData {
+
+ /**
+ * @param nodeFqnWrapper
+ * @param mobicentsCluster
+ * @param container
+ */
+ public ServerSLhSessionDataReplicatedImpl(FqnWrapper nodeFqnWrapper, MobicentsCluster mobicentsCluster, IContainer container) {
+ super(nodeFqnWrapper, mobicentsCluster, container);
+
+ if (super.create()) {
+ setAppSessionIface(this, ServerSLhSession.class);
+ setSLhSessionState(SLhSessionState.IDLE);
+ }
+ }
+
+ /**
+ * @param sessionId
+ * @param mobicentsCluster
+ * @param container
+ */
+ public ServerSLhSessionDataReplicatedImpl(String sessionId, MobicentsCluster mobicentsCluster, IContainer container) {
+ this(
+ FqnWrapper.fromRelativeElementsWrapper(ReplicatedSessionDatasource.SESSIONS_FQN, sessionId), mobicentsCluster, container);
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/api/src/main/java/org/jdiameter/api/Avp.java b/core/jdiameter/api/src/main/java/org/jdiameter/api/Avp.java
index c020f35ae..7afe1767e 100644
--- a/core/jdiameter/api/src/main/java/org/jdiameter/api/Avp.java
+++ b/core/jdiameter/api/src/main/java/org/jdiameter/api/Avp.java
@@ -2302,6 +2302,427 @@ public interface Avp extends Wrapper, Serializable {
*/
int TGPP2_MEID = 1471;
+ /********************************************************/
+ /*** SLh interface (GMLC - HSS) AVPs (3GPP TS 29.173) ***/
+ /********************************************************/
+
+ /**
+ * SLh (3GPP TS 29.173) LMSI AVP code
+ */
+ int LMSI = 2400;
+
+ /**
+ * SLh (3GPP TS 29.173) Serving-Node AVP code
+ */
+ int SERVING_NODE = 2401;
+
+ /**
+ * SLh (3GPP TS 29.173) MME-Name AVP code
+ */
+ int MME_NAME = 2402;
+
+ /**
+ * SLh (3GPP TS 29.173) MCS-Number AVP code
+ */
+ int MSC_NUMBER = 2403;
+
+ /**
+ * SLh (3GPP TS 29.173) LCS-Capabilities-Sets AVP code
+ */
+ int LCS_CAPABILITIES_SETS = 2404;
+
+ /**
+ * SLh (3GPP TS 29.173) GMLC-Address AVP code
+ */
+ int GMLC_ADDRESS = 2405;
+
+ /**
+ * SLh (3GPP TS 29.173) Additional-Serving-Node AVP code
+ */
+ int ADDITIONAL_SERVING_NODE = 2406;
+
+ /**
+ * SLh (3GPP TS 29.173) PPR-Address AVP code
+ */
+ int PPR_ADDRESS = 2407;
+
+ /**
+ * SLh (3GPP TS 29.173) MME-Realm AVP code
+ */
+ int MME_REALM = 2408;
+
+ /**
+ * SLh (3GPP TS 29.173) SGSN-Name AVP code
+ */
+ int SGSN_NAME = 2409;
+
+ /**
+ * SLh (3GPP TS 29.173) SGSN-Realm AVP code
+ */
+ int SGSN_REALM = 2410;
+
+ /**
+ * SLh (3GPP TS 29.173) RIA-Flags AVP code
+ */
+ int RIA_FLAGS = 2411;
+
+ /**
+ * SLh (3GPP TS 29.173) SGSN-Number AVP code (reused from 3GPP TS 29.272, MME - SGSN interface)
+ */
+ int SGSN_NUMBER = 1489;
+
+ /**
+ * SLh (3GPP TS 29.173) GMLC-Number AVP code (reused from 3GPP TS 29.272, MME - SGSN interface)
+ */
+ int GMLC_NUMBER = 1474;
+
+ /**
+ * SLh (3GPP TS 29.173) 3GPP-AAA-Server-Name AVP code (reused from 3GPP TS 29.273, 3GPP AAA EPS interface)
+ */
+ int TGPP_AAA_SERVER_NAME = 318;
+
+ // SLh re-used Diameter AVPs:
+ // MSISDN 3GPP TS 29.329;
+ // SGSN-Number 3GPP TS 29.272;
+ // Supported-Features 3GPP TS 29.229;
+ // Feature-List-ID 3GPP TS 29.229;
+ // Feature-List 3GPP TS 29.229;
+ // GMLC-Number 3GPP TS 29.272;
+ // 3GPP-AAA-Server-Name 3GPP TS 29.273
+
+ /********************************************************/
+ /*** SLg interface (GMLC - MME) AVPs (3GPP TS 29.172) ***/
+ /*** Diameter ELP Application (EPC LCS Protocol) ***/
+ /********************************************************/
+
+ /**
+ * SLg (3GPP TS 29.172) SLg-Location-Type AVP code
+ */
+ int SLG_LOCATION_TYPE = 2500;
+
+ /**
+ * SLg (3GPP TS 29.172) LCS-EPS-Client-Name AVP code
+ */
+ int LCS_EPS_CLIENT_NAME = 2501;
+
+ /**
+ * SLg (3GPP TS 29.172) LCS_Requestor_Name AVP code
+ */
+ int LCS_REQUESTOR_NAME = 2502;
+
+ /**
+ * SLg (3GPP TS 29.172) LCS-Priority AVP code
+ */
+ int LCS_PRIORITY = 2503;
+
+ /**
+ * SLg (3GPP TS 29.172) LCS-QoS AVP code
+ */
+ int LCS_QOS = 2504;
+
+ /**
+ * SLg (3GPP TS 29.172) Horizontal-Accuracy AVP code
+ */
+ int HORIZONTAL_ACCURACY = 2505;
+
+ /**
+ * SLg (3GPP TS 29.172) Vertical-Accuracy AVP code
+ */
+ int VERTICAL_ACCURACY = 2506;
+
+ /**
+ * SLg (3GPP TS 29.172) Vertical-Requested AVP code
+ */
+ int VERTICAL_REQUESTED = 2507;
+
+ /**
+ * SLg (3GPP TS 29.172) Velocity-Requested AVP code
+ */
+ int VELOCITY_REQUESTED = 2508;
+
+ /**
+ * SLg (3GPP TS 29.172) Response-Time AVP code
+ */
+ int RESPONSE_TIME = 2509;
+
+ /**
+ * SLg (3GPP TS 29.172) Supported-GAD-Shapes AVP code
+ */
+ int SUPPORTED_GAD_SHAPES = 2510;
+
+ /**
+ * SLg (3GPP TS 29.172) LCS-Codeword AVP code
+ */
+ int LCS_CODEWORD = 2511;
+
+ /**
+ * SLg (3GPP TS 29.172) LCS-Privacy-Check AVP code
+ */
+ int LCS_PRIVACY_CHECK = 2512;
+
+ /**
+ * SLg (3GPP TS 29.172) Accuracy-Fulfilment-Indicator AVP code
+ */
+ int ACCURACY_FULFILMENT_INDICATOR = 2513;
+
+ /**
+ * SLg (3GPP TS 29.172) Age-Of-Location-Estimate AVP code
+ */
+ int AGE_OF_LOCATION_ESTIMATE = 2514;
+
+ /**
+ * SLg (3GPP TS 29.172) Velocity-Estimate 2515 AVP code
+ */
+ int VELOCITY_ESTIMATE = 2515;
+
+ /**
+ * SLg (3GPP TS 29.172) EUTRAN-Positioning-Data AVP code
+ */
+ int EUTRAN_POSITIONING_DATA = 2516;
+
+ /**
+ * SLg (3GPP TS 29.172) ECGI AVP code
+ */
+ int ECGI = 2517;
+
+ /**
+ * SLg (3GPP TS 29.172) Location_Event AVP code
+ */
+ int LOCATION_EVENT = 2518;
+
+ /**
+ * SLg (3GPP TS 29.172) Pseudonym-Indicator
+ */
+ int PSEUDONYM_INDICATOR = 2519;
+
+ /**
+ * SLg (3GPP TS 29.172) LCS-Service-Type-ID AVP Code
+ */
+ int LCS_SERVICE_TYPE_ID = 2520;
+
+ /**
+ * SLg (3GPP TS 29.172) LCS-Privacy-Check-Non-Session AVP Code
+ */
+ int LCS_PRIVACY_CHECK_NON_SESSION = 2521;
+
+ /**
+ * SLg (3GPP TS 29.172) LCS-Privacy-Check-Session AVP Code
+ */
+ int LCS_PRIVACY_CHECK_SESSION = 2522;
+
+ /**
+ * SLg (3GPP TS 29.172) LCS-QoS-Class AVP Code
+ */
+ int LCS_QOS_CLASS = 2523;
+
+ /**
+ * SLg (3GPP TS 29.172) GERAN-Positioning-Info AVP Code
+ */
+ int GERAN_POSITIONING_INFO = 2524;
+
+ /**
+ * SLg (3GPP TS 29.172) GERAN-Positioning-Data AVP Code
+ */
+ int GERAN_POSITIONING_DATA = 2525;
+
+ /**
+ * SLg (3GPP TS 29.172) GERAN-GANSS-Positioning-Data AVP Code
+ */
+ int GERAN_GANSS_POSITIONING_DATA = 2526;
+
+ /**
+ * SLg (3GPP TS 29.172) UTRAN-Positioning-Info AVP Code
+ */
+ int UTRAN_POSITIONING_INFO = 2527;
+
+ /**
+ * SLg (3GPP TS 29.172) UTRAN-Positioning-Data AVP Code
+ */
+ int UTRAN_POSITIONING_DATA = 2528;
+
+ /**
+ * SLg (3GPP TS 29.172) UTRAN-GANSS-Positioning-Data AVP Code
+ */
+ int UTRAN_GANSS_POSITIONING_DATA = 2529;
+
+ /**
+ * SLg (3GPP TS 29.172) LRR-Flags AVP Code
+ */
+ int LRR_FLAGS = 2530;
+
+ /**
+ * SLg (3GPP TS 29.172) LCS-Reference-Number AVP Code
+ */
+ int LCS_REFERENCE_NUMBER = 2531;
+
+ /**
+ * SLg (3GPP TS 29.172) Deferred-Location-Type AVP Code
+ */
+ int DEFERRED_LOCATION_TYPE = 2532;
+
+ /**
+ * SLg (3GPP TS 29.172) Area-Event-Info AVP Code
+ */
+ int AREA_EVENT_INFO = 2533;
+
+ /**
+ * SLg (3GPP TS 29.172) Area-Definition AVP Code
+ */
+ int AREA_DEFINITION = 2534;
+
+ /**
+ * SLg (3GPP TS 29.172) Area AVP Code
+ */
+ int AREA = 2535;
+
+ /**
+ * SLg (3GPP TS 29.172) Area-Type AVP Code
+ */
+ int AREA_TYPE = 2536;
+
+ /**
+ * SLg (3GPP TS 29.172) Area-Identification AVP Code
+ */
+ int AREA_IDENTIFICATION = 2537;
+
+ /**
+ * SLg (3GPP TS 29.172) Occurrence-Info AVP Code
+ */
+ int OCCURRENCE_INFO = 2538;
+
+ /**
+ * SLg (3GPP TS 29.172) Interval-Time AVP Code
+ */
+ int INTERVAL_TIME = 2539;
+
+ /**
+ * SLg (3GPP TS 29.172) Periodic-LDR-Information AVP Code
+ */
+ int PERIODIC_LDR_INFORMATION = 2540;
+
+ /**
+ * SLg (3GPP TS 29.172) Reporting-Amount AVP Code
+ */
+ int REPORTING_AMOUNT = 2541;
+
+ /**
+ * SLg (3GPP TS 29.172) Reporting-Interval AVP Code
+ */
+ int REPORTING_INTERVAL = 2542;
+
+ /**
+ * SLg (3GPP TS 29.172) Reporting-PLMN-List AVP Code
+ */
+ int REPORTING_PLMN_LIST = 2543;
+
+ /**
+ * SLg (3GPP TS 29.172) PLMN-ID-List AVP Code
+ */
+ int PLMN_ID_LIST = 2544;
+
+ /**
+ * SLg (3GPP TS 29.172) PLR-Flags AVP Code
+ */
+ int PLR_FLAGS = 2545;
+
+ /**
+ * SLg (3GPP TS 29.172) PLA-Flags AVP Code
+ */
+ int PLA_FLAGS = 2546;
+
+ /**
+ * SLg (3GPP TS 29.172) Deferred-MT-LR-Data AVP Code
+ */
+ int DEFERRED_MT_LR_DATA = 2547;
+
+ /**
+ * SLg (3GPP TS 29.172) Termination-Cause AVP Code;
+ */
+ int TERMINATION_CAUSE_LCS = 2548;
+
+ /**
+ * SLg (3GPP TS 29.172) LRA-Flags AVP Code
+ */
+ int LRA_FLAGS = 2549;
+
+ /**
+ * SLg (3GPP TS 29.172) Periodic-Location-Support-Indicator AVP Code
+ */
+ int PERIODIC_LOCATION_SUPPORT_INDICATOR = 2550;
+
+ /**
+ * SLg (3GPP TS 29.172)
+ */
+ int PRIORITIZED_LIST_INDICATOR = 2551;
+
+ /**
+ * SLg (3GPP TS 29.172)ESMLC-Cell-Info AVP Code
+ */
+ int ESMLC_CELL_INFO = 2552;
+
+ /**
+ * SLg (3GPP TS 29.172) Cell-Portion-ID AVP Code
+ */
+ int CELL_PORTION_ID = 2553;
+
+ /**
+ * SLg (3GPP TS 29.172) 1xRTT-RCID AVP Code
+ */
+ int ONEXRTT_RCID = 2554;
+
+ /**
+ * SLg (3GPP TS 29.172) Civic-Address AVP Code
+ */
+ int CIVIC_ADDRESS = 2556;
+
+ /**
+ * SLg (3GPP TS 29.172) Barometric-Pressure AVP Code
+ */
+ int BAROMETRIC_PRESSURE = 2557;
+
+ /**
+ * SLg (3GPP TS 29.172) UTRAN-Additional-Positioning-Data AVP Code
+ */
+ int UTRAN_ADDITIONAL_POSITIONING_DATA = 2558;
+
+ /**
+ * SLg (3GPP TS 29.172) Service-Selection AVP Code (reused from 3GPP TS 29.272 & IETF RFC 5778)
+ */
+ int SERVICE_SELECTION = 493;
+
+ /**
+ * SLg (3GPP TS 29.172) Cell-Global-Identity AVP Code (reused from 3GPP TS 29.272)
+ */
+ int CELL_GLOBAL_IDENTITY = 1604;
+
+ /**
+ * SLg (3GPP TS 29.172) Visited-PLMN-Id AVP Code (reused from 3GPP TS 29.272)
+ */
+ int VISITED_PLMN_ID = 1407;
+
+ /**
+ * SLg (3GPP TS 29.172) Service-Area-Identity AVP Code (reused from 3GPP TS 29.272)
+ */
+ int SERVICE_AREA_IDENTITY = 1607;
+
+ // Diameter ELP Application (SLg) reused AVPs:
+ // LCS-Format-Indicator 1237 3GPP TS 32.299;
+ // LCS-Name-String 1238 3GPP TS 2.299;
+ // LCS-Client-Type 1241 3GPP TS 32.299
+ // LCS-Requestor-Id-String 1240 3GPP TS 32.299;
+ // Location-Estimate 1242 3GPP TS 32.299;
+ // IMEI 1402 3GPP TS 29.272;
+ // MSISDN 701 3GPP TS 29.329;
+ // Service-Selection 493 3GPP TS 29.272, IETF RFC 5778
+ // User-Name 1 IETF RFC 3588;
+ // Supported-Features 628 3GPP TS 29.229;
+ // Feature-List-ID 629 3GPP TS 29.229;
+ // Feature-List 630 3GPP TS 29.229;
+ // Serving-Node 2401 3GPP TS 29.173;
+ // Cell-Global-Identity 1604 3GPP TS 29.272;
+ // Service-Area-Identity 1607 3GPP TS 29.272;
+ // GMLC-Address 2405 3GPP TS 29.173;
+ // Visited-PLMN-Id 1407 3GPP TS 29.272
/**
* @return the AVP code.
diff --git a/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/ClientSLgSession.java b/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/ClientSLgSession.java
new file mode 100644
index 000000000..f0e6c7802
--- /dev/null
+++ b/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/ClientSLgSession.java
@@ -0,0 +1,85 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.api.slg;
+
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.app.StateMachine;
+import org.jdiameter.api.slg.events.LocationReportRequest;
+import org.jdiameter.api.slg.events.ProvideLocationRequest;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public interface ClientSLgSession extends AppSession, StateMachine {
+
+ /**
+ * Send Provide-Location-Request to server
+ *
+ * @param request Provide-Location-Request event instance
+ * @throws InternalException The InternalException signals that internal error is occurred.
+ * @throws IllegalDiameterStateException The IllegalStateException signals that session has incorrect state (invalid).
+ * @throws RouteException The NoRouteException signals that no route exist for a given realm.
+ * @throws OverloadException The OverloadException signals that destination host is overloaded.
+ */
+ void sendProvideLocationRequest(ProvideLocationRequest request)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException;
+
+ /**
+ * Send Location-Report-Request to server
+ *
+ * @param request Location-Report-Request event instance
+ * @throws InternalException The InternalException signals that internal error is occurred.
+ * @throws IllegalDiameterStateException The IllegalStateException signals that session has incorrect state (invalid).
+ * @throws RouteException The NoRouteException signals that no route exist for a given realm.
+ * @throws OverloadException The OverloadException signals that destination host is overloaded.
+ */
+ void sendLocationReportRequest(LocationReportRequest request)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException;
+
+}
diff --git a/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/ClientSLgSessionListener.java b/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/ClientSLgSessionListener.java
new file mode 100644
index 000000000..3d3cf3ae9
--- /dev/null
+++ b/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/ClientSLgSessionListener.java
@@ -0,0 +1,73 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.api.slg;
+
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.app.AppAnswerEvent;
+import org.jdiameter.api.app.AppRequestEvent;
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.slg.events.ProvideLocationRequest;
+import org.jdiameter.api.slg.events.ProvideLocationAnswer;
+import org.jdiameter.api.slg.events.LocationReportAnswer;
+import org.jdiameter.api.slg.events.LocationReportRequest;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public interface ClientSLgSessionListener {
+
+ void doOtherEvent(AppSession session, AppRequestEvent request, AppAnswerEvent answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException;
+
+ void doProvideLocationAnswerEvent(ClientSLgSession session, ProvideLocationRequest request, ProvideLocationAnswer answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException;
+
+ void doLocationReportAnswerEvent(ClientSLgSession session, LocationReportRequest request, LocationReportAnswer answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException;
+
+}
diff --git a/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/ServerSLgSession.java b/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/ServerSLgSession.java
new file mode 100644
index 000000000..f3f7c2027
--- /dev/null
+++ b/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/ServerSLgSession.java
@@ -0,0 +1,85 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.api.slg;
+
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.app.StateMachine;
+import org.jdiameter.api.slg.events.LocationReportAnswer;
+import org.jdiameter.api.slg.events.ProvideLocationAnswer;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public interface ServerSLgSession extends AppSession, StateMachine {
+
+ /**
+ * Send Provide-Location-Answer to client
+ *
+ * @param answer Provide-Location-Answer event instance
+ * @throws InternalException The InternalException signals that internal error is occurred.
+ * @throws IllegalDiameterStateException The IllegalStateException signals that session has incorrect state (invalid).
+ * @throws RouteException The NoRouteException signals that no route exist for a given realm.
+ * @throws OverloadException The OverloadException signals that destination host is overloaded.
+ */
+ void sendProvideLocationAnswer(ProvideLocationAnswer answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException;
+
+ /**
+ * Send Location-Report-Answer to client
+ *
+ * @param answer Location-Report-Answer event instance
+ * @throws InternalException The InternalException signals that internal error is occurred.
+ * @throws IllegalDiameterStateException The IllegalStateException signals that session has incorrect state (invalid).
+ * @throws RouteException The NoRouteException signals that no route exist for a given realm.
+ * @throws OverloadException The OverloadException signals that destination host is overloaded.
+ */
+ void sendLocationReportAnswer(LocationReportAnswer answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException;
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/ServerSLgSessionListener.java b/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/ServerSLgSessionListener.java
new file mode 100644
index 000000000..8149fed73
--- /dev/null
+++ b/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/ServerSLgSessionListener.java
@@ -0,0 +1,70 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.api.slg;
+
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.app.AppAnswerEvent;
+import org.jdiameter.api.app.AppRequestEvent;
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.slg.events.LocationReportRequest;
+import org.jdiameter.api.slg.events.ProvideLocationRequest;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public interface ServerSLgSessionListener {
+
+ void doOtherEvent(AppSession session, AppRequestEvent request, AppAnswerEvent answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException;
+
+ void doProvideLocationRequestEvent(ServerSLgSession session, ProvideLocationRequest request)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException;
+
+ void doLocationReportRequestEvent(ServerSLgSession session, LocationReportRequest request)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException;
+}
\ No newline at end of file
diff --git a/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/events/LocationReportAnswer.java b/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/events/LocationReportAnswer.java
new file mode 100644
index 000000000..12d99e092
--- /dev/null
+++ b/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/events/LocationReportAnswer.java
@@ -0,0 +1,70 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, Telestax Inc and individual contributors
+ * by the @authors tag.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jdiameter.api.slg.events;
+
+import org.jdiameter.api.app.AppAnswerEvent;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+/*
+ * As for 3GPP TS 29.172 v13.0.0, Subscriber Location Report operation is used by an MME or SGSN to provide the location of a
+ * target UE to a GMLC, when a request for location has been implicitly issued or when a Delayed Location Reporting is triggered
+ * after receipt of a request for location for a UE transiently not reachable.
+ *
+ * The Location-Report-Answer (LRA) command, indicated by the Command-Code field set to 8388621 and the "R" bit cleared in the
+ * Command Flags field, is sent by the GMLC to the MME or SGSN in response to the Location-Report-Request command (Subscriber
+ * Location Report operation answer)
+ */
+
+public interface LocationReportAnswer extends AppAnswerEvent{
+
+ String _SHORT_NAME = "LRA";
+ String _LONG_NAME = "Location-Report-Answer";
+
+ int code = 8388621;
+
+ boolean isGMLCAddressAvpPresent();
+ java.net.InetAddress getGMLCAddress();
+
+ boolean isLRAFlagsAvpPresent();
+ long getLRAFLags();
+
+ boolean isReportingPLMNListAvpPresent();
+ // Reporting-PLMN-List AVP of type grouped, includes:
+ // PLMN-ID-List, Prioritized-List-Indicator
+ boolean isPrioritizedListIndicatorAvpPresent();
+ int getPrioritizedListIndicator();
+ boolean isPLMNIDListAvpPresent();
+ // PLMN-ID-List AVP of type grouped, includes:
+ // Visited-PLMN-Id, Periodic-Location-Support-Indicator
+ boolean isVisitedPLMNIdAvpPresent();
+ byte[] getVisitedPLMNId();
+ boolean isPeriodicLocationSupportIndicatorAvpPresent();
+ int getPeriodicLocationSupportIndicator();
+
+ boolean isLCSReferenceNumberAvpPresent();
+ byte[] getLCSReferenceNumber();
+
+}
diff --git a/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/events/LocationReportRequest.java b/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/events/LocationReportRequest.java
new file mode 100644
index 000000000..1c6566a72
--- /dev/null
+++ b/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/events/LocationReportRequest.java
@@ -0,0 +1,192 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, Telestax Inc and individual contributors
+ * by the @authors tag.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jdiameter.api.slg.events;
+
+import org.jdiameter.api.app.AppRequestEvent;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+/*
+ * As for 3GPP TS 29.172 v13.0.0, Subscriber Location Report operation is used by an MME or SGSN to provide the location of a
+ * target UE to a GMLC, when a request for location has been implicitly issued or when a Delayed Location Reporting is triggered
+ * after receipt of a request for location for a UE transiently not reachable.
+ *
+ * The Location-Report-Request (LRR) command, indicated by the Command-Code field set to 8388621 and the "R" bit set in the
+ * Command Flags field, is sent by the MME or SGSN in order to provide subscriber location data to the GMLC (Subscriber Location
+ * Report operation request)
+ */
+
+public interface LocationReportRequest extends AppRequestEvent {
+
+ String _SHORT_NAME = "LRR";
+ String _LONG_NAME = "Location-Report-Request";
+
+ int code = 8388621;
+
+ boolean isLocationEventAvpPresent();
+ int getLocationEvent();
+
+ boolean isUserNameAvpPresent(); // Mapped IE: IMSI
+ String getUserName(); // Mapped IE: IMSI
+
+ boolean isMSISDNAvpPresent();
+ byte[] getMSISDN();
+
+ boolean isIMEIAvpPresent();
+ String getIMEI();
+
+ boolean isLCSEPSClientNameAvpPresent();
+ // LCS-EPS-Client-Name AVP of type grouped, includes:
+ // LCS-Name-String, LCS-Format-Indicator
+ boolean isLSCNameStringAvpPresent();
+ String getLSCNameString();
+ boolean isLCSFormatIndicatorAvpPresent();
+ int getLCSFormatIndicator();
+
+ boolean isLocationEstimateAvpPresent();
+ byte[] getLocationEstimate();
+
+ boolean isAccuracyFulfilmentIndicatorAvpPresent();
+ int getAccuracyFulfilmentIndicator();
+
+ boolean isAgeOfLocationEstimateAvpPresent();
+ long getAgeOfLocationEstimate();
+
+ boolean isVelocityEstimateAvpPresent();
+ byte[] getVelocityEstimate();
+
+ boolean isEUTRANPositioningDataAvpPresent();
+ byte[] getEUTRANPositioningData();
+
+ boolean isECGIAvpPresent();
+ byte[] getECGI();
+
+ boolean isGERANPositioningInfoAvpPresent();
+ // GERAN-Positioning-Info AVP of type grouped, includes:
+ // GERAN-Positioning-Data, GERAN-GANSS-Positioning-Data
+ boolean isGERANPositioningDataAvpPresent();
+ byte[] getGERANPositioningData();
+ boolean isGERANGANSSPositioningDataAvpPresent();
+ byte[] getGERANGANSSPositioningData();
+
+ boolean isCellGlobalIdentityAvpPresent();
+ byte[] getCellGlobalIdentity();
+
+ boolean isUTRANPositioningInfoAvpPresent();
+ // UTRAN-Positioning-Info AVP of type grouped, includes:
+ // UTRAN-Positioning-Data, UTRAN-GANSS-Positioning-Data
+ boolean isUTRANPositioningDataAvpPresent();
+ byte[] getUTRANPositioningData();
+ boolean isUTRANGANSSPositioningDataAvpPresent();
+ byte[] getUTRANGANSSPositioningData();
+
+ boolean isServiceAreaIdentityAvpPresent();
+ byte[] getServiceAreaIdentity();
+
+ boolean isLCSServiceTypeIDAvpPresent();
+ long getLCSServiceTypeID();
+
+ boolean isPseudonymIndicatorAvpPresent();
+ int getPseudonymIndicator();
+
+ boolean isLCSQoSAvpPresent();
+ // LCS-QoS AVP of type grouped, includes:
+ // LCS-QoS-Class, Horizontal-Accuracy, Vertical-Accuracy
+ // Vertical-Requested, Response-Time
+ boolean isLCSQoSClassAvpPresent();
+ int getLCSQoSClass();
+ boolean isHorizontalAccuracyAvpPresent();
+ long getHorizontalAccuracy();
+ boolean isVerticalAccuracyAvpPresent();
+ long getVerticalAccuracy();
+ boolean isVerticalRequestedAvpPresent();
+ int getVerticalRequested();
+ boolean isResponseTimeAvpPresent();
+ int getResponseTime();
+
+ boolean isServingNodeAvpPresent();
+ // [ Serving-Node ] IE: Target Serving Node Identity
+ // Serving-Node AVP of type grouped, includes:
+ // SGSN-Number, SGSN-Name, SGSN-Realm.
+ // MME-Name, MME-Realm
+ // MSC-Number
+ // 3GPP-AAA-Server-Name, LCS-Capabilities-Sets, GMLC-Address
+ boolean isSGSNNumberAvpPresent();
+ byte[] getSGSNNumber();
+ boolean isSGSNNameAvpPresent();
+ String getSGSNName();
+ boolean isSGSNRealmAvpPresent();
+ String getSGSNRealm();
+ boolean isMMENameAvpPresent();
+ String getMMEName();
+ boolean isMMERealmAvpPresent();
+ String getMMERealm();
+ boolean isMSCNumberAvpPresent();
+ byte[] getMSCNumber();
+ boolean is3GPPAAAServerNameAvpPresent();
+ String get3GPPAAAServerName();
+ boolean isLCSCapabilitiesSetsAvpPresent();
+ long getLCSCapabilitiesSets();
+ boolean isGMLCAddressAvpPresent();
+ java.net.InetAddress getGMLCAddress();
+
+ boolean isLRRFlagsAvpPresent();
+ long getLRRFLags();
+
+ boolean isLCSReferenceNumberAvpPresent();
+ byte[] getLCSReferenceNumber();
+
+ boolean isDeferredMTLRDataAvpPresent();
+ // Deferred-MT-LR-Data AVP of type grouped, includes:
+ // Deferred-Location-Type, Termination-Cause.
+ boolean isDeferredLocationTypeAvpPresent();
+ long getDeferredLocationType();
+ boolean isTerminationCauseAvpPresent();
+ long getTerminationCause();
+
+ boolean isHGMLCAddressAvpPresent(); // IE: H-GMLC Address mapped to GMLC-Address AVP
+ java.net.InetAddress getHGMLCAddress();
+
+ boolean isPeriodicLDRInfoAvpPresent();
+ // Periodic-LDR-Info AVP of type grouped, includes:
+ // Reporting-Amount, Reporting-Interval
+ boolean isReportingAmountAvpPresent();
+ long getReportingAmount();
+ boolean isReportingIntervalAvpPresent();
+ long getReportingInterval();
+
+ boolean isESMLCCellInfoAvpPresent();
+ long getCellPortionId();
+
+ boolean is1xRTTRCIDAvpPresent();
+ byte[] get1xRTTRCID();
+
+ boolean isCivicAddressAvpPresent();
+ String getCivicAddress();
+
+ boolean isBarometricPressureAvpPresent();
+ long getBarometricPressure();
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/events/ProvideLocationAnswer.java b/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/events/ProvideLocationAnswer.java
new file mode 100644
index 000000000..71a524da5
--- /dev/null
+++ b/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/events/ProvideLocationAnswer.java
@@ -0,0 +1,129 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, Telestax Inc and individual contributors
+ * by the @authors tag.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jdiameter.api.slg.events;
+
+import org.jdiameter.api.app.AppAnswerEvent;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+/*
+ * As for 3GPP TS 29.172 v13.0.0, the Provide Subscriber Location operation is used by a GMLC to request the location of a
+ * target UE from the MME or SGSN at any time, as part of EPC-MT-LR (Evolved Packet Core Mobile Terminated Location Request) or
+ * PS-MT-LR (Packet Switched Mobile Terminated Location Request) positioning procedures. The response contains a location
+ * estimate of the target UE and other additional information. This operation is also used by a GMLC to request the location of
+ * the target UE from the SGSN at any time, as part of deferred MT-LR procedure. The response contains the acknowledgment of the
+ * receipt of the request and other additional information.
+ *
+ * The Provide-Location-Answer (PLA) command, indicated by the Command-Code field set to 8388620 and the "R" bit cleared in the
+ * Command Flags field, is sent by the MME or SGSN to the GMLC in response to the Provide-Location-Request command (Provide
+ * Subscriber Location operation answer)
+ */
+
+public interface ProvideLocationAnswer extends AppAnswerEvent{
+
+ String _SHORT_NAME = "PLA";
+ String _LONG_NAME = "Provide-Location-Answer";
+
+ int code = 8388620;
+
+ boolean isLocationEstimateAvpPresent();
+ byte[] getLocationEstimate();
+
+ boolean isAccuracyFulfilmentIndicatorAvpPresent();
+ int getAccuracyFulfilmentIndicator();
+
+ boolean isAgeOfLocationEstimateAvpPresent();
+ long getAgeOfLocationEstimate();
+
+ boolean isVelocityEstimateAvpPresent();
+ byte[] getVelocityEstimate();
+
+ boolean isEUTRANPositioningDataAvpPresent();
+ byte[] getEUTRANPositioningData();
+
+ boolean isECGIAvpPresent();
+ byte[] getECGI();
+
+ boolean isGERANPositioningInfoAvpPresent();
+ // GERAN-Positioning-Info AVP of type grouped, includes:
+ // GERAN-Positioning-Data, GERAN-GANSS-Positioning-Data
+ boolean isGERANPositioningDataAVPPresent();
+ byte[] getGERANPositioningData();
+ boolean isGERANGANSSPositioningDataAVPPresent();
+ byte[] getGERANGANSSPositioningData();
+
+ boolean isCellGlobalIdentityAvpPresent();
+ byte[] getCellGlobalIdentity();
+
+ boolean isUTRANPositioningInfoAvpPresent();
+ // UTRAN-Positioning-Info AVP of type grouped, includes:
+ // UTRAN-Positioning-Data, UTRAN-GANSS-Positioning-Data
+ boolean isUTRANPositioningDataAVPPresent();
+ byte[] getUTRANPositioningData();
+ boolean isUTRANGANSSPositioningDataAVPPresent();
+ byte[] getUTRANGANSSPositioningData();
+
+ boolean isServiceAreaIdentityAvpPresent();
+ byte[] getServiceAreaIdentity();
+
+ boolean isServingNodeAvpPresent();
+ // [ Serving-Node ] IE: Target Serving Node Identity
+ // Serving-Node AVP of type grouped, includes:
+ // SGSN-Number, SGSN-Name, SGSN-Realm.
+ // MME-Name, MME-Realm
+ // MSC-Number
+ // 3GPP-AAA-Server-Name, LCS-Capabilities-Sets, GMLC-Address
+ boolean isSGSNNumberAvpPresent();
+ byte[] getSGSNNumber();
+ boolean isSGSNNameAvpPresent();
+ String getSGSNName();
+ boolean isSGSNRealmAvpPresent();
+ String getSGSNRealm();
+ boolean isMMENameAvpPresent();
+ String getMMEName();
+ boolean isMMERealmAvpPresent();
+ String getMMERealm();
+ boolean isMSCNumberAvpPresent();
+ byte[] getMSCNumber();
+ boolean is3GPPAAAServerNameAvpPResent();
+ String get3GPPAAAServerName();
+ boolean isLCSCapabilitiesSetsAvpPresent();
+ long getLCSCapabilitiesSets();
+ boolean isGMLCAddressAvpPresent();
+ java.net.InetAddress getGMLCAddress();
+
+ boolean isPLAFlagsAvpPresent();
+ long getPLAFlags();
+
+ boolean isESMLCCellInfoAvpPresent();
+ long getCellPortionId();
+
+ boolean isCivicAddressAvpPresent();
+ String getCivicAddress();
+
+ boolean isBarometricPressureAvpPresent();
+ long getBarometricPressure();
+
+}
diff --git a/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/events/ProvideLocationRequest.java b/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/events/ProvideLocationRequest.java
new file mode 100644
index 000000000..f8b8bf4ad
--- /dev/null
+++ b/core/jdiameter/api/src/main/java/org/jdiameter/api/slg/events/ProvideLocationRequest.java
@@ -0,0 +1,174 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, Telestax Inc and individual contributors
+ * by the @authors tag.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jdiameter.api.slg.events;
+
+import org.jdiameter.api.app.AppRequestEvent;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+/*
+ * As for 3GPP TS 29.172 v13.0.0, the Provide Subscriber Location operation is used by a GMLC to request the location of a
+ * target UE from the MME or SGSN at any time, as part of EPC-MT-LR (Evolved Packet Core Mobile Terminated Location Request) or
+ * PS-MT-LR (Packet Switched Mobile Terminated Location Request) positioning procedures. The response contains a location
+ * estimate of the target UE and other additional information. This operation is also used by a GMLC to request the location of
+ * the target UE from the SGSN at any time, as part of deferred MT-LR procedure. The response contains the acknowledgment of the
+ * receipt of the request and other additional information.
+ *
+ * The Provide-Location-Request (PLR) command, indicated by the Command-Code field set to 8388620 and the "R" bit set in the
+ * Command Flags field, is sent by the GMLC in order to request subscriber location to the MME or SGSN (Provide Subscriber
+ * Location operation request)
+ */
+
+public interface ProvideLocationRequest extends AppRequestEvent {
+
+ String _SHORT_NAME = "PLR";
+ String _LONG_NAME = "Provide-Location-Request";
+
+ int code = 8388620;
+
+ boolean isSLgLocationTypeAvpPresent();
+ int getSLgLocationType();
+
+ boolean isUserNameAvpPresent(); // Mapped IE: IMSI
+ String getUserName(); // Mapped IE: IMSI
+
+ boolean isMSISDNAvpPresent();
+ byte[] getMSISDN();
+
+ boolean isIMEIAvpPresent();
+ String getIMEI();
+
+ boolean isLCSEPSClientNameAvpPresent();
+ // LCS-EPS-Client-Name AVP of type grouped, includes:
+ // LCS-Name-String, LCS-Format-Indicator
+ boolean isLSCNameStringAvpPresent();
+ String getLSCNameString();
+ boolean isLCSFormatIndicatorAvpPresent();
+ int getLCSFormatIndicator();
+
+ boolean isLCSCLientTypeAvpPresent();
+ int getLCSClientType();
+
+ boolean isLCSRequestorNamePresent();
+ // LCS-Requestor-NAme AVP of type grouped, includes:
+ // LCS-Requestor-Id-String, LCS-Format-Indicator
+ boolean isLCSRequestorIdStringAvpPresent();
+ String getLCSRequestorIdString();
+ boolean isReqLCSFormatIndicatorAvpPresent();
+ int getReqLCSFormatIndicator();
+
+ boolean isLCSPriorityPresent();
+ long getLCSPriority();
+
+ boolean isLCSQoSAvpPresent();
+ // LCS-QoS AVP of type grouped, includes:
+ // LCS-QoS-Class, Horizontal-Accuracy, Vertical-Accuracy
+ // Vertical-Requested, Response-Time
+ boolean isLCSQoSClassAvpPresent();
+ int getLCSQoSClass();
+ boolean isHorizontalAccuracyAvpPresent();
+ long getHorizontalAccuracy();
+ boolean isVerticalAccuracyAvpPresent();
+ long getVerticalAccuracy();
+ boolean isVerticalRequestedAvpPresent();
+ int getVerticalRequested();
+ boolean isResponseTimeAvpPresent();
+ int getResponseTime();
+
+ boolean isVelocityRequestedAvpPresent();
+ int getVelocityRequested();
+
+ boolean isSupportedGADShapesAvpPresent();
+ long getSupportedGADSahpes();
+
+ boolean isLSCServiceTypeIdAvpPresent();
+ long getLSCServiceTypeId();
+
+ boolean isLCSCodewordAvpPresent();
+ String getLCSCodeword();
+
+ boolean isServiceSelectionAvpPresent();
+ String getServiceSelection(); // IE: APN
+
+ boolean isLCSPrivacyCheckSessionAvpPresent(); // IE: Session-Related Privacy Check
+ // LCS-Privacy-Check-Session of type grouped, includes
+ // LCS-Privacy-Check
+ boolean isLCSPrivacyCheckAvpPresent();
+ int getLCSPrivacyCheck();
+
+ boolean isLCSPrivacyCheckNonSessionAvpPresent(); // IE: Non-Session-Related Privacy Check
+ // LCS-Privacy-Check-Non-Session of type grouped, includes
+ // LCS-Privacy-Check
+ boolean isLCSPrivacyCheckNSAvpPresent();
+ int getLCSPrivacyCheckNS();
+
+ boolean isDeferredLocationTypeAvpPresent();
+ long getDeferredLocationType();
+
+ boolean isLCSReferenceNumberAvpPresent();
+ byte[] getLCSReferenceNumber();
+
+ boolean isAreaEventInfoAvpPresent();
+ // Area-Event-Info AVP of type grouped, includes:
+ // Area-Definition, Occurrence-Info, Interval-Time
+ boolean isOccurrenceInfoAvpPresent();
+ int getOccurrenceInfo();
+ boolean isIntervalTimeAvpPresent();
+ long getIntervalTime();
+ boolean isAreaDefinitionAvpPresent();
+ // Area-Definition AVP of type grouped, includes:
+ // Area-Type, Area-Identification
+ boolean isAreaTypeAvpPresent();
+ long getAreaType();
+ boolean isAreaIdentificationAvpPresent();
+ byte[] getAreaIdentification();
+
+ boolean isGMLCAddressAvpPresent();
+ java.net.InetAddress getGMLCAddress();
+
+ boolean isPLRFlagsAvpPresent();
+ long getPLRFLags();
+
+ boolean isPeriodicLDRInfoAvpPresent();
+ // Periodic-LDR-Info AVP of type grouped, includes:
+ // Reporting-Amount, Reporting-Interval
+ boolean isReportingAmountAvpPresent();
+ long getReportingAmount();
+ boolean isReportingIntervalAvpPresent();
+ long getReportingInterval();
+
+ boolean isReportingPLMNListAvpPresent();
+ // Reporting-PLMN-List AVP of type grouped, includes:
+ // PLMN-ID-List, Prioritized-List-Indicator
+ boolean isPrioritizedListIndicatorAvpPresent();
+ int getPrioritizedListIndicator();
+ boolean isPLMNIDListAvpPresent();
+ // PLMN-ID-List AVP of type grouped, includes:
+ // Visited-PLMN-Id, Periodic-Location-Support-Indicator
+ boolean isVisitedPLMNIdAvpPresent();
+ byte[] getVisitedPLMNId();
+ boolean isPeriodicLocationSupportIndicatorAvpPresent();
+ int getPeriodicLocationSupportIndicator();
+}
diff --git a/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/ClientSLhSession.java b/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/ClientSLhSession.java
new file mode 100644
index 000000000..dc98bd7bd
--- /dev/null
+++ b/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/ClientSLhSession.java
@@ -0,0 +1,73 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.api.slh;
+
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.app.StateMachine;
+import org.jdiameter.api.slh.events.LCSRoutingInfoRequest;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public interface ClientSLhSession extends AppSession, StateMachine {
+
+ /**
+ * Send LCS-Routing-Info-Request to server
+ *
+ * @param request LCS-Routing-Info-Request event instance
+ * @throws InternalException The InternalException signals that internal error is occurred.
+ * @throws IllegalDiameterStateException The IllegalStateException signals that session has incorrect state (invalid).
+ * @throws RouteException The NoRouteException signals that no route exist for a given realm.
+ * @throws OverloadException The OverloadException signals that destination host is overloaded.
+ */
+
+ void sendLCSRoutingInfoRequest(LCSRoutingInfoRequest request)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException;
+
+}
diff --git a/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/ClientSLhSessionListener.java b/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/ClientSLhSessionListener.java
new file mode 100644
index 000000000..3213720f4
--- /dev/null
+++ b/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/ClientSLhSessionListener.java
@@ -0,0 +1,69 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.api.slh;
+
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.app.AppAnswerEvent;
+import org.jdiameter.api.app.AppRequestEvent;
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.slh.events.LCSRoutingInfoAnswer;
+import org.jdiameter.api.slh.events.LCSRoutingInfoRequest;
+
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public interface ClientSLhSessionListener {
+
+ void doOtherEvent(AppSession session, AppRequestEvent request, AppAnswerEvent answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException;
+
+ void doLCSRoutingInfoAnswerEvent(ClientSLhSession session, LCSRoutingInfoRequest request, LCSRoutingInfoAnswer answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException;
+
+}
diff --git a/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/ServerSLhSession.java b/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/ServerSLhSession.java
new file mode 100644
index 000000000..9e86782cf
--- /dev/null
+++ b/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/ServerSLhSession.java
@@ -0,0 +1,72 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.api.slh;
+
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.app.StateMachine;
+import org.jdiameter.api.slh.events.LCSRoutingInfoAnswer;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public interface ServerSLhSession extends AppSession, StateMachine {
+
+ /**
+ * Send LCS-Routing-Info-Answer to client
+ *
+ * @param answer LCS-Routing-Info-Answer event instance
+ * @throws InternalException The InternalException signals that internal error is occurred.
+ * @throws IllegalDiameterStateException The IllegalStateException signals that session has incorrect state (invalid).
+ * @throws RouteException The NoRouteException signals that no route exist for a given realm.
+ * @throws OverloadException The OverloadException signals that destination host is overloaded.
+ */
+ void sendLCSRoutingInfoAnswer(LCSRoutingInfoAnswer answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException;
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/ServerSLhSessionListener.java b/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/ServerSLhSessionListener.java
new file mode 100644
index 000000000..f7087776d
--- /dev/null
+++ b/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/ServerSLhSessionListener.java
@@ -0,0 +1,67 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.api.slh;
+
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.app.AppAnswerEvent;
+import org.jdiameter.api.app.AppRequestEvent;
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.slh.events.LCSRoutingInfoRequest;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public interface ServerSLhSessionListener {
+
+ void doOtherEvent(AppSession session, AppRequestEvent request, AppAnswerEvent answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException;
+
+ void doLCSRoutingInfoRequestEvent(ServerSLhSession session, LCSRoutingInfoRequest request)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException;
+
+}
diff --git a/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/events/LCSRoutingInfoAnswer.java b/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/events/LCSRoutingInfoAnswer.java
new file mode 100644
index 000000000..ee5e56e98
--- /dev/null
+++ b/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/events/LCSRoutingInfoAnswer.java
@@ -0,0 +1,132 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, Telestax Inc and individual contributors
+ * by the @authors tag.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jdiameter.api.slh.events;
+
+import org.jdiameter.api.app.AppAnswerEvent;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+/*
+ * As for 3GPP TS 29.173 v13.0.0, the LCS-Routing-Info-Answer (RIA) command, indicated by the Command-Code field set to 8388622
+ * and the "R" bit cleared in the Command Flags field, is sent from HSS to GMLC. The procedure invoked by the GMLC is used for
+ * retrieving routing information for LCS (Location Services) for a specified user from the HSS via a LCS-Routing-Info-Request
+ * (RIR) command.
+ *
+ */
+public interface LCSRoutingInfoAnswer extends AppAnswerEvent {
+
+ String _SHORT_NAME = "RIA";
+ String _LONG_NAME = "LCS-Routing-Info-Answer";
+
+ int code = 8388622;
+
+ boolean isUserNameAVPPresent(); // Mapped IE: IMSI
+ String getUserName(); // Mapped IE: IMSI
+
+ boolean isMSISDNAVPPresent();
+ byte[] getMSISDN();
+
+ boolean isLMSIAVPPresent();
+ byte[] getLMSI();
+
+ boolean isServingNodeAVPPresent();
+ // Serving-Node AVP of type grouped, includes:
+ // SGSN-Number, SGSN-Name, SGSN-Realm
+ // MME-Name, MME-Realm
+ // MSC-Number
+ // 3GPP-AAA-Server-Name
+ // LCS-Capabilities-Sets
+ // GMLC-Address
+
+ boolean isSGSNNumberAVPPresent();
+ byte[] getSGSNNumber();
+
+ boolean isSGSNNameAVPPresent();
+ String getSGSNName();
+
+ boolean isSGSNRealmAVPPresent();
+ String getSGSNRealm();
+
+ boolean isMMENameAVPPresent();
+ String getMMEName();
+
+ boolean isMMERealmAVPPresent();
+ String getMMERealm();
+
+ boolean isMSCNumberAVPPresent();
+ byte[] getMSCNumber();
+
+ boolean is3GPPAAAServerNameAVPPresent();
+ String get3GPPAAAServerName();
+
+ boolean isLCSCapabilitiesSetsAVPPresent();
+ long getLCSCapabilitiesSets();
+
+ boolean isGMLCAddressAVPPresent();
+ java.net.InetAddress getGMLCAddress();
+
+ boolean isAdditionalServingNodeAVPPresent();
+ // Serving-Node AVP of type grouped, includes:
+ // SGSN-Number, SGSN-Name, SGSN-Realm
+ // MME-Name, MME-Realm
+ // MSC-Number
+ // 3GPP-AAA-Server-Name
+ // LCS-Capabilities-Sets
+ // GMLC-Address
+
+ boolean isAdditionalSGSNNumberAVPPresent();
+ byte[] getAdditionalSGSNNumber();
+
+ boolean isAdditionalSGSNNameAVPPresent();
+ String getAdditionalSGSNName();
+
+ boolean isAdditionalSGSNRealmAVPPresent();
+ String getAdditionalSGSNRealm();
+
+ boolean isAdditionalMMENameAVPPresent();
+ String getAdditionalMMEName();
+
+ boolean isAdditionalMMERealmAVPPresent();
+ String getAdditionalMMERealm();
+
+ boolean isAdditionalMSCNumberAVPPresent();
+ byte[] getAdditionalMSCNumber();
+
+ boolean isAdditional3GPPAAAServerNameAVPPresent();
+ String getAdditional3GPPAAAServerName();
+
+ boolean isAdditionalLCSCapabilitiesSetsAVPPresent();
+ long getAdditionalLCSCapabilitiesSets();
+
+ boolean isAdditionalGMLCAddressAVPPresent();
+ java.net.InetAddress getAdditionalGMLCAddress();
+
+ boolean isPPRAddressAVPPresent();
+ java.net.InetAddress getPPRAddress();
+
+ boolean isRIAFlagsAVPPresent();
+ long getRIAFLags();
+
+}
diff --git a/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/events/LCSRoutingInfoRequest.java b/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/events/LCSRoutingInfoRequest.java
new file mode 100644
index 000000000..71f97885a
--- /dev/null
+++ b/core/jdiameter/api/src/main/java/org/jdiameter/api/slh/events/LCSRoutingInfoRequest.java
@@ -0,0 +1,53 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, Telestax Inc and individual contributors
+ * by the @authors tag.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jdiameter.api.slh.events;
+
+import org.jdiameter.api.app.AppRequestEvent;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+/*
+ * As for 3GPP TS 29.173 v13.0.0, the LCS-Routing-Info-Request (RIR) command, indicated by the Command-Code field set to 8388622
+ * and the "R" bit set in the Command Flags field, is sent from GMLC to HSS. The procedure invoked by the GMLC is used for
+ * retrieving routing information for LCS (Location Services) for a specified user from the HSS.
+ *
+ */
+public interface LCSRoutingInfoRequest extends AppRequestEvent {
+
+ String _SHORT_NAME = "RIR";
+ String _LONG_NAME = "LCS-Routing-Info-Request";
+
+ int code = 8388622;
+
+ boolean isUserNameAVPPresent(); // Mapped IE: IMSI
+ String getUserName(); // Mapped IE: IMSI
+
+ boolean isMSISDNAVPPresent();
+ byte[] getMSISDN();
+
+ boolean isGMLCNumberAVPPresent();
+ byte[] getGMLCNumber();
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slg/ClientSLgSessionDataLocalImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slg/ClientSLgSessionDataLocalImpl.java
new file mode 100644
index 000000000..48fb95984
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slg/ClientSLgSessionDataLocalImpl.java
@@ -0,0 +1,57 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.client.impl.app.slg;
+
+import org.jdiameter.common.impl.app.slg.SLgLocalSessionDataImpl;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class ClientSLgSessionDataLocalImpl extends SLgLocalSessionDataImpl implements IClientSLgSessionData {
+
+ public ClientSLgSessionDataLocalImpl() {
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slg/Event.java b/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slg/Event.java
new file mode 100644
index 000000000..cf7aa30c8
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slg/Event.java
@@ -0,0 +1,107 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.client.impl.app.slg;
+
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.app.AppEvent;
+import org.jdiameter.api.app.StateEvent;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class Event implements StateEvent {
+
+ enum Type {
+ SEND_MESSAGE, TIMEOUT_EXPIRES, RECEIVE_PLA, RECEIVE_LRA;
+ }
+
+ AppEvent request;
+ AppEvent answer;
+ Type type;
+
+ Event(Type type, AppEvent request, AppEvent answer) {
+ this.type = type;
+ this.answer = answer;
+ this.request = request;
+ }
+
+ @SuppressWarnings("unchecked")
+ public E encodeType(Class eClass) {
+ return eClass == Type.class ? (E) type : null;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public Enum getType() {
+ return type;
+ }
+
+ public AppEvent getRequest() {
+ return request;
+ }
+
+ public AppEvent getAnswer() {
+ return answer;
+ }
+
+ public int compareTo(Object o) {
+ return 0;
+ }
+
+ public Object getData() {
+ return request != null ? request : answer;
+ }
+
+ public void setData(Object data) {
+ try {
+ if (((AppEvent) data).getMessage().isRequest()) {
+ request = (AppEvent) data;
+ } else {
+ answer = (AppEvent) data;
+ }
+ } catch (InternalException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slg/IClientSLgSessionData.java b/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slg/IClientSLgSessionData.java
new file mode 100644
index 000000000..bf25296ca
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slg/IClientSLgSessionData.java
@@ -0,0 +1,54 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.client.impl.app.slg;
+
+import org.jdiameter.common.api.app.slg.ISLgSessionData;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public interface IClientSLgSessionData extends ISLgSessionData {
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slg/SLgClientSessionImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slg/SLgClientSessionImpl.java
new file mode 100644
index 000000000..4369e2e2f
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slg/SLgClientSessionImpl.java
@@ -0,0 +1,358 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.client.impl.app.slg;
+
+import org.jdiameter.api.Answer;
+import org.jdiameter.api.EventListener;
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.NetworkReqListener;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.Request;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.app.AppEvent;
+import org.jdiameter.api.app.StateChangeListener;
+import org.jdiameter.api.app.StateEvent;
+import org.jdiameter.api.slg.ClientSLgSession;
+import org.jdiameter.api.slg.ClientSLgSessionListener;
+import org.jdiameter.api.slg.events.LocationReportAnswer;
+import org.jdiameter.api.slg.events.LocationReportRequest;
+import org.jdiameter.api.slg.events.ProvideLocationAnswer;
+import org.jdiameter.api.slg.events.ProvideLocationRequest;
+import org.jdiameter.client.api.ISessionFactory;
+import org.jdiameter.client.impl.app.slg.Event.Type;
+import org.jdiameter.common.api.app.slg.ISLgMessageFactory;
+import org.jdiameter.common.api.app.slg.SLgSessionState;
+import org.jdiameter.common.impl.app.AppAnswerEventImpl;
+import org.jdiameter.common.impl.app.AppRequestEventImpl;
+import org.jdiameter.common.impl.app.slg.SLgSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class SLgClientSessionImpl extends SLgSession
+ implements ClientSLgSession, EventListener, NetworkReqListener {
+
+ private static final Logger logger = LoggerFactory.getLogger(SLgClientSessionImpl.class);
+
+ private transient ClientSLgSessionListener listener;
+
+ protected long appId = -1;
+ protected IClientSLgSessionData sessionData;
+
+ public SLgClientSessionImpl(IClientSLgSessionData sessionData, ISLgMessageFactory fct, ISessionFactory sf,
+ ClientSLgSessionListener lst) {
+ super(sf, sessionData);
+ if (lst == null) {
+ throw new IllegalArgumentException("Listener can not be null");
+ }
+ if (fct.getApplicationId() < 0) {
+ throw new IllegalArgumentException("ApplicationId can not be less than zero");
+ }
+
+ this.appId = fct.getApplicationId();
+ this.listener = lst;
+ super.messageFactory = fct;
+ this.sessionData = sessionData;
+ }
+
+ @SuppressWarnings("unchecked")
+ public E getState(Class stateType) {
+ return stateType == SLgSessionState.class ? (E) this.sessionData.getSLgSessionState() : null;
+ }
+
+ public Answer processRequest(Request request) {
+ RequestDelivery rd = new RequestDelivery();
+ rd.session = this;
+ rd.request = request;
+ super.scheduler.execute(rd);
+ return null;
+ }
+
+ public void sendProvideLocationRequest(ProvideLocationRequest request)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
+ send(Event.Type.SEND_MESSAGE, request, null);
+ }
+
+ public void sendLocationReportRequest(LocationReportRequest request)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
+ send(Event.Type.SEND_MESSAGE, request, null);
+ }
+
+ public void receivedSuccessMessage(Request request, Answer answer) {
+ AnswerDelivery rd = new AnswerDelivery();
+ rd.session = this;
+ rd.request = request;
+ rd.answer = answer;
+ super.scheduler.execute(rd);
+ }
+
+ public void timeoutExpired(Request request) {
+ try {
+ handleEvent(new Event(Event.Type.TIMEOUT_EXPIRES, new AppRequestEventImpl(request), null));
+ } catch (Exception e) {
+ logger.debug("Failed to process timeout message", e);
+ }
+ }
+
+ protected void send(Event.Type type, AppEvent request, AppEvent answer) throws InternalException {
+ try {
+ if (type != null) {
+ handleEvent(new Event(type, request, answer));
+ }
+ } catch (Exception e) {
+ throw new InternalException(e);
+ }
+ }
+
+ public boolean handleEvent(StateEvent event) throws InternalException, OverloadException {
+ try {
+ sendAndStateLock.lock();
+ if (!super.session.isValid()) {
+ // FIXME: throw new InternalException("Generic session is not valid.");
+ return false;
+ }
+ final SLgSessionState state = this.sessionData.getSLgSessionState();
+ SLgSessionState newState = null;
+ Event localEvent = (Event) event;
+ Event.Type eventType = (Type) event.getType();
+ switch (state) {
+
+ case IDLE:
+ switch (eventType) {
+
+ case SEND_MESSAGE:
+ newState = SLgSessionState.MESSAGE_SENT_RECEIVED;
+ super.session.send(((AppEvent) event.getData()).getMessage(), this);
+ setState(newState); // FIXME: is this ok to be here?
+ break;
+
+ default:
+ logger.error("Invalid Event Type {} for SLg Client Session at state {}.", eventType,
+ sessionData.getSLgSessionState());
+ break;
+ }
+ break;
+
+ case MESSAGE_SENT_RECEIVED:
+ switch (eventType) {
+ case TIMEOUT_EXPIRES:
+ newState = SLgSessionState.TIMEDOUT;
+ setState(newState);
+ break;
+
+ case SEND_MESSAGE:
+ try {
+ super.session.send(((AppEvent) event.getData()).getMessage(), this);
+ } finally {
+ newState = SLgSessionState.TERMINATED;
+ setState(newState);
+ }
+ break;
+
+ case RECEIVE_PLA:
+ newState = SLgSessionState.TERMINATED;
+ setState(newState);
+ super.cancelMsgTimer();
+ listener.doProvideLocationAnswerEvent(this, (ProvideLocationRequest) localEvent.getRequest(),
+ (ProvideLocationAnswer) localEvent.getAnswer());
+ break;
+
+ case RECEIVE_LRA:
+ newState = SLgSessionState.TERMINATED;
+ setState(newState);
+ super.cancelMsgTimer();
+ listener.doLocationReportAnswerEvent(this, (LocationReportRequest) localEvent.getRequest(),
+ (LocationReportAnswer) localEvent.getAnswer());
+ break;
+
+ default:
+ throw new InternalException("Unexpected/Unknown message received: " + event.getData());
+ }
+ break;
+
+ case TERMINATED:
+ throw new InternalException("Cant receive message in state TERMINATED. Command: " + event.getData());
+
+ case TIMEDOUT:
+ throw new InternalException("Cant receive message in state TIMEDOUT. Command: " + event.getData());
+
+ default:
+ logger.error("SLg Client FSM in wrong state: {}", state);
+ break;
+ }
+ } catch (Exception e) {
+ throw new InternalException(e);
+ } finally {
+ sendAndStateLock.unlock();
+ }
+ return true;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected void setState(SLgSessionState newState) {
+ SLgSessionState oldState = this.sessionData.getSLgSessionState();
+ this.sessionData.setSLgSessionState(newState);
+
+ for (StateChangeListener i : stateListeners) {
+ i.stateChanged(this, (Enum) oldState, (Enum) newState);
+ }
+ if (newState == SLgSessionState.TERMINATED || newState == SLgSessionState.TIMEDOUT) {
+ super.cancelMsgTimer();
+ this.release();
+ }
+ }
+
+ public void onTimer(String timerName) {
+ if (timerName.equals(SLgSession.TIMER_NAME_MSG_TIMEOUT)) {
+ try {
+ sendAndStateLock.lock();
+ try {
+ handleEvent(
+ new Event(Event.Type.TIMEOUT_EXPIRES, new AppRequestEventImpl(this.sessionData.getBuffer()), null));
+ } catch (Exception e) {
+ logger.debug("Failure handling Timeout event.");
+ }
+ this.sessionData.setBuffer(null);
+ this.sessionData.setTsTimerId(null);
+ } finally {
+ sendAndStateLock.unlock();
+ }
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + (int) (appId ^ (appId >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ SLgClientSessionImpl other = (SLgClientSessionImpl) obj;
+ if (appId != other.appId) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void release() {
+ if (isValid()) {
+ try {
+ sendAndStateLock.lock();
+ super.release();
+ } catch (Exception e) {
+ logger.debug("Failed to release session", e);
+ } finally {
+ sendAndStateLock.unlock();
+ }
+ } else {
+ logger.debug("Trying to release an already invalid session, with Session ID '{}'", getSessionId());
+ }
+ }
+
+ private class RequestDelivery implements Runnable {
+ ClientSLgSession session;
+ Request request;
+
+ public void run() {
+ try {
+ switch (request.getCommandCode()) {
+
+ default:
+ listener.doOtherEvent(session, new AppRequestEventImpl(request), null);
+ break;
+ }
+ } catch (Exception e) {
+ logger.debug("Failed to process request message", e);
+ }
+ }
+ }
+
+ private class AnswerDelivery implements Runnable {
+ ClientSLgSession session;
+ Answer answer;
+ Request request;
+
+ public void run() {
+ try {
+ switch (answer.getCommandCode()) {
+
+ case ProvideLocationAnswer.code:
+ handleEvent(new Event(Event.Type.RECEIVE_PLA, messageFactory.createProvideLocationRequest(request),
+ messageFactory.createProvideLocationAnswer(answer)));
+ break;
+
+ case LocationReportAnswer.code:
+ handleEvent(new Event(Event.Type.RECEIVE_LRA, messageFactory.createLocationReportRequest(request),
+ messageFactory.createLocationReportAnswer(answer)));
+ break;
+
+ default:
+ listener.doOtherEvent(session, new AppRequestEventImpl(request), new AppAnswerEventImpl(answer));
+ break;
+ }
+ } catch (Exception e) {
+ logger.debug("Failed to process success message", e);
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slh/ClientSLhSessionDataLocalImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slh/ClientSLhSessionDataLocalImpl.java
new file mode 100644
index 000000000..35574cf27
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slh/ClientSLhSessionDataLocalImpl.java
@@ -0,0 +1,57 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.client.impl.app.slh;
+
+import org.jdiameter.common.impl.app.slh.SLhLocalSessionDataImpl;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class ClientSLhSessionDataLocalImpl extends SLhLocalSessionDataImpl implements IClientSLhSessionData {
+
+ public ClientSLhSessionDataLocalImpl() {
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slh/Event.java b/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slh/Event.java
new file mode 100644
index 000000000..0c319912f
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slh/Event.java
@@ -0,0 +1,107 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.client.impl.app.slh;
+
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.app.AppEvent;
+import org.jdiameter.api.app.StateEvent;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+public class Event implements StateEvent {
+
+ enum Type {
+ SEND_MESSAGE, TIMEOUT_EXPIRES, RECEIVE_RIA;
+ }
+
+ AppEvent request;
+ AppEvent answer;
+ Type type;
+
+ Event(Type type, AppEvent request, AppEvent answer) {
+ this.type = type;
+ this.answer = answer;
+ this.request = request;
+ }
+
+ @SuppressWarnings("unchecked")
+ public E encodeType(Class eClass) {
+ return eClass == Type.class ? (E) type : null;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public Enum getType() {
+ return type;
+ }
+
+ public AppEvent getRequest() {
+ return request;
+ }
+
+ public AppEvent getAnswer() {
+ return answer;
+ }
+
+ public int compareTo(Object o) {
+ return 0;
+ }
+
+ public Object getData() {
+ return request != null ? request : answer;
+ }
+
+ public void setData(Object data) {
+ try {
+ if (((AppEvent) data).getMessage().isRequest()) {
+ request = (AppEvent) data;
+ } else {
+ answer = (AppEvent) data;
+ }
+ } catch (InternalException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slh/IClientSLhSessionData.java b/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slh/IClientSLhSessionData.java
new file mode 100644
index 000000000..ccec9ab3c
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slh/IClientSLhSessionData.java
@@ -0,0 +1,54 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.client.impl.app.slh;
+
+import org.jdiameter.common.api.app.slh.ISLhSessionData;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public interface IClientSLhSessionData extends ISLhSessionData {
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slh/SLhClientSessionImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slh/SLhClientSessionImpl.java
new file mode 100644
index 000000000..3fe11c2ec
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/client/impl/app/slh/SLhClientSessionImpl.java
@@ -0,0 +1,336 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.client.impl.app.slh;
+
+import org.jdiameter.api.Answer;
+import org.jdiameter.api.EventListener;
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.NetworkReqListener;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.Request;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.app.AppEvent;
+import org.jdiameter.api.app.StateChangeListener;
+import org.jdiameter.api.app.StateEvent;
+import org.jdiameter.api.slh.ClientSLhSession;
+import org.jdiameter.api.slh.ClientSLhSessionListener;
+import org.jdiameter.api.slh.events.LCSRoutingInfoRequest;
+import org.jdiameter.api.slh.events.LCSRoutingInfoAnswer;
+import org.jdiameter.client.api.ISessionFactory;
+import org.jdiameter.client.impl.app.slh.Event.Type;
+import org.jdiameter.common.api.app.slh.ISLhMessageFactory;
+import org.jdiameter.common.api.app.slh.SLhSessionState;
+import org.jdiameter.common.impl.app.AppAnswerEventImpl;
+import org.jdiameter.common.impl.app.AppRequestEventImpl;
+import org.jdiameter.common.impl.app.slh.SLhSession;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+public class SLhClientSessionImpl extends SLhSession
+ implements ClientSLhSession, EventListener, NetworkReqListener {
+
+ private static final Logger logger = LoggerFactory.getLogger(SLhClientSessionImpl.class);
+
+ private transient ClientSLhSessionListener listener;
+
+ protected long appId = -1;
+ protected IClientSLhSessionData sessionData;
+
+ public SLhClientSessionImpl(IClientSLhSessionData sessionData, ISLhMessageFactory fct, ISessionFactory sf, ClientSLhSessionListener lst) {
+ super(sf, sessionData);
+ if (lst == null) {
+ throw new IllegalArgumentException("Listener can not be null");
+ }
+ if (fct.getApplicationId() < 0) {
+ throw new IllegalArgumentException("ApplicationId can not be less than zero");
+ }
+
+ this.appId = fct.getApplicationId();
+ this.listener = lst;
+ super.messageFactory = fct;
+ this.sessionData = sessionData;
+ }
+
+ @SuppressWarnings("unchecked")
+ public E getState(Class stateType) {
+ return stateType == SLhSessionState.class ? (E) this.sessionData.getSLhSessionState() : null;
+ }
+
+ public Answer processRequest(Request request) {
+ RequestDelivery rd = new RequestDelivery();
+ rd.session = this;
+ rd.request = request;
+ super.scheduler.execute(rd);
+ return null;
+ }
+
+ public void sendLCSRoutingInfoRequest(LCSRoutingInfoRequest request)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
+ send(Event.Type.SEND_MESSAGE, request, null);
+ }
+
+ public void receivedSuccessMessage(Request request, Answer answer) {
+ AnswerDelivery rd = new AnswerDelivery();
+ rd.session = this;
+ rd.request = request;
+ rd.answer = answer;
+ super.scheduler.execute(rd);
+ }
+
+ public void timeoutExpired(Request request) {
+ try {
+ handleEvent(new Event(Event.Type.TIMEOUT_EXPIRES, new AppRequestEventImpl(request), null));
+ } catch (Exception e) {
+ logger.debug("Failed to process timeout message", e);
+ }
+ }
+
+ protected void send(Event.Type type, AppEvent request, AppEvent answer) throws InternalException {
+ try {
+ if (type != null) {
+ handleEvent(new Event(type, request, answer));
+ }
+ } catch (Exception e) {
+ throw new InternalException(e);
+ }
+ }
+
+ public boolean handleEvent(StateEvent event) throws InternalException, OverloadException {
+ try {
+ sendAndStateLock.lock();
+ if (!super.session.isValid()) {
+ // FIXME: throw new InternalException("Generic session is not valid.");
+ return false;
+ }
+ final SLhSessionState state = this.sessionData.getSLhSessionState();
+ SLhSessionState newState = null;
+ Event localEvent = (Event) event;
+ Event.Type eventType = (Type) event.getType();
+ switch (state) {
+
+ case IDLE:
+ switch (eventType) {
+
+ case SEND_MESSAGE:
+ newState = SLhSessionState.MESSAGE_SENT_RECEIVED;
+ super.session.send(((AppEvent) event.getData()).getMessage(), this);
+ setState(newState); // FIXME: is this ok to be here?
+ break;
+
+ default:
+ logger.error("Invalid Event Type {} for SLh Client Session at state {}.", eventType,
+ sessionData.getSLhSessionState());
+ break;
+ }
+ break;
+
+ case MESSAGE_SENT_RECEIVED:
+ switch (eventType) {
+ case TIMEOUT_EXPIRES:
+ newState = SLhSessionState.TIMEDOUT;
+ setState(newState);
+ break;
+
+ case SEND_MESSAGE:
+ try {
+ super.session.send(((AppEvent) event.getData()).getMessage(), this);
+ } finally {
+ newState = SLhSessionState.TERMINATED;
+ setState(newState);
+ }
+ break;
+
+ case RECEIVE_RIA:
+ newState = SLhSessionState.TERMINATED;
+ setState(newState);
+ super.cancelMsgTimer();
+ listener.doLCSRoutingInfoAnswerEvent(this, (LCSRoutingInfoRequest) localEvent.getRequest(),
+ (LCSRoutingInfoAnswer) localEvent.getAnswer());
+ break;
+
+ default:
+ throw new InternalException("Unexpected/Unknown message received: " + event.getData());
+ }
+ break;
+
+ case TERMINATED:
+ throw new InternalException("Cant receive message in state TERMINATED. Command: " + event.getData());
+
+ case TIMEDOUT:
+ throw new InternalException("Cant receive message in state TIMEDOUT. Command: " + event.getData());
+
+ default:
+ logger.error("SLh Client FSM in wrong state: {}", state);
+ break;
+ }
+ } catch (Exception e) {
+ throw new InternalException(e);
+ } finally {
+ sendAndStateLock.unlock();
+ }
+ return true;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected void setState(SLhSessionState newState) {
+ SLhSessionState oldState = this.sessionData.getSLhSessionState();
+ this.sessionData.setSLhSessionState(newState);
+
+ for (StateChangeListener i : stateListeners) {
+ i.stateChanged(this, (Enum) oldState, (Enum) newState);
+ }
+ if (newState == SLhSessionState.TERMINATED || newState == SLhSessionState.TIMEDOUT) {
+ super.cancelMsgTimer();
+ this.release();
+ }
+ }
+
+ public void onTimer(String timerName) {
+ if (timerName.equals(SLhSession.TIMER_NAME_MSG_TIMEOUT)) {
+ try {
+ sendAndStateLock.lock();
+ try {
+ handleEvent(
+ new Event(Event.Type.TIMEOUT_EXPIRES, new AppRequestEventImpl(this.sessionData.getBuffer()), null));
+ } catch (Exception e) {
+ logger.debug("Failure handling Timeout event.");
+ }
+ this.sessionData.setBuffer(null);
+ this.sessionData.setTsTimerId(null);
+ } finally {
+ sendAndStateLock.unlock();
+ }
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + (int) (appId ^ (appId >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ SLhClientSessionImpl other = (SLhClientSessionImpl) obj;
+ if (appId != other.appId) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void release() {
+ if (isValid()) {
+ try {
+ sendAndStateLock.lock();
+ super.release();
+ } catch (Exception e) {
+ logger.debug("Failed to release session", e);
+ } finally {
+ sendAndStateLock.unlock();
+ }
+ } else {
+ logger.debug("Trying to release an already invalid session, with Session ID '{}'", getSessionId());
+ }
+ }
+
+ private class RequestDelivery implements Runnable {
+ ClientSLhSession session;
+ Request request;
+
+ public void run() {
+ try {
+ switch (request.getCommandCode()) {
+
+ default:
+ listener.doOtherEvent(session, new AppRequestEventImpl(request), null);
+ break;
+ }
+ } catch (Exception e) {
+ logger.debug("Failed to process request message", e);
+ }
+ }
+ }
+
+ private class AnswerDelivery implements Runnable {
+ ClientSLhSession session;
+ Answer answer;
+ Request request;
+
+ public void run() {
+ try {
+ switch (answer.getCommandCode()) {
+
+ case LCSRoutingInfoAnswer.code:
+ handleEvent(new Event(Event.Type.RECEIVE_RIA, messageFactory.createLCSRoutingInfoRequest(request),
+ messageFactory.createLCSRoutingInfoAnswer(answer)));
+ break;
+
+ default:
+ listener.doOtherEvent(session, new AppRequestEventImpl(request), new AppAnswerEventImpl(answer));
+ break;
+ }
+ } catch (Exception e) {
+ logger.debug("Failed to process success message", e);
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slg/ISLgMessageFactory.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slg/ISLgMessageFactory.java
new file mode 100644
index 000000000..53fc7cac3
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slg/ISLgMessageFactory.java
@@ -0,0 +1,74 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.api.app.slg;
+
+import org.jdiameter.api.Answer;
+import org.jdiameter.api.Request;
+import org.jdiameter.api.slg.events.LocationReportAnswer;
+import org.jdiameter.api.slg.events.LocationReportRequest;
+import org.jdiameter.api.slg.events.ProvideLocationAnswer;
+import org.jdiameter.api.slg.events.ProvideLocationRequest;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public interface ISLgMessageFactory {
+
+ ProvideLocationRequest createProvideLocationRequest(Request request);
+
+ ProvideLocationAnswer createProvideLocationAnswer(Answer answer);
+
+ LocationReportRequest createLocationReportRequest(Request request);
+
+ LocationReportAnswer createLocationReportAnswer(Answer answer);
+
+ /**
+ * Returns the Application-Id that this message factory is related to
+ *
+ * @return the Application-Id value
+ */
+ long getApplicationId();
+
+}
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slg/ISLgSessionData.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slg/ISLgSessionData.java
new file mode 100644
index 000000000..39644e95a
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slg/ISLgSessionData.java
@@ -0,0 +1,68 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.api.app.slg;
+
+import java.io.Serializable;
+
+import org.jdiameter.api.Request;
+import org.jdiameter.common.api.app.IAppSessionData;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+public interface ISLgSessionData extends IAppSessionData {
+
+ void setSLgSessionState(SLgSessionState state);
+
+ SLgSessionState getSLgSessionState();
+
+ Serializable getTsTimerId();
+
+ void setTsTimerId(Serializable tid);
+
+ void setBuffer(Request buffer);
+
+ Request getBuffer();
+
+}
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slg/ISLgSessionFactory.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slg/ISLgSessionFactory.java
new file mode 100644
index 000000000..6dc72e34b
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slg/ISLgSessionFactory.java
@@ -0,0 +1,111 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.api.app.slg;
+
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.app.StateChangeListener;
+import org.jdiameter.api.slg.ClientSLgSessionListener;
+import org.jdiameter.api.slg.ServerSLgSessionListener;
+import org.jdiameter.common.api.app.IAppSessionFactory;
+// import org.jdiameter.common.api.app.slg.ISLgMessageFactory;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public interface ISLgSessionFactory extends IAppSessionFactory {
+
+ /**
+ * Get stack wide listener for sessions. In local mode it has similar effect as setting this directly in app session.
+ * However clustered session use this value when recreated!
+ *
+ * @return the serverSessionListener
+ */
+ ServerSLgSessionListener getServerSessionListener();
+
+ /**
+ * Set stack wide listener for sessions. In local mode it has similar effect as setting this directly in app session.
+ * However clustered session use this value when recreated!
+ *
+ * @param serverSessionListener the serverSessionListener to set
+ */
+ void setServerSessionListener(ServerSLgSessionListener serverSessionListener);
+
+ /**
+ * Get stack wide listener for sessions. In local mode it has similar effect as setting this directly in app session.
+ * However clustered session use this value when recreated!
+ *
+ * @return the clientSessionListener
+ */
+ ClientSLgSessionListener getClientSessionListener();
+
+ /**
+ * Set stack wide listener for sessions. In local mode it has similar effect as setting this directly in app session.
+ * However clustered session use this value when recreated!
+ *
+ * @param clientSessionListener the clientSessionListener to set
+ */
+ void setClientSessionListener(ClientSLgSessionListener clientSessionListener);
+
+ /**
+ * @return the messageFactory
+ */
+ ISLgMessageFactory getMessageFactory();
+
+ /**
+ * @param messageFactory the messageFactory to set
+ */
+ void setMessageFactory(ISLgMessageFactory messageFactory);
+
+ /**
+ * @return the stateListener
+ */
+ StateChangeListener getStateListener();
+
+ /**
+ * @param stateListener the stateListener to set
+ */
+ void setStateListener(StateChangeListener stateListener);
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slg/SLgSessionState.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slg/SLgSessionState.java
new file mode 100644
index 000000000..8b6512641
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slg/SLgSessionState.java
@@ -0,0 +1,54 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.api.app.slg;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public enum SLgSessionState {
+
+ IDLE, MESSAGE_SENT_RECEIVED, TERMINATED, TIMEDOUT;
+
+}
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slh/ISLhMessageFactory.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slh/ISLhMessageFactory.java
new file mode 100644
index 000000000..a637b15ca
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slh/ISLhMessageFactory.java
@@ -0,0 +1,68 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.api.app.slh;
+
+import org.jdiameter.api.Answer;
+import org.jdiameter.api.Request;
+import org.jdiameter.api.slh.events.LCSRoutingInfoAnswer;
+import org.jdiameter.api.slh.events.LCSRoutingInfoRequest;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public interface ISLhMessageFactory {
+
+ LCSRoutingInfoRequest createLCSRoutingInfoRequest(Request request);
+
+ LCSRoutingInfoAnswer createLCSRoutingInfoAnswer(Answer answer);
+
+ /**
+ * Returns the Application-Id that this message factory is related to
+ *
+ * @return the Application-Id value
+ */
+ long getApplicationId();
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slh/ISLhSessionData.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slh/ISLhSessionData.java
new file mode 100644
index 000000000..49e22dfa4
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slh/ISLhSessionData.java
@@ -0,0 +1,69 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.api.app.slh;
+
+import java.io.Serializable;
+
+import org.jdiameter.api.Request;
+import org.jdiameter.common.api.app.IAppSessionData;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public interface ISLhSessionData extends IAppSessionData {
+
+ void setSLhSessionState(SLhSessionState state);
+
+ SLhSessionState getSLhSessionState();
+
+ Serializable getTsTimerId();
+
+ void setTsTimerId(Serializable tid);
+
+ void setBuffer(Request buffer);
+
+ Request getBuffer();
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slh/ISLhSessionFactory.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slh/ISLhSessionFactory.java
new file mode 100644
index 000000000..cc0e1341a
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slh/ISLhSessionFactory.java
@@ -0,0 +1,111 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.api.app.slh;
+
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.app.StateChangeListener;
+import org.jdiameter.api.slh.ClientSLhSessionListener;
+import org.jdiameter.api.slh.ServerSLhSessionListener;
+import org.jdiameter.common.api.app.IAppSessionFactory;
+// import org.jdiameter.common.api.app.slh.ISLhMessageFactory;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public interface ISLhSessionFactory extends IAppSessionFactory {
+
+ /**
+ * Get stack wide listener for sessions. In local mode it has similar effect
+ * as setting this directly in app session. However clustered session use this value when recreated!
+ *
+ * @return the serverSessionListener
+ */
+ ServerSLhSessionListener getServerSessionListener();
+
+ /**
+ * Set stack wide listener for sessions. In local mode it has similar effect
+ * as setting this directly in app session. However clustered session use this value when recreated!
+ *
+ * @param serverSessionListener the serverSessionListener to set
+ */
+ void setServerSessionListener(ServerSLhSessionListener serverSessionListener);
+
+ /**
+ * Get stack wide listener for sessions. In local mode it has similar effect
+ * as setting this directly in app session. However clustered session use this value when recreated!
+ *
+ * @return the clientSessionListener
+ */
+ ClientSLhSessionListener getClientSessionListener();
+
+ /**
+ * Set stack wide listener for sessions. In local mode it has similar effect
+ * as setting this directly in app session. However clustered session use this value when recreated!
+ *
+ * @param clientSessionListener the clientSessionListener to set
+ */
+ void setClientSessionListener(ClientSLhSessionListener clientSessionListener);
+
+ /**
+ * @return the messageFactory
+ */
+ ISLhMessageFactory getMessageFactory();
+
+ /**
+ * @param messageFactory the messageFactory to set
+ */
+ void setMessageFactory(ISLhMessageFactory messageFactory);
+
+ /**
+ * @return the stateListener
+ */
+ StateChangeListener getStateListener();
+
+ /**
+ * @param stateListener the stateListener to set
+ */
+ void setStateListener(StateChangeListener stateListener);
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slh/SLhSessionState.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slh/SLhSessionState.java
new file mode 100644
index 000000000..77b03afbb
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/api/app/slh/SLhSessionState.java
@@ -0,0 +1,54 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.api.app.slh;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public enum SLhSessionState {
+
+ IDLE, MESSAGE_SENT_RECEIVED, TERMINATED, TIMEDOUT;
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/LocationReportAnswerImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/LocationReportAnswerImpl.java
new file mode 100644
index 000000000..0b65df013
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/LocationReportAnswerImpl.java
@@ -0,0 +1,245 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.impl.app.slg;
+
+import org.jdiameter.api.Avp;
+import org.jdiameter.api.Answer;
+import org.jdiameter.api.Request;
+import org.jdiameter.api.AvpDataException;
+import org.jdiameter.api.slg.events.LocationReportAnswer;
+import org.jdiameter.common.impl.app.AppRequestEventImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class LocationReportAnswerImpl extends AppRequestEventImpl implements LocationReportAnswer {
+
+ private static final long serialVersionUID = 1L;
+
+ protected static final Logger logger = LoggerFactory.getLogger(LocationReportAnswerImpl.class);
+
+ /**
+ *
+ * @param answer
+ */
+ public LocationReportAnswerImpl(Answer answer) {
+ super(answer);
+ }
+
+ /**
+ *
+ * @param request
+ * @param resultCode
+ */
+ public LocationReportAnswerImpl(Request request, long resultCode) {
+ super(request.createAnswer(resultCode));
+ }
+
+ public Avp getResultCodeAvp() throws AvpDataException {
+ return null;
+ }
+
+ @Override
+ public boolean isGMLCAddressAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.GMLC_ADDRESS) != null;
+ }
+
+ @Override
+ public java.net.InetAddress getGMLCAddress() {
+ Avp lcsGMLCAddressAvp = super.message.getAvps().getAvp(Avp.GMLC_ADDRESS);
+ if (lcsGMLCAddressAvp != null) {
+ try {
+ return lcsGMLCAddressAvp.getAddress();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain GMLC Address AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isLRAFlagsAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LRA_FLAGS) != null;
+ }
+
+ @Override
+ public long getLRAFLags() {
+ Avp lcsLRAFlagsAvp = super.message.getAvps().getAvp(Avp.LRA_FLAGS);
+ if (lcsLRAFlagsAvp != null) {
+ try {
+ return lcsLRAFlagsAvp.getUnsigned32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS LRA Flags AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isReportingPLMNListAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.REPORTING_PLMN_LIST) != null;
+ }
+
+ @Override
+ public boolean isPrioritizedListIndicatorAvpPresent() {
+ Avp lcsReportingPLMNListAvp = super.message.getAvps().getAvp(Avp.REPORTING_PLMN_LIST);
+ if (lcsReportingPLMNListAvp != null) {
+ try {
+ return lcsReportingPLMNListAvp.getGrouped().getAvp(Avp.PRIORITIZED_LIST_INDICATOR) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Prioritized-List-Indicator AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getPrioritizedListIndicator() {
+ Avp lcsReportingPLMNListAvp = super.message.getAvps().getAvp(Avp.REPORTING_PLMN_LIST);
+ if (lcsReportingPLMNListAvp != null) {
+ try {
+ Avp lcsPrioritizedListIndicatorAvp = lcsReportingPLMNListAvp.getGrouped().getAvp(Avp.PRIORITIZED_LIST_INDICATOR);
+ if (lcsPrioritizedListIndicatorAvp != null){
+ return lcsPrioritizedListIndicatorAvp.getInteger32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS GERAN-Positioning-Data AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isPLMNIDListAvpPresent() {
+ Avp lcsReportingPLMNListAvp = super.message.getAvps().getAvp(Avp.REPORTING_PLMN_LIST);
+ if (lcsReportingPLMNListAvp != null) {
+ try {
+ return lcsReportingPLMNListAvp.getGrouped().getAvp(Avp.PLMN_ID_LIST) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain PLMN-Id-List AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isVisitedPLMNIdAvpPresent() {
+ Avp lcsPLMNIdListAvp = super.message.getAvps().getAvp(Avp.PLMN_ID_LIST);
+ if (lcsPLMNIdListAvp != null) {
+ try {
+ return lcsPLMNIdListAvp.getGrouped().getAvp(Avp.VISITED_PLMN_ID) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Visited-PLMN-Id AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getVisitedPLMNId() {
+ Avp lcsPLMNIdListAvp = super.message.getAvps().getAvp(Avp.PLMN_ID_LIST);
+ if (lcsPLMNIdListAvp != null) {
+ try {
+ Avp lcsVisitedPLMNIdAvp = lcsPLMNIdListAvp.getGrouped().getAvp(Avp.VISITED_PLMN_ID);
+ if (lcsVisitedPLMNIdAvp != null){
+ return lcsVisitedPLMNIdAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Visited PLMN ID AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isPeriodicLocationSupportIndicatorAvpPresent() {
+ Avp lcsPLMNIdListAvp = super.message.getAvps().getAvp(Avp.PLMN_ID_LIST);
+ if (lcsPLMNIdListAvp != null) {
+ try {
+ return lcsPLMNIdListAvp.getGrouped().getAvp(Avp.PERIODIC_LOCATION_SUPPORT_INDICATOR) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Periodic-Location-Support-Indicator AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getPeriodicLocationSupportIndicator() {
+ Avp lcsPLMNIdListAvp = super.message.getAvps().getAvp(Avp.PLMN_ID_LIST);
+ if (lcsPLMNIdListAvp != null) {
+ try {
+ Avp lcsPeriodicLocationSupportIndicatorAvp = lcsPLMNIdListAvp.getGrouped().getAvp(Avp.PERIODIC_LOCATION_SUPPORT_INDICATOR);
+ if (lcsPeriodicLocationSupportIndicatorAvp != null){
+ return lcsPeriodicLocationSupportIndicatorAvp.getInteger32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Periodic Location Support Indicator AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isLCSReferenceNumberAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LCS_REFERENCE_NUMBER) != null;
+ }
+
+ @Override
+ public byte[] getLCSReferenceNumber() {
+ Avp lcsLCSReferenceNumberAvp = super.message.getAvps().getAvp(Avp.LCS_REFERENCE_NUMBER);
+ if (lcsLCSReferenceNumberAvp != null) {
+ try {
+ return lcsLCSReferenceNumberAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Reference Number AVP value", e);
+ }
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/LocationReportRequestImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/LocationReportRequestImpl.java
new file mode 100644
index 000000000..eb0982d8d
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/LocationReportRequestImpl.java
@@ -0,0 +1,1176 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.impl.app.slg;
+
+import org.jdiameter.api.Avp;
+import org.jdiameter.api.AvpDataException;
+import org.jdiameter.api.Message;
+import org.jdiameter.api.slg.events.LocationReportRequest;
+import org.jdiameter.common.impl.app.AppRequestEventImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+public class LocationReportRequestImpl extends AppRequestEventImpl implements LocationReportRequest {
+
+ private static final long serialVersionUID = 1L;
+
+ protected static final Logger logger = LoggerFactory.getLogger(LocationReportRequestImpl.class);
+
+ public LocationReportRequestImpl(Message message) {
+ super(message);
+ message.setRequest(true);
+ }
+
+ @Override
+ public boolean isLocationEventAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LOCATION_EVENT) != null;
+ }
+
+ @Override
+ public int getLocationEvent() {
+ Avp slgLocationEventAvp = super.message.getAvps().getAvp(Avp.LOCATION_EVENT);
+ if (slgLocationEventAvp != null) {
+ try {
+ return slgLocationEventAvp.getInteger32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Location-Event AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isUserNameAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.USER_NAME) != null; // IE: IMSI
+ }
+
+ @Override
+ public String getUserName() {
+ Avp userNameAvp = super.message.getAvps().getAvp(Avp.USER_NAME);
+ if (userNameAvp != null) {
+ try {
+ return userNameAvp.getUTF8String(); // IE: IMSI mapped to User-Name
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain User-Name AVP value (IMSI)", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isMSISDNAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.MSISDN) != null;
+ }
+
+ @Override
+ public byte[] getMSISDN() {
+ Avp msisdnAvp = super.message.getAvps().getAvp(Avp.MSISDN);
+ if (msisdnAvp != null) {
+ try {
+ return msisdnAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain MSISDN AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isIMEIAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.TGPP_IMEI) != null;
+ }
+
+ @Override
+ public String getIMEI() {
+ Avp imeiAvp = super.message.getAvps().getAvp(Avp.TGPP_IMEI);
+ if (imeiAvp != null) {
+ try {
+ return imeiAvp.getUTF8String();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain IMEI AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isLCSEPSClientNameAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LCS_EPS_CLIENT_NAME) != null;
+ }
+
+ @Override
+ public boolean isLSCNameStringAvpPresent() {
+ Avp lcsEPSClientNameAvp = super.message.getAvps().getAvp(Avp.LCS_EPS_CLIENT_NAME);
+ if (lcsEPSClientNameAvp != null) {
+ try {
+ return lcsEPSClientNameAvp.getGrouped().getAvp(Avp.LCS_NAME_STRING) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Name-String AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getLSCNameString() {
+ Avp lcsEPSClientNameAvp = super.message.getAvps().getAvp(Avp.LCS_EPS_CLIENT_NAME);
+ if (lcsEPSClientNameAvp != null) {
+ try {
+ Avp lcsNameStringAvp = lcsEPSClientNameAvp.getGrouped().getAvp(Avp.LCS_NAME_STRING);
+ if (lcsNameStringAvp != null){
+ return lcsNameStringAvp.getUTF8String();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Name-String AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isLCSFormatIndicatorAvpPresent() {
+ Avp lcsEPSClientNameAvp = super.message.getAvps().getAvp(Avp.LCS_EPS_CLIENT_NAME);
+ if (lcsEPSClientNameAvp != null) {
+ try {
+ return lcsEPSClientNameAvp.getGrouped().getAvp(Avp.LCS_FORMAT_INDICATOR) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Format-Indicator AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getLCSFormatIndicator() {
+ Avp lcsEPSClientNameAvp = super.message.getAvps().getAvp(Avp.LCS_EPS_CLIENT_NAME);
+ if (lcsEPSClientNameAvp != null) {
+ try {
+ Avp lcsFormatIndicatorAvp = lcsEPSClientNameAvp.getGrouped().getAvp(Avp.LCS_FORMAT_INDICATOR);
+ if (lcsFormatIndicatorAvp != null){
+ return lcsFormatIndicatorAvp.getInteger32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Format-Indicator AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isLocationEstimateAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LOCATION_ESTIMATE) != null;
+ }
+
+ @Override
+ public byte[] getLocationEstimate() {
+ Avp lcsLocationEstimateAvp = super.message.getAvps().getAvp(Avp.LOCATION_ESTIMATE);
+ if (lcsLocationEstimateAvp != null) {
+ try {
+ return lcsLocationEstimateAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Location-Estimate AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isAccuracyFulfilmentIndicatorAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.ACCURACY_FULFILMENT_INDICATOR) != null;
+ }
+
+ @Override
+ public int getAccuracyFulfilmentIndicator() {
+ Avp lcsAccuracyFulfilmentIndAvp = super.message.getAvps().getAvp(Avp.ACCURACY_FULFILMENT_INDICATOR);
+ if (lcsAccuracyFulfilmentIndAvp != null) {
+ try {
+ return lcsAccuracyFulfilmentIndAvp.getInteger32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Accuracy fulfilment indicator AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isAgeOfLocationEstimateAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.AGE_OF_LOCATION_ESTIMATE) != null;
+ }
+
+ @Override
+ public long getAgeOfLocationEstimate() {
+ Avp lcsAgeOfLocEstimateAvp = super.message.getAvps().getAvp(Avp.AGE_OF_LOCATION_ESTIMATE);
+ if (lcsAgeOfLocEstimateAvp != null) {
+ try {
+ return lcsAgeOfLocEstimateAvp.getUnsigned32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Age of Location Estimate AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isVelocityEstimateAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.VELOCITY_ESTIMATE) != null;
+ }
+
+ @Override
+ public byte[] getVelocityEstimate() {
+ Avp lcsVelEstimateAvp = super.message.getAvps().getAvp(Avp.VELOCITY_ESTIMATE);
+ if (lcsVelEstimateAvp != null) {
+ try {
+ return lcsVelEstimateAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Velocity Estimate AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isEUTRANPositioningDataAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.EUTRAN_POSITIONING_DATA) != null;
+ }
+
+ @Override
+ public byte[] getEUTRANPositioningData() {
+ Avp lcsEUTRANPosDataAvp = super.message.getAvps().getAvp(Avp.EUTRAN_POSITIONING_DATA);
+ if (lcsEUTRANPosDataAvp != null) {
+ try {
+ return lcsEUTRANPosDataAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS E-UTRAN-Positioning-Data AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isECGIAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.ECGI) != null;
+ }
+
+ @Override
+ public byte[] getECGI() {
+ Avp lcsECGIAvp = super.message.getAvps().getAvp(Avp.ECGI);
+ if (lcsECGIAvp != null) {
+ try {
+ return lcsECGIAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS ECGI AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isGERANPositioningInfoAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.GERAN_POSITIONING_INFO) != null;
+ }
+
+ @Override
+ public boolean isGERANPositioningDataAvpPresent() {
+ Avp lcsGERANPositioningInfoAvp = super.message.getAvps().getAvp(Avp.GERAN_POSITIONING_INFO);
+ if (lcsGERANPositioningInfoAvp != null) {
+ try {
+ return lcsGERANPositioningInfoAvp.getGrouped().getAvp(Avp.GERAN_POSITIONING_DATA) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Reporting-Interval AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getGERANPositioningData() {
+ Avp lcsGERANPositioningInfoAvp = super.message.getAvps().getAvp(Avp.GERAN_POSITIONING_INFO);
+ if (lcsGERANPositioningInfoAvp != null) {
+ try {
+ Avp lcsGERANPositioningDataAvp = lcsGERANPositioningInfoAvp.getGrouped().getAvp(Avp.GERAN_POSITIONING_DATA);
+ if (lcsGERANPositioningDataAvp != null){
+ return lcsGERANPositioningDataAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS GERAN-Positioning-Data AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isGERANGANSSPositioningDataAvpPresent() {
+ Avp lcsGERANPositioningInfoAvp = super.message.getAvps().getAvp(Avp.GERAN_POSITIONING_INFO);
+ if (lcsGERANPositioningInfoAvp != null) {
+ try {
+ return lcsGERANPositioningInfoAvp.getGrouped().getAvp(Avp.GERAN_GANSS_POSITIONING_DATA) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain GERAN-GANSS-Positioning-Data AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getGERANGANSSPositioningData() {
+ Avp lcsGERANPositioningInfoAvp = super.message.getAvps().getAvp(Avp.GERAN_POSITIONING_INFO);
+ if (lcsGERANPositioningInfoAvp != null) {
+ try {
+ Avp lcsGERANGANSSPositioningDataAvp = lcsGERANPositioningInfoAvp.getGrouped().getAvp(Avp.GERAN_GANSS_POSITIONING_DATA);
+ if (lcsGERANGANSSPositioningDataAvp != null){
+ return lcsGERANGANSSPositioningDataAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS GERAN-GANSS-Positioning-Data AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isCellGlobalIdentityAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.CELL_GLOBAL_IDENTITY) != null;
+ }
+
+ @Override
+ public byte[] getCellGlobalIdentity() {
+ Avp lcsCellGlobalIdAvp = super.message.getAvps().getAvp(Avp.CELL_GLOBAL_IDENTITY);
+ if (lcsCellGlobalIdAvp != null) {
+ try {
+ return lcsCellGlobalIdAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Cell-Global-Identity AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isUTRANPositioningInfoAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.UTRAN_POSITIONING_INFO) != null;
+ }
+
+ @Override
+ public boolean isUTRANPositioningDataAvpPresent() {
+ Avp lcsUTRANPositioningInfoAvp = super.message.getAvps().getAvp(Avp.UTRAN_POSITIONING_INFO);
+ if (lcsUTRANPositioningInfoAvp != null) {
+ try {
+ return lcsUTRANPositioningInfoAvp.getGrouped().getAvp(Avp.UTRAN_POSITIONING_DATA) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain UTRAN-Positioning-Data AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getUTRANPositioningData() {
+ Avp lcsUTRANPositioningInfoAvp = super.message.getAvps().getAvp(Avp.UTRAN_POSITIONING_INFO);
+ if (lcsUTRANPositioningInfoAvp != null) {
+ try {
+ Avp lcsUTRANPositioningDataAvp = lcsUTRANPositioningInfoAvp.getGrouped().getAvp(Avp.UTRAN_POSITIONING_DATA);
+ if (lcsUTRANPositioningDataAvp != null){
+ return lcsUTRANPositioningDataAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS UTRAN-Positioning-Data AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isUTRANGANSSPositioningDataAvpPresent() {
+ Avp lcsUTRANPositioningInfoAvp = super.message.getAvps().getAvp(Avp.UTRAN_POSITIONING_INFO);
+ if (lcsUTRANPositioningInfoAvp != null) {
+ try {
+ return lcsUTRANPositioningInfoAvp.getGrouped().getAvp(Avp.UTRAN_GANSS_POSITIONING_DATA) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain UTRAN-GANSS-Positioning-Data AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getUTRANGANSSPositioningData() {
+ Avp lcsUTRANPositioningInfoAvp = super.message.getAvps().getAvp(Avp.UTRAN_POSITIONING_INFO);
+ if (lcsUTRANPositioningInfoAvp != null) {
+ try {
+ Avp lcsUTRANGANSSPositioningDataAvp = lcsUTRANPositioningInfoAvp.getGrouped().getAvp(Avp.UTRAN_GANSS_POSITIONING_DATA);
+ if (lcsUTRANGANSSPositioningDataAvp != null){
+ return lcsUTRANGANSSPositioningDataAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS UTRAN-GANSS-Positioning-Data AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isServiceAreaIdentityAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.SERVICE_AREA_IDENTITY) != null;
+ }
+
+ @Override
+ public byte[] getServiceAreaIdentity() {
+ Avp lcsServiceAreaIdentityAvp = super.message.getAvps().getAvp(Avp.SERVICE_AREA_IDENTITY);
+ if (lcsServiceAreaIdentityAvp != null) {
+ try {
+ return lcsServiceAreaIdentityAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS SERVICE-AREA-IDENTITY AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isLCSServiceTypeIDAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LCS_SERVICE_TYPE_ID) != null;
+ }
+
+ @Override
+ public long getLCSServiceTypeID() {
+ Avp lcsLCSServiceTypeIDAvp = super.message.getAvps().getAvp(Avp.LCS_SERVICE_TYPE_ID);
+ if (lcsLCSServiceTypeIDAvp != null) {
+ try {
+ return lcsLCSServiceTypeIDAvp.getUnsigned32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Service Type ID AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isPseudonymIndicatorAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.PSEUDONYM_INDICATOR) != null;
+ }
+
+ @Override
+ public int getPseudonymIndicator() {
+ Avp lcsPseudonymIndicatorAvp = super.message.getAvps().getAvp(Avp.PSEUDONYM_INDICATOR);
+ if (lcsPseudonymIndicatorAvp != null) {
+ try {
+ return lcsPseudonymIndicatorAvp.getInteger32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Pseudonym Indicator AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isLCSQoSAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LCS_QOS) != null;
+ }
+
+ @Override
+ public boolean isLCSQoSClassAvpPresent() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ return lcsQoSAvp.getGrouped().getAvp(Avp.LCS_QOS_CLASS) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-QoS-Class AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getLCSQoSClass() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ Avp lcsQoSClassAvp = lcsQoSAvp.getGrouped().getAvp(Avp.LCS_QOS_CLASS);
+ if (lcsQoSClassAvp != null){
+ return lcsQoSClassAvp.getInteger32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-QoS-Class AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isHorizontalAccuracyAvpPresent() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ return lcsQoSAvp.getGrouped().getAvp(Avp.HORIZONTAL_ACCURACY) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Horizontal-Accuracy AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public long getHorizontalAccuracy() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ Avp lcsQoSHorizontalAccuracyAvp = lcsQoSAvp.getGrouped().getAvp(Avp.HORIZONTAL_ACCURACY);
+ if (lcsQoSHorizontalAccuracyAvp != null){
+ return lcsQoSHorizontalAccuracyAvp.getUnsigned32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Horizontal-Accuracy AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isVerticalAccuracyAvpPresent() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ return lcsQoSAvp.getGrouped().getAvp(Avp.VERTICAL_ACCURACY) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Vertical-Accuracy AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public long getVerticalAccuracy() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ Avp lcsQoSVerticalAccuracyAvp = lcsQoSAvp.getGrouped().getAvp(Avp.HORIZONTAL_ACCURACY);
+ if (lcsQoSVerticalAccuracyAvp != null){
+ return lcsQoSVerticalAccuracyAvp.getUnsigned32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Vertical-Accuracy AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isVerticalRequestedAvpPresent() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ return lcsQoSAvp.getGrouped().getAvp(Avp.VERTICAL_REQUESTED) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Vertical-Requested AVP", e);
+ }
+ }
+ return false;
+ }
+
+ public int getVerticalRequested() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ Avp lcsQoSVerticalRequestedAvp = lcsQoSAvp.getGrouped().getAvp(Avp.VERTICAL_REQUESTED);
+ if (lcsQoSVerticalRequestedAvp != null){
+ return lcsQoSVerticalRequestedAvp.getInteger32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Vertical-Requested AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isResponseTimeAvpPresent() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ return lcsQoSAvp.getGrouped().getAvp(Avp.RESPONSE_TIME) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Response-Time AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getResponseTime() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ Avp lcsQoSResponseTimeAvp = lcsQoSAvp.getGrouped().getAvp(Avp.RESPONSE_TIME);
+ if (lcsQoSResponseTimeAvp != null){
+ return lcsQoSResponseTimeAvp.getInteger32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Response-Time AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isServingNodeAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.SERVING_NODE) != null;
+ }
+
+ @Override
+ public boolean isSGSNNumberAvpPresent() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.SGSN_NUMBER) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS SGSN-Number AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getSGSNNumber() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcsSGSNNumberAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.SGSN_NUMBER);
+ if (lcsSGSNNumberAvp != null){
+ return lcsSGSNNumberAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS SGSN-Number AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isSGSNNameAvpPresent() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.SGSN_NAME) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS SGSN-Name AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getSGSNName() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcsSGSNNameAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.SGSN_NAME);
+ if (lcsSGSNNameAvp != null){
+ return lcsSGSNNameAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS SGSN-Name AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isSGSNRealmAvpPresent() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.SGSN_REALM) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS SGSN-Realm AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getSGSNRealm() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcsSGSNRealmAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.SGSN_REALM);
+ if (lcsSGSNRealmAvp != null){
+ return lcsSGSNRealmAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS SGSN-Realm AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isMMENameAvpPresent() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.MME_NAME) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS MME-Name AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getMMEName() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcsMMENameAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.MME_NAME);
+ if (lcsMMENameAvp != null){
+ return lcsMMENameAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS MME-Name AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isMMERealmAvpPresent() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.MME_REALM) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS MME-Realm AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getMMERealm() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcsMMERealmAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.MME_REALM);
+ if (lcsMMERealmAvp != null){
+ return lcsMMERealmAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS MME-Realm AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isMSCNumberAvpPresent() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.MSC_NUMBER) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS MSC-Number AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getMSCNumber() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcsMSCNumberAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.MSC_NUMBER);
+ if (lcsMSCNumberAvp != null){
+ return lcsMSCNumberAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS MSC-Number AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean is3GPPAAAServerNameAvpPresent() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.TGPP_AAA_SERVER_NAME) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS 3GPP-AAA-Server-Name AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String get3GPPAAAServerName() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcs3GPPAAAServerNameAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.TGPP_AAA_SERVER_NAME);
+ if (lcs3GPPAAAServerNameAvp != null){
+ return lcs3GPPAAAServerNameAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS 3GPP-AAA-Server-Name AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isLCSCapabilitiesSetsAvpPresent() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.LCS_CAPABILITIES_SETS) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Capabilities-Sets AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public long getLCSCapabilitiesSets() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcsCapabilitiesSetsAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.LCS_CAPABILITIES_SETS);
+ if (lcsCapabilitiesSetsAvp != null){
+ return lcsCapabilitiesSetsAvp.getUnsigned32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Capabilities-Sets AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isGMLCAddressAvpPresent() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.GMLC_ADDRESS) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS GMLC-Address AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public java.net.InetAddress getGMLCAddress() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcsCapabilitiesSetsAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.GMLC_ADDRESS);
+ if (lcsCapabilitiesSetsAvp != null){
+ return lcsCapabilitiesSetsAvp.getAddress();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS GMLC-Address AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isLRRFlagsAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LRR_FLAGS) != null;
+ }
+
+ @Override
+ public long getLRRFLags() {
+ Avp lcsLRRFlagsAvp = super.message.getAvps().getAvp(Avp.LRR_FLAGS);
+ if (lcsLRRFlagsAvp != null) {
+ try {
+ return lcsLRRFlagsAvp.getUnsigned32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS LRR Flags AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isLCSReferenceNumberAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LCS_REFERENCE_NUMBER) != null;
+ }
+
+ @Override
+ public byte[] getLCSReferenceNumber() {
+ Avp lcsLCSReferenceNumberAvp = super.message.getAvps().getAvp(Avp.LCS_REFERENCE_NUMBER);
+ if (lcsLCSReferenceNumberAvp != null) {
+ try {
+ return lcsLCSReferenceNumberAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Reference Number AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isDeferredMTLRDataAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.DEFERRED_MT_LR_DATA) != null;
+ }
+
+ @Override
+ public boolean isDeferredLocationTypeAvpPresent() {
+ Avp lcsDeferredMTLRDataAvp = super.message.getAvps().getAvp(Avp.DEFERRED_MT_LR_DATA);
+ if (lcsDeferredMTLRDataAvp != null) {
+ try {
+ return lcsDeferredMTLRDataAvp.getGrouped().getAvp(Avp.DEFERRED_LOCATION_TYPE) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Deferred-Location-Type AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public long getDeferredLocationType() {
+ Avp lcsDeferredMTLRDataAvp = super.message.getAvps().getAvp(Avp.DEFERRED_MT_LR_DATA);
+ if (lcsDeferredMTLRDataAvp != null) {
+ try {
+ Avp deferredLocationType = lcsDeferredMTLRDataAvp.getGrouped().getAvp(Avp.DEFERRED_LOCATION_TYPE);
+ if (deferredLocationType != null){
+ return deferredLocationType.getUnsigned32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Deferred Location Type AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isTerminationCauseAvpPresent() {
+ Avp lcsDeferredMTLRDataAvp = super.message.getAvps().getAvp(Avp.DEFERRED_MT_LR_DATA);
+ if (lcsDeferredMTLRDataAvp != null) {
+ try {
+ return lcsDeferredMTLRDataAvp.getGrouped().getAvp(Avp.TERMINATION_CAUSE_LCS) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Termination-Cause AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public long getTerminationCause() {
+ Avp lcsDeferredMTLRDataAvp = super.message.getAvps().getAvp(Avp.DEFERRED_MT_LR_DATA);
+ if (lcsDeferredMTLRDataAvp != null) {
+ try {
+ Avp lcsTerminationCause = lcsDeferredMTLRDataAvp.getGrouped().getAvp(Avp.TERMINATION_CAUSE_LCS);
+ if (lcsTerminationCause != null){
+ return lcsTerminationCause.getUnsigned32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Termination-Cause AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isHGMLCAddressAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.GMLC_ADDRESS) != null; // IE: H-GMLC Address mapped to GMLC-Address AVP
+ }
+
+ @Override
+ public java.net.InetAddress getHGMLCAddress() {
+ Avp lcsHGMLCAddressAvp = super.message.getAvps().getAvp(Avp.GMLC_ADDRESS); // IE: H-GMLC Address mapped to GMLC-Address AVP
+ if (lcsHGMLCAddressAvp != null) {
+ try {
+ return lcsHGMLCAddressAvp.getAddress();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain H-GMLC-Address AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isPeriodicLDRInfoAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.PERIODIC_LDR_INFORMATION) != null;
+ }
+
+ @Override
+ public boolean isReportingAmountAvpPresent() {
+ Avp lcsPeriodicLDRInfoAvp = super.message.getAvps().getAvp(Avp.PERIODIC_LDR_INFORMATION);
+ if (lcsPeriodicLDRInfoAvp != null) {
+ try {
+ return lcsPeriodicLDRInfoAvp.getGrouped().getAvp(Avp.REPORTING_AMOUNT) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Reporting-Amount AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public long getReportingAmount() {
+ Avp lcsPeriodicLDRInfoAvp = super.message.getAvps().getAvp(Avp.PERIODIC_LDR_INFORMATION);
+ if (lcsPeriodicLDRInfoAvp != null) {
+ try {
+ Avp lcsReportingAmountAvp = lcsPeriodicLDRInfoAvp.getGrouped().getAvp(Avp.REPORTING_AMOUNT);
+ if (lcsReportingAmountAvp != null){
+ return lcsReportingAmountAvp.getUnsigned32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Reporting amount AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isReportingIntervalAvpPresent() {
+ Avp lcsPeriodicLDRInfo = super.message.getAvps().getAvp(Avp.PERIODIC_LDR_INFORMATION);
+ if (lcsPeriodicLDRInfo != null) {
+ try {
+ return lcsPeriodicLDRInfo.getGrouped().getAvp(Avp.REPORTING_INTERVAL) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Reporting-Interval AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public long getReportingInterval() {
+ Avp lcsPeriodicLDRInfo = super.message.getAvps().getAvp(Avp.PERIODIC_LDR_INFORMATION);
+ if (lcsPeriodicLDRInfo != null) {
+ try {
+ Avp lcsReportingIntervalAvp = lcsPeriodicLDRInfo.getGrouped().getAvp(Avp.REPORTING_INTERVAL);
+ if (lcsReportingIntervalAvp != null){
+ return lcsReportingIntervalAvp.getUnsigned32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Reporting-Interval AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isESMLCCellInfoAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.ESMLC_CELL_INFO) != null;
+ }
+
+ @Override
+ public long getCellPortionId() {
+ Avp lcsCellPortionIdAvp = super.message.getAvps().getAvp(Avp.CELL_PORTION_ID);
+ if (lcsCellPortionIdAvp != null) {
+ try {
+ return lcsCellPortionIdAvp.getUnsigned32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Cell-Portion-Id AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean is1xRTTRCIDAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.ONEXRTT_RCID) != null;
+ }
+
+ @Override
+ public byte[] get1xRTTRCID() {
+ Avp lcs1xRTTRCIDAvp = super.message.getAvps().getAvp(Avp.ONEXRTT_RCID);
+ if (lcs1xRTTRCIDAvp != null) {
+ try {
+ return lcs1xRTTRCIDAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS 1xRTT_RCID AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isCivicAddressAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.CIVIC_ADDRESS) != null;
+ }
+
+ @Override
+ public String getCivicAddress() {
+ Avp lcsCivicAddressAvp = super.message.getAvps().getAvp(Avp.CIVIC_ADDRESS);
+ if (lcsCivicAddressAvp != null) {
+ try {
+ return lcsCivicAddressAvp.getUTF8String();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Civic Address AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isBarometricPressureAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.BAROMETRIC_PRESSURE) != null;
+ }
+
+ @Override
+ public long getBarometricPressure() {
+ Avp lcsBarometricPressureAvp = super.message.getAvps().getAvp(Avp.BAROMETRIC_PRESSURE);
+ if (lcsBarometricPressureAvp != null) {
+ try {
+ return lcsBarometricPressureAvp.getUnsigned32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Barometric Pressure AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/ProvideLocationAnswerImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/ProvideLocationAnswerImpl.java
new file mode 100644
index 000000000..ae66d33f7
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/ProvideLocationAnswerImpl.java
@@ -0,0 +1,695 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.impl.app.slg;
+
+import org.jdiameter.api.Avp;
+import org.jdiameter.api.Answer;
+import org.jdiameter.api.Request;
+import org.jdiameter.api.AvpDataException;
+import org.jdiameter.api.slg.events.ProvideLocationAnswer;
+import org.jdiameter.common.impl.app.AppRequestEventImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class ProvideLocationAnswerImpl extends AppRequestEventImpl implements ProvideLocationAnswer {
+
+ private static final long serialVersionUID = 1L;
+
+ protected static final Logger logger = LoggerFactory.getLogger(ProvideLocationRequestImpl.class);
+
+ /**
+ *
+ * @param answer
+ */
+ public ProvideLocationAnswerImpl(Answer answer) {
+ super(answer);
+ }
+
+ /**
+ *
+ * @param request
+ * @param resultCode
+ */
+ public ProvideLocationAnswerImpl(Request request, long resultCode) {
+ super(request.createAnswer(resultCode));
+ }
+
+ public Avp getResultCodeAvp() throws AvpDataException {
+ return null;
+ }
+
+ @Override
+ public boolean isLocationEstimateAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LOCATION_ESTIMATE) != null;
+ }
+
+ @Override
+ public byte[] getLocationEstimate() {
+ Avp lcsLocationEstimateAvp = super.message.getAvps().getAvp(Avp.LOCATION_ESTIMATE);
+ if (lcsLocationEstimateAvp != null) {
+ try {
+ return lcsLocationEstimateAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Location-Estimate AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isAccuracyFulfilmentIndicatorAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.ACCURACY_FULFILMENT_INDICATOR) != null;
+ }
+
+ @Override
+ public int getAccuracyFulfilmentIndicator() {
+ Avp lcsAccuracyFulfilmentIndAvp = super.message.getAvps().getAvp(Avp.ACCURACY_FULFILMENT_INDICATOR);
+ if (lcsAccuracyFulfilmentIndAvp != null) {
+ try {
+ return lcsAccuracyFulfilmentIndAvp.getInteger32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Accuracy fulfilment indicator AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isAgeOfLocationEstimateAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.AGE_OF_LOCATION_ESTIMATE) != null;
+ }
+
+ @Override
+ public long getAgeOfLocationEstimate() {
+ Avp lcsAgeOfLocEstimateAvp = super.message.getAvps().getAvp(Avp.AGE_OF_LOCATION_ESTIMATE);
+ if (lcsAgeOfLocEstimateAvp != null) {
+ try {
+ return lcsAgeOfLocEstimateAvp.getUnsigned32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Age of Location Estimate AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isVelocityEstimateAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.VELOCITY_ESTIMATE) != null;
+ }
+
+ @Override
+ public byte[] getVelocityEstimate() {
+ Avp lcsVelEstimateAvp = super.message.getAvps().getAvp(Avp.VELOCITY_ESTIMATE);
+ if (lcsVelEstimateAvp != null) {
+ try {
+ return lcsVelEstimateAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Velocity Estimate AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isEUTRANPositioningDataAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.EUTRAN_POSITIONING_DATA) != null;
+ }
+
+ @Override
+ public byte[] getEUTRANPositioningData() {
+ Avp lcsEUTRANPosDataAvp = super.message.getAvps().getAvp(Avp.EUTRAN_POSITIONING_DATA);
+ if (lcsEUTRANPosDataAvp != null) {
+ try {
+ return lcsEUTRANPosDataAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS E-UTRAN-Positioning-Data AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isECGIAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.ECGI) != null;
+ }
+
+ @Override
+ public byte[] getECGI(){
+ Avp lcsECGIAvp = super.message.getAvps().getAvp(Avp.ECGI);
+ if (lcsECGIAvp != null) {
+ try {
+ return lcsECGIAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS ECGI AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isGERANPositioningInfoAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.GERAN_POSITIONING_INFO) != null;
+ }
+
+ @Override
+ public boolean isGERANPositioningDataAVPPresent(){
+ Avp lcsGERANPositioningInfoAvp = super.message.getAvps().getAvp(Avp.GERAN_POSITIONING_INFO);
+ if (lcsGERANPositioningInfoAvp != null) {
+ try {
+ return lcsGERANPositioningInfoAvp.getGrouped().getAvp(Avp.GERAN_POSITIONING_DATA) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Reporting-Interval AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getGERANPositioningData() {
+ Avp lcsGERANPositioningInfoAvp = super.message.getAvps().getAvp(Avp.GERAN_POSITIONING_INFO);
+ if (lcsGERANPositioningInfoAvp != null) {
+ try {
+ Avp lcsGERANPositioningDataAvp = lcsGERANPositioningInfoAvp.getGrouped().getAvp(Avp.GERAN_POSITIONING_DATA);
+ if (lcsGERANPositioningDataAvp != null){
+ return lcsGERANPositioningDataAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS GERAN-Positioning-Data AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isGERANGANSSPositioningDataAVPPresent() {
+ Avp lcsGERANPositioningInfoAvp = super.message.getAvps().getAvp(Avp.GERAN_POSITIONING_INFO);
+ if (lcsGERANPositioningInfoAvp != null) {
+ try {
+ return lcsGERANPositioningInfoAvp.getGrouped().getAvp(Avp.GERAN_GANSS_POSITIONING_DATA) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain GERAN-GANSS-Positioning-Data AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getGERANGANSSPositioningData() {
+ Avp lcsGERANPositioningInfoAvp = super.message.getAvps().getAvp(Avp.GERAN_POSITIONING_INFO);
+ if (lcsGERANPositioningInfoAvp != null) {
+ try {
+ Avp lcsGERANGANSSPositioningDataAvp = lcsGERANPositioningInfoAvp.getGrouped().getAvp(Avp.GERAN_GANSS_POSITIONING_DATA);
+ if (lcsGERANGANSSPositioningDataAvp != null){
+ return lcsGERANGANSSPositioningDataAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS GERAN-GANSS-Positioning-Data AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isCellGlobalIdentityAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.CELL_GLOBAL_IDENTITY) != null;
+ }
+
+ @Override
+ public byte[] getCellGlobalIdentity() {
+ Avp lcsCellGlobalIdAvp = super.message.getAvps().getAvp(Avp.CELL_GLOBAL_IDENTITY);
+ if (lcsCellGlobalIdAvp != null) {
+ try {
+ return lcsCellGlobalIdAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Cell-Global-Identity AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isUTRANPositioningInfoAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.UTRAN_POSITIONING_INFO) != null;
+ }
+
+ @Override
+ public boolean isUTRANPositioningDataAVPPresent() {
+ Avp lcsUTRANPositioningInfoAvp = super.message.getAvps().getAvp(Avp.UTRAN_POSITIONING_INFO);
+ if (lcsUTRANPositioningInfoAvp != null) {
+ try {
+ return lcsUTRANPositioningInfoAvp.getGrouped().getAvp(Avp.UTRAN_POSITIONING_DATA) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain UTRAN-Positioning-Data AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getUTRANPositioningData() {
+ Avp lcsUTRANPositioningInfoAvp = super.message.getAvps().getAvp(Avp.UTRAN_POSITIONING_INFO);
+ if (lcsUTRANPositioningInfoAvp != null) {
+ try {
+ Avp lcsUTRANPositioningDataAvp = lcsUTRANPositioningInfoAvp.getGrouped().getAvp(Avp.UTRAN_POSITIONING_DATA);
+ if (lcsUTRANPositioningDataAvp != null){
+ return lcsUTRANPositioningDataAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS UTRAN-Positioning-Data AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isUTRANGANSSPositioningDataAVPPresent() {
+ Avp lcsUTRANPositioningInfoAvp = super.message.getAvps().getAvp(Avp.UTRAN_POSITIONING_INFO);
+ if (lcsUTRANPositioningInfoAvp != null) {
+ try {
+ return lcsUTRANPositioningInfoAvp.getGrouped().getAvp(Avp.UTRAN_GANSS_POSITIONING_DATA) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain UTRAN-GANSS-Positioning-Data AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getUTRANGANSSPositioningData() {
+ Avp lcsUTRANPositioningInfoAvp = super.message.getAvps().getAvp(Avp.UTRAN_POSITIONING_INFO);
+ if (lcsUTRANPositioningInfoAvp != null) {
+ try {
+ Avp lcsUTRANGANSSPositioningDataAvp = lcsUTRANPositioningInfoAvp.getGrouped().getAvp(Avp.UTRAN_GANSS_POSITIONING_DATA);
+ if (lcsUTRANGANSSPositioningDataAvp != null){
+ return lcsUTRANGANSSPositioningDataAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS UTRAN-GANSS-Positioning-Data AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isServiceAreaIdentityAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.SERVICE_AREA_IDENTITY) != null;
+ }
+
+ @Override
+ public byte[] getServiceAreaIdentity() {
+ Avp lcsServiceAreaIdentityAvp = super.message.getAvps().getAvp(Avp.SERVICE_AREA_IDENTITY);
+ if (lcsServiceAreaIdentityAvp != null) {
+ try {
+ return lcsServiceAreaIdentityAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS SERVICE-AREA-IDENTITY AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isServingNodeAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.SERVING_NODE) != null;
+ }
+
+ @Override
+ public boolean isSGSNNumberAvpPresent(){
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.SGSN_NUMBER) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS SGSN-Number AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getSGSNNumber() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcsSGSNNumberAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.SGSN_NUMBER);
+ if (lcsSGSNNumberAvp != null){
+ return lcsSGSNNumberAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS SGSN-Number AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isSGSNNameAvpPresent() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.SGSN_NAME) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS SGSN-Name AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getSGSNName() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcsSGSNNameAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.SGSN_NAME);
+ if (lcsSGSNNameAvp != null){
+ return lcsSGSNNameAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS SGSN-Name AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isSGSNRealmAvpPresent() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.SGSN_REALM) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS SGSN-Realm AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getSGSNRealm() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcsSGSNRealmAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.SGSN_REALM);
+ if (lcsSGSNRealmAvp != null){
+ return lcsSGSNRealmAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS SGSN-Realm AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isMMENameAvpPresent() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.MME_NAME) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS MME-Name AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getMMEName() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcsMMENameAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.MME_NAME);
+ if (lcsMMENameAvp != null){
+ return lcsMMENameAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS MME-Name AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isMMERealmAvpPresent() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.MME_REALM) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS MME-Realm AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getMMERealm() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcsMMERealmAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.MME_REALM);
+ if (lcsMMERealmAvp != null){
+ return lcsMMERealmAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS MME-Realm AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isMSCNumberAvpPresent() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.MSC_NUMBER) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS MSC-Number AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getMSCNumber() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcsMSCNumberAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.MSC_NUMBER);
+ if (lcsMSCNumberAvp != null){
+ return lcsMSCNumberAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS MSC-Number AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean is3GPPAAAServerNameAvpPResent() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.TGPP_AAA_SERVER_NAME) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS 3GPP-AAA-Server-Name AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String get3GPPAAAServerName() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcs3GPPAAAServerNameAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.TGPP_AAA_SERVER_NAME);
+ if (lcs3GPPAAAServerNameAvp != null){
+ return lcs3GPPAAAServerNameAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS 3GPP-AAA-Server-Name AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isLCSCapabilitiesSetsAvpPresent() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.LCS_CAPABILITIES_SETS) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Capabilities-Sets AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public long getLCSCapabilitiesSets() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcsCapabilitiesSetsAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.LCS_CAPABILITIES_SETS);
+ if (lcsCapabilitiesSetsAvp != null){
+ return lcsCapabilitiesSetsAvp.getUnsigned32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Capabilities-Sets AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isGMLCAddressAvpPresent() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ return lcsServingNodeAvp.getGrouped().getAvp(Avp.GMLC_ADDRESS) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS GMLC-Address AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public java.net.InetAddress getGMLCAddress() {
+ Avp lcsServingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (lcsServingNodeAvp != null) {
+ try {
+ Avp lcsCapabilitiesSetsAvp = lcsServingNodeAvp.getGrouped().getAvp(Avp.GMLC_ADDRESS);
+ if (lcsCapabilitiesSetsAvp != null){
+ return lcsCapabilitiesSetsAvp.getAddress();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS GMLC-Address AVP value", e);
+ }
+ }
+ return null;
+ }
+
+
+ @Override
+ public boolean isPLAFlagsAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.PLA_FLAGS) != null;
+ }
+
+ @Override
+ public long getPLAFlags(){
+ Avp lcsPLAFlagsAvp = super.message.getAvps().getAvp(Avp.PLA_FLAGS);
+ if (lcsPLAFlagsAvp != null) {
+ try {
+ return lcsPLAFlagsAvp.getUnsigned32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS PLA-Flags AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isESMLCCellInfoAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.ESMLC_CELL_INFO) != null;
+ }
+
+ @Override
+ public long getCellPortionId() {
+ Avp lcsCellPortionIdAvp = super.message.getAvps().getAvp(Avp.CELL_PORTION_ID);
+ if (lcsCellPortionIdAvp != null) {
+ try {
+ return lcsCellPortionIdAvp.getUnsigned32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Cell-Portion-Id AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isCivicAddressAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.CIVIC_ADDRESS) != null;
+ }
+
+ @Override
+ public String getCivicAddress(){
+ Avp lcsCivicAddressAvp = super.message.getAvps().getAvp(Avp.CIVIC_ADDRESS);
+ if (lcsCivicAddressAvp != null) {
+ try {
+ return lcsCivicAddressAvp.getUTF8String();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Civic Address AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isBarometricPressureAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.BAROMETRIC_PRESSURE) != null;
+ }
+
+ @Override
+ public long getBarometricPressure() {
+ Avp lcsBarometricPressureAvp = super.message.getAvps().getAvp(Avp.BAROMETRIC_PRESSURE);
+ if (lcsBarometricPressureAvp != null) {
+ try {
+ return lcsBarometricPressureAvp.getUnsigned32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Barometric Pressure AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/ProvideLocationRequestImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/ProvideLocationRequestImpl.java
new file mode 100644
index 000000000..4bf7cde32
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/ProvideLocationRequestImpl.java
@@ -0,0 +1,983 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.impl.app.slg;
+
+import org.jdiameter.api.Avp;
+import org.jdiameter.api.AvpDataException;
+import org.jdiameter.api.Message;
+import org.jdiameter.api.slg.events.ProvideLocationRequest;
+import org.jdiameter.common.impl.app.AppRequestEventImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+public class ProvideLocationRequestImpl extends AppRequestEventImpl implements ProvideLocationRequest {
+
+ private static final long serialVersionUID = 1L;
+
+ protected static final Logger logger = LoggerFactory.getLogger(ProvideLocationRequestImpl.class);
+
+ public ProvideLocationRequestImpl(Message message) {
+ super(message);
+ message.setRequest(true);
+ }
+
+ @Override
+ public boolean isSLgLocationTypeAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.SLG_LOCATION_TYPE) != null;
+ }
+
+ @Override
+ public int getSLgLocationType() {
+ Avp slgLocationTypeAvp = super.message.getAvps().getAvp(Avp.SLG_LOCATION_TYPE);
+ if (slgLocationTypeAvp != null) {
+ try {
+ return slgLocationTypeAvp.getInteger32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain SLg-Location-Type AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isUserNameAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.USER_NAME) != null; // IE: IMSI
+ }
+
+ @Override
+ public String getUserName() {
+ Avp userNameAvp = super.message.getAvps().getAvp(Avp.USER_NAME);
+ if (userNameAvp != null) {
+ try {
+ return userNameAvp.getUTF8String(); // IE: IMSI mapped to User-Name
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain User-Name AVP value (IMSI)", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isMSISDNAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.MSISDN) != null;
+ }
+
+ @Override
+ public byte[] getMSISDN() {
+ Avp msisdnAvp = super.message.getAvps().getAvp(Avp.MSISDN);
+ if (msisdnAvp != null) {
+ try {
+ return msisdnAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain MSISDN AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isIMEIAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.TGPP_IMEI) != null;
+ }
+
+ @Override
+ public String getIMEI() {
+ Avp imeiAvp = super.message.getAvps().getAvp(Avp.TGPP_IMEI);
+ if (imeiAvp != null) {
+ try {
+ return imeiAvp.getUTF8String();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain IMEI AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isLCSEPSClientNameAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LCS_EPS_CLIENT_NAME) != null;
+ }
+
+ @Override
+ public boolean isLSCNameStringAvpPresent() {
+ Avp lcsEPSClientNameAvp = super.message.getAvps().getAvp(Avp.LCS_EPS_CLIENT_NAME);
+ if (lcsEPSClientNameAvp != null) {
+ try {
+ return lcsEPSClientNameAvp.getGrouped().getAvp(Avp.LCS_NAME_STRING) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Name-String AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getLSCNameString() {
+ Avp lcsEPSClientNameAvp = super.message.getAvps().getAvp(Avp.LCS_EPS_CLIENT_NAME);
+ if (lcsEPSClientNameAvp != null) {
+ try {
+ Avp lcsNameStringAvp = lcsEPSClientNameAvp.getGrouped().getAvp(Avp.LCS_NAME_STRING);
+ if (lcsNameStringAvp != null){
+ return lcsNameStringAvp.getUTF8String();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Name-String AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isLCSFormatIndicatorAvpPresent() {
+ Avp lcsEPSClientNameAvp = super.message.getAvps().getAvp(Avp.LCS_EPS_CLIENT_NAME);
+ if (lcsEPSClientNameAvp != null) {
+ try {
+ return lcsEPSClientNameAvp.getGrouped().getAvp(Avp.LCS_FORMAT_INDICATOR) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Format-Indicator AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getLCSFormatIndicator() {
+ Avp lcsEPSClientNameAvp = super.message.getAvps().getAvp(Avp.LCS_EPS_CLIENT_NAME);
+ if (lcsEPSClientNameAvp != null) {
+ try {
+ Avp lcsFormatIndicatorAvp = lcsEPSClientNameAvp.getGrouped().getAvp(Avp.LCS_FORMAT_INDICATOR);
+ if (lcsFormatIndicatorAvp != null){
+ return lcsFormatIndicatorAvp.getInteger32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Format-Indicator AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isLCSCLientTypeAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LCS_CLIENT_TYPE) != null;
+ }
+
+ @Override
+ public int getLCSClientType() {
+ Avp lcsClientTypeAvp = super.message.getAvps().getAvp(Avp.LCS_CLIENT_TYPE);
+ if (lcsClientTypeAvp != null) {
+ try {
+ return lcsClientTypeAvp.getInteger32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Client-Type AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isLCSRequestorNamePresent() {
+ return super.message.getAvps().getAvp(Avp.LCS_REQUESTOR_NAME) != null;
+ }
+
+ @Override
+ public boolean isLCSRequestorIdStringAvpPresent() {
+ Avp lcsRequestorNameAvp = super.message.getAvps().getAvp(Avp.LCS_REQUESTOR_NAME);
+ if (lcsRequestorNameAvp != null) {
+ try {
+ return lcsRequestorNameAvp.getGrouped().getAvp(Avp.LCS_REQUESTOR_ID_STRING) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Requestor-Id-String AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getLCSRequestorIdString() {
+ Avp lcsRequestorNameAvp = super.message.getAvps().getAvp(Avp.LCS_REQUESTOR_NAME);
+ if (lcsRequestorNameAvp != null) {
+ try {
+ Avp lcsRequestorIdStringAvp = lcsRequestorNameAvp.getGrouped().getAvp(Avp.LCS_REQUESTOR_ID_STRING);
+ if (lcsRequestorIdStringAvp != null){
+ return lcsRequestorIdStringAvp.getUTF8String();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Requestor-Id-String AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isReqLCSFormatIndicatorAvpPresent() {
+ Avp lcsRequestorNameAvp = super.message.getAvps().getAvp(Avp.LCS_REQUESTOR_NAME);
+ if (lcsRequestorNameAvp != null) {
+ try {
+ return lcsRequestorNameAvp.getGrouped().getAvp(Avp.LCS_FORMAT_INDICATOR) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Format-Indicator AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getReqLCSFormatIndicator() {
+ Avp lcsRequestorNameAvp = super.message.getAvps().getAvp(Avp.LCS_REQUESTOR_NAME);
+ if (lcsRequestorNameAvp != null) {
+ try {
+ Avp lcsFormatIndicatorAvp = lcsRequestorNameAvp.getGrouped().getAvp(Avp.LCS_FORMAT_INDICATOR);
+ if (lcsFormatIndicatorAvp != null){
+ return lcsFormatIndicatorAvp.getInteger32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Format-Indicator AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isLCSPriorityPresent() {
+ return super.message.getAvps().getAvp(Avp.LCS_PRIORITY) != null;
+ }
+
+ @Override
+ public long getLCSPriority() {
+ Avp lcsPriorityAvp = super.message.getAvps().getAvp(Avp.LCS_PRIORITY);
+ if (lcsPriorityAvp != null) {
+ try {
+ return lcsPriorityAvp.getUnsigned32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Priority AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isLCSQoSAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LCS_QOS) != null;
+ }
+
+ @Override
+ public boolean isLCSQoSClassAvpPresent() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ return lcsQoSAvp.getGrouped().getAvp(Avp.LCS_QOS_CLASS) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-QoS-Class AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getLCSQoSClass() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ Avp lcsQoSClassAvp = lcsQoSAvp.getGrouped().getAvp(Avp.LCS_QOS_CLASS);
+ if (lcsQoSClassAvp != null){
+ return lcsQoSClassAvp.getInteger32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-QoS-Class AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isHorizontalAccuracyAvpPresent() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ return lcsQoSAvp.getGrouped().getAvp(Avp.HORIZONTAL_ACCURACY) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Horizontal-Accuracy AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public long getHorizontalAccuracy() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ Avp lcsQoSHorizontalAccuracyAvp = lcsQoSAvp.getGrouped().getAvp(Avp.HORIZONTAL_ACCURACY);
+ if (lcsQoSHorizontalAccuracyAvp != null){
+ return lcsQoSHorizontalAccuracyAvp.getUnsigned32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Horizontal-Accuracy AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isVerticalAccuracyAvpPresent() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ return lcsQoSAvp.getGrouped().getAvp(Avp.VERTICAL_ACCURACY) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Vertical-Accuracy AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public long getVerticalAccuracy() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ Avp lcsQoSVerticalAccuracyAvp = lcsQoSAvp.getGrouped().getAvp(Avp.VERTICAL_ACCURACY);
+ if (lcsQoSVerticalAccuracyAvp != null){
+ return lcsQoSVerticalAccuracyAvp.getUnsigned32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Vertical-Accuracy AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isVerticalRequestedAvpPresent() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ return lcsQoSAvp.getGrouped().getAvp(Avp.VERTICAL_REQUESTED) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Vertical-Requested AVP", e);
+ }
+ }
+ return false;
+ }
+
+ public int getVerticalRequested() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ Avp lcsQoSVerticalRequestedAvp = lcsQoSAvp.getGrouped().getAvp(Avp.VERTICAL_REQUESTED);
+ if (lcsQoSVerticalRequestedAvp != null){
+ return lcsQoSVerticalRequestedAvp.getInteger32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Vertical-Requested AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isResponseTimeAvpPresent() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ return lcsQoSAvp.getGrouped().getAvp(Avp.RESPONSE_TIME) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Response-Time AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getResponseTime() {
+ Avp lcsQoSAvp = super.message.getAvps().getAvp(Avp.LCS_QOS);
+ if (lcsQoSAvp != null) {
+ try {
+ Avp lcsQoSResponseTimeAvp = lcsQoSAvp.getGrouped().getAvp(Avp.RESPONSE_TIME);
+ if (lcsQoSResponseTimeAvp != null){
+ return lcsQoSResponseTimeAvp.getInteger32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Response-Time AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isVelocityRequestedAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.VELOCITY_REQUESTED) != null;
+ }
+
+ @Override
+ public int getVelocityRequested() {
+ Avp lcsVelocityRequestedAvp = super.message.getAvps().getAvp(Avp.VELOCITY_REQUESTED);
+ if (lcsVelocityRequestedAvp != null) {
+ try {
+ return lcsVelocityRequestedAvp.getInteger32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Velocity-Requested AVP value", e);
+ }
+ }
+ return-1;
+ }
+
+ @Override
+ public boolean isSupportedGADShapesAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.SUPPORTED_GAD_SHAPES) != null;
+ }
+
+ @Override
+ public long getSupportedGADSahpes() {
+ Avp lcsSupportedGADShapesAvp = super.message.getAvps().getAvp(Avp.SUPPORTED_GAD_SHAPES);
+ if (lcsSupportedGADShapesAvp != null) {
+ try {
+ return lcsSupportedGADShapesAvp.getUnsigned32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Supported GAD Shapes AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isLSCServiceTypeIdAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LCS_SERVICE_TYPE_ID) != null;
+ }
+
+ @Override
+ public long getLSCServiceTypeId() {
+ Avp lcsServiceTypeIdAvp = super.message.getAvps().getAvp(Avp.LCS_SERVICE_TYPE_ID);
+ if (lcsServiceTypeIdAvp != null) {
+ try {
+ return lcsServiceTypeIdAvp.getUnsigned32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Service Type ID AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isLCSCodewordAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LCS_CODEWORD) != null;
+ }
+
+ @Override
+ public String getLCSCodeword() {
+ Avp lcsCodewordAvp = super.message.getAvps().getAvp(Avp.LCS_CODEWORD);
+ if (lcsCodewordAvp != null) {
+ try {
+ return lcsCodewordAvp.getUTF8String();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Codeword AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isServiceSelectionAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.SERVICE_SELECTION) != null;
+ }
+
+ @Override
+ public String getServiceSelection() {
+ Avp lcsServiceSelectionAvp = super.message.getAvps().getAvp(Avp.SERVICE_SELECTION);
+ if (lcsServiceSelectionAvp != null) {
+ try {
+ return lcsServiceSelectionAvp.getUTF8String();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Service Selection AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isLCSPrivacyCheckSessionAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LCS_PRIVACY_CHECK_SESSION) != null;
+ }
+
+ @Override
+ public boolean isLCSPrivacyCheckAvpPresent() {
+ Avp lcPrivacyCheckSessionAvp = super.message.getAvps().getAvp(Avp.LCS_PRIVACY_CHECK_SESSION);
+ if (lcPrivacyCheckSessionAvp != null) {
+ try {
+ return lcPrivacyCheckSessionAvp.getGrouped().getAvp(Avp.LCS_PRIVACY_CHECK) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Privacy-Check AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getLCSPrivacyCheck() {
+ Avp lcPrivacyCheckSessionAvp = super.message.getAvps().getAvp(Avp.LCS_PRIVACY_CHECK_SESSION);
+ if (lcPrivacyCheckSessionAvp != null) {
+ try {
+ Avp lcsPrivacyCheckAvp = lcPrivacyCheckSessionAvp.getGrouped().getAvp(Avp.LCS_PRIVACY_CHECK);
+ if (lcsPrivacyCheckAvp != null){
+ return lcsPrivacyCheckAvp.getInteger32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Privacy-Check AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isLCSPrivacyCheckNonSessionAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LCS_PRIVACY_CHECK_NON_SESSION) != null;
+ }
+
+ @Override
+ public boolean isLCSPrivacyCheckNSAvpPresent() {
+ Avp lcPrivacyCheckNonSessionAvp = super.message.getAvps().getAvp(Avp.LCS_PRIVACY_CHECK_NON_SESSION);
+ if (lcPrivacyCheckNonSessionAvp != null) {
+ try {
+ return lcPrivacyCheckNonSessionAvp.getGrouped().getAvp(Avp.LCS_PRIVACY_CHECK) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Privacy-Check AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getLCSPrivacyCheckNS() {
+ Avp lcPrivacyCheckNonSessionAvp = super.message.getAvps().getAvp(Avp.LCS_PRIVACY_CHECK_NON_SESSION);
+ if (lcPrivacyCheckNonSessionAvp != null) {
+ try {
+ Avp lcsPrivacyCheckAvp = lcPrivacyCheckNonSessionAvp.getGrouped().getAvp(Avp.LCS_PRIVACY_CHECK);
+ if (lcsPrivacyCheckAvp != null){
+ return lcsPrivacyCheckAvp.getInteger32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Privacy-Check AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isDeferredLocationTypeAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.DEFERRED_LOCATION_TYPE) != null;
+ }
+
+ @Override
+ public long getDeferredLocationType() {
+ Avp lcsDeferredLocationTypeAvp = super.message.getAvps().getAvp(Avp.DEFERRED_LOCATION_TYPE);
+ if (lcsDeferredLocationTypeAvp != null) {
+ try {
+ return lcsDeferredLocationTypeAvp.getUnsigned32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Deferred Location Type AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isLCSReferenceNumberAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.LCS_REFERENCE_NUMBER) != null;
+ }
+
+ @Override
+ public byte[] getLCSReferenceNumber() {
+ Avp lcsLCSReferenceNumberAvp = super.message.getAvps().getAvp(Avp.LCS_REFERENCE_NUMBER);
+ if (lcsLCSReferenceNumberAvp != null) {
+ try {
+ return lcsLCSReferenceNumberAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Reference Number AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isAreaEventInfoAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.AREA_EVENT_INFO) != null;
+ }
+
+ @Override
+ public boolean isOccurrenceInfoAvpPresent() {
+ Avp lcsAreaEventInfoAvp = super.message.getAvps().getAvp(Avp.AREA_EVENT_INFO);
+ if (lcsAreaEventInfoAvp != null) {
+ try {
+ return lcsAreaEventInfoAvp.getGrouped().getAvp(Avp.OCCURRENCE_INFO) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Ocurrence-Info AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getOccurrenceInfo() {
+ Avp lcsAreaEventInfoAvp = super.message.getAvps().getAvp(Avp.AREA_EVENT_INFO);
+ if (lcsAreaEventInfoAvp != null) {
+ try {
+ Avp lcsOccurrenceInfoAvp = lcsAreaEventInfoAvp.getGrouped().getAvp(Avp.OCCURRENCE_INFO);
+ if (lcsOccurrenceInfoAvp != null){
+ return lcsOccurrenceInfoAvp.getInteger32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Ocurrence-Info AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isIntervalTimeAvpPresent() {
+ Avp lcsAreaEventInfoAvp = super.message.getAvps().getAvp(Avp.AREA_EVENT_INFO);
+ if (lcsAreaEventInfoAvp != null) {
+ try {
+ return lcsAreaEventInfoAvp.getGrouped().getAvp(Avp.INTERVAL_TIME) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Interval-Time AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public long getIntervalTime() {
+ Avp lcsAreaEventInfoAvp = super.message.getAvps().getAvp(Avp.AREA_EVENT_INFO);
+ if (lcsAreaEventInfoAvp != null) {
+ try {
+ Avp lcsIntervalTimeAvp = lcsAreaEventInfoAvp.getGrouped().getAvp(Avp.INTERVAL_TIME);
+ if (lcsIntervalTimeAvp != null){
+ return lcsIntervalTimeAvp.getUnsigned32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Interval-Time AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isAreaDefinitionAvpPresent() {
+ Avp lcsAreaEventInfoAvp = super.message.getAvps().getAvp(Avp.AREA_EVENT_INFO);
+ if (lcsAreaEventInfoAvp != null) {
+ try {
+ return lcsAreaEventInfoAvp.getGrouped().getAvp(Avp.AREA_DEFINITION) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Area-Definition AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isAreaTypeAvpPresent() {
+ Avp lcsAreaDefinitionAvp = super.message.getAvps().getAvp(Avp.AREA_DEFINITION);
+ if (lcsAreaDefinitionAvp != null) {
+ try {
+ return lcsAreaDefinitionAvp.getGrouped().getAvp(Avp.AREA_TYPE) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Area-Type AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public long getAreaType() {
+ Avp lcsAreaDefinitionAvp = super.message.getAvps().getAvp(Avp.AREA_DEFINITION);
+ if (lcsAreaDefinitionAvp != null) {
+ try {
+ Avp lcsAreaTypeAvp = lcsAreaDefinitionAvp.getGrouped().getAvp(Avp.AREA_TYPE);
+ if (lcsAreaTypeAvp != null){
+ return lcsAreaTypeAvp.getUnsigned32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Area-Type AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isAreaIdentificationAvpPresent() {
+ Avp lcsAreaDefinitionAvp = super.message.getAvps().getAvp(Avp.AREA_DEFINITION);
+ if (lcsAreaDefinitionAvp != null) {
+ try {
+ return lcsAreaDefinitionAvp.getGrouped().getAvp(Avp.AREA_IDENTIFICATION) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Area-Identification AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getAreaIdentification() {
+ Avp lcsAreaDefinitionAvp = super.message.getAvps().getAvp(Avp.AREA_DEFINITION);
+ if (lcsAreaDefinitionAvp != null) {
+ try {
+ Avp lcsAreaIdAvp = lcsAreaDefinitionAvp.getGrouped().getAvp(Avp.AREA_DEFINITION);
+ if (lcsAreaIdAvp != null){
+ return lcsAreaIdAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Area Identification AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isGMLCAddressAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.GMLC_ADDRESS) != null;
+ }
+
+ @Override
+ public java.net.InetAddress getGMLCAddress() {
+ Avp lcsGMLCAddressAvp = super.message.getAvps().getAvp(Avp.GMLC_ADDRESS);
+ if (lcsGMLCAddressAvp != null) {
+ try {
+ return lcsGMLCAddressAvp.getAddress();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain GMLC Address AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isPLRFlagsAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.PLR_FLAGS) != null;
+ }
+
+ @Override
+ public long getPLRFLags() {
+ Avp lcsPLRFlagsAvp = super.message.getAvps().getAvp(Avp.PLR_FLAGS);
+ if (lcsPLRFlagsAvp != null) {
+ try {
+ return lcsPLRFlagsAvp.getUnsigned32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS PLR Flags AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isPeriodicLDRInfoAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.PERIODIC_LDR_INFORMATION) != null;
+ }
+
+ @Override
+ public boolean isReportingAmountAvpPresent() {
+ Avp lcsPeriodicLDRInfo = super.message.getAvps().getAvp(Avp.PERIODIC_LDR_INFORMATION);
+ if (lcsPeriodicLDRInfo != null) {
+ try {
+ return lcsPeriodicLDRInfo.getGrouped().getAvp(Avp.REPORTING_AMOUNT) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Reporting-Amount AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public long getReportingAmount() {
+ Avp lcsPeriodicLDRInfo = super.message.getAvps().getAvp(Avp.PERIODIC_LDR_INFORMATION);
+ if (lcsPeriodicLDRInfo != null) {
+ try {
+ Avp lcsReportingAmountAvp = lcsPeriodicLDRInfo.getGrouped().getAvp(Avp.REPORTING_AMOUNT);
+ if (lcsReportingAmountAvp != null){
+ return lcsReportingAmountAvp.getUnsigned32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Reporting amount AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isReportingIntervalAvpPresent() {
+ Avp lcsPeriodicLDRInfo = super.message.getAvps().getAvp(Avp.PERIODIC_LDR_INFORMATION);
+ if (lcsPeriodicLDRInfo != null) {
+ try {
+ return lcsPeriodicLDRInfo.getGrouped().getAvp(Avp.REPORTING_INTERVAL) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Reporting-Interval AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public long getReportingInterval() {
+ Avp lcsPeriodicLDRInfo = super.message.getAvps().getAvp(Avp.PERIODIC_LDR_INFORMATION);
+ if (lcsPeriodicLDRInfo != null) {
+ try {
+ Avp lcsReportingIntervalAvp = lcsPeriodicLDRInfo.getGrouped().getAvp(Avp.REPORTING_INTERVAL);
+ if (lcsReportingIntervalAvp != null){
+ return lcsReportingIntervalAvp.getUnsigned32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Reporting-Interval AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isReportingPLMNListAvpPresent() {
+ return super.message.getAvps().getAvp(Avp.REPORTING_PLMN_LIST) != null;
+ }
+
+ @Override
+ public boolean isPrioritizedListIndicatorAvpPresent() {
+ Avp lcsReportingPLMNListAvp = super.message.getAvps().getAvp(Avp.REPORTING_PLMN_LIST);
+ if (lcsReportingPLMNListAvp != null) {
+ try {
+ return lcsReportingPLMNListAvp.getGrouped().getAvp(Avp.PRIORITIZED_LIST_INDICATOR) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Prioritized-List-Indicator AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getPrioritizedListIndicator() {
+ Avp lcsReportingPLMNListAvp = super.message.getAvps().getAvp(Avp.REPORTING_PLMN_LIST);
+ if (lcsReportingPLMNListAvp != null) {
+ try {
+ Avp lcsPrioritizedListIndicatorAvp = lcsReportingPLMNListAvp.getGrouped().getAvp(Avp.PRIORITIZED_LIST_INDICATOR);
+ if (lcsPrioritizedListIndicatorAvp != null){
+ return lcsPrioritizedListIndicatorAvp.getInteger32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS GERAN-Positioning-Data AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isPLMNIDListAvpPresent() {
+ Avp lcsReportingPLMNListAvp = super.message.getAvps().getAvp(Avp.REPORTING_PLMN_LIST);
+ if (lcsReportingPLMNListAvp != null) {
+ try {
+ return lcsReportingPLMNListAvp.getGrouped().getAvp(Avp.PLMN_ID_LIST) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain PLMN-Id-List AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isVisitedPLMNIdAvpPresent() {
+ Avp lcsPLMNIdListAvp = super.message.getAvps().getAvp(Avp.PLMN_ID_LIST);
+ if (lcsPLMNIdListAvp != null) {
+ try {
+ return lcsPLMNIdListAvp.getGrouped().getAvp(Avp.VISITED_PLMN_ID) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Visited-PLMN-Id AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getVisitedPLMNId() {
+ Avp lcsPLMNIdListAvp = super.message.getAvps().getAvp(Avp.PLMN_ID_LIST);
+ if (lcsPLMNIdListAvp != null) {
+ try {
+ Avp lcsVisitedPLMNIdAvp = lcsPLMNIdListAvp.getGrouped().getAvp(Avp.VISITED_PLMN_ID);
+ if (lcsVisitedPLMNIdAvp != null){
+ return lcsVisitedPLMNIdAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Visited PLMN ID AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isPeriodicLocationSupportIndicatorAvpPresent() {
+ Avp lcsPLMNIdListAvp = super.message.getAvps().getAvp(Avp.PLMN_ID_LIST);
+ if (lcsPLMNIdListAvp != null) {
+ try {
+ return lcsPLMNIdListAvp.getGrouped().getAvp(Avp.PERIODIC_LOCATION_SUPPORT_INDICATOR) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain Periodic-Location-Support-Indicator AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getPeriodicLocationSupportIndicator() {
+ Avp lcsPLMNIdListAvp = super.message.getAvps().getAvp(Avp.PLMN_ID_LIST);
+ if (lcsPLMNIdListAvp != null) {
+ try {
+ Avp lcsPeriodicLocationSupportIndicatorAvp = lcsPLMNIdListAvp.getGrouped().getAvp(Avp.PERIODIC_LOCATION_SUPPORT_INDICATOR);
+ if (lcsPeriodicLocationSupportIndicatorAvp != null){
+ return lcsPeriodicLocationSupportIndicatorAvp.getInteger32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS Periodic Location Support Indicator AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/SLgLocalSessionDataFactory.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/SLgLocalSessionDataFactory.java
new file mode 100644
index 000000000..a249ecc23
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/SLgLocalSessionDataFactory.java
@@ -0,0 +1,73 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.impl.app.slg;
+
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.slg.ClientSLgSession;
+import org.jdiameter.api.slg.ServerSLgSession;
+import org.jdiameter.client.impl.app.slg.ClientSLgSessionDataLocalImpl;
+import org.jdiameter.common.api.app.IAppSessionDataFactory;
+import org.jdiameter.common.api.app.slg.ISLgSessionData;
+import org.jdiameter.server.impl.app.slg.ServerSLgSessionDataLocalImpl;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class SLgLocalSessionDataFactory implements IAppSessionDataFactory {
+
+ public ISLgSessionData getAppSessionData(Class extends AppSession> clazz, String sessionId) {
+ if (clazz.equals(ClientSLgSession.class)) {
+ ClientSLgSessionDataLocalImpl data = new ClientSLgSessionDataLocalImpl();
+ data.setSessionId(sessionId);
+ return data;
+ } else if (clazz.equals(ServerSLgSession.class)) {
+ ServerSLgSessionDataLocalImpl data = new ServerSLgSessionDataLocalImpl();
+ data.setSessionId(sessionId);
+ return data;
+ } else {
+ throw new IllegalArgumentException("Invalid Session Class: " + clazz.toString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/SLgLocalSessionDataImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/SLgLocalSessionDataImpl.java
new file mode 100644
index 000000000..692f1de47
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/SLgLocalSessionDataImpl.java
@@ -0,0 +1,86 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.impl.app.slg;
+
+import java.io.Serializable;
+
+import org.jdiameter.api.Request;
+import org.jdiameter.common.api.app.AppSessionDataLocalImpl;
+import org.jdiameter.common.api.app.slg.ISLgSessionData;
+import org.jdiameter.common.api.app.slg.SLgSessionState;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class SLgLocalSessionDataImpl extends AppSessionDataLocalImpl implements ISLgSessionData {
+
+ protected SLgSessionState state = SLgSessionState.IDLE;
+ protected Request buffer;
+ protected Serializable tsTimerId;
+
+ public void setSLgSessionState(SLgSessionState state) {
+ this.state = state;
+ }
+
+ public SLgSessionState getSLgSessionState() {
+ return this.state;
+ }
+
+ public Serializable getTsTimerId() {
+ return this.tsTimerId;
+ }
+
+ public void setTsTimerId(Serializable tid) {
+ this.tsTimerId = tid;
+ }
+
+ public void setBuffer(Request buffer) {
+ this.buffer = buffer;
+ }
+
+ public Request getBuffer() {
+ return this.buffer;
+ }
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/SLgSession.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/SLgSession.java
new file mode 100644
index 000000000..37e7eb113
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/SLgSession.java
@@ -0,0 +1,156 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.impl.app.slg;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.jdiameter.api.NetworkReqListener;
+import org.jdiameter.api.app.StateChangeListener;
+import org.jdiameter.api.app.StateMachine;
+import org.jdiameter.client.api.ISessionFactory;
+import org.jdiameter.common.impl.app.AppSessionImpl;
+import org.jdiameter.common.api.app.slg.ISLgMessageFactory;
+import org.jdiameter.common.api.app.slg.ISLgSessionData;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public abstract class SLgSession extends AppSessionImpl implements NetworkReqListener, StateMachine {
+
+ public static final int _TX_TIMEOUT = 30 * 1000;
+
+ protected Lock sendAndStateLock = new ReentrantLock();
+
+ @SuppressWarnings("rawtypes")
+ protected transient List stateListeners = new CopyOnWriteArrayList();
+ protected transient ISLgMessageFactory messageFactory;
+
+ protected static final String TIMER_NAME_MSG_TIMEOUT = "MSG_TIMEOUT";
+ protected ISLgSessionData sessionData;
+
+ public SLgSession(ISessionFactory sf, ISLgSessionData sessionData) {
+ super(sf, sessionData);
+ this.sessionData = sessionData;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public void addStateChangeNotification(StateChangeListener listener) {
+ if (!stateListeners.contains(listener)) {
+ stateListeners.add(listener);
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ public void removeStateChangeNotification(StateChangeListener listener) {
+ stateListeners.remove(listener);
+ }
+
+ public boolean isStateless() {
+ return true;
+ }
+
+ @Override
+ public boolean isReplicable() {
+ return false;
+ }
+
+ protected void startMsgTimer() {
+ try {
+ sendAndStateLock.lock();
+ sessionData.setTsTimerId(super.timerFacility.schedule(getSessionId(), TIMER_NAME_MSG_TIMEOUT, _TX_TIMEOUT));
+ } finally {
+ sendAndStateLock.unlock();
+ }
+ }
+
+ protected void cancelMsgTimer() {
+ try {
+ sendAndStateLock.lock();
+ final Serializable timerId = this.sessionData.getTsTimerId();
+ if (timerId == null) {
+ return;
+ }
+ super.timerFacility.cancel(timerId);
+ this.sessionData.setTsTimerId(null);
+ } finally {
+ sendAndStateLock.unlock();
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((sessionData == null) ? 0 : sessionData.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ SLgSession other = (SLgSession) obj;
+ if (sessionData == null) {
+ if (other.sessionData != null) {
+ return false;
+ }
+ } else if (!sessionData.equals(other.sessionData)) {
+ return false;
+ }
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/SLgSessionFactoryImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/SLgSessionFactoryImpl.java
new file mode 100644
index 000000000..580155a55
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slg/SLgSessionFactoryImpl.java
@@ -0,0 +1,313 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.impl.app.slg;
+
+import org.jdiameter.api.Answer;
+import org.jdiameter.api.ApplicationId;
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.Request;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.SessionFactory;
+import org.jdiameter.api.app.AppAnswerEvent;
+import org.jdiameter.api.app.AppRequestEvent;
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.app.StateChangeListener;
+import org.jdiameter.api.slg.ClientSLgSession;
+import org.jdiameter.api.slg.ClientSLgSessionListener;
+import org.jdiameter.api.slg.ServerSLgSession;
+import org.jdiameter.api.slg.ServerSLgSessionListener;
+import org.jdiameter.api.slg.events.ProvideLocationRequest;
+import org.jdiameter.api.slg.events.LocationReportAnswer;
+import org.jdiameter.api.slg.events.LocationReportRequest;
+import org.jdiameter.api.slg.events.ProvideLocationAnswer;
+import org.jdiameter.client.api.ISessionFactory;
+import org.jdiameter.client.impl.app.slg.IClientSLgSessionData;
+import org.jdiameter.client.impl.app.slg.SLgClientSessionImpl;
+import org.jdiameter.common.api.app.IAppSessionDataFactory;
+import org.jdiameter.common.api.app.slg.ISLgMessageFactory;
+import org.jdiameter.common.api.app.slg.ISLgSessionData;
+import org.jdiameter.common.api.app.slg.ISLgSessionFactory;
+import org.jdiameter.common.api.data.ISessionDatasource;
+import org.jdiameter.server.impl.app.slg.IServerSLgSessionData;
+import org.jdiameter.server.impl.app.slg.SLgServerSessionImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class SLgSessionFactoryImpl implements ISLgSessionFactory, ServerSLgSessionListener, ClientSLgSessionListener,
+ ISLgMessageFactory, StateChangeListener {
+
+ private static final Logger logger = LoggerFactory.getLogger(SLgSessionFactoryImpl.class);
+
+ protected ISessionFactory sessionFactory;
+
+ protected ServerSLgSessionListener serverSessionListener;
+ protected ClientSLgSessionListener clientSessionListener;
+
+ protected ISLgMessageFactory messageFactory;
+ protected StateChangeListener stateListener;
+ protected ISessionDatasource iss;
+ protected IAppSessionDataFactory sessionDataFactory;
+
+ public SLgSessionFactoryImpl() {
+ };
+
+ public SLgSessionFactoryImpl(SessionFactory sessionFactory) {
+ super();
+ init(sessionFactory);
+ }
+
+ public void init(SessionFactory sessionFactory) {
+ this.sessionFactory = (ISessionFactory) sessionFactory;
+ this.iss = this.sessionFactory.getContainer().getAssemblerFacility().getComponentInstance(ISessionDatasource.class);
+ this.sessionDataFactory = (IAppSessionDataFactory) this.iss.getDataFactory(ISLgSessionData.class);
+ }
+
+ /**
+ * @return the serverSessionListener
+ */
+ public ServerSLgSessionListener getServerSessionListener() {
+ return serverSessionListener != null ? serverSessionListener : this;
+ }
+
+ /**
+ * @param serverSessionListener the serverSessionListener to set
+ */
+ public void setServerSessionListener(ServerSLgSessionListener serverSessionListener) {
+ this.serverSessionListener = serverSessionListener;
+ }
+
+ /**
+ * @return the serverSessionListener
+ */
+ public ClientSLgSessionListener getClientSessionListener() {
+ return clientSessionListener != null ? clientSessionListener : this;
+ }
+
+ /**
+ * @param clientSessionListener theclientSessionListener to set
+ */
+ public void setClientSessionListener(ClientSLgSessionListener clientSessionListener) {
+ this.clientSessionListener = clientSessionListener;
+ }
+
+ /**
+ * @return the messageFactory
+ */
+ public ISLgMessageFactory getMessageFactory() {
+ return messageFactory != null ? messageFactory : this;
+ }
+
+ /**
+ * @param messageFactory the messageFactory to set
+ */
+ public void setMessageFactory(ISLgMessageFactory messageFactory) {
+ this.messageFactory = messageFactory;
+ }
+
+ /**
+ * @return the stateListener
+ */
+ public StateChangeListener getStateListener() {
+ return stateListener != null ? stateListener : this;
+ }
+
+ /**
+ * @param stateListener the stateListener to set
+ */
+ public void setStateListener(StateChangeListener stateListener) {
+ this.stateListener = stateListener;
+ }
+
+ public AppSession getSession(String sessionId, Class extends AppSession> aClass) {
+ if (sessionId == null) {
+ throw new IllegalArgumentException("SessionId must not be null");
+ }
+ if (!this.iss.exists(sessionId)) {
+ return null;
+ }
+ AppSession appSession = null;
+ try {
+ if (aClass == ServerSLgSession.class) {
+ IServerSLgSessionData sessionData = (IServerSLgSessionData) this.sessionDataFactory
+ .getAppSessionData(ServerSLgSession.class, sessionId);
+ SLgServerSessionImpl serverSession = new SLgServerSessionImpl(sessionData, getMessageFactory(), sessionFactory,
+ this.getServerSessionListener());
+ serverSession.getSessions().get(0).setRequestListener(serverSession);
+ appSession = serverSession;
+ } else if (aClass == ClientSLgSession.class) {
+ IClientSLgSessionData sessionData = (IClientSLgSessionData) this.sessionDataFactory
+ .getAppSessionData(ClientSLgSession.class, sessionId);
+ SLgClientSessionImpl clientSession = new SLgClientSessionImpl(sessionData, getMessageFactory(), sessionFactory,
+ this.getClientSessionListener());
+ clientSession.getSessions().get(0).setRequestListener(clientSession);
+ appSession = clientSession;
+ } else {
+ throw new IllegalArgumentException(
+ "Wrong session class: " + aClass + ". Supported[" + ServerSLgSession.class + "]");
+ }
+ } catch (Exception e) {
+ logger.error("Failure to obtain new SLg Session.", e);
+ }
+ return appSession;
+ }
+
+ public AppSession getNewSession(String sessionId, Class extends AppSession> aClass, ApplicationId applicationId,
+ Object[] args) {
+ AppSession appSession = null;
+
+ try {
+ if (aClass == ServerSLgSession.class) {
+ if (sessionId == null) {
+ if (args != null && args.length > 0 && args[0] instanceof Request) {
+ Request request = (Request) args[0];
+ sessionId = request.getSessionId();
+ } else {
+ sessionId = this.sessionFactory.getSessionId();
+ }
+ }
+ IServerSLgSessionData sessionData = (IServerSLgSessionData) this.sessionDataFactory
+ .getAppSessionData(ServerSLgSession.class, sessionId);
+ sessionData.setApplicationId(applicationId);
+ SLgServerSessionImpl serverSession = new SLgServerSessionImpl(sessionData, getMessageFactory(), sessionFactory,
+ this.getServerSessionListener());
+
+ iss.addSession(serverSession);
+ serverSession.getSessions().get(0).setRequestListener(serverSession);
+ appSession = serverSession;
+ } else if (aClass == ClientSLgSession.class) {
+ if (sessionId == null) {
+ if (args != null && args.length > 0 && args[0] instanceof Request) {
+ Request request = (Request) args[0];
+ sessionId = request.getSessionId();
+ } else {
+ sessionId = this.sessionFactory.getSessionId();
+ }
+ }
+ IClientSLgSessionData sessionData = (IClientSLgSessionData) this.sessionDataFactory
+ .getAppSessionData(ClientSLgSession.class, sessionId);
+ sessionData.setApplicationId(applicationId);
+ SLgClientSessionImpl clientSession = new SLgClientSessionImpl(sessionData, getMessageFactory(), sessionFactory,
+ this.getClientSessionListener());
+
+ iss.addSession(clientSession);
+ clientSession.getSessions().get(0).setRequestListener(clientSession);
+ appSession = clientSession;
+ } else {
+ throw new IllegalArgumentException(
+ "Wrong session class: " + aClass + ". Supported[" + ServerSLgSession.class + "]");
+ }
+ } catch (Exception e) {
+ logger.error("Failure to obtain new SLg Session.", e);
+ }
+ return appSession;
+ }
+
+ public void stateChanged(Enum oldState, Enum newState) {
+ logger.info("Diameter SLg Session Factory :: stateChanged :: oldState[{}], newState[{}]", oldState, newState);
+ }
+
+ public long getApplicationId() {
+ return 16777255;
+ }
+
+ public void stateChanged(AppSession source, Enum oldState, Enum newState) {
+ logger.info("Diameter SLg Session Factory :: stateChanged :: Session, [{}], oldState[{}], newState[{}]",
+ new Object[] { source, oldState, newState });
+ }
+
+ public ProvideLocationRequest createProvideLocationRequest(Request request) {
+ return new ProvideLocationRequestImpl(request);
+ }
+
+ public ProvideLocationAnswer createProvideLocationAnswer(Answer answer) {
+ return new ProvideLocationAnswerImpl(answer);
+ }
+
+ public void doProvideLocationRequestEvent(ServerSLgSession appSession, ProvideLocationRequest request)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
+ logger.info("Diameter SLg Session Factory :: doProvideLocationRequestEvent :: appSession[{}], Request[{}]", appSession,
+ request);
+ }
+
+ public void doProvideLocationAnswerEvent(ClientSLgSession appSession, ProvideLocationRequest request,
+ ProvideLocationAnswer answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
+ logger.info("Diameter SLg Session Factory :: doProvideLocationAnswerEvent :: appSession[{}], Request[{}], Answer[{}]",
+ new Object[] { appSession, request, answer });
+ }
+
+ public LocationReportRequest createLocationReportRequest(Request request) {
+ return new LocationReportRequestImpl(request);
+ }
+
+ public LocationReportAnswer createLocationReportAnswer(Answer answer) {
+ return new LocationReportAnswerImpl(answer);
+ }
+
+ public void doLocationReportRequestEvent(ServerSLgSession appSession, LocationReportRequest request)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
+ logger.info("Diameter SLg Session Factory :: doLocationReportRequestEvent :: appSession[{}], Request[{}]", appSession,
+ request);
+ }
+
+ public void doLocationReportAnswerEvent(ClientSLgSession appSession, LocationReportRequest request,
+ LocationReportAnswer answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
+ logger.info("Diameter SLg Session Factory :: doLocationReportAnswerEvent :: appSession[{}], Request[{}], Answer[{}]",
+ new Object[] { appSession, request, answer });
+ }
+
+ public void doOtherEvent(AppSession appSession, AppRequestEvent request, AppAnswerEvent answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
+ logger.info("Diameter SLg Session Factory :: doOtherEvent :: appSession[{}], Request[{}], Answer[{}]",
+ new Object[] { appSession, request, answer });
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/LCSRoutingInfoAnswerImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/LCSRoutingInfoAnswerImpl.java
new file mode 100644
index 000000000..c86a222dc
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/LCSRoutingInfoAnswerImpl.java
@@ -0,0 +1,708 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.impl.app.slh;
+
+import org.jdiameter.api.Answer;
+import org.jdiameter.api.Avp;
+import org.jdiameter.api.AvpDataException;
+import org.jdiameter.api.Request;
+import org.jdiameter.api.slh.events.LCSRoutingInfoAnswer;
+import org.jdiameter.common.impl.app.AppRequestEventImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+// import java.net.InetAddress;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+public class LCSRoutingInfoAnswerImpl extends AppRequestEventImpl implements LCSRoutingInfoAnswer {
+
+ private static final long serialVersionUID = 1L;
+
+ protected static final Logger logger = LoggerFactory.getLogger(LCSRoutingInfoAnswer.class);
+
+ /**
+ *
+ * @param answer
+ */
+ public LCSRoutingInfoAnswerImpl(Answer answer) {
+ super(answer);
+ }
+
+ /**
+ *
+ * @param request
+ * @param resultCode
+ */
+ public LCSRoutingInfoAnswerImpl(Request request, long resultCode) {
+ super(request.createAnswer(resultCode));
+ }
+
+ @Override
+ public boolean isUserNameAVPPresent() {
+ return super.message.getAvps().getAvp(Avp.USER_NAME) != null; // IE: IMSI mapped to User-Name AVP
+ }
+
+ @Override
+ public String getUserName() {
+ Avp userNameAvp = super.message.getAvps().getAvp(Avp.USER_NAME);
+ if (userNameAvp != null) {
+ try {
+ return userNameAvp.getUTF8String(); // IE: IMSI mapped to User-Name AVP
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain User-Name AVP value (IMSI)", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isMSISDNAVPPresent() {
+ return super.message.getAvps().getAvp(Avp.MSISDN) != null;
+ }
+
+ @Override
+ public byte[] getMSISDN() {
+ Avp msisdnAvp = super.message.getAvps().getAvp(Avp.MSISDN);
+ if (msisdnAvp != null) {
+ try {
+ return msisdnAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain MSISDN AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isLMSIAVPPresent() {
+ return super.message.getAvps().getAvp(Avp.LMSI) != null;
+ }
+
+ @Override
+ public byte[] getLMSI() {
+ Avp localMobileStationIdentityAvp = super.message.getAvps().getAvp(Avp.LMSI);
+ if (localMobileStationIdentityAvp != null) {
+ try {
+ return localMobileStationIdentityAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LMSI AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isServingNodeAVPPresent() {
+ return super.message.getAvps().getAvp(Avp.SERVING_NODE) != null;
+ }
+
+ @Override
+ public boolean isSGSNNumberAVPPresent() {
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ return servingNodeAvp.getGrouped().getAvp(Avp.SGSN_NUMBER) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain SGSN-Number AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getSGSNNumber(){
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ Avp sgsnNumberAvp = servingNodeAvp.getGrouped().getAvp(Avp.SGSN_NUMBER);
+ if (sgsnNumberAvp != null){
+ return sgsnNumberAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain SGSN-Number AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isSGSNNameAVPPresent() {
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ return servingNodeAvp.getGrouped().getAvp(Avp.SGSN_NAME) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain SGSN-Name AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getSGSNName(){
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ Avp sgsnNameAvp = servingNodeAvp.getGrouped().getAvp(Avp.SGSN_NAME);
+ if (sgsnNameAvp != null){
+ return sgsnNameAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain SGSN-Name AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isSGSNRealmAVPPresent() {
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ return servingNodeAvp.getGrouped().getAvp(Avp.SGSN_REALM) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain SGSN-Realm AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getSGSNRealm(){
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ Avp sgsnRealmAvp = servingNodeAvp.getGrouped().getAvp(Avp.SGSN_REALM);
+ if (sgsnRealmAvp != null){
+ return sgsnRealmAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain SGSN-Realm AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isMMENameAVPPresent() {
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ return servingNodeAvp.getGrouped().getAvp(Avp.MME_NAME) != null;
+ } catch (AvpDataException ex) {
+ logger.debug("Failure trying to obtain MME-Name AVP", ex);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getMMEName(){
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ Avp mmeNameAvp = servingNodeAvp.getGrouped().getAvp(Avp.MME_NAME);
+ if (mmeNameAvp != null){
+ return mmeNameAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain MME-Name AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isMMERealmAVPPresent() {
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ return servingNodeAvp.getGrouped().getAvp(Avp.MME_REALM) != null;
+ } catch (AvpDataException ex) {
+ logger.debug("Failure trying to obtain MME-Realm AVP", ex);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getMMERealm(){
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ Avp mmeRealmAvp = servingNodeAvp.getGrouped().getAvp(Avp.MME_REALM);
+ if (mmeRealmAvp != null){
+ return mmeRealmAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain MME-Realm AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isMSCNumberAVPPresent() {
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ return servingNodeAvp.getGrouped().getAvp(Avp.MSC_NUMBER) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain MSC-Number AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getMSCNumber(){
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ Avp mscNumberAvp = servingNodeAvp.getGrouped().getAvp(Avp.MSC_NUMBER);
+ if (mscNumberAvp != null){
+ return mscNumberAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain MSC-Number AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean is3GPPAAAServerNameAVPPresent() {
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ return servingNodeAvp.getGrouped().getAvp(Avp.TGPP_AAA_SERVER_NAME) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain 3GPP-AAA-Server-Name AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String get3GPPAAAServerName(){
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ Avp tgppAAAServerNameAvp = servingNodeAvp.getGrouped().getAvp(Avp.TGPP_AAA_SERVER_NAME);
+ if (tgppAAAServerNameAvp != null){
+ return tgppAAAServerNameAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain MSC-Number AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isLCSCapabilitiesSetsAVPPresent(){
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ return servingNodeAvp.getGrouped().getAvp(Avp.LCS_CAPABILITIES_SETS) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Capabilities-Sets AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public long getLCSCapabilitiesSets(){
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ Avp lcsCapabilitiesSetsAvp = servingNodeAvp.getGrouped().getAvp(Avp.LCS_CAPABILITIES_SETS);
+ if (lcsCapabilitiesSetsAvp != null){
+ return lcsCapabilitiesSetsAvp.getUnsigned32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Capabilities-Sets value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isGMLCAddressAVPPresent(){
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ return servingNodeAvp.getGrouped().getAvp(Avp.GMLC_ADDRESS) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain GMLC-Address AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public java.net.InetAddress getGMLCAddress(){
+ Avp servingNodeAvp = super.message.getAvps().getAvp(Avp.SERVING_NODE);
+ if (servingNodeAvp != null) {
+ try {
+ Avp gmlcAddressAvp = servingNodeAvp.getGrouped().getAvp(Avp.GMLC_ADDRESS);
+ if (gmlcAddressAvp != null){
+ return gmlcAddressAvp.getAddress();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain GMLC-Address AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isAdditionalServingNodeAVPPresent(){
+ return super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE) != null;
+ }
+
+ @Override
+ public boolean isAdditionalSGSNNumberAVPPresent() {
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ return additionalServingNodeAvp.getGrouped().getAvp(Avp.SGSN_NUMBER) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain SGSN-Number AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getAdditionalSGSNNumber(){
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ Avp sgsnNumberAvp = additionalServingNodeAvp.getGrouped().getAvp(Avp.SGSN_NUMBER);
+ if (sgsnNumberAvp != null){
+ return sgsnNumberAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain SGSN-Number AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isAdditionalSGSNNameAVPPresent() {
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ return additionalServingNodeAvp.getGrouped().getAvp(Avp.SGSN_NAME) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain SGSN-Name AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getAdditionalSGSNName(){
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ Avp sgsnNameAvp = additionalServingNodeAvp.getGrouped().getAvp(Avp.SGSN_NAME);
+ if (sgsnNameAvp != null){
+ return sgsnNameAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain SGSN-Name AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isAdditionalSGSNRealmAVPPresent() {
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ return additionalServingNodeAvp.getGrouped().getAvp(Avp.SGSN_REALM) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain SGSN-Realm AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getAdditionalSGSNRealm(){
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ Avp sgsnRealmAvp = additionalServingNodeAvp.getGrouped().getAvp(Avp.SGSN_REALM);
+ if (sgsnRealmAvp != null){
+ return sgsnRealmAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain SGSN-Realm AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isAdditionalMMENameAVPPresent() {
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ return additionalServingNodeAvp.getGrouped().getAvp(Avp.MME_NAME) != null;
+ } catch (AvpDataException ex) {
+ logger.debug("Failure trying to obtain MME-Name AVP", ex);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getAdditionalMMEName(){
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ Avp mmeNameAvp = additionalServingNodeAvp.getGrouped().getAvp(Avp.MME_NAME);
+ if (mmeNameAvp != null){
+ return mmeNameAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain MME-Name AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isAdditionalMMERealmAVPPresent() {
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ return additionalServingNodeAvp.getGrouped().getAvp(Avp.MME_REALM) != null;
+ } catch (AvpDataException ex) {
+ logger.debug("Failure trying to obtain MME-Realm AVP", ex);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getAdditionalMMERealm(){
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ Avp mmeRealmAvp = additionalServingNodeAvp.getGrouped().getAvp(Avp.MME_REALM);
+ if (mmeRealmAvp != null){
+ return mmeRealmAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain MME-Realm AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isAdditionalMSCNumberAVPPresent() {
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ return additionalServingNodeAvp.getGrouped().getAvp(Avp.MSC_NUMBER) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain MSC-Number AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public byte[] getAdditionalMSCNumber(){
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ Avp mscNumberAvp = additionalServingNodeAvp.getGrouped().getAvp(Avp.MSC_NUMBER);
+ if (mscNumberAvp != null){
+ return mscNumberAvp.getOctetString();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain MSC-Number AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isAdditional3GPPAAAServerNameAVPPresent() {
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ return additionalServingNodeAvp.getGrouped().getAvp(Avp.TGPP_AAA_SERVER_NAME) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain 3GPP-AAA-Server-Name AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getAdditional3GPPAAAServerName(){
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ Avp tgppAAAServerNameAvp = additionalServingNodeAvp.getGrouped().getAvp(Avp.TGPP_AAA_SERVER_NAME);
+ if (tgppAAAServerNameAvp != null){
+ return tgppAAAServerNameAvp.getDiameterIdentity();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain MSC-Number AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isAdditionalLCSCapabilitiesSetsAVPPresent(){
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ return additionalServingNodeAvp.getGrouped().getAvp(Avp.LCS_CAPABILITIES_SETS) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Capabilities-Sets AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public long getAdditionalLCSCapabilitiesSets(){
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ Avp lcsCapabilitiesSetsAvp = additionalServingNodeAvp.getGrouped().getAvp(Avp.LCS_CAPABILITIES_SETS);
+ if (lcsCapabilitiesSetsAvp != null){
+ return lcsCapabilitiesSetsAvp.getUnsigned32();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain LCS-Capabilities-Sets value", e);
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public boolean isAdditionalGMLCAddressAVPPresent(){
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ return additionalServingNodeAvp.getGrouped().getAvp(Avp.GMLC_ADDRESS) != null;
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain GMLC-Address AVP", e);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public java.net.InetAddress getAdditionalGMLCAddress(){
+ Avp additionalServingNodeAvp = super.message.getAvps().getAvp(Avp.ADDITIONAL_SERVING_NODE);
+ if (additionalServingNodeAvp != null) {
+ try {
+ Avp gmlcAddressAvp = additionalServingNodeAvp.getGrouped().getAvp(Avp.GMLC_ADDRESS);
+ if (gmlcAddressAvp != null){
+ return gmlcAddressAvp.getAddress();
+ }
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain GMLC-Address AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isPPRAddressAVPPresent(){
+ return super.message.getAvps().getAvp(Avp.PPR_ADDRESS) != null;
+ }
+
+ @Override
+ public java.net.InetAddress getPPRAddress(){
+ Avp pprAddressAvp = super.message.getAvps().getAvp(Avp.PPR_ADDRESS);
+ if (pprAddressAvp != null) {
+ try {
+ return pprAddressAvp.getAddress();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain PPR-Address AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isRIAFlagsAVPPresent() {
+ return super.message.getAvps().getAvp(Avp.RIA_FLAGS) != null;
+ }
+
+ @Override
+ public long getRIAFLags(){
+ Avp riaFlagsAvp = super.message.getAvps().getAvp(Avp.RIA_FLAGS);
+ if (riaFlagsAvp != null) {
+ try {
+ return riaFlagsAvp.getUnsigned32();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain RIA-FLAGS AVP value", e);
+ }
+ }
+ return -1;
+ }
+
+ public Avp getResultCodeAvp() throws AvpDataException {
+ return null;
+ }
+
+}
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/LCSRoutingInfoRequestImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/LCSRoutingInfoRequestImpl.java
new file mode 100644
index 000000000..f25df0a36
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/LCSRoutingInfoRequestImpl.java
@@ -0,0 +1,122 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.impl.app.slh;
+
+import org.jdiameter.api.Avp;
+import org.jdiameter.api.AvpDataException;
+import org.jdiameter.api.slh.events.LCSRoutingInfoRequest;
+import org.jdiameter.common.impl.app.AppRequestEventImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.jdiameter.api.Message;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+public class LCSRoutingInfoRequestImpl extends AppRequestEventImpl implements LCSRoutingInfoRequest {
+
+ private static final long serialVersionUID = 1L;
+
+ protected static final Logger logger = LoggerFactory.getLogger(LCSRoutingInfoRequestImpl.class);
+
+ public LCSRoutingInfoRequestImpl(Message message) {
+ super(message);
+ message.setRequest(true);
+ }
+
+ @Override
+ public boolean isUserNameAVPPresent() {
+ return super.message.getAvps().getAvp(Avp.USER_NAME) != null; // IE: IMSI
+ }
+
+ @Override
+ public String getUserName() {
+ Avp userNameAvp = super.message.getAvps().getAvp(Avp.USER_NAME);
+ if (userNameAvp != null) {
+ try {
+ return userNameAvp.getUTF8String(); // IE: IMSI mapped to User-Name
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain User-Name AVP value (IMSI)", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isMSISDNAVPPresent() {
+ return super.message.getAvps().getAvp(Avp.MSISDN) != null;
+ }
+
+ @Override
+ public byte[] getMSISDN() {
+ Avp msisdnAvp = super.message.getAvps().getAvp(Avp.MSISDN);
+ if (msisdnAvp != null) {
+ try {
+ return msisdnAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain MSISDN AVP value", e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isGMLCNumberAVPPresent() {
+ return super.message.getAvps().getAvp(Avp.GMLC_NUMBER) != null;
+ }
+
+ @Override
+ public byte[] getGMLCNumber() {
+ Avp gmlcNumberAvp = super.message.getAvps().getAvp(Avp.GMLC_NUMBER);
+ if (gmlcNumberAvp != null) {
+ try {
+ return gmlcNumberAvp.getOctetString();
+ } catch (AvpDataException e) {
+ logger.debug("Failure trying to obtain GMLC-Number AVP value", e);
+ }
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/SLhLocalSessionDataFactory.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/SLhLocalSessionDataFactory.java
new file mode 100644
index 000000000..30ec4e5cf
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/SLhLocalSessionDataFactory.java
@@ -0,0 +1,73 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.impl.app.slh;
+
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.slh.ClientSLhSession;
+import org.jdiameter.api.slh.ServerSLhSession;
+import org.jdiameter.client.impl.app.slh.ClientSLhSessionDataLocalImpl;
+import org.jdiameter.common.api.app.IAppSessionDataFactory;
+import org.jdiameter.common.api.app.slh.ISLhSessionData;
+import org.jdiameter.server.impl.app.slh.ServerSLhSessionDataLocalImpl;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class SLhLocalSessionDataFactory implements IAppSessionDataFactory {
+
+ public ISLhSessionData getAppSessionData(Class extends AppSession> clazz, String sessionId) {
+ if (clazz.equals(ClientSLhSession.class)) {
+ ClientSLhSessionDataLocalImpl data = new ClientSLhSessionDataLocalImpl();
+ data.setSessionId(sessionId);
+ return data;
+ } else if (clazz.equals(ServerSLhSession.class)) {
+ ServerSLhSessionDataLocalImpl data = new ServerSLhSessionDataLocalImpl();
+ data.setSessionId(sessionId);
+ return data;
+ } else {
+ throw new IllegalArgumentException("Invalid Session Class: " + clazz.toString());
+ }
+ }
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/SLhLocalSessionDataImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/SLhLocalSessionDataImpl.java
new file mode 100644
index 000000000..0211ef5be
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/SLhLocalSessionDataImpl.java
@@ -0,0 +1,87 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.impl.app.slh;
+
+import java.io.Serializable;
+
+import org.jdiameter.api.Request;
+import org.jdiameter.common.api.app.AppSessionDataLocalImpl;
+import org.jdiameter.common.api.app.slh.ISLhSessionData;
+import org.jdiameter.common.api.app.slh.SLhSessionState;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class SLhLocalSessionDataImpl extends AppSessionDataLocalImpl implements ISLhSessionData {
+
+ protected SLhSessionState state = SLhSessionState.IDLE;
+ protected Request buffer;
+ protected Serializable tsTimerId;
+
+ public void setSLhSessionState(SLhSessionState state) {
+ this.state = state;
+ }
+
+ public SLhSessionState getSLhSessionState() {
+ return this.state;
+ }
+
+ public Serializable getTsTimerId() {
+ return this.tsTimerId;
+ }
+
+ public void setTsTimerId(Serializable tid) {
+ this.tsTimerId = tid;
+ }
+
+ public void setBuffer(Request buffer) {
+ this.buffer = buffer;
+ }
+
+ public Request getBuffer() {
+ return this.buffer;
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/SLhSession.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/SLhSession.java
new file mode 100644
index 000000000..5ebc92f9c
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/SLhSession.java
@@ -0,0 +1,156 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.impl.app.slh;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.jdiameter.api.NetworkReqListener;
+import org.jdiameter.api.app.StateChangeListener;
+import org.jdiameter.api.app.StateMachine;
+import org.jdiameter.client.api.ISessionFactory;
+import org.jdiameter.common.impl.app.AppSessionImpl;
+import org.jdiameter.common.api.app.slh.ISLhMessageFactory;
+import org.jdiameter.common.api.app.slh.ISLhSessionData;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public abstract class SLhSession extends AppSessionImpl implements NetworkReqListener, StateMachine {
+
+ public static final int _TX_TIMEOUT = 30 * 1000;
+
+ protected Lock sendAndStateLock = new ReentrantLock();
+
+ @SuppressWarnings("rawtypes")
+ protected transient List stateListeners = new CopyOnWriteArrayList();
+ protected transient ISLhMessageFactory messageFactory;
+
+ protected static final String TIMER_NAME_MSG_TIMEOUT = "MSG_TIMEOUT";
+ protected ISLhSessionData sessionData;
+
+ public SLhSession(ISessionFactory sf, ISLhSessionData sessionData) {
+ super(sf, sessionData);
+ this.sessionData = sessionData;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public void addStateChangeNotification(StateChangeListener listener) {
+ if (!stateListeners.contains(listener)) {
+ stateListeners.add(listener);
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ public void removeStateChangeNotification(StateChangeListener listener) {
+ stateListeners.remove(listener);
+ }
+
+ public boolean isStateless() {
+ return true;
+ }
+
+ @Override
+ public boolean isReplicable() {
+ return false;
+ }
+
+ protected void startMsgTimer() {
+ try {
+ sendAndStateLock.lock();
+ sessionData.setTsTimerId(super.timerFacility.schedule(getSessionId(), TIMER_NAME_MSG_TIMEOUT, _TX_TIMEOUT));
+ } finally {
+ sendAndStateLock.unlock();
+ }
+ }
+
+ protected void cancelMsgTimer() {
+ try {
+ sendAndStateLock.lock();
+ final Serializable timerId = this.sessionData.getTsTimerId();
+ if (timerId == null) {
+ return;
+ }
+ super.timerFacility.cancel(timerId);
+ this.sessionData.setTsTimerId(null);
+ } finally {
+ sendAndStateLock.unlock();
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((sessionData == null) ? 0 : sessionData.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ SLhSession other = (SLhSession) obj;
+ if (sessionData == null) {
+ if (other.sessionData != null) {
+ return false;
+ }
+ } else if (!sessionData.equals(other.sessionData)) {
+ return false;
+ }
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/SLhSessionFactoryImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/SLhSessionFactoryImpl.java
new file mode 100644
index 000000000..b7224f6d9
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/app/slh/SLhSessionFactoryImpl.java
@@ -0,0 +1,278 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.common.impl.app.slh;
+
+import org.jdiameter.api.Answer;
+import org.jdiameter.api.ApplicationId;
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.Request;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.SessionFactory;
+import org.jdiameter.api.app.AppAnswerEvent;
+import org.jdiameter.api.app.AppRequestEvent;
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.app.StateChangeListener;
+import org.jdiameter.api.slh.ClientSLhSession;
+import org.jdiameter.api.slh.ClientSLhSessionListener;
+import org.jdiameter.api.slh.ServerSLhSession;
+import org.jdiameter.api.slh.ServerSLhSessionListener;
+import org.jdiameter.api.slh.events.LCSRoutingInfoRequest;
+import org.jdiameter.api.slh.events.LCSRoutingInfoAnswer;
+import org.jdiameter.client.api.ISessionFactory;
+import org.jdiameter.client.impl.app.slh.IClientSLhSessionData;
+import org.jdiameter.client.impl.app.slh.SLhClientSessionImpl;
+import org.jdiameter.common.api.app.IAppSessionDataFactory;
+import org.jdiameter.common.api.app.slh.ISLhMessageFactory;
+import org.jdiameter.common.api.app.slh.ISLhSessionData;
+import org.jdiameter.common.api.app.slh.ISLhSessionFactory;
+import org.jdiameter.common.api.data.ISessionDatasource;
+import org.jdiameter.server.impl.app.slh.IServerSLhSessionData;
+import org.jdiameter.server.impl.app.slh.SLhServerSessionImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class SLhSessionFactoryImpl implements ISLhSessionFactory, ServerSLhSessionListener, ClientSLhSessionListener,
+ ISLhMessageFactory, StateChangeListener {
+
+ private static final Logger logger = LoggerFactory.getLogger(SLhSessionFactoryImpl.class);
+
+ protected ISessionFactory sessionFactory;
+
+ protected ServerSLhSessionListener serverSessionListener;
+ protected ClientSLhSessionListener clientSessionListener;
+
+ protected ISLhMessageFactory messageFactory;
+ protected StateChangeListener stateListener;
+ protected ISessionDatasource iss;
+ protected IAppSessionDataFactory sessionDataFactory;
+
+ public SLhSessionFactoryImpl() {
+ };
+
+ public SLhSessionFactoryImpl(SessionFactory sessionFactory) {
+ super();
+ init(sessionFactory);
+ }
+
+ public void init(SessionFactory sessionFactory) {
+ this.sessionFactory = (ISessionFactory) sessionFactory;
+ this.iss = this.sessionFactory.getContainer().getAssemblerFacility().getComponentInstance(ISessionDatasource.class);
+ this.sessionDataFactory = (IAppSessionDataFactory) this.iss.getDataFactory(ISLhSessionData.class);
+ }
+
+ /**
+ * @return the serverSessionListener
+ */
+ public ServerSLhSessionListener getServerSessionListener() {
+ return serverSessionListener != null ? serverSessionListener : this;
+ }
+
+ /**
+ * @param serverSessionListener the serverSessionListener to set
+ */
+ public void setServerSessionListener(ServerSLhSessionListener serverSessionListener) {
+ this.serverSessionListener = serverSessionListener;
+ }
+
+ /**
+ * @return the serverSessionListener
+ */
+ public ClientSLhSessionListener getClientSessionListener() {
+ return clientSessionListener != null ? clientSessionListener : this;
+ }
+
+ /**
+ * @param clientSessionListener the clientSessionListener to set
+ */
+ public void setClientSessionListener(ClientSLhSessionListener clientSessionListener) {
+ this.clientSessionListener = clientSessionListener;
+ }
+
+ /**
+ * @return the messageFactory
+ */
+ public ISLhMessageFactory getMessageFactory() {
+ return messageFactory != null ? messageFactory : this;
+ }
+
+ /**
+ * @param messageFactory the messageFactory to set
+ */
+ public void setMessageFactory(ISLhMessageFactory messageFactory) {
+ this.messageFactory = messageFactory;
+ }
+
+ /**
+ * @return the stateListener
+ */
+ public StateChangeListener getStateListener() {
+ return stateListener != null ? stateListener : this;
+ }
+
+ /**
+ * @param stateListener the stateListener to set
+ */
+ public void setStateListener(StateChangeListener stateListener) {
+ this.stateListener = stateListener;
+ }
+
+ public AppSession getSession(String sessionId, Class extends AppSession> aClass) {
+ if (sessionId == null) {
+ throw new IllegalArgumentException("SessionId must not be null");
+ }
+ if (!this.iss.exists(sessionId)) {
+ return null;
+ }
+ AppSession appSession = null;
+ try {
+ if (aClass == ServerSLhSession.class) {
+ IServerSLhSessionData sessionData = (IServerSLhSessionData) this.sessionDataFactory.getAppSessionData(ServerSLhSession.class, sessionId);
+ SLhServerSessionImpl serverSession = new SLhServerSessionImpl(sessionData, getMessageFactory(), sessionFactory, this.getServerSessionListener());
+ serverSession.getSessions().get(0).setRequestListener(serverSession);
+ appSession = serverSession;
+ } else if (aClass == ClientSLhSession.class) {
+ IClientSLhSessionData sessionData = (IClientSLhSessionData) this.sessionDataFactory.getAppSessionData(ClientSLhSession.class, sessionId);
+ SLhClientSessionImpl clientSession = new SLhClientSessionImpl(sessionData, getMessageFactory(), sessionFactory, this.getClientSessionListener());
+ clientSession.getSessions().get(0).setRequestListener(clientSession);
+ appSession = clientSession;
+ } else {
+ throw new IllegalArgumentException(
+ "Wrong session class: " + aClass + ". Supported[" + ServerSLhSession.class + "]");
+ }
+ } catch (Exception e) {
+ logger.error("Failure to obtain new SLh Session.", e);
+ }
+ return appSession;
+ }
+
+ public AppSession getNewSession(String sessionId, Class extends AppSession> aClass, ApplicationId applicationId, Object[] args) {
+ AppSession appSession = null;
+
+ try {
+ if (aClass == ServerSLhSession.class) {
+ if (sessionId == null) {
+ if (args != null && args.length > 0 && args[0] instanceof Request) {
+ Request request = (Request) args[0];
+ sessionId = request.getSessionId();
+ } else {
+ sessionId = this.sessionFactory.getSessionId();
+ }
+ }
+ IServerSLhSessionData sessionData = (IServerSLhSessionData) this.sessionDataFactory.getAppSessionData(ServerSLhSession.class, sessionId);
+ sessionData.setApplicationId(applicationId);
+ SLhServerSessionImpl serverSession = new SLhServerSessionImpl(sessionData, getMessageFactory(), sessionFactory, this.getServerSessionListener());
+
+ iss.addSession(serverSession);
+ serverSession.getSessions().get(0).setRequestListener(serverSession);
+ appSession = serverSession;
+ } else if (aClass == ClientSLhSession.class) {
+ if (sessionId == null) {
+ if (args != null && args.length > 0 && args[0] instanceof Request) {
+ Request request = (Request) args[0];
+ sessionId = request.getSessionId();
+ } else {
+ sessionId = this.sessionFactory.getSessionId();
+ }
+ }
+ IClientSLhSessionData sessionData = (IClientSLhSessionData) this.sessionDataFactory.getAppSessionData(ClientSLhSession.class, sessionId);
+ sessionData.setApplicationId(applicationId);
+ SLhClientSessionImpl clientSession = new SLhClientSessionImpl(sessionData, getMessageFactory(), sessionFactory, this.getClientSessionListener());
+
+ iss.addSession(clientSession);
+ clientSession.getSessions().get(0).setRequestListener(clientSession);
+ appSession = clientSession;
+ } else {
+ throw new IllegalArgumentException(
+ "Wrong session class: " + aClass + ". Supported[" + ServerSLhSession.class + "]");
+ }
+ } catch (Exception e) {
+ logger.error("Failure to obtain new SLh Session.", e);
+ }
+ return appSession;
+ }
+
+ public void stateChanged(Enum oldState, Enum newState) {
+ logger.info("Diameter SLh Session Factory :: stateChanged :: oldState[{}], newState[{}]", oldState, newState);
+ }
+
+ public long getApplicationId() {
+ return 16777291;
+ }
+
+ public void stateChanged(AppSession source, Enum oldState, Enum newState) {
+ logger.info("Diameter SLh Session Factory :: stateChanged :: Session, [{}], oldState[{}], newState[{}]", new Object[] { source, oldState, newState });
+ }
+
+ public LCSRoutingInfoAnswer createLCSRoutingInfoAnswer(Answer answer) {
+ return new LCSRoutingInfoAnswerImpl(answer);
+ }
+
+ public LCSRoutingInfoRequest createLCSRoutingInfoRequest(Request request) {
+ return new LCSRoutingInfoRequestImpl(request);
+ }
+
+ public void doLCSRoutingInfoRequestEvent(ServerSLhSession appSession, LCSRoutingInfoRequest request)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
+ logger.info("Diameter SLh Session Factory :: doLCSRoutingInfoRequestEvent :: appSession[{}], Request[{}]", appSession, request);
+ }
+
+ public void doOtherEvent(AppSession appSession, AppRequestEvent request, AppAnswerEvent answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
+ logger.info("Diameter SLh Session Factory :: doOtherEvent :: appSession[{}], Request[{}], Answer[{}]", new Object[] { appSession, request, answer });
+ }
+
+ public void doLCSRoutingInfoAnswerEvent(ClientSLhSession appSession, LCSRoutingInfoRequest request, LCSRoutingInfoAnswer answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
+ logger.info(
+ "Diameter SLh Session Factory :: doLCSRoutingInfoAnswerEvent :: appSession[{}], Request[{}], Answer[{}]",
+ new Object[] { appSession, request, answer });
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/data/LocalDataSource.java b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/data/LocalDataSource.java
index d066798e6..017451023 100644
--- a/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/data/LocalDataSource.java
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/common/impl/data/LocalDataSource.java
@@ -62,6 +62,8 @@
import org.jdiameter.common.api.app.s13.IS13SessionData;
import org.jdiameter.common.api.app.s6a.IS6aSessionData;
import org.jdiameter.common.api.app.sh.IShSessionData;
+import org.jdiameter.common.api.app.slg.ISLgSessionData;
+import org.jdiameter.common.api.app.slh.ISLhSessionData;
import org.jdiameter.common.api.data.ISessionDatasource;
import org.jdiameter.common.impl.app.acc.AccLocalSessionDataFactory;
import org.jdiameter.common.impl.app.auth.AuthLocalSessionDataFactory;
@@ -74,6 +76,8 @@
import org.jdiameter.common.impl.app.s13.S13LocalSessionDataFactory;
import org.jdiameter.common.impl.app.s6a.S6aLocalSessionDataFactory;
import org.jdiameter.common.impl.app.sh.ShLocalSessionDataFactory;
+import org.jdiameter.common.impl.app.slg.SLgLocalSessionDataFactory;
+import org.jdiameter.common.impl.app.slh.SLhLocalSessionDataFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -105,6 +109,8 @@ public LocalDataSource() {
appSessionDataFactories.put(IRxSessionData.class, new RxLocalSessionDataFactory());
appSessionDataFactories.put(IS6aSessionData.class, new S6aLocalSessionDataFactory());
appSessionDataFactories.put(IS13SessionData.class, new S13LocalSessionDataFactory());
+ appSessionDataFactories.put(ISLhSessionData.class, new SLhLocalSessionDataFactory());
+ appSessionDataFactories.put(ISLgSessionData.class, new SLgLocalSessionDataFactory());
}
public LocalDataSource(IContainer container) {
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slg/Event.java b/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slg/Event.java
new file mode 100644
index 000000000..68066d7f3
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slg/Event.java
@@ -0,0 +1,108 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.server.impl.app.slg;
+
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.app.AppEvent;
+import org.jdiameter.api.app.StateEvent;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class Event implements StateEvent {
+
+ enum Type {
+ SEND_MESSAGE, TIMEOUT_EXPIRES, RECEIVE_PLR, RECEIVE_LRR
+ }
+
+ AppEvent request;
+ AppEvent answer;
+ Type type;
+
+ Event(Type type, AppEvent request, AppEvent answer) {
+ this.type = type;
+ this.answer = answer;
+ this.request = request;
+ }
+
+ @SuppressWarnings("unchecked")
+ public E encodeType(Class eClass) {
+ return eClass == Type.class ? (E) type : null;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public Enum getType() {
+ return type;
+ }
+
+ public AppEvent getRequest() {
+ return request;
+ }
+
+ public AppEvent getAnswer() {
+ return answer;
+ }
+
+ public int compareTo(Object o) {
+ return 0;
+ }
+
+ public Object getData() {
+ return request != null ? request : answer;
+ }
+
+ public void setData(Object data) {
+ try {
+ if (((AppEvent) data).getMessage().isRequest()) {
+ request = (AppEvent) data;
+ } else {
+ answer = (AppEvent) data;
+ }
+ } catch (InternalException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slg/IServerSLgSessionData.java b/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slg/IServerSLgSessionData.java
new file mode 100644
index 000000000..cf1315a52
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slg/IServerSLgSessionData.java
@@ -0,0 +1,54 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.server.impl.app.slg;
+
+import org.jdiameter.common.api.app.slg.ISLgSessionData;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public interface IServerSLgSessionData extends ISLgSessionData {
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slg/SLgServerSessionImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slg/SLgServerSessionImpl.java
new file mode 100644
index 000000000..0548280a2
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slg/SLgServerSessionImpl.java
@@ -0,0 +1,333 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.server.impl.app.slg;
+
+import org.jdiameter.api.Answer;
+import org.jdiameter.api.EventListener;
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.NetworkReqListener;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.Request;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.app.AppEvent;
+import org.jdiameter.api.app.StateChangeListener;
+import org.jdiameter.api.app.StateEvent;
+import org.jdiameter.api.slg.ServerSLgSession;
+import org.jdiameter.api.slg.ServerSLgSessionListener;
+import org.jdiameter.api.slg.events.LocationReportAnswer;
+import org.jdiameter.api.slg.events.LocationReportRequest;
+import org.jdiameter.api.slg.events.ProvideLocationAnswer;
+import org.jdiameter.api.slg.events.ProvideLocationRequest;
+import org.jdiameter.client.api.ISessionFactory;
+import org.jdiameter.common.api.app.slg.ISLgMessageFactory;
+import org.jdiameter.common.api.app.slg.SLgSessionState;
+import org.jdiameter.common.impl.app.AppAnswerEventImpl;
+import org.jdiameter.common.impl.app.AppRequestEventImpl;
+import org.jdiameter.common.impl.app.slg.SLgSession;
+import org.jdiameter.server.impl.app.slg.Event.Type;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class SLgServerSessionImpl extends SLgSession
+ implements ServerSLgSession, EventListener, NetworkReqListener {
+
+ private static final Logger logger = LoggerFactory.getLogger(SLgServerSessionImpl.class);
+
+ // Factories and Listeners
+ // --------------------------------------------------
+ private transient ServerSLgSessionListener listener;
+ protected long appId = -1;
+ protected IServerSLgSessionData sessionData;
+
+ public SLgServerSessionImpl(IServerSLgSessionData sessionData, ISLgMessageFactory fct, ISessionFactory sf,
+ ServerSLgSessionListener lst) {
+ super(sf, sessionData);
+ if (lst == null) {
+ throw new IllegalArgumentException("Listener can not be null");
+ }
+ if ((this.appId = fct.getApplicationId()) < 0) {
+ throw new IllegalArgumentException("ApplicationId can not be less than zero");
+ }
+
+ this.listener = lst;
+ super.messageFactory = fct;
+ this.sessionData = sessionData;
+ }
+
+ public void sendProvideLocationAnswer(ProvideLocationAnswer answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
+ send(Event.Type.SEND_MESSAGE, null, answer);
+ }
+
+ public void sendLocationReportAnswer(LocationReportAnswer answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
+ send(Event.Type.SEND_MESSAGE, null, answer);
+ }
+
+ @SuppressWarnings("unchecked")
+ public E getState(Class stateType) {
+ return stateType == SLgSessionState.class ? (E) this.sessionData.getSLgSessionState() : null;
+ }
+
+ @SuppressWarnings("unused")
+ public boolean handleEvent(StateEvent event) throws InternalException, OverloadException {
+ try {
+ sendAndStateLock.lock();
+ if (!super.session.isValid()) {
+ // FIXME: throw new InternalException("Generic session is not valid.");
+ return false;
+ }
+ final SLgSessionState state = this.sessionData.getSLgSessionState();
+ SLgSessionState newState = null;
+ Event localEvent = (Event) event;
+ Event.Type eventType = (Type) event.getType();
+
+ switch (state) {
+
+ case IDLE:
+ switch (eventType) {
+
+ case RECEIVE_PLR:
+ this.sessionData.setBuffer((Request) ((AppEvent) event.getData()).getMessage());
+ super.cancelMsgTimer();
+ super.startMsgTimer();
+ newState = SLgSessionState.MESSAGE_SENT_RECEIVED;
+ setState(newState);
+ listener.doProvideLocationRequestEvent(this, (ProvideLocationRequest) event.getData());
+ break;
+
+ case RECEIVE_LRR:
+ this.sessionData.setBuffer((Request) ((AppEvent) event.getData()).getMessage());
+ super.cancelMsgTimer();
+ super.startMsgTimer();
+ newState = SLgSessionState.MESSAGE_SENT_RECEIVED;
+ setState(newState);
+ listener.doLocationReportRequestEvent(this, (LocationReportRequest) event.getData());
+ break;
+
+ case SEND_MESSAGE:
+ super.session.send(((AppEvent) event.getData()).getMessage(), this);
+ newState = SLgSessionState.MESSAGE_SENT_RECEIVED;
+ setState(newState);
+ break;
+
+ default:
+ logger.error("Wrong action in SLg Server FSM. State: IDLE, Event Type: {}", eventType);
+ break;
+ }
+ break;
+
+ case MESSAGE_SENT_RECEIVED:
+ switch (eventType) {
+ case TIMEOUT_EXPIRES:
+ newState = SLgSessionState.TIMEDOUT;
+ setState(newState);
+ break;
+
+ case SEND_MESSAGE:
+ try {
+ super.session.send(((AppEvent) event.getData()).getMessage(), this);
+ } finally {
+ newState = SLgSessionState.TERMINATED;
+ setState(newState);
+ }
+ break;
+
+ default:
+ throw new InternalException(
+ "Should not receive more messages after initial. Command: " + event.getData());
+ }
+ break;
+
+ case TERMINATED:
+ throw new InternalException("Cant receive message in state TERMINATED. Command: " + event.getData());
+
+ case TIMEDOUT:
+ throw new InternalException("Cant receive message in state TIMEDOUT. Command: " + event.getData());
+
+ default:
+ logger.error("SLg Server FSM in wrong state: {}", state);
+ break;
+ }
+ } catch (Exception e) {
+ throw new InternalException(e);
+ } finally {
+ sendAndStateLock.unlock();
+ }
+ return true;
+ }
+
+ public void receivedSuccessMessage(Request request, Answer answer) {
+ AnswerDelivery rd = new AnswerDelivery();
+ rd.session = this;
+ rd.request = request;
+ rd.answer = answer;
+ super.scheduler.execute(rd);
+ }
+
+ public void timeoutExpired(Request request) {
+ try {
+ handleEvent(new Event(Event.Type.TIMEOUT_EXPIRES, new AppRequestEventImpl(request), null));
+ } catch (Exception e) {
+ logger.debug("Failed to process timeout message", e);
+ }
+ }
+
+ public Answer processRequest(Request request) {
+ RequestDelivery rd = new RequestDelivery();
+ rd.session = this;
+ rd.request = request;
+ super.scheduler.execute(rd);
+ return null;
+ }
+
+ protected void send(Event.Type type, AppEvent request, AppEvent answer) throws InternalException {
+ try {
+ if (type != null) {
+ handleEvent(new Event(type, request, answer));
+ }
+ } catch (Exception e) {
+ throw new InternalException(e);
+ }
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected void setState(SLgSessionState newState) {
+ SLgSessionState oldState = this.sessionData.getSLgSessionState();
+ this.sessionData.setSLgSessionState(newState);
+
+ for (StateChangeListener i : stateListeners) {
+ i.stateChanged(this, (Enum) oldState, (Enum) newState);
+ }
+ if (newState == SLgSessionState.TERMINATED || newState == SLgSessionState.TIMEDOUT) {
+ super.cancelMsgTimer();
+ this.release();
+ }
+ }
+
+ @Override
+ public void onTimer(String timerName) {
+ if (timerName.equals(SLgSession.TIMER_NAME_MSG_TIMEOUT)) {
+ try {
+ sendAndStateLock.lock();
+ try {
+ handleEvent(
+ new Event(Event.Type.TIMEOUT_EXPIRES, new AppRequestEventImpl(this.sessionData.getBuffer()), null));
+ } catch (Exception e) {
+ logger.debug("Failure handling Timeout event.");
+ }
+ this.sessionData.setBuffer(null);
+ this.sessionData.setTsTimerId(null);
+ } finally {
+ sendAndStateLock.unlock();
+ }
+ }
+ }
+
+ public void release() {
+ if (isValid()) {
+ try {
+ sendAndStateLock.lock();
+ super.release();
+ } catch (Exception e) {
+ logger.debug("Failed to release session", e);
+ } finally {
+ sendAndStateLock.unlock();
+ }
+ } else {
+ logger.debug("Trying to release an already invalid session, with Session ID '{}'", getSessionId());
+ }
+ }
+
+ private class RequestDelivery implements Runnable {
+ ServerSLgSession session;
+ Request request;
+
+ public void run() {
+ try {
+ switch (request.getCommandCode()) {
+ case ProvideLocationRequest.code:
+ handleEvent(
+ new Event(Event.Type.RECEIVE_PLR, messageFactory.createProvideLocationRequest(request), null));
+ break;
+
+ case LocationReportRequest.code:
+ handleEvent(
+ new Event(Event.Type.RECEIVE_LRR, messageFactory.createLocationReportRequest(request), null));
+ break;
+
+ default:
+ listener.doOtherEvent(session, new AppRequestEventImpl(request), null);
+ break;
+ }
+ } catch (Exception e) {
+ logger.debug("Failed to process request message", e);
+ }
+ }
+ }
+
+ private class AnswerDelivery implements Runnable {
+ ServerSLgSession session;
+ Answer answer;
+ Request request;
+
+ public void run() {
+ try {
+ switch (answer.getCommandCode()) {
+ default:
+ listener.doOtherEvent(session, new AppRequestEventImpl(request), new AppAnswerEventImpl(answer));
+ break;
+ }
+ } catch (Exception e) {
+ logger.debug("Failed to process success message", e);
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slg/ServerSLgSessionDataLocalImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slg/ServerSLgSessionDataLocalImpl.java
new file mode 100644
index 000000000..3dc1fa092
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slg/ServerSLgSessionDataLocalImpl.java
@@ -0,0 +1,57 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.server.impl.app.slg;
+
+import org.jdiameter.common.impl.app.slg.SLgLocalSessionDataImpl;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class ServerSLgSessionDataLocalImpl extends SLgLocalSessionDataImpl implements IServerSLgSessionData {
+
+ public ServerSLgSessionDataLocalImpl() {
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slh/Event.java b/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slh/Event.java
new file mode 100644
index 000000000..71984c8bc
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slh/Event.java
@@ -0,0 +1,107 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.server.impl.app.slh;
+
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.app.AppEvent;
+import org.jdiameter.api.app.StateEvent;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class Event implements StateEvent {
+ enum Type {
+ SEND_MESSAGE, TIMEOUT_EXPIRES, RECEIVE_RIR;
+ }
+
+ AppEvent request;
+ AppEvent answer;
+ Type type;
+
+ Event(Type type, AppEvent request, AppEvent answer) {
+ this.type = type;
+ this.answer = answer;
+ this.request = request;
+ }
+
+ @SuppressWarnings("unchecked")
+ public E encodeType(Class eClass) {
+ return eClass == Type.class ? (E) type : null;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public Enum getType() {
+ return type;
+ }
+
+ public AppEvent getRequest() {
+ return request;
+ }
+
+ public AppEvent getAnswer() {
+ return answer;
+ }
+
+ public int compareTo(Object o) {
+ return 0;
+ }
+
+ public Object getData() {
+ return request != null ? request : answer;
+ }
+
+ public void setData(Object data) {
+ try {
+ if (((AppEvent) data).getMessage().isRequest()) {
+ request = (AppEvent) data;
+ } else {
+ answer = (AppEvent) data;
+ }
+ } catch (InternalException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slh/IServerSLhSessionData.java b/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slh/IServerSLhSessionData.java
new file mode 100644
index 000000000..e61de6d40
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slh/IServerSLhSessionData.java
@@ -0,0 +1,54 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.server.impl.app.slh;
+
+import org.jdiameter.common.api.app.slh.ISLhSessionData;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public interface IServerSLhSessionData extends ISLhSessionData {
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slh/SLhServerSessionImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slh/SLhServerSessionImpl.java
new file mode 100644
index 000000000..2f7e63d99
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slh/SLhServerSessionImpl.java
@@ -0,0 +1,310 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.server.impl.app.slh;
+
+import org.jdiameter.api.Answer;
+import org.jdiameter.api.EventListener;
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.NetworkReqListener;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.Request;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.app.AppEvent;
+import org.jdiameter.api.app.StateChangeListener;
+import org.jdiameter.api.app.StateEvent;
+import org.jdiameter.api.slh.ServerSLhSession;
+import org.jdiameter.api.slh.ServerSLhSessionListener;
+import org.jdiameter.api.slh.events.LCSRoutingInfoRequest;
+import org.jdiameter.api.slh.events.LCSRoutingInfoAnswer;
+import org.jdiameter.client.api.ISessionFactory;
+import org.jdiameter.common.api.app.slh.ISLhMessageFactory;
+import org.jdiameter.common.api.app.slh.SLhSessionState;
+import org.jdiameter.common.impl.app.AppAnswerEventImpl;
+import org.jdiameter.common.impl.app.AppRequestEventImpl;
+import org.jdiameter.common.impl.app.slh.SLhSession;
+import org.jdiameter.server.impl.app.slh.Event.Type;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class SLhServerSessionImpl extends SLhSession implements ServerSLhSession, EventListener, NetworkReqListener {
+
+ private static final Logger logger = LoggerFactory.getLogger(SLhServerSessionImpl.class);
+
+ // Factories and Listeners
+ // --------------------------------------------------
+ private transient ServerSLhSessionListener listener;
+ protected long appId = -1;
+ protected IServerSLhSessionData sessionData;
+
+ public SLhServerSessionImpl(IServerSLhSessionData sessionData, ISLhMessageFactory fct, ISessionFactory sf, ServerSLhSessionListener lst) {
+ super(sf, sessionData);
+ if (lst == null) {
+ throw new IllegalArgumentException("Listener can not be null");
+ }
+ if ((this.appId = fct.getApplicationId()) < 0) {
+ throw new IllegalArgumentException("ApplicationId can not be less than zero");
+ }
+
+ this.listener = lst;
+ super.messageFactory = fct;
+ this.sessionData = sessionData;
+ }
+
+ public void sendLCSRoutingInfoAnswer(LCSRoutingInfoAnswer answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
+ send(Event.Type.SEND_MESSAGE, null, answer);
+ }
+
+ @SuppressWarnings("unchecked")
+ public E getState(Class stateType) {
+ return stateType == SLhSessionState.class ? (E) this.sessionData.getSLhSessionState() : null;
+ }
+
+ @SuppressWarnings("unused")
+ public boolean handleEvent(StateEvent event) throws InternalException, OverloadException {
+ try {
+ sendAndStateLock.lock();
+ if (!super.session.isValid()) {
+ // FIXME: throw new InternalException("Generic session is not valid.");
+ return false;
+ }
+ final SLhSessionState state = this.sessionData.getSLhSessionState();
+ SLhSessionState newState = null;
+ Event localEvent = (Event) event;
+ Event.Type eventType = (Type) event.getType();
+
+ switch (state) {
+
+ case IDLE:
+ switch (eventType) {
+
+ case RECEIVE_RIR:
+ this.sessionData.setBuffer((Request) ((AppEvent) event.getData()).getMessage());
+ super.cancelMsgTimer();
+ super.startMsgTimer();
+ newState = SLhSessionState.MESSAGE_SENT_RECEIVED;
+ setState(newState);
+ listener.doLCSRoutingInfoRequestEvent(this, (LCSRoutingInfoRequest) event.getData());
+ break;
+
+ case SEND_MESSAGE:
+ super.session.send(((AppEvent) event.getData()).getMessage(), this);
+ newState = SLhSessionState.MESSAGE_SENT_RECEIVED;
+ setState(newState);
+ break;
+
+ default:
+ logger.error("Wrong action in SLh Server FSM. State: IDLE, Event Type: {}", eventType);
+ break;
+ }
+ break;
+
+ case MESSAGE_SENT_RECEIVED:
+ switch (eventType) {
+ case TIMEOUT_EXPIRES:
+ newState = SLhSessionState.TIMEDOUT;
+ setState(newState);
+ break;
+
+ case SEND_MESSAGE:
+ try {
+ super.session.send(((AppEvent) event.getData()).getMessage(), this);
+ } finally {
+ newState = SLhSessionState.TERMINATED;
+ setState(newState);
+ }
+ break;
+
+ default:
+ throw new InternalException(
+ "Should not receive more messages after initial. Command: " + event.getData());
+ }
+ break;
+
+ case TERMINATED:
+ throw new InternalException("Cant receive message in state TERMINATED. Command: " + event.getData());
+
+ case TIMEDOUT:
+ throw new InternalException("Cant receive message in state TIMEDOUT. Command: " + event.getData());
+
+ default:
+ logger.error("SLh Server FSM in wrong state: {}", state);
+ break;
+ }
+ } catch (Exception e) {
+ throw new InternalException(e);
+ } finally {
+ sendAndStateLock.unlock();
+ }
+ return true;
+ }
+
+ public void receivedSuccessMessage(Request request, Answer answer) {
+ AnswerDelivery rd = new AnswerDelivery();
+ rd.session = this;
+ rd.request = request;
+ rd.answer = answer;
+ super.scheduler.execute(rd);
+ }
+
+ public void timeoutExpired(Request request) {
+ try {
+ handleEvent(new Event(Event.Type.TIMEOUT_EXPIRES, new AppRequestEventImpl(request), null));
+ } catch (Exception e) {
+ logger.debug("Failed to process timeout message", e);
+ }
+ }
+
+ public Answer processRequest(Request request) {
+ RequestDelivery rd = new RequestDelivery();
+ rd.session = this;
+ rd.request = request;
+ super.scheduler.execute(rd);
+ return null;
+ }
+
+ protected void send(Event.Type type, AppEvent request, AppEvent answer) throws InternalException {
+ try {
+ if (type != null) {
+ handleEvent(new Event(type, request, answer));
+ }
+ } catch (Exception e) {
+ throw new InternalException(e);
+ }
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected void setState(SLhSessionState newState) {
+ SLhSessionState oldState = this.sessionData.getSLhSessionState();
+ this.sessionData.setSLhSessionState(newState);
+
+ for (StateChangeListener i : stateListeners) {
+ i.stateChanged(this, (Enum) oldState, (Enum) newState);
+ }
+ if (newState == SLhSessionState.TERMINATED || newState == SLhSessionState.TIMEDOUT) {
+ super.cancelMsgTimer();
+ this.release();
+ }
+ }
+
+ @Override
+ public void onTimer(String timerName) {
+ if (timerName.equals(SLhSession.TIMER_NAME_MSG_TIMEOUT)) {
+ try {
+ sendAndStateLock.lock();
+ try {
+ handleEvent(
+ new Event(Event.Type.TIMEOUT_EXPIRES, new AppRequestEventImpl(this.sessionData.getBuffer()), null));
+ } catch (Exception e) {
+ logger.debug("Failure handling Timeout event.");
+ }
+ this.sessionData.setBuffer(null);
+ this.sessionData.setTsTimerId(null);
+ } finally {
+ sendAndStateLock.unlock();
+ }
+ }
+ }
+
+ public void release() {
+ if (isValid()) {
+ try {
+ sendAndStateLock.lock();
+ super.release();
+ } catch (Exception e) {
+ logger.debug("Failed to release session", e);
+ } finally {
+ sendAndStateLock.unlock();
+ }
+ } else {
+ logger.debug("Trying to release an already invalid session, with Session ID '{}'", getSessionId());
+ }
+ }
+
+ private class RequestDelivery implements Runnable {
+ ServerSLhSession session;
+ Request request;
+
+ public void run() {
+ try {
+ switch (request.getCommandCode()) {
+ case LCSRoutingInfoRequest.code:
+ handleEvent(
+ new Event(Event.Type.RECEIVE_RIR, messageFactory.createLCSRoutingInfoRequest(request), null));
+ break;
+
+ default:
+ listener.doOtherEvent(session, new AppRequestEventImpl(request), null);
+ break;
+ }
+ } catch (Exception e) {
+ logger.debug("Failed to process request message", e);
+ }
+ }
+ }
+
+ private class AnswerDelivery implements Runnable {
+ ServerSLhSession session;
+ Answer answer;
+ Request request;
+
+ public void run() {
+ try {
+ switch (answer.getCommandCode()) {
+ default:
+ listener.doOtherEvent(session, new AppRequestEventImpl(request), new AppAnswerEventImpl(answer));
+ break;
+ }
+ } catch (Exception e) {
+ logger.debug("Failed to process success message", e);
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slh/ServerSLhSessionDataLocalImpl.java b/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slh/ServerSLhSessionDataLocalImpl.java
new file mode 100644
index 000000000..3e1914e9e
--- /dev/null
+++ b/core/jdiameter/impl/src/main/java/org/jdiameter/server/impl/app/slh/ServerSLhSessionDataLocalImpl.java
@@ -0,0 +1,57 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.jdiameter.server.impl.app.slh;
+
+import org.jdiameter.common.impl.app.slh.SLhLocalSessionDataImpl;
+
+/**
+ * @author Fernando Mendioroz
+ *
+ */
+
+public class ServerSLhSessionDataLocalImpl extends SLhLocalSessionDataImpl implements IServerSLhSessionData {
+
+ public ServerSLhSessionDataLocalImpl() {
+ }
+
+}
\ No newline at end of file
diff --git a/core/mux/common/config/dictionary.xml b/core/mux/common/config/dictionary.xml
index 6f7c02bc2..6aac1b8f1 100644
--- a/core/mux/common/config/dictionary.xml
+++ b/core/mux/common/config/dictionary.xml
@@ -7867,4 +7867,637 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/AbstractDeferredClient.java b/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/AbstractDeferredClient.java
new file mode 100644
index 000000000..7dab8906b
--- /dev/null
+++ b/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/AbstractDeferredClient.java
@@ -0,0 +1,530 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.mobicents.diameter.stack.functional.slg;
+
+import java.io.InputStream;
+import java.util.concurrent.TimeUnit;
+
+import org.jdiameter.api.ApplicationId;
+import org.jdiameter.api.Avp;
+import org.jdiameter.api.AvpSet;
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.Mode;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.app.AppAnswerEvent;
+import org.jdiameter.api.app.AppRequestEvent;
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.slg.ClientSLgSession;
+import org.jdiameter.api.slg.ClientSLgSessionListener;
+import org.jdiameter.api.slg.ServerSLgSession;
+import org.jdiameter.api.slg.events.ProvideLocationRequest;
+import org.jdiameter.api.slg.events.ProvideLocationAnswer;
+import org.jdiameter.api.slg.events.LocationReportRequest;
+import org.jdiameter.api.slg.events.LocationReportAnswer;
+import org.jdiameter.client.api.ISessionFactory;
+import org.jdiameter.common.impl.app.slg.LocationReportRequestImpl;
+import org.jdiameter.common.impl.app.slg.SLgSessionFactoryImpl;
+import org.mobicents.diameter.stack.functional.TBase;
+
+/**
+ *
+ * @author Fernando Mendioroz
+ *
+ */
+public abstract class AbstractDeferredClient extends TBase implements ClientSLgSessionListener {
+
+ // NOTE: implementing NetworkReqListener since its required for stack to
+ // know we support it... ech.
+
+ protected ClientSLgSession clientSLgSession;
+
+ public void init(InputStream configStream, String clientID) throws Exception {
+ try {
+ super.init(configStream, clientID, ApplicationId.createByAuthAppId(10415, 16777255));
+ SLgSessionFactoryImpl sLgSessionFactory = new SLgSessionFactoryImpl(this.sessionFactory);
+ ((ISessionFactory) sessionFactory).registerAppFacory(ServerSLgSession.class, sLgSessionFactory);
+ ((ISessionFactory) sessionFactory).registerAppFacory(ClientSLgSession.class, sLgSessionFactory);
+
+ sLgSessionFactory .setClientSessionListener(this);
+
+ this.clientSLgSession = ((ISessionFactory) this.sessionFactory).getNewAppSession(this.sessionFactory.getSessionId("xx-SLg-TESTxx"), getApplicationId(),
+ ClientSLgSession.class, null);
+ } finally {
+ try {
+ configStream.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ // ----------- delegate methods so
+
+ public void start() throws IllegalDiameterStateException, InternalException {
+ stack.start();
+ }
+
+ public void start(Mode mode, long timeOut, TimeUnit timeUnit) throws IllegalDiameterStateException, InternalException {
+ stack.start(mode, timeOut, timeUnit);
+ }
+
+ public void stop(long timeOut, TimeUnit timeUnit, int disconnectCause) throws IllegalDiameterStateException, InternalException {
+ stack.stop(timeOut, timeUnit, disconnectCause);
+ }
+
+ public void stop(int disconnectCause) {
+ stack.stop(disconnectCause);
+ }
+
+ // ------- def methods, to fail :)
+
+ public void doOtherEvent(AppSession session, AppRequestEvent request, AppAnswerEvent answer) throws InternalException, IllegalDiameterStateException,
+ RouteException, OverloadException {
+ fail("Received \"Other\" event, request[" + request + "], answer[" + answer + "], on session[" + session + "]", null);
+ }
+
+ public void doLocationReportAnswerEvent(ClientSLgSession session, LocationReportRequest request, LocationReportAnswer answer) throws InternalException,
+ IllegalDiameterStateException, RouteException, OverloadException {
+ fail("Received \"LRA\" event, request[" + request + "], answer[" + answer + "], on session[" + session + "]", null);
+ }
+
+ public void doProvideLocationAnswerEvent(ClientSLgSession session, ProvideLocationRequest request, ProvideLocationAnswer answer) throws InternalException,
+ IllegalDiameterStateException, RouteException, OverloadException {
+ fail("Received \"PLA\" event, request[" + request + "], answer[" + answer + "], on session[" + session + "]", null);
+ }
+
+ // ----------- conf parts
+
+ public String getSessionId() {
+ return this.clientSLgSession.getSessionId();
+ }
+
+ public ClientSLgSession getSession() {
+ return this.clientSLgSession;
+ }
+
+ // Attributes for Location Report Request (LRR)
+ protected abstract String getUserName(); // IE: IMSI
+ protected abstract byte[] getMSISDN();
+ protected abstract String getIMEI();
+ protected abstract String getLCSNameString();
+ protected abstract int getLCSFormatIndicator();
+ protected abstract int getLCSQoSClass();
+ protected abstract long getLSCServiceTypeId();
+ protected abstract long getDeferredLocationType();
+ protected abstract byte[] getLCSReferenceNumber();
+ protected abstract java.net.InetAddress getGMLCAddress();
+ protected abstract long getReportingAmount();
+ protected abstract long getReportingInterval();
+ protected abstract int getLocationEvent();
+ protected abstract byte[] getLocationEstimate();
+ protected abstract int getAccuracyFulfilmentIndicator();
+ protected abstract long getAgeOfLocationEstimate();
+ protected abstract byte[] getVelocityEstimate();
+ protected abstract byte[] getEUTRANPositioningData();
+ protected abstract byte[] getECGI();
+ protected abstract byte[] getGERANPositioningData();
+ protected abstract byte[] getGERANGANSSPositioningData();
+ protected abstract byte[] getCellGlobalIdentity();
+ protected abstract byte[] getUTRANPositioningData();
+ protected abstract byte[] getUTRANGANSSPositioningData();
+ protected abstract byte[] getServiceAreaIdentity();
+ protected abstract int getPseudonymIndicator();
+ protected abstract byte[] getSGSNNumber();
+ protected abstract String getSGSNName();
+ protected abstract String getSGSNRealm();
+ protected abstract String getMMEName();
+ protected abstract String getMMERealm();
+ protected abstract byte[] getMSCNumber();
+ protected abstract String get3GPPAAAServerName();
+ protected abstract long getLCSCapabilitiesSets();
+ protected abstract long getLRRFLags();
+ protected abstract long getTerminationCause();
+ protected abstract long getCellPortionId();
+ protected abstract byte[] get1xRTTRCID();
+ protected abstract String getCivicAddress();
+ protected abstract long getBarometricPressure();
+
+ // ----------- 3GPP TS 29.172 reference
+
+ protected LocationReportRequest createLRR(ClientSLgSession slgSession) throws Exception {
+ /*
+ < Location-Report-Request> ::= < Diameter Header: 8388621, REQ, PXY, 16777255 >
+
+ < Session-Id >
+ [ Vendor-Specific-Application-Id ]
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Host }
+ { Destination-Realm }
+ { Location-Event }
+ [ LCS-EPS-Client-Name ]
+ [ User-Name ]
+ [ MSISDN]
+ [ IMEI ]
+ [ Location-Estimate ]
+ [ Accuracy-Fulfilment-Indicator ]
+ [ Age-Of-Location-Estimate ]
+ [ Velocity-Estimate ]
+ [ EUTRAN-Positioning-Data ]
+ [ ECGI ]
+ [ GERAN-Positioning-Info ]
+ [ Cell-Global-Identity ]
+ [ UTRAN-Positioning-Info ]
+ [ Service-Area-Identity ]
+ [ LCS-Service-Type-ID ]
+ [ Pseudonym-Indicator ]
+ [ LCS-QoS-Class ]
+ [ Serving-Node ]
+ [ LRR-Flags ]
+ [ LCS-Reference-Number ]
+ [ Deferred-MT-LR-Data]
+ [ GMLC-Address ]
+ [ Periodic-LDR-Information ]
+ [ ESMLC-Cell-Info ]
+ [ 1xRTT-RCID ]
+ [ Civic-Address ]
+ [ Barometric-Pressure ]
+ *[ Supported-Features ]
+ *[ AVP ]
+ *[ Proxy-Info ]
+ *[ Route-Record ]
+
+ */
+ // Create LocationReportRequest
+ LocationReportRequest lrr = new LocationReportRequestImpl(slgSession.getSessions().get(0).createRequest(LocationReportRequest.code, getApplicationId(),
+ getServerRealmName()));
+ // < Location-Report-Request> ::= < Diameter Header: 8388621, REQ, PXY, 16777255 >
+
+ AvpSet reqSet = lrr.getMessage().getAvps();
+
+ if (reqSet.getAvp(Avp.VENDOR_SPECIFIC_APPLICATION_ID) == null) {
+ AvpSet vendorSpecificApplicationId = reqSet.addGroupedAvp(Avp.VENDOR_SPECIFIC_APPLICATION_ID, 0, false, false);
+ // 1* [ Vendor-Id ]
+ vendorSpecificApplicationId.addAvp(Avp.VENDOR_ID, getApplicationId().getVendorId(), true);
+ // 0*1{ Auth-Application-Id }
+ vendorSpecificApplicationId.addAvp(Avp.AUTH_APPLICATION_ID, getApplicationId().getAuthAppId(), true);
+ }
+
+ // { Auth-Session-State }
+ if (reqSet.getAvp(Avp.AUTH_SESSION_STATE) == null) {
+ reqSet.addAvp(Avp.AUTH_SESSION_STATE, 1);
+ }
+
+ // { Origin-Host }
+ reqSet.removeAvp(Avp.ORIGIN_HOST);
+ reqSet.addAvp(Avp.ORIGIN_HOST, getClientURI(), true);
+
+ // { Location-Event }
+ int locationEvent = getLocationEvent();
+ if (locationEvent != -1){
+ reqSet.addAvp(Avp.LOCATION_EVENT, locationEvent, 10415, true, false);
+ }
+
+ // { LCS-EPS-Client-Name }
+ AvpSet lcsEPSClientName = reqSet.addGroupedAvp(Avp.LCS_EPS_CLIENT_NAME, 10415, false, false);
+ String lcsNameString = getLCSNameString();
+ int lcsFormatIndicator = getLCSFormatIndicator();
+
+ if (lcsNameString != null){
+ lcsEPSClientName.addAvp(Avp.LCS_NAME_STRING, lcsNameString, 10415, false, false, false);
+ }
+ if (lcsFormatIndicator != -1){
+ lcsEPSClientName.addAvp(Avp.LCS_FORMAT_INDICATOR, lcsFormatIndicator, 10415, false, false);
+ }
+
+ // [ User-Name ] IE: IMSI
+ String userName = getUserName();
+ if (userName != null) {
+ reqSet.addAvp(Avp.USER_NAME, userName, 10415, true, false, false);
+ }
+
+ // [ MSISDN ]
+ byte[] msisdn = getMSISDN();
+ if (msisdn != null){
+ reqSet.addAvp(Avp.MSISDN, msisdn, 10415, true, false);
+ }
+
+ // [ IMEI ]
+ String imei = getIMEI();
+ if (imei != null){
+ reqSet.addAvp(Avp.TGPP_IMEI, imei, 10415, false, false, false);
+ }
+
+ // [ Location-Estimate ]
+ byte[] locationEstimate = getLocationEstimate();
+ if (locationEstimate != null){
+ reqSet.addAvp(Avp.LOCATION_ESTIMATE, locationEstimate, 10415, true, false);
+ }
+
+ // [ Accuracy-Fulfilment-Indicator ]
+ int accuracyFulfilmentIndicator = getAccuracyFulfilmentIndicator();
+ if (accuracyFulfilmentIndicator != -1){
+ reqSet.addAvp(Avp.ACCURACY_FULFILMENT_INDICATOR, accuracyFulfilmentIndicator, 10415, false, false);
+ }
+
+ // [ Age-Of-Location-Estimate ]
+ long ageOfLocationEstimate = getAgeOfLocationEstimate();
+ if (ageOfLocationEstimate != -1){
+ reqSet.addAvp(Avp.AGE_OF_LOCATION_ESTIMATE, ageOfLocationEstimate, 10415, false, false, true);
+ }
+
+ // [ Velocity-Estimate ]
+ byte[] velocityEstimate = getVelocityEstimate();
+ if (velocityEstimate != null){
+ reqSet.addAvp(Avp.VELOCITY_ESTIMATE, velocityEstimate, 10415, false, false);
+ }
+
+ // [ EUTRAN-Positioning-Data ]
+ byte[] eutranPositioningData = getEUTRANPositioningData();
+ if (eutranPositioningData != null){
+ reqSet.addAvp(Avp.EUTRAN_POSITIONING_DATA, eutranPositioningData, 10415, false, false);
+ }
+
+ // [ ECGI ]
+ byte[] ecgi = getECGI();
+ if (ecgi != null){
+ reqSet.addAvp(Avp.ECGI, ecgi, 10415, false, false);
+ }
+
+ // [ GERAN-Positioning-Info ]
+ AvpSet geranPositioningInfo = reqSet.addGroupedAvp(Avp.GERAN_POSITIONING_INFO, 10415, false, false);
+ byte[] geranPositioningData = getGERANPositioningData();
+ byte[] geranGanssPositioningData = getGERANGANSSPositioningData();
+
+ if (geranPositioningData != null){
+ geranPositioningInfo.addAvp(Avp.GERAN_POSITIONING_DATA, geranPositioningData, 10415, false, false);
+ }
+ if (geranGanssPositioningData != null){
+ geranPositioningInfo.addAvp(Avp.GERAN_GANSS_POSITIONING_DATA, geranGanssPositioningData, 10415, false, false);
+ }
+
+ // [ Cell-Global-Identity ]
+ byte[] cellGlobalIdentity = getCellGlobalIdentity();
+ if (cellGlobalIdentity != null){
+ reqSet.addAvp(Avp.CELL_GLOBAL_IDENTITY, cellGlobalIdentity, 10415, false, false);
+ }
+
+ // [ UTRAN-Positioning-Info ]
+ AvpSet utranPositioningInfo = reqSet.addGroupedAvp(Avp.UTRAN_POSITIONING_INFO, 10415, false, false);
+ byte[] utranPositioningData = getUTRANPositioningData();
+ byte[] utranGanssPositioningData = getUTRANGANSSPositioningData();
+
+ if (utranPositioningData != null){
+ utranPositioningInfo.addAvp(Avp.UTRAN_POSITIONING_DATA, utranPositioningData, 10415, false, false);
+ }
+ if (utranGanssPositioningData != null){
+ utranPositioningInfo.addAvp(Avp.UTRAN_GANSS_POSITIONING_DATA, utranGanssPositioningData, 10415, false, false);
+ }
+
+ // [ Service-Area-Identity ]
+ byte[] serviceAreaIdentity = getServiceAreaIdentity();
+ if (serviceAreaIdentity != null){
+ reqSet.addAvp(Avp.SERVICE_AREA_IDENTITY, serviceAreaIdentity, 10415, false, false);
+ }
+
+ // [ LCS-Service-Type-ID ]
+ long lscServiceTypeId = getLSCServiceTypeId();
+ if (lscServiceTypeId != -1){
+ reqSet.addAvp(Avp.LCS_SERVICE_TYPE_ID, lscServiceTypeId, 10415, false, false, true);
+ }
+
+ // [ Pseudonym-Indicator ]
+ int pseudonymIndicator = getPseudonymIndicator();
+ if (pseudonymIndicator != -1){
+ reqSet.addAvp(Avp.PSEUDONYM_INDICATOR, pseudonymIndicator, 10415, false, false);
+ }
+
+ // [ LCS-QoS-Class ]
+ int lcsQoSClass = getLCSQoSClass();
+ if (lcsQoSClass != -1){
+ reqSet.addAvp(Avp.LCS_QOS_CLASS, lcsQoSClass, 10415, false, false);
+ }
+
+ // [ Serving-Node ] IE: Target Serving Node Identity
+/*
+ Serving-Node ::=
+ [ SGSN-Number ]
+ [ SGSN-Name ]
+ [ SGSN-Realm ]
+ [ MME-Name ]
+ [ MME-Realm ]
+ [ MSC-Number ]
+ [ 3GPP-AAA-Server-Name ]
+ [ LCS-Capabilities-Sets ]
+ [ GMLC-Address ]
+ *[AVP]
+
+*/
+ AvpSet servingNode = reqSet.addGroupedAvp(Avp.SERVING_NODE, 10415, true, false);
+ byte[] sgsnNumber = getSGSNNumber();
+ String sgsnName= getSGSNName();
+ String sgsnRealm = getSGSNRealm();
+ String mmeName = getMMEName();
+ String mmeRealm = getMMERealm();
+ byte[] mscNumber = getMSCNumber();
+ String tgppAAAServerName= get3GPPAAAServerName();
+ long lcsCapabilitiesSet = getLCSCapabilitiesSets();
+ java.net.InetAddress gmlcAddress = getGMLCAddress();
+
+ if (sgsnNumber != null){
+ servingNode.addAvp(Avp.SGSN_NUMBER, sgsnNumber, 10415, false, false);
+ }
+ if (sgsnName != null){
+ servingNode.addAvp(Avp.SGSN_NAME, sgsnName, 10415, false, false, false);
+ }
+ if (sgsnRealm != null){
+ servingNode.addAvp(Avp.SGSN_REALM, sgsnRealm, 10415, false, false, false);
+ }
+ if (mmeName != null){
+ servingNode.addAvp(Avp.MME_NAME, mmeName, 10415, false, false, false);
+ }
+ if (mmeRealm != null){
+ servingNode.addAvp(Avp.MME_REALM, mmeRealm, 10415, false, false, false);
+ }
+ if (mscNumber != null){
+ servingNode.addAvp(Avp.MSC_NUMBER, mscNumber, 10415, false, false);
+ }
+ if (tgppAAAServerName != null){
+ servingNode.addAvp(Avp.TGPP_AAA_SERVER_NAME, tgppAAAServerName, 10415, false, false, false);
+ }
+ if (lcsCapabilitiesSet != -1){
+ servingNode.addAvp(Avp.LCS_CAPABILITIES_SETS, lcsCapabilitiesSet, 10415, false, false, true);
+ }
+ if (gmlcAddress != null){
+ servingNode.addAvp(Avp.GMLC_ADDRESS, gmlcAddress, 10415, false, false);
+ }
+
+ // [ LRR-Flags ]
+ long lrrFlags = getLRRFLags();
+ if (lrrFlags != -1){
+ reqSet.addAvp(Avp.LRR_FLAGS, lrrFlags, 10415, false, false, true);
+ }
+
+ // [ LCS-Reference-Number ]
+ byte[] lcsReferenceNumber = getLCSReferenceNumber();
+ if (lcsReferenceNumber != null){
+ reqSet.addAvp(Avp.LCS_REFERENCE_NUMBER, lcsReferenceNumber, 10415, true, false);
+ }
+
+ // [ Deferred-MT-LR-Data]
+ AvpSet deferredMTLRData = reqSet.addGroupedAvp(Avp.DEFERRED_MT_LR_DATA, 10415, false, false);
+ long deferredLocationType = getDeferredLocationType();
+ long terminationCause = getTerminationCause();
+
+ if (deferredLocationType != -1){
+ deferredMTLRData.addAvp(Avp.DEFERRED_LOCATION_TYPE, deferredLocationType, 10415, false, false, true);
+ }
+ if (terminationCause != -1){
+ deferredMTLRData.addAvp(Avp.TERMINATION_CAUSE_LCS, terminationCause, 10415, false, false, true);
+ }
+
+ // [ GMLC-Address ]
+ // attribute already defined for grouped AVP Serving Node
+ if (gmlcAddress != null){
+ reqSet.addAvp(Avp.GMLC_ADDRESS, gmlcAddress, 10415, false, false);
+ }
+
+ //[ Periodic-LDR-Information ]
+/*
+Periodic-LDR-Info ::=
+ { Reporting-Amount }
+ { Reporting-Interval }
+ *[ AVP ]
+Reporting-Interval x Rreporting-Amount shall not exceed 8639999 (99 days, 23 hours, 59 minutes and 59 seconds)
+for compatibility with OMA MLP and RLP.
+*/
+ AvpSet periodicLDRInfo = reqSet.addGroupedAvp(Avp.PERIODIC_LDR_INFORMATION, 10415, false, false);
+ long reportingAmount = getReportingAmount();
+ long reportingInterval = getReportingInterval();
+
+ if (reportingAmount != -1){
+ periodicLDRInfo.addAvp(Avp.REPORTING_AMOUNT, reportingAmount, 10415, false, false, true);
+ }
+ if (reportingInterval != -1){
+ periodicLDRInfo.addAvp(Avp.REPORTING_INTERVAL, reportingInterval, 10415, false, false, true);
+ }
+
+ // [ ESMLC-Cell-Info ]
+/*
+ ESMLC-Cell-Info ::=
+ [ ECGI ]
+ [ Cell-Portion-ID ]
+ *[ AVP ]
+*/
+ AvpSet esmlcCellInfo = reqSet.addGroupedAvp(Avp.ESMLC_CELL_INFO, 10415, false, false);
+ // ECGI attribute already defined
+ long cellPortionId = getCellPortionId();
+
+ if (ecgi != null){
+ esmlcCellInfo.addAvp(Avp.ECGI, ecgi, 10415, false, false);
+ }
+ if (cellPortionId != -1){
+ esmlcCellInfo.addAvp(Avp.CELL_PORTION_ID, cellPortionId, 10415, false, false, true);
+ }
+
+ // [ 1xRTT-RCID ]
+ byte[] onexRTTRCID = get1xRTTRCID();
+ if (onexRTTRCID != null){
+ reqSet.addAvp(Avp.ONEXRTT_RCID, onexRTTRCID, 10415, false, false);
+ }
+
+ // [ Civic-Address ]
+ String civicAddress = getCivicAddress();
+ if (civicAddress != null){
+ reqSet.addAvp(Avp.CIVIC_ADDRESS, civicAddress, 10415, false, false, false);
+ }
+
+ // [ Barometric-Pressure ]
+ long barometricPressure = getBarometricPressure();
+ if (barometricPressure != -1){
+ reqSet.addAvp(Avp.BAROMETRIC_PRESSURE, barometricPressure, 10415, false, false, true);
+ }
+
+ return lrr;
+ }
+
+}
diff --git a/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/AbstractDeferredServer.java b/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/AbstractDeferredServer.java
new file mode 100644
index 000000000..d83fcf547
--- /dev/null
+++ b/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/AbstractDeferredServer.java
@@ -0,0 +1,247 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.mobicents.diameter.stack.functional.slg;
+
+import org.jdiameter.api.ApplicationId;
+import org.jdiameter.api.Avp;
+import org.jdiameter.api.AvpSet;
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.Mode;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.Request;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.app.AppAnswerEvent;
+import org.jdiameter.api.app.AppRequestEvent;
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.slg.ClientSLgSession;
+import org.jdiameter.api.slg.ServerSLgSession;
+import org.jdiameter.api.slg.ServerSLgSessionListener;
+import org.jdiameter.api.slg.events.LocationReportAnswer;
+import org.jdiameter.api.slg.events.LocationReportRequest;
+import org.jdiameter.client.api.ISessionFactory;
+import org.jdiameter.common.impl.app.slg.LocationReportAnswerImpl;
+import org.jdiameter.common.impl.app.slg.SLgSessionFactoryImpl;
+import org.mobicents.diameter.stack.functional.TBase;
+
+import java.io.InputStream;
+import java.util.concurrent.TimeUnit;
+
+/**
+ *
+ * @author Fernando Mendioroz
+ *
+ */
+public abstract class AbstractDeferredServer extends TBase implements ServerSLgSessionListener {
+
+ // NOTE: implementing NetworkReqListener since its required for stack to
+ // know we support it... ech.
+
+ protected ServerSLgSession serverSLgSession;
+
+ public void init(InputStream configStream, String clientID) throws Exception {
+ try {
+ super.init(configStream, clientID, ApplicationId.createByAuthAppId(10415, 16777255));
+ SLgSessionFactoryImpl slgSessionFactory = new SLgSessionFactoryImpl(this.sessionFactory);
+ ((ISessionFactory) sessionFactory).registerAppFacory(ServerSLgSession.class, slgSessionFactory);
+ ((ISessionFactory) sessionFactory).registerAppFacory(ClientSLgSession.class, slgSessionFactory);
+ slgSessionFactory.setServerSessionListener(this);
+ } finally {
+ try {
+ configStream.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ // ----------- delegate methods so
+
+ public void start() throws IllegalDiameterStateException, InternalException {
+ stack.start();
+ }
+
+ public void start(Mode mode, long timeOut, TimeUnit timeUnit) throws IllegalDiameterStateException, InternalException {
+ stack.start(mode, timeOut, timeUnit);
+ }
+
+ public void stop(long timeOut, TimeUnit timeUnit, int disconnectCause) throws IllegalDiameterStateException, InternalException {
+ stack.stop(timeOut, timeUnit, disconnectCause);
+ }
+
+ public void stop(int disconnectCause) {
+ stack.stop(disconnectCause);
+ }
+
+ public void doOtherEvent(AppSession session, AppRequestEvent request, AppAnswerEvent answer) throws InternalException, IllegalDiameterStateException,
+ RouteException,
+ OverloadException {
+ fail("Received \"Other\" event, request[" + request + "], answer[" + answer + "], on session[" + session + "]", null);
+ }
+
+ public void doLocationReportRequestEvent(ServerSLgSession session, LocationReportRequest request) throws InternalException, IllegalDiameterStateException,
+ RouteException, OverloadException {
+ fail("Received \"LRR\" event, request[" + request + "], on session[" + session + "]", null);
+ }
+ // -------- conf
+
+ public String getSessionId() {
+ return this.serverSLgSession.getSessionId();
+ }
+
+ public void fetchSession(String sessionId) throws InternalException {
+ this.serverSLgSession = stack.getSession(sessionId, ServerSLgSession.class);
+ }
+
+ public ServerSLgSession getSession() {
+ return this.serverSLgSession;
+ }
+
+ // Attributes for Location Report Answer (LRA)
+ protected abstract java.net.InetAddress getGMLCAddress();
+ protected abstract long getLRAFLags();
+ protected abstract int getPrioritizedListIndicator();
+ protected abstract byte[] getVisitedPLMNId();
+ protected abstract int getPeriodicLocationSupportIndicator();
+ protected abstract byte[] getLCSReferenceNumber();
+
+ // ----------- 3GPP TS 29.172 reference
+
+ public LocationReportAnswer createLRA(LocationReportRequest lrr, long resultCode) throws Exception {
+ /*
+ < Location-Report-Answer > ::= < Diameter Header: 8388621, PXY, 16777255>
+
+ < Session-Id >
+ [ Vendor-Specific-Application-Id ]
+ [ Result-Code ]
+ [ Experimental-Result ]
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ [ GMLC-Address ]
+ [ LRA-Flags ]
+ [ Reporting-PLMN-List ]
+ [ LCS-Reference-Number ]
+ *[ Supported-Features ]
+ *[ AVP ]
+ *[ Failed-AVP ]
+ *[ Proxy-Info ]
+ *[ Route-Record ]
+
+ */
+ LocationReportAnswer lra = new LocationReportAnswerImpl((Request) lrr.getMessage(), resultCode);
+
+ AvpSet reqSet = lrr.getMessage().getAvps();
+ AvpSet set = lra.getMessage().getAvps();
+ set.removeAvp(Avp.DESTINATION_HOST);
+ set.removeAvp(Avp.DESTINATION_REALM);
+ set.addAvp(reqSet.getAvp(Avp.AUTH_APPLICATION_ID));
+
+ // { Vendor-Specific-Application-Id }
+ if (set.getAvp(Avp.VENDOR_SPECIFIC_APPLICATION_ID) == null) {
+ AvpSet vendorSpecificApplicationId = set.addGroupedAvp(Avp.VENDOR_SPECIFIC_APPLICATION_ID, 0, false, false);
+ // 1* [ Vendor-Id ]
+ vendorSpecificApplicationId.addAvp(Avp.VENDOR_ID, getApplicationId().getVendorId(), true);
+ // 0*1{ Auth-Application-Id }
+ vendorSpecificApplicationId.addAvp(Avp.AUTH_APPLICATION_ID, getApplicationId().getAuthAppId(), true);
+ }
+ // [ Result-Code ]
+ // [ Experimental-Result ]
+ // { Auth-Session-State }
+ if (set.getAvp(Avp.AUTH_SESSION_STATE) == null) {
+ set.addAvp(Avp.AUTH_SESSION_STATE, 1);
+ }
+
+ //[ GMLC-Address ]
+ java.net.InetAddress gmlcAddress = getGMLCAddress();
+ if (gmlcAddress != null){
+ set.addAvp(Avp.GMLC_ADDRESS, gmlcAddress, 10415, false, false);
+ }
+
+ // [ LRA-Flags ]
+ long lraFlags = getLRAFLags();
+ if (lraFlags != -1){
+ set.addAvp(Avp.LRA_FLAGS, lraFlags, 10415, false, false, true);
+ }
+
+ //[ Reporting-PLMN-List ]
+/*
+ Reporting-PLMN-List ::=
+ 1*20{ PLMN-ID-List }
+ [ Prioritized-List-Indicator ]
+ *[ AVP ]
+
+ PLMN-ID-List ::=
+ { Visited-PLMN-Id }
+ [ Periodic-Location-Support-Indicator ]
+ *[ AVP ]
+*/
+ AvpSet reportingPLMNList = set.addGroupedAvp(Avp.REPORTING_PLMN_LIST, 10415, false, false);
+ int prioritizedListIndicator = getPrioritizedListIndicator();
+ AvpSet plmnIdList = set.addGroupedAvp(Avp.PLMN_ID_LIST, 10415, false, false);
+ byte[] visitedPLMNId = getVisitedPLMNId();
+ int periodicLocationSupportIndicator = getPeriodicLocationSupportIndicator();
+
+ if (prioritizedListIndicator != -1){
+ reportingPLMNList.addAvp(Avp.PRIORITIZED_LIST_INDICATOR, prioritizedListIndicator, 10415, false, false);
+ }
+ if (plmnIdList != null){
+ reportingPLMNList.addAvp(plmnIdList);
+ }
+ if (visitedPLMNId != null){
+ plmnIdList.addAvp(Avp.VISITED_PLMN_ID, visitedPLMNId, 10415, false, false);
+ }
+ if (periodicLocationSupportIndicator != -1){
+ plmnIdList.addAvp(Avp.PERIODIC_LOCATION_SUPPORT_INDICATOR, periodicLocationSupportIndicator, 10415, false, false);
+ }
+
+ // [ LCS-Reference-Number ]
+ byte[] lcsReferenceNumber = getLCSReferenceNumber();
+ if (lcsReferenceNumber != null){
+ set.addAvp(Avp.LCS_REFERENCE_NUMBER, lcsReferenceNumber, 10415, true, false);
+ }
+
+ return lra;
+ }
+
+}
\ No newline at end of file
diff --git a/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/AbstractImmediateClient.java b/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/AbstractImmediateClient.java
new file mode 100644
index 000000000..1ff3b5afb
--- /dev/null
+++ b/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/AbstractImmediateClient.java
@@ -0,0 +1,472 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.mobicents.diameter.stack.functional.slg;
+
+import java.io.InputStream;
+import java.util.concurrent.TimeUnit;
+
+import org.jdiameter.api.ApplicationId;
+import org.jdiameter.api.Avp;
+import org.jdiameter.api.AvpSet;
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.Mode;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.app.AppAnswerEvent;
+import org.jdiameter.api.app.AppRequestEvent;
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.slg.ClientSLgSession;
+import org.jdiameter.api.slg.ClientSLgSessionListener;
+import org.jdiameter.api.slg.ServerSLgSession;
+import org.jdiameter.api.slg.events.ProvideLocationRequest;
+import org.jdiameter.api.slg.events.ProvideLocationAnswer;
+import org.jdiameter.api.slg.events.LocationReportRequest;
+import org.jdiameter.api.slg.events.LocationReportAnswer;
+import org.jdiameter.client.api.ISessionFactory;
+import org.jdiameter.common.impl.app.slg.ProvideLocationRequestImpl;
+import org.jdiameter.common.impl.app.slg.SLgSessionFactoryImpl;
+import org.mobicents.diameter.stack.functional.TBase;
+
+/**
+ *
+ *@author Fernando Mendioroz
+ *
+ */
+public abstract class AbstractImmediateClient extends TBase implements ClientSLgSessionListener {
+
+ // NOTE: implementing NetworkReqListener since its required for stack to
+ // know we support it... ech.
+
+ protected ClientSLgSession clientSLgSession;
+
+ public void init(InputStream configStream, String clientID) throws Exception {
+ try {
+ super.init(configStream, clientID, ApplicationId.createByAuthAppId(10415, 16777255));
+ SLgSessionFactoryImpl sLgSessionFactory = new SLgSessionFactoryImpl(this.sessionFactory);
+ ((ISessionFactory) sessionFactory).registerAppFacory(ServerSLgSession.class, sLgSessionFactory);
+ ((ISessionFactory) sessionFactory).registerAppFacory(ClientSLgSession.class, sLgSessionFactory);
+
+ sLgSessionFactory .setClientSessionListener(this);
+
+ this.clientSLgSession = ((ISessionFactory) this.sessionFactory).getNewAppSession(this.sessionFactory.getSessionId("xx-SLg-TESTxx"), getApplicationId(),
+ ClientSLgSession.class, null);
+ } finally {
+ try {
+ configStream.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ // ----------- delegate methods so
+
+ public void start() throws IllegalDiameterStateException, InternalException {
+ stack.start();
+ }
+
+ public void start(Mode mode, long timeOut, TimeUnit timeUnit) throws IllegalDiameterStateException, InternalException {
+ stack.start(mode, timeOut, timeUnit);
+ }
+
+ public void stop(long timeOut, TimeUnit timeUnit, int disconnectCause) throws IllegalDiameterStateException, InternalException {
+ stack.stop(timeOut, timeUnit, disconnectCause);
+ }
+
+ public void stop(int disconnectCause) {
+ stack.stop(disconnectCause);
+ }
+
+ // ------- def methods, to fail :)
+
+ public void doOtherEvent(AppSession session, AppRequestEvent request, AppAnswerEvent answer) throws InternalException, IllegalDiameterStateException,
+ RouteException, OverloadException {
+ fail("Received \"Other\" event, request[" + request + "], answer[" + answer + "], on session[" + session + "]", null);
+ }
+
+ public void doProvideLocationAnswerEvent(ClientSLgSession session, ProvideLocationRequest request, ProvideLocationAnswer answer) throws InternalException,
+ IllegalDiameterStateException, RouteException, OverloadException {
+ fail("Received \"PLA\" event, request[" + request + "], answer[" + answer + "], on session[" + session + "]", null);
+ }
+
+ public void doLocationReportAnswerEvent(ClientSLgSession session, LocationReportRequest request, LocationReportAnswer answer) throws InternalException,
+ IllegalDiameterStateException, RouteException, OverloadException {
+ fail("Received \"LRA\" event, request[" + request + "], answer[" + answer + "], on session[" + session + "]", null);
+ }
+
+ // ----------- conf parts
+
+ public String getSessionId() {
+ return this.clientSLgSession.getSessionId();
+ }
+
+ public ClientSLgSession getSession() {
+ return this.clientSLgSession;
+ }
+
+ // Attributes for Provide Location Request (PLR)
+ protected abstract int getSLgLocationType();
+ protected abstract String getUserName(); // IE: IMSI
+ protected abstract byte[] getMSISDN();
+ protected abstract String getIMEI();
+ protected abstract String getLCSNameString();
+ protected abstract int getLCSFormatIndicator();
+ protected abstract int getLCSClientType();
+ protected abstract String getLCSRequestorIdString();
+ protected abstract int getReqLCSFormatIndicator();
+ protected abstract long getLCSPriority();
+ protected abstract int getLCSQoSClass();
+ protected abstract long getHorizontalAccuracy();
+ protected abstract long getVerticalAccuracy();
+ protected abstract int getVerticalRequested();
+ protected abstract int getResponseTime();
+ protected abstract int getVelocityRequested();
+ protected abstract long getSupportedGADShapes();
+ protected abstract long getLSCServiceTypeId();
+ protected abstract String getLCSCodeword();
+ protected abstract String getServiceSelection(); // IE: APN
+ protected abstract int getLCSPrivacyCheckSession();
+ protected abstract int getLCSPrivacyCheckNonSession();
+ protected abstract long getDeferredLocationType();
+ protected abstract byte[] getLCSReferenceNumber();
+ protected abstract int getOccurrenceInfo();
+ protected abstract long getIntervalTime();
+ protected abstract long getAreaType();
+ protected abstract byte[] getAreaIdentification();
+ protected abstract java.net.InetAddress getGMLCAddress();
+ protected abstract long getPLRFLags();
+ protected abstract long getReportingAmount();
+ protected abstract long getReportingInterval();
+ protected abstract int getPrioritizedListIndicator();
+ protected abstract byte[] getVisitedPLMNId();
+ protected abstract int getPeriodicLocationSupportIndicator();
+
+ // ----------- 3GPP TS 29.172 reference
+
+ protected ProvideLocationRequest createPLR(ClientSLgSession slgSession) throws Exception {
+ /*
+ < Provide-Location-Request> ::= < Diameter Header: 8388620, REQ, PXY, 16777255 >
+
+ < Session-Id >
+ [ Vendor-Specific-Application-Id ]
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ { Destination-Host }
+ { Destination-Realm }
+ { SLg-Location-Type }
+ [ User-Name ]
+ [ MSISDN ]
+ [ IMEI ]
+ { LCS-EPS-Client-Name }
+ { LCS-Client-Type }
+ [ LCS-Requestor-Name ]
+ [ LCS-Priority ]
+ [ LCS-QoS ]
+ [ Velocity-Requested ]
+ [ LCS-Supported-GAD-Shapes ]
+ [ LCS-Service-Type-ID ]
+ [ LCS-Codeword ]
+ [ LCS-Privacy-Check-Non-Session ]
+ [ LCS-Privacy-Check-Session ]
+ [ Service-Selection ]
+ [ Deferred-Location-Type ]
+ [ PLR-Flags ]
+ *[ Supported-Features ]
+ *[ AVP ]
+ *[ Proxy-Info ]
+ *[ Route-Record ]
+ Note: plus all extra AVPs defined in Table 6.2.2-1: Provide Subscriber Location Request, i.e.
+ [ LCS-Reference-Number ]
+ [ Area-Event-Info ]
+ [ GMLC-Address ]
+ [ Periodic-LDR-Information ]
+ [ Reporting-PLMN-List ]
+ */
+ // Create ProvideLocationRequest
+ ProvideLocationRequest plr = new ProvideLocationRequestImpl(slgSession.getSessions().get(0).createRequest(ProvideLocationRequest.code, getApplicationId(),
+ getServerRealmName()));
+ // < Provide-Location-Request> ::= < Diameter Header: 8388620, REQ, PXY, 16777255 >
+
+ AvpSet reqSet = plr.getMessage().getAvps();
+
+ if (reqSet.getAvp(Avp.VENDOR_SPECIFIC_APPLICATION_ID) == null) {
+ AvpSet vendorSpecificApplicationId = reqSet.addGroupedAvp(Avp.VENDOR_SPECIFIC_APPLICATION_ID, 0, false, false);
+ // 1* [ Vendor-Id ]
+ vendorSpecificApplicationId.addAvp(Avp.VENDOR_ID, getApplicationId().getVendorId(), true);
+ // 0*1{ Auth-Application-Id }
+ vendorSpecificApplicationId.addAvp(Avp.AUTH_APPLICATION_ID, getApplicationId().getAuthAppId(), true);
+ }
+
+ // { Auth-Session-State }
+ if (reqSet.getAvp(Avp.AUTH_SESSION_STATE) == null) {
+ reqSet.addAvp(Avp.AUTH_SESSION_STATE, 1);
+ }
+
+ // { Origin-Host }
+ reqSet.removeAvp(Avp.ORIGIN_HOST);
+ reqSet.addAvp(Avp.ORIGIN_HOST, getClientURI(), true);
+
+
+ // { SLg-Location-Type }
+ int slgLocationType = getSLgLocationType();
+ if (slgLocationType != -1){
+ reqSet.addAvp(Avp.SLG_LOCATION_TYPE, slgLocationType, 10415, true, false);
+ }
+
+ // [ User-Name ] IE: IMSI
+ String userName = getUserName();
+ if (userName != null) {
+ reqSet.addAvp(Avp.USER_NAME, userName, 10415, true, false, false);
+ }
+
+ // [ MSISDN ]
+ byte[] msisdn = getMSISDN();
+ if (msisdn != null){
+ reqSet.addAvp(Avp.MSISDN, msisdn, 10415, true, false);
+ }
+
+ // [ IMEI ]
+ String imei = getIMEI();
+ if (imei != null){
+ reqSet.addAvp(Avp.TGPP_IMEI, imei, 10415, false, false, false);
+ }
+
+ // { LCS-EPS-Client-Name }
+ AvpSet lcsEPSClientName = reqSet.addGroupedAvp(Avp.LCS_EPS_CLIENT_NAME, 10415, false, false);
+ String lcsNameString = getLCSNameString();
+ int lcsFormatIndicator = getLCSFormatIndicator();
+
+ if (lcsNameString != null){
+ lcsEPSClientName.addAvp(Avp.LCS_NAME_STRING, lcsNameString, 10415, false, false, false);
+ }
+ if (lcsFormatIndicator != -1){
+ lcsEPSClientName.addAvp(Avp.LCS_FORMAT_INDICATOR, lcsFormatIndicator, 10415, false, false);
+ }
+
+ // { LCS-Client-Type }
+ int lcsClientType = getLCSClientType();
+ if (lcsClientType != -1){
+ reqSet.addAvp(Avp.LCS_CLIENT_TYPE, lcsClientType, 10415, false, false);
+ }
+
+ // [ LCS-Requestor-Name ]
+ AvpSet lcsRequestorName = reqSet.addGroupedAvp(Avp.LCS_REQUESTOR_NAME, 10415, false, false);
+ String lcsRequestorIdString = getLCSRequestorIdString();
+ int reqLCSFormatIndicator = getReqLCSFormatIndicator();
+
+ if (lcsRequestorIdString != null){
+ lcsRequestorName.addAvp(Avp.LCS_REQUESTOR_ID_STRING, lcsRequestorIdString, 10415, false, false, false);
+ }
+ if (reqLCSFormatIndicator != -1){
+ lcsRequestorName.addAvp(Avp.LCS_FORMAT_INDICATOR, reqLCSFormatIndicator, 10415, false, false);
+ }
+
+ // [ LCS-Priority ]
+ long lcsPriority = getLCSPriority();
+ if (lcsPriority != -1){
+ reqSet.addAvp(Avp.LCS_PRIORITY, lcsPriority, 10415, false, false, true);
+ }
+
+ // [ LCS-QoS ]
+ AvpSet lcsQoS = reqSet.addGroupedAvp(Avp.LCS_QOS, 10415, false, false);
+ int lcsQoSClass = getLCSQoSClass();
+ long horizontalAccuracy = getHorizontalAccuracy();
+ long verticalAccuracy = getVerticalAccuracy();
+ int verticalRequested = getVerticalRequested();
+ int responseTime = getResponseTime();
+
+ if (lcsQoSClass != -1){
+ lcsQoS.addAvp(Avp.LCS_QOS_CLASS, lcsQoSClass, 10415, false, false);
+ }
+ if (horizontalAccuracy != -1){
+ lcsQoS.addAvp(Avp.HORIZONTAL_ACCURACY, horizontalAccuracy, 10415, false, false, true);
+ }
+ if(verticalAccuracy != -1){
+ lcsQoS.addAvp(Avp.VERTICAL_ACCURACY, verticalAccuracy, 10415, false, false, true);
+ }
+ if(verticalRequested != -1){
+ lcsQoS.addAvp(Avp.VERTICAL_REQUESTED, verticalRequested, 10415, false, false);
+ }
+ if(responseTime != -1){
+ lcsQoS.addAvp(Avp.RESPONSE_TIME, responseTime, 10415, false, false);
+ }
+
+ // [ Velocity-Requested ]
+ int velocityRequested = getVelocityRequested();
+ if (velocityRequested != -1){
+ reqSet.addAvp(Avp.VELOCITY_REQUESTED, velocityRequested, 10415, false, false);
+ }
+
+ // [ LCS-Supported-GAD-Shapes ]
+ long supportedGADShapes = getSupportedGADShapes();
+ if (supportedGADShapes != -1){
+ reqSet.addAvp(Avp.SUPPORTED_GAD_SHAPES, supportedGADShapes, 10415, false, false, true);
+ }
+
+ // [ LCS-Service-Type-ID ]
+ long lscServiceTypeId = getLSCServiceTypeId();
+ if (lscServiceTypeId != -1){
+ reqSet.addAvp(Avp.LCS_SERVICE_TYPE_ID, lscServiceTypeId, 10415, true, false, true);
+ }
+
+ // [ LCS-Codeword ]
+ String lcsCodeword = getLCSCodeword();
+ if (lcsCodeword != null){
+ reqSet.addAvp(Avp.LCS_CODEWORD, lcsCodeword, 10415, false, false, false);
+ }
+
+ //[ Service-Selection ]
+ String serviceSelection = getServiceSelection(); // IE: APN
+ if (serviceSelection != null){
+ reqSet.addAvp(Avp.SERVICE_SELECTION, serviceSelection, false, false, false);
+ }
+
+ // [ LCS-Privacy-Check-Session ] // IE: Session-Related Privacy Check
+ AvpSet lcsPrivacyCheckSession = reqSet.addGroupedAvp(Avp.LCS_PRIVACY_CHECK_SESSION, 10415, false, false);
+ int lcsPrivacyCheck = getLCSPrivacyCheckSession();
+
+ if (lcsPrivacyCheck != -1){
+ lcsPrivacyCheckSession.addAvp(Avp.LCS_PRIVACY_CHECK, lcsPrivacyCheck, 10415, false, false);
+ }
+
+ // [ LCS-Privacy-Check-Non-Session ] // IE: Non-Session-Related Privacy Check
+ AvpSet lcsPrivacyCheckNonSession = reqSet.addGroupedAvp(Avp.LCS_PRIVACY_CHECK_SESSION, 10415, false, false);
+ int lcsPrivacyCheckNS = getLCSPrivacyCheckNonSession();
+
+ if (lcsPrivacyCheckNS != -1){
+ lcsPrivacyCheckNonSession.addAvp(Avp.LCS_PRIVACY_CHECK, lcsPrivacyCheck, 10415, false, false);
+ }
+
+ // [ Deferred-Location-Type ]
+ long deferredLocationType = getDeferredLocationType();
+ if (deferredLocationType != -1){
+ reqSet.addAvp(Avp.DEFERRED_LOCATION_TYPE, deferredLocationType, 10415, false, false, true);
+ }
+
+ // [ LCS-Reference-Number ]
+ byte[] lcsReferenceNumber = getLCSReferenceNumber();
+ if (lcsReferenceNumber != null){
+ reqSet.addAvp(Avp.LCS_REFERENCE_NUMBER, lcsReferenceNumber, 10415, true, false);
+ }
+
+ // [ Area-Event-Info ]
+/*
+ Area-Event-Info AVP of type grouped, includes:
+ Area-Definition, Occurrence-Info, Interval-Time
+ Area-Definition AVP of type grouped, includes:
+ Area-Type, Area-Identification
+*/
+ AvpSet areaEventInfo = reqSet.addGroupedAvp(Avp.AREA_EVENT_INFO, 10415, false, false);
+ int occurrenceInfo = getOccurrenceInfo();
+ long intervalTime = getIntervalTime();
+ AvpSet areaDefinition =reqSet.addGroupedAvp(Avp.AREA_DEFINITION, 10415, false, false);
+ long areaType = getAreaType();
+ byte[] areaIdentification = getAreaIdentification();
+
+ if (occurrenceInfo != -1){
+ areaEventInfo.addAvp(Avp.OCCURRENCE_INFO, occurrenceInfo, 10415, false, false);
+ }
+ if (intervalTime != -1){
+ areaEventInfo.addAvp(Avp.INTERVAL_TIME, intervalTime, 10415, false, false, true);
+ }
+ if (areaDefinition != null){
+ areaEventInfo.addAvp(areaDefinition);
+ }
+ if (areaType != -1){
+ areaDefinition.addAvp(Avp.AREA_TYPE, areaType, 10415, false, false, true);
+ }
+ if (areaIdentification != null){
+ areaDefinition.addAvp(Avp.AREA_IDENTIFICATION, areaIdentification, 10415, false, false);
+ }
+
+
+ //[ GMLC-Address ]
+ java.net.InetAddress gmlcAddress = getGMLCAddress();
+ if (gmlcAddress != null){
+ reqSet.addAvp(Avp.GMLC_ADDRESS, gmlcAddress, 10415, false, false);
+ }
+
+ //[ PLR-Flags ]
+ long plrfLags = getPLRFLags();
+ if (plrfLags != -1){
+ reqSet.addAvp(Avp.PLR_FLAGS, plrfLags, 10415, false, false, true);
+ }
+
+ // [ Periodic-LDR-Information ]
+ AvpSet periodicLDRInformation = reqSet.addGroupedAvp(Avp.AREA_EVENT_INFO, 10415, false, false);
+ long reportingAmount = getReportingAmount();
+ long reportingInterval = getReportingInterval();
+
+ if (reportingAmount != -1){
+ periodicLDRInformation.addAvp(Avp.REPORTING_AMOUNT, reportingAmount, 10415, false, false, true);
+ }
+ if (reportingInterval != -1){
+ periodicLDRInformation.addAvp(Avp.REPORTING_INTERVAL, reportingInterval, 10415, false, false, true);
+ }
+
+ // [ Reporting-PLMN-List ]
+ AvpSet reportingPLMNList = reqSet.addGroupedAvp(Avp.REPORTING_PLMN_LIST, 10415, false, false);
+ int prioritizedListIndicator = getPrioritizedListIndicator();
+ AvpSet plmnIdList = reqSet.addGroupedAvp(Avp.PLMN_ID_LIST, 10415, false, false);
+ byte[] visitedPLMNId = getVisitedPLMNId();
+ int periodicLocationSupportIndicator = getPeriodicLocationSupportIndicator();
+
+ if (prioritizedListIndicator != -1){
+ reportingPLMNList.addAvp(Avp.PRIORITIZED_LIST_INDICATOR, prioritizedListIndicator, 10415, false, false);
+ }
+ if (plmnIdList != null){
+ reportingPLMNList.addAvp(plmnIdList);
+ }
+ if (visitedPLMNId != null){
+ plmnIdList.addAvp(Avp.VISITED_PLMN_ID, visitedPLMNId, 10415, false, false);
+ }
+ if (periodicLocationSupportIndicator != -1){
+ plmnIdList.addAvp(Avp.PERIODIC_LOCATION_SUPPORT_INDICATOR, periodicLocationSupportIndicator, 10415, false, false);
+ }
+
+ return plr;
+ }
+
+}
diff --git a/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/AbstractImmediateServer.java b/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/AbstractImmediateServer.java
new file mode 100644
index 000000000..7b7eb66b2
--- /dev/null
+++ b/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/AbstractImmediateServer.java
@@ -0,0 +1,388 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.mobicents.diameter.stack.functional.slg;
+
+import java.io.InputStream;
+import java.util.concurrent.TimeUnit;
+
+import org.jdiameter.api.ApplicationId;
+import org.jdiameter.api.Avp;
+import org.jdiameter.api.AvpSet;
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.Mode;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.Request;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.app.AppAnswerEvent;
+import org.jdiameter.api.app.AppRequestEvent;
+import org.jdiameter.api.app.AppSession;
+import org.jdiameter.api.slg.ClientSLgSession;
+import org.jdiameter.api.slg.ServerSLgSession;
+import org.jdiameter.api.slg.ServerSLgSessionListener;
+import org.jdiameter.api.slg.events.ProvideLocationRequest;
+import org.jdiameter.api.slg.events.ProvideLocationAnswer;
+import org.jdiameter.client.api.ISessionFactory;
+import org.jdiameter.common.impl.app.slg.ProvideLocationAnswerImpl;
+import org.jdiameter.common.impl.app.slg.SLgSessionFactoryImpl;
+import org.mobicents.diameter.stack.functional.TBase;
+
+/**
+ *
+ * @author Fernando Mendioroz
+ *
+ */
+public abstract class AbstractImmediateServer extends TBase implements ServerSLgSessionListener {
+
+ // NOTE: implementing NetworkReqListener since its required for stack to
+ // know we support it... ech.
+
+ protected ServerSLgSession serverSLgSession;
+
+ public void init(InputStream configStream, String clientID) throws Exception {
+ try {
+ super.init(configStream, clientID, ApplicationId.createByAuthAppId(10415, 16777255));
+ SLgSessionFactoryImpl slgSessionFactory = new SLgSessionFactoryImpl(this.sessionFactory);
+ ((ISessionFactory) sessionFactory).registerAppFacory(ServerSLgSession.class, slgSessionFactory);
+ ((ISessionFactory) sessionFactory).registerAppFacory(ClientSLgSession.class, slgSessionFactory);
+ slgSessionFactory.setServerSessionListener(this);
+ } finally {
+ try {
+ configStream.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ // ----------- delegate methods so
+
+ public void start() throws IllegalDiameterStateException, InternalException {
+ stack.start();
+ }
+
+ public void start(Mode mode, long timeOut, TimeUnit timeUnit) throws IllegalDiameterStateException, InternalException {
+ stack.start(mode, timeOut, timeUnit);
+ }
+
+ public void stop(long timeOut, TimeUnit timeUnit, int disconnectCause) throws IllegalDiameterStateException, InternalException {
+ stack.stop(timeOut, timeUnit, disconnectCause);
+ }
+
+ public void stop(int disconnectCause) {
+ stack.stop(disconnectCause);
+ }
+
+ public void doOtherEvent(AppSession session, AppRequestEvent request, AppAnswerEvent answer) throws InternalException, IllegalDiameterStateException,
+ RouteException,
+ OverloadException {
+ fail("Received \"Other\" event, request[" + request + "], answer[" + answer + "], on session[" + session + "]", null);
+ }
+
+ public void doProvideLocationRequestEvent(ServerSLgSession session, ProvideLocationRequest request) throws InternalException, IllegalDiameterStateException,
+ RouteException, OverloadException {
+ fail("Received \"PLR\" event, request[" + request + "], on session[" + session + "]", null);
+ }
+ // -------- conf
+
+ public String getSessionId() {
+ return this.serverSLgSession.getSessionId();
+ }
+
+ public void fetchSession(String sessionId) throws InternalException {
+ this.serverSLgSession = stack.getSession(sessionId, ServerSLgSession.class);
+ }
+
+ public ServerSLgSession getSession() {
+ return this.serverSLgSession;
+ }
+
+ // Attributes for Provide Location Answer (PLA)
+ protected abstract byte[] getLocationEstimate();
+ protected abstract int getAccuracyFulfilmentIndicator();
+ protected abstract long getAgeOfLocationEstimate();
+ protected abstract byte[] getVelocityEstimate();
+ protected abstract byte[] getEUTRANPositioningData();
+ protected abstract byte[] getECGI();
+ protected abstract byte[] getGERANPositioningData();
+ protected abstract byte[] getGERANGANSSPositioningData();
+ protected abstract byte[] getCellGlobalIdentity();
+ protected abstract byte[] getUTRANPositioningData();
+ protected abstract byte[] getUTRANGANSSPositioningData();
+ protected abstract byte[] getServiceAreaIdentity();
+ protected abstract byte[] getSGSNNumber();
+ protected abstract String getSGSNName();
+ protected abstract String getSGSNRealm();
+ protected abstract String getMMEName();
+ protected abstract String getMMERealm();
+ protected abstract byte[] getMSCNumber();
+ protected abstract String get3GPPAAAServerName();
+ protected abstract long getLCSCapabilitiesSets();
+ protected abstract long getPLAFLags();
+ protected abstract long getCellPortionId();
+ protected abstract String getCivicAddress();
+ protected abstract long getBarometricPressure();
+ protected abstract java.net.InetAddress getGMLCAddress();
+
+ // ----------- 3GPP TS 29.172 reference
+
+ public ProvideLocationAnswer createPLA(ProvideLocationRequest plr, long resultCode) throws Exception {
+ /*
+ < Provide-Location-Answer > ::= < Diameter Header: 8388620, PXY, 16777255 >
+ < Session-Id >
+ [ Vendor-Specific-Application-Id ]
+ [ Result-Code ]
+ [ Experimental-Result ]
+ { Auth-Session-State }
+ { Origin-Host }
+ { Origin-Realm }
+ [ Location-Estimate ]
+ [ Accuracy-Fulfilment-Indicator ]
+ [ Age-Of-Location-Estimate]
+ [ Velocity-Estimate ]
+ [ EUTRAN-Positioning-Data]
+ [ ECGI ]
+ [ GERAN-Positioning-Info ]
+ [ Cell-Global-Identity ]
+ [ UTRAN-Positioning-Info ]
+ [ Service-Area-Identity ]
+ [ Serving-Node ]
+ [ PLA-Flags ]
+ [ ESMLC-Cell-Info ]
+ [ Civic-Address ]
+ [ Barometric-Pressure ]
+ *[ Supported-Features ]
+ *[ AVP ]
+ *[ Failed-AVP ]
+ *[ Proxy-Info ]
+ *[ Route-Record ]
+
+ */
+ ProvideLocationAnswer pla = new ProvideLocationAnswerImpl((Request) plr.getMessage(), resultCode);
+
+ AvpSet reqSet = plr.getMessage().getAvps();
+ AvpSet set = pla.getMessage().getAvps();
+ set.removeAvp(Avp.DESTINATION_HOST);
+ set.removeAvp(Avp.DESTINATION_REALM);
+ set.addAvp(reqSet.getAvp(Avp.AUTH_APPLICATION_ID));
+
+ // { Vendor-Specific-Application-Id }
+ if (set.getAvp(Avp.VENDOR_SPECIFIC_APPLICATION_ID) == null) {
+ AvpSet vendorSpecificApplicationId = set.addGroupedAvp(Avp.VENDOR_SPECIFIC_APPLICATION_ID, 0, false, false);
+ // 1* [ Vendor-Id ]
+ vendorSpecificApplicationId.addAvp(Avp.VENDOR_ID, getApplicationId().getVendorId(), true);
+ // 0*1{ Auth-Application-Id }
+ vendorSpecificApplicationId.addAvp(Avp.AUTH_APPLICATION_ID, getApplicationId().getAuthAppId(), true);
+ }
+ // [ Result-Code ]
+ // [ Experimental-Result ]
+ // { Auth-Session-State }
+ if (set.getAvp(Avp.AUTH_SESSION_STATE) == null) {
+ set.addAvp(Avp.AUTH_SESSION_STATE, 1);
+ }
+
+ // [ Location-Estimate ]
+ byte[] locationEstimate = getLocationEstimate();
+ if (locationEstimate != null){
+ set.addAvp(Avp.LOCATION_ESTIMATE, locationEstimate, 10415, true, false);
+ }
+
+ // [ Accuracy-Fulfilment-Indicator ]
+ int accuracyFulfilmentIndicator = getAccuracyFulfilmentIndicator();
+ if (accuracyFulfilmentIndicator != -1){
+ set.addAvp(Avp.ACCURACY_FULFILMENT_INDICATOR, accuracyFulfilmentIndicator, 10415, false, false);
+ }
+
+ // [ Age-Of-Location-Estimate ]
+ long ageOfLocationEstimate = getAgeOfLocationEstimate();
+ if (ageOfLocationEstimate != -1){
+ set.addAvp(Avp.AGE_OF_LOCATION_ESTIMATE, ageOfLocationEstimate, 10415, false, false, true);
+ }
+
+ // [ Velocity-Estimate ]
+ byte[] velocityEstimate = getVelocityEstimate();
+ if (velocityEstimate != null){
+ set.addAvp(Avp.VELOCITY_ESTIMATE, velocityEstimate, 10415, false, false);
+ }
+
+ // [ EUTRAN-Positioning-Data ]
+ byte[] eutranPositioningData = getEUTRANPositioningData();
+ if (eutranPositioningData != null){
+ set.addAvp(Avp.EUTRAN_POSITIONING_DATA, eutranPositioningData, 10415, false, false);
+ }
+
+ // [ ECGI ]
+ byte[] ecgi = getECGI();
+ if (ecgi != null){
+ set.addAvp(Avp.ECGI, ecgi, 10415, false, false);
+ }
+
+ // [ GERAN-Positioning-Info ]
+ AvpSet geranPositioningInfo = set.addGroupedAvp(Avp.GERAN_POSITIONING_INFO, 10415, false, false);
+ byte[] geranPositioningData = getGERANPositioningData();
+ byte[] geranGanssPositioningData = getGERANGANSSPositioningData();
+
+ if (geranPositioningData != null){
+ geranPositioningInfo.addAvp(Avp.GERAN_POSITIONING_DATA, geranPositioningData, 10415, false, false);
+ }
+ if (geranGanssPositioningData != null){
+ geranPositioningInfo.addAvp(Avp.GERAN_GANSS_POSITIONING_DATA, geranGanssPositioningData, 10415, false, false);
+ }
+
+ // [ Cell-Global-Identity ]
+ byte[] cellGlobalIdentity = getCellGlobalIdentity();
+ if (cellGlobalIdentity != null){
+ set.addAvp(Avp.CELL_GLOBAL_IDENTITY, cellGlobalIdentity, 10415, false, false);
+ }
+
+ // [ UTRAN-Positioning-Info ]
+ AvpSet utranPositioningInfo = set.addGroupedAvp(Avp.UTRAN_POSITIONING_INFO, 10415, false, false);
+ byte[] utranPositioningData = getUTRANPositioningData();
+ byte[] utranGanssPositioningData = getUTRANGANSSPositioningData();
+
+ if ( utranPositioningData != null){
+ utranPositioningInfo.addAvp(Avp.UTRAN_POSITIONING_DATA, utranPositioningData, 10415, false, false);
+ }
+ if ( utranGanssPositioningData != null){
+ utranPositioningInfo.addAvp(Avp.UTRAN_GANSS_POSITIONING_DATA, utranGanssPositioningData, 10415, false, false);
+ }
+
+ // [ Service-Area-Identity ]
+ byte[] serviceAreaIdentity = getServiceAreaIdentity();
+ if (serviceAreaIdentity != null){
+ set.addAvp(Avp.SERVICE_AREA_IDENTITY, serviceAreaIdentity, 10415, false, false);
+ }
+
+// [ Serving-Node ] IE: Target Serving Node Identity
+/*
+ Serving-Node ::=
+ [ SGSN-Number ]
+ [ SGSN-Name ]
+ [ SGSN-Realm ]
+ [ MME-Name ]
+ [ MME-Realm ]
+ [ MSC-Number ]
+ [ 3GPP-AAA-Server-Name ]
+ [ LCS-Capabilities-Sets ]
+ [ GMLC-Address ]
+ *[AVP]
+*/
+ AvpSet servingNode = set.addGroupedAvp(Avp.SERVING_NODE, 10415, false, false);
+ byte[] sgsnNumber = getSGSNNumber();
+ String sgsnName= getSGSNName();
+ String sgsnRealm = getSGSNRealm();
+ String mmeName = getMMEName();
+ String mmeRealm = getMMERealm();
+ byte[] mscNumber = getMSCNumber();
+ String tgppAAAServerName= get3GPPAAAServerName();
+ long lcsCapabilitiesSet = getLCSCapabilitiesSets();
+ java.net.InetAddress gmlcAddress = getGMLCAddress();
+
+ if (sgsnNumber != null){
+ servingNode.addAvp(Avp.SGSN_NUMBER, sgsnNumber, 10415, false, false);
+ }
+ if (sgsnName != null){
+ servingNode.addAvp(Avp.SGSN_NAME, sgsnName, 10415, false, false, false);
+ }
+ if (sgsnRealm != null){
+ servingNode.addAvp(Avp.SGSN_REALM, sgsnRealm, 10415, false, false, false);
+ }
+ if (mmeName != null){
+ servingNode.addAvp(Avp.MME_NAME, mmeName, 10415, false, false, false);
+ }
+ if (mmeRealm != null){
+ servingNode.addAvp(Avp.MME_REALM, mmeRealm, 10415, false, false, false);
+ }
+ if (mscNumber != null){
+ servingNode.addAvp(Avp.MSC_NUMBER, mscNumber, 10415, false, false);
+ }
+ if (tgppAAAServerName != null){
+ servingNode.addAvp(Avp.TGPP_AAA_SERVER_NAME, tgppAAAServerName, 10415, false, false, false);
+ }
+ if (lcsCapabilitiesSet != -1){
+ servingNode.addAvp(Avp.LCS_CAPABILITIES_SETS, lcsCapabilitiesSet, 10415, false, false, true);
+ }
+ if (gmlcAddress != null){
+ servingNode.addAvp(Avp.GMLC_ADDRESS, gmlcAddress, 10415, false, false);
+ }
+
+ // [ PLA-Flags ]
+ long plaFlags = getPLAFLags();
+ if (plaFlags != -1){
+ set.addAvp(Avp.PLA_FLAGS, plaFlags, 10415, false, false, true);
+ }
+
+ // [ ESMLC-Cell-Info ]
+/*
+ ESMLC-Cell-Info ::=
+ [ ECGI ]
+ [ Cell-Portion-ID ]
+ *[ AVP ]
+*/
+ AvpSet esmlcCellInfo = set.addGroupedAvp(Avp.ESMLC_CELL_INFO, 10415, false, false);
+ // ECGI attribute already defined
+ long cellPortionId = getCellPortionId();
+
+ if (ecgi != null){
+ esmlcCellInfo.addAvp(Avp.ECGI, ecgi, 10415, false, false);
+ }
+ if (cellPortionId != -1){
+ esmlcCellInfo.addAvp(Avp.CELL_PORTION_ID, cellPortionId, 10415, false, false, true);
+ }
+
+ // [ Civic-Address ]
+ String civicAddress = getCivicAddress();
+ if (civicAddress != null){
+ set.addAvp(Avp.CIVIC_ADDRESS, civicAddress, 10415, false, false, false);
+ }
+
+ // [ Barometric-Pressure ]
+ long barometricPressure = getBarometricPressure();
+ if (barometricPressure != -1){
+ set.addAvp(Avp.BAROMETRIC_PRESSURE, barometricPressure, 10415, false, false, true);
+ }
+
+ return pla;
+ }
+
+}
\ No newline at end of file
diff --git a/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/base/ClientLRR.java b/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/base/ClientLRR.java
new file mode 100644
index 000000000..c1089ccfa
--- /dev/null
+++ b/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/base/ClientLRR.java
@@ -0,0 +1,528 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.mobicents.diameter.stack.functional.slg.base;
+
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.slg.ClientSLgSession;
+import org.jdiameter.api.slg.events.LocationReportRequest;
+import org.jdiameter.api.slg.events.LocationReportAnswer;
+import org.mobicents.diameter.stack.functional.Utils;
+import org.mobicents.diameter.stack.functional.slg.AbstractDeferredClient;
+
+/**
+ *
+ * @author Fernando Mendioroz
+ *
+ */
+public class ClientLRR extends AbstractDeferredClient {
+
+ protected boolean receivedLRA;
+ protected boolean sentLRR;
+
+ public ClientLRR() {
+ }
+
+ public void sendLocationReportRequest() throws Exception {
+ LocationReportRequest lrr = super.createLRR(super.clientSLgSession);
+ super.clientSLgSession.sendLocationReportRequest(lrr);
+ Utils.printMessage(log, super.stack.getDictionary(), lrr.getMessage(), true);
+ this.sentLRR = true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.mobicents.diameter.stack.functional.slg.AbstractIDeferredClient#doLocationReportAnswerEvent(
+ * org.jdiameter.api.slg.ClientSLgSession, org.jdiameter.api.slg.events.LocationReportRequest, org.jdiameter.api.slg.events.LocationReportAnswer)
+ */
+
+ @Override
+ public void doLocationReportAnswerEvent(ClientSLgSession session, LocationReportRequest request, LocationReportAnswer answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
+ Utils.printMessage(log, super.stack.getDictionary(), answer.getMessage(), false);
+
+ if (this.receivedLRA) {
+ fail("Received PLA more than once", null);
+ return;
+ }
+ this.receivedLRA = true;
+ }
+
+ @Override
+ protected String getLCSNameString() {
+ String lcsNameString = "Restcomm Geolocation API";
+ return lcsNameString;
+ }
+
+ @Override
+ protected int getLCSFormatIndicator() {
+ /*
+ "0" = "LOGICAL_NAME"
+ "1" = "EMAIL_ADDRESS"
+ "2" = "MSISDN"
+ "3" = "URL"
+ "4" = "SIP_URL"
+ */
+ int lcsFormatIndicator = 2;
+ return lcsFormatIndicator;
+ }
+
+ @Override
+ protected String getUserName() {
+ // Information Element IMSI Mapped to AVP User-Name
+ String imsi = "748039876543210";
+ return imsi;
+ }
+
+ @Override
+ protected byte[] getMSISDN() {
+ String msisdnString = "59899077937";
+ byte[] msisdn = msisdnString.getBytes();
+ return msisdn;
+ }
+
+ @Override
+ protected String getIMEI() {
+ String imei = "011714004661057";
+ return imei;
+ }
+
+ @Override
+ protected long getDeferredLocationType() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.36
+ Bit Event Type Description
+ 0 UE-Available Any event in which the SGSN has established a contact with the UE.
+ 1 Entering-Into-Area An event where the UE enters a pre-defined geographical area.
+ 2 Leaving-From-Area An event where the UE leaves a pre-defined geographical area.
+ 3 Being-Inside-Area An event where the UE is currently within the pre-defined geographical area.For this event,
+ the value of Occurrence-Info AVP is always treated as set to “ONE_TIME_EVENT”.
+ 4 Periodic-LDR An event where a defined periodic timer expires in the UE and activates a location report or a location request.
+ */
+ long deferredLocationType = 8;
+ return deferredLocationType;
+ }
+
+ @Override
+ protected byte[] getLCSReferenceNumber() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.37
+ The LCS-Reference-Number AVP is of type OctetString of length 1. It shall contain the reference number identifying the deferred location request.
+ */
+ String lcsRefNumber = "4C4353353739";
+ byte[] lcsRefNum = lcsRefNumber.getBytes();
+ return lcsRefNum;
+ }
+
+ @Override
+ protected java.net.InetAddress getGMLCAddress() {
+ /*
+ 3GPP TS 29.173 v13.0.0 section 6.4.7
+ The GMLC-Address AVP is of type Address and shall contain the IPv4 or IPv6 address of H-GMLC or the V-GMLC associated with the serving node.
+ */
+ try {
+ java.net.InetAddress gmlcAddress = java.net.InetAddress.getLocalHost();
+ return gmlcAddress;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ protected long getReportingAmount() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.46
+ The Reporting-Amount AVP is of type Unsigned32 and it contains reporting frequency. Its minimum value shall be 1 and maximum value shall be 8639999.
+ */
+ long reportingAmount = 8639910L;
+ return reportingAmount;
+ }
+
+ @Override
+ protected long getReportingInterval() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.47
+ The Interval-Time AVP is of type Unsigned32 and it contains reporting frequency. Its minimum value shall be 1 and maximum value shall be 8639999.
+ */
+ long reportingInterval = 8639998L;
+ return reportingInterval;
+ }
+
+ @Override
+ protected int getLocationEvent() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.20
+ EMERGENCY_CALL_ORIGINATION (0)
+ EMERGENCY_CALL_RELEASE (1)
+ MO_LR (2)
+ EMERGENCY_CALL_HANDOVER (3)
+ DEFERRED_MT_LR_RESPONSE (4)
+ DEFERRED_MO_LR_TTTP_INITIATION (5)
+ DELAYED_LOCATION_REPORTING (6)
+ */
+ int locationEvent = 4;
+ return locationEvent;
+ }
+
+ @Override
+ protected byte[] getLocationEstimate() {
+ String locEstimate = "N43°38'19.39\" W116°14'28.86\"";
+ byte[] locationEstimate = locEstimate.getBytes();
+ return locationEstimate;
+ }
+
+ @Override
+ protected int getAccuracyFulfilmentIndicator() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.15
+ REQUESTED_ACCURACY_FULFILLED (0)
+ REQUESTED_ACCURACY_NOT_FULFILLED (1)
+ */
+ int accuracyFulfilmentIndicator = 0;
+ return accuracyFulfilmentIndicator;
+ }
+
+ @Override
+ protected long getAgeOfLocationEstimate() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.19
+ The Age-Of-Location-Estimate AVP is of type Unsigned32.
+ It indicates how long ago the location estimate was obtained in minutes, as indicated in 3GPP TS 29.002 [19].
+ */
+ long ageOfLocationEstimate = 374312L;
+ return ageOfLocationEstimate;
+ }
+
+ @Override
+ protected byte[] getVelocityEstimate() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.17
+ The Velocity-Estimate AVP is of type OctetString.
+ It is composed of 4 or more octets with an internal structure according to 3GPP TS 23.032 [3].
+ */
+ String vel = "210";
+ byte[] velocityEstimate = vel.getBytes();
+ return velocityEstimate;
+ }
+
+ @Override
+ protected byte[] getEUTRANPositioningData() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.18
+ The EUTRAN-Positioning-Data AVP is of type OctetString.
+ It shall contain the encoded content of the "Positioning-Data" Information Element as defined in 3GPP TS 29.171 [7].
+ */
+ String eutran = "654E423435336C7465613233";
+ byte[] eutranPositioningData = eutran.getBytes();
+ return eutranPositioningData;
+ }
+
+ @Override
+ protected byte[] getECGI() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.19
+ The ECGI AVP is of type OctetString. It indicates the E-UTRAN Cell Global Identifier.
+ It is coded according to clause 8.21.5, in 3GPP TS 29.274 [8].
+ */
+ String eCgi = "654E4239343337";
+ byte[] ecgi = eCgi.getBytes();
+ return ecgi;
+ }
+
+ @Override
+ protected byte[] getGERANPositioningData() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.30
+ The GERAN-Positioning-Data AVP is of type OctetString.
+ It shall contain the encoded content of the "Positioning Data" Information Element as defined in 3GPP TS 49.031 [20]
+ */
+ String geran = "42545339343342534333";
+ byte[] geranPositioningData = geran.getBytes();
+ return geranPositioningData;
+ }
+
+ @Override
+ protected byte[] getGERANGANSSPositioningData() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.30
+ The GERAN-GANSS-Positioning-Data AVP is of type OctetString.
+ It shall contain the encoded content of the "GANSS Positioning Data" Information Element as defined in 3GPP TS 49.031 [20]
+ */
+ String geranGanss = "4254533733524E4331473433";
+ byte[] geranGanssPositioningData = geranGanss.getBytes();
+ return geranGanssPositioningData;
+ }
+
+ @Override
+ protected byte[] getCellGlobalIdentity() {
+ String cgi = "9342784713907";
+ byte[] CellGlobalIdentity = cgi.getBytes();
+ return CellGlobalIdentity;
+ }
+
+ @Override
+ protected byte[] getUTRANPositioningData() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.33
+ The UTRAN-Positioning-Data AVP is of type OctetString.
+ It shall contain the encoded content of the "positioningDataDiscriminator" and the "positioningDataSet" included in the
+ "positionData" Information Element as defined in 3GPP TS 25.413 [21].
+ */
+ String utran = "4E42393433524E4331";
+ byte[] utranPositioningData = utran.getBytes();
+ return utranPositioningData;
+ }
+
+ @Override
+ protected byte[] getUTRANGANSSPositioningData() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.33
+ The UTRAN-Positioning-Data AVP is of type OctetString.
+ It shall contain the encoded content of the "positioningDataDiscriminator" and the "positioningDataSet" included in the
+ "positionData" Information Element as defined in 3GPP TS 25.413 [21].
+ */
+ String utranGanss = "4E42303331524E4335473433";
+ byte[] utranGanssPositioningData = utranGanss.getBytes();
+ return utranGanssPositioningData;
+ }
+
+ @Override
+ protected byte[] getServiceAreaIdentity() {
+ /*
+ 3GPP TS 29.172 v13.0.0 -> 3GPP TS 29.272
+ SAI shall contain the current service area of the target UE. The Service Area Identifier (SAI) is used to globally identify a service area.
+ This Information Element is applicable only when the UE is attached to UTRAN access and when the message is sent by the SGSN or combined MME/SGSN
+ */
+ String sai = "service-area-umts-3";
+ byte[] serviceAreaIdentity = sai.getBytes();
+ return serviceAreaIdentity;
+ }
+
+ @Override
+ protected long getLSCServiceTypeId() {
+ long lcsServiceTypeId = 234567012L;
+ return lcsServiceTypeId;
+ }
+
+ @Override
+ protected int getPseudonymIndicator() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.21
+ PSEUDONYM_NOT_REQUESTED (0)
+ PSEUDONYM_REQUESTED (1)
+ */
+ int pseudonymIndicator = 0;
+ return pseudonymIndicator;
+ }
+
+ @Override
+ protected int getLCSQoSClass() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.27
+ ASSURED (0)
+ BEST EFFORT (1)
+ */
+ int lcsQoSClass = 1;
+ return lcsQoSClass;
+ }
+
+ @Override
+ protected byte[] getSGSNNumber() {
+ String sgsnNumString = "59899004501";
+ byte[] sgsnNumber = sgsnNumString.getBytes();
+ return sgsnNumber;
+ }
+
+ @Override
+ protected String getSGSNName() {
+ String sgsnName = "SGSN01";
+ return sgsnName;
+ }
+
+ @Override
+ protected String getSGSNRealm() {
+ String sgsnRealm = "sgsn.restcomm.com";
+ return sgsnRealm;
+ }
+
+ @Override
+ protected String getMMEName() {
+ String mmeName = "MME710";
+ return mmeName;
+ }
+
+ @Override
+ protected String getMMERealm() {
+ String mmeRealm = "mme.restcomm.com";
+ return mmeRealm;
+ }
+
+ @Override
+ protected byte[] getMSCNumber() {
+ String mscNumString = "59899001207";
+ byte[] mscNumber = mscNumString.getBytes();
+ return mscNumber;
+ }
+
+ @Override
+ protected String get3GPPAAAServerName() {
+ String tgppAAAServerName = "aaa.restcomm.com";
+ return tgppAAAServerName;
+ }
+
+ @Override
+ protected long getLCSCapabilitiesSets() {
+ long lcsCapabilitiesSets = 99900123L;
+ return lcsCapabilitiesSets;
+ }
+
+ @Override
+ protected long getLRRFLags() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.35
+ Bit Event Type Description
+ 0 Lgd/SLg-Indicator This bit, when set, indicates that the Location Report Request message is sent on the Lgd interface,
+ i.e. the source node is an SGSN (or a combined MME/SGSN to which the UE is attached via UTRAN or GERAN).
+ This bit, when cleared, indicates that the Location Report Request message is sent on the SLg interface,
+ i.e. the source node is an MME (or a combined MME/SGSN to which the UE is attached via E-UTRAN).
+ 1 MO-LR-ShortCircuit-Indicator This bit, when set, indicates that the MO-LR short circuit feature is used by the UE for
+ location estimate. This bit is applicable only when for deferred MT-LR procedure and
+ when the message is sent over Lgd interface.
+ 2 MO-LR-ShortCircuit-Requested This bit, when set, indicates that the UE is requesting to use MO-LR short circuit feature
+ for location estimate.
+ This bit is applicable only when periodic MO-LR TTTP procedure is initiated by the UE and when the
+ message is sent over Lgd interface.
+ */
+ long lrrFlags = 1;
+ return lrrFlags;
+ }
+
+ @Override
+ protected long getTerminationCause() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.55
+ "Normal" 0
+ "Error Undefined" 1
+ "Internal Timeout" 2
+ "Congestion" 3
+ "MT_LR_Restart" 4
+ "Privacy Violation" 5
+ "Shape of Location Estimate Not Supported" 6
+ "Subscriber Termination" 7
+ "UE Termination" 8
+ "Network Termination" 9
+ */
+ long terminationCause = 7;
+ return terminationCause;
+ }
+
+ @Override
+ protected long getCellPortionId() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.58
+ The Cell-Portion-ID AVP is of type Unsigned32. It indicates the current Cell Portion location of the target UE as provided by the E-SMLC.
+ It shall contain the value of the "Cell Portion ID" Information Element as defined in 3GPP TS 29.171
+ */
+ long cellPortionId = 349232432L;
+ return cellPortionId;
+ }
+
+ @Override
+ protected byte[] get1xRTTRCID() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.59
+ The 1xRTT-RCID AVP is of type OctetString.
+ It indicates the 1xRTT Reference Cell Id that consists of a Cell Identification Discriminator and a Cell Identification and shall be formatted
+ according to octets 3 through the end of the Cell Identifier element defined in subclause 4.2.17 in 3GPP2 A.S0014-D [22].
+ The allowable cell discriminator values are "0000 0010", and "0000 0111".
+ */
+ String oxrttrcid = "00000010";
+ byte[] onexrttrcid = oxrttrcid.getBytes();
+ return onexrttrcid;
+ }
+
+ @Override
+ protected String getCivicAddress() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.61
+ The Civic-Address AVP is of type UTF8String.
+ It contains the XML document carried in the "Civic Address" Information Element as defined in 3GPP TS 29.171.
+ */
+ String civicAddress = "\n" +
+ " UK\n" +
+ " Devon\n" +
+ " Monkokehampton\n" +
+ " Deckport\n" +
+ " Cross\n" +
+ "\n" +
+ " 21451338\n" +
+ "\n" +
+ " "; // From IETF RFC 6848, Extended Civic Address Example
+ return civicAddress;
+ }
+
+ @Override
+ protected long getBarometricPressure() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.62
+ The Barometric-Pressure AVP is of type Unsigned32.
+ It contains the "Barometric Pressure" Information Element as defined in 3GPP TS 29.171.
+ */
+ long barometricPressure = 101327L;
+ return barometricPressure;
+ }
+
+ public boolean isReceivedLRA() {
+ return receivedLRA;
+ }
+
+ public boolean isSentLRR() {
+ return sentLRR;
+ }
+
+}
+
diff --git a/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/base/ClientPLR.java b/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/base/ClientPLR.java
new file mode 100644
index 000000000..bb7555594
--- /dev/null
+++ b/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/base/ClientPLR.java
@@ -0,0 +1,516 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.mobicents.diameter.stack.functional.slg.base;
+
+import org.jdiameter.api.IllegalDiameterStateException;
+import org.jdiameter.api.InternalException;
+import org.jdiameter.api.OverloadException;
+import org.jdiameter.api.RouteException;
+import org.jdiameter.api.slg.ClientSLgSession;
+import org.jdiameter.api.slg.events.ProvideLocationRequest;
+import org.jdiameter.api.slg.events.ProvideLocationAnswer;
+import org.mobicents.diameter.stack.functional.Utils;
+import org.mobicents.diameter.stack.functional.slg.AbstractImmediateClient;
+
+import static sun.jdbc.odbc.JdbcOdbcObject.hexStringToByteArray;
+
+/**
+ *
+ * @author Fernando Mendioroz
+ *
+ */
+public class ClientPLR extends AbstractImmediateClient {
+
+ protected boolean receivedPLA;
+ protected boolean sentPLR;
+
+ public ClientPLR() {
+ }
+
+ public void sendProvideLocationRequest() throws Exception {
+ ProvideLocationRequest plr = super.createPLR(super.clientSLgSession);
+ super.clientSLgSession.sendProvideLocationRequest(plr);
+ Utils.printMessage(log, super.stack.getDictionary(), plr.getMessage(), true);
+ this.sentPLR = true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.mobicents.diameter.stack.functional.slg.AbstractImmediateClient#doProvideLocationAnswerEvent(
+ * org.jdiameter.api.slg.ClientSLgSession, org.jdiameter.api.slg.events.ProvideLocationRequest, org.jdiameter.api.slg.events.ProvideLocationAnswer)
+ */
+ @Override
+ public void doProvideLocationAnswerEvent(ClientSLgSession session, ProvideLocationRequest request, ProvideLocationAnswer answer)
+ throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
+ Utils.printMessage(log, super.stack.getDictionary(), answer.getMessage(), false);
+
+ if (this.receivedPLA) {
+ fail("Received PLA more than once", null);
+ return;
+ }
+ this.receivedPLA = true;
+ }
+
+ // PLR methods
+
+ // { SLg-Location-Type }
+ protected int getSLgLocationType() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.2
+ The SLg-Location-Type AVP is of type Enumerated. The following values are defined:
+ CURRENT_LOCATION (0)
+ CURRENT_OR_LAST_KNOWN_LOCATION (1)
+ INITIAL_LOCATION (2)
+ ACTIVATE_DEFERRED_LOCATION (3)
+ CANCEL_DEFERRED_LOCATION (4)
+ NOTIFICATION_VERIFICATION_ONLY (5)
+ */
+ int slgLocationType = 0;
+ return slgLocationType;
+ }
+
+ @Override
+ protected String getLCSNameString() {
+ String lcsNameString = "Restcomm Geolocation API";
+ return lcsNameString;
+ }
+
+ protected int getLCSFormatIndicator() {
+ /*
+ "0" = "LOGICAL_NAME"
+ "1" = "EMAIL_ADDRESS"
+ "2" = "MSISDN"
+ "3" = "URL"
+ "4" = "SIP_URL"
+ */
+ int lcsFormatIndicator = 2;
+ return lcsFormatIndicator;
+ }
+
+ @Override
+ protected String getUserName() {
+ // Information Element IMSI Mapped to AVP User-Name
+ String imsi = "748039876543210";
+ return imsi;
+ }
+
+ @Override
+ protected byte[] getMSISDN() {
+ String msisdnString = "59899077937";
+ byte[] msisdn = msisdnString.getBytes();
+ return msisdn;
+ }
+
+ @Override
+ protected String getIMEI() {
+ String imei = "011714004661057";
+ return imei;
+ }
+
+ @Override
+ protected int getLCSClientType() {
+ /*
+ "0" = "EMERGENCY_SERVICES"
+ "1" = "VALUE_ADDED_SERVICES"
+ "2" = "PLMN_OPERATOR_SERVICES"
+ "3" = "LAWFUL_INTERCEPT_SERVICES"
+ */
+ int lcsClientType = 1;
+ return lcsClientType;
+ }
+
+ @Override
+ protected String getLCSRequestorIdString() {
+ String lcsRequestorIdString = "restcomm_geolocation_23";
+ return lcsRequestorIdString;
+ }
+
+ @Override
+ protected int getReqLCSFormatIndicator() {
+ /*
+ "0" = "LOGICAL_NAME"
+ "1" = "EMAIL_ADDRESS"
+ "2" = "MSISDN"
+ "3" = "URL"
+ "4" = "SIP_URL"
+ */
+ int requestorLCSFormatIndicator = 3;
+ return requestorLCSFormatIndicator;
+ }
+
+ @Override
+ protected long getLCSPriority() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.5
+ The LCS-Priority AVP is of type Unsigned32. It indicates the priority of the location request.
+ The value 0 shall indicate the highest priority, and the value 1 shall indicate normal priority.
+ All other values shall be treated as 1 (normal priority). For details, refer to 3GPP TS 22.071.
+ */
+ int lcsPriority = 1;
+ return lcsPriority;
+ }
+
+ @Override
+ protected int getLCSQoSClass() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.27
+ ASSURED (0)
+ BEST EFFORT (1)
+ */
+ int lcsQoSClass = 1;
+ return lcsQoSClass;
+ }
+
+ @Override
+ protected long getHorizontalAccuracy() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.7
+ The Horizontal-Accuracy AVP is of type Unsigned32. Bits 6-0 corresponds to Uncertainty Code defined in 3GPP TS 23.032 [3].
+ The horizontal location error should be less than the error indicated by the uncertainty code with 67% confidence.
+ Bits 7 to 31 shall be ignored
+ */
+ long horizontalAccuracy = 120L;
+ return horizontalAccuracy;
+ }
+
+ @Override
+ protected long getVerticalAccuracy() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.8
+ The Vertical-Accuracy AVP is of type Unsigned32. Bits 6-0 corresponds to Uncertainty Code defined in 3GPP TS 23.032 [3].
+ The Vertical location error should be less than the error indicated by the uncertainty code with 67% confidence.
+ Bits 7 to 31 shall be ignored
+ */
+ long verticalAccuracy = 3237L;
+ return verticalAccuracy;
+ }
+
+ @Override
+ protected int getVerticalRequested() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.9
+ VERTICAL_COORDINATE_IS_NOT REQUESTED (0)
+ VERTICAL_COORDINATE_IS_REQUESTED (1)
+ */
+ int verticalRequested = 0;
+ return verticalRequested;
+ }
+
+ @Override
+ protected int getResponseTime() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.11
+ LOW_DELAY (0)
+ DELAY_TOLERANT (1)
+ */
+ int responseTime = 1;
+ return responseTime;
+ }
+
+ @Override
+ protected int getVelocityRequested() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.10
+ VELOCITY_IS_NOT_REQUESTED (0)
+ VELOCITY_IS_REQUESTED (1)
+ */
+ int velocityRequested = 0;
+ return velocityRequested;
+ }
+
+ @Override
+ protected long getSupportedGADShapes() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.12
+ The Supported-GAD-Shapes AVP is of type Unsigned32 and it shall contain a bitmask.
+ A node shall mark in the BIT STRING all Shapes defined in 3GPP TS 23.032 [3] it supports.
+ Bits 6-0 in shall indicate the supported Shapes defined in 3GPP TS 23.032 [3]. Bits 7 to 31 shall be ignored.
+ ellipsoidPoint (0)
+ ellipsoidPointWithUncertaintyCircle (1)
+ ellipsoidPointWithUncertaintyEllipse (2)
+ polygon (3)
+ ellipsoidPointWithAltitude (4)
+ ellipsoidPointWithAltitudeAndUncertaintyElipsoid (5)
+ ellipsoidArc (6)
+ */
+ long supportedGADShapes = 3L;
+ return supportedGADShapes;
+ }
+
+ @Override
+ protected long getLSCServiceTypeId() {
+ long lcsServiceTypeId = 234L;
+ return lcsServiceTypeId;
+ }
+
+ @Override
+ protected String getLCSCodeword() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.1
+ The LCS-Codeword AVP is of type UTF8String.
+ It indicates the potential codeword string to send in a notification message to the UE
+ */
+ String lcsCodeword = "rcgl49f9f$#ERSD";
+ return lcsCodeword;
+ }
+
+ @Override
+ protected String getServiceSelection() {
+ String apn = "restcomm.org";
+ return apn;
+ }
+
+ @Override
+ protected int getLCSPrivacyCheckSession() {
+ /*
+ 3GPP TS 291.172 v13.0.0 section 7.4.22
+ LCS-Privacy-Check-Session ::=
+ { LCS-Privacy-Check }
+ 3GPP TS 29.172 v13.0.0 section 7.4.14
+ ALLOWED_WITHOUT_NOTIFICATION (0)
+ ALLOWED_WITH_NOTIFICATION (1)
+ ALLOWED_IF_NO_RESPONSE (2)
+ RESTRICTED_IF_NO_RESPONSE (3)
+ NOT_ALLOWED (4)
+ */
+ int lcsPrivacyCheckSession = 2;
+ return lcsPrivacyCheckSession;
+ }
+
+ @Override
+ protected int getLCSPrivacyCheckNonSession() {
+ /*
+ 3GPP TS 291.172 v13.0.0 section 7.4.22
+ LCS-Privacy-Check-Non-Session ::=
+ { LCS-Privacy-Check }
+ 3GPP TS 29.172 v13.0.0 section 7.4.14
+ ALLOWED_WITHOUT_NOTIFICATION (0)
+ ALLOWED_WITH_NOTIFICATION (1)
+ ALLOWED_IF_NO_RESPONSE (2)
+ RESTRICTED_IF_NO_RESPONSE (3)
+ NOT_ALLOWED (4)
+ */
+ int lcsPrivacyCheckNonSession = 4;
+ return lcsPrivacyCheckNonSession;
+ }
+
+ @Override
+ protected long getDeferredLocationType() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.36
+ Bit Event Type Description
+ 0 UE-Available Any event in which the SGSN has established a contact with the UE.
+ 1 Entering-Into-Area An event where the UE enters a pre-defined geographical area.
+ 2 Leaving-From-Area An event where the UE leaves a pre-defined geographical area.
+ 3 Being-Inside-Area An event where the UE is currently within the pre-defined geographical area.For this event,
+ the value of Occurrence-Info AVP is always treated as set to “ONE_TIME_EVENT”.
+ 4 Periodic-LDR An event where a defined periodic timer expires in the UE and activates a location report or a location request.
+ */
+ long deferredLocationType = 8L;
+ return deferredLocationType;
+ }
+
+ @Override
+ protected byte[] getLCSReferenceNumber() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.37
+ The LCS-Reference-Number AVP is of type OctetString of length 1. It shall contain the reference number identifying the deferred location request.
+ */
+ String lcsRefNumber = "4C4353353739";
+ byte[] lcsRefNum = lcsRefNumber.getBytes();
+ return lcsRefNum;
+ }
+
+ @Override
+ protected int getOccurrenceInfo() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.43
+ The Occurrence-Info AVP is of type Enumerated. The following values are defined:
+ ONE_TIME_EVENT (0)
+ MULTIPLE_TIME_EVENT (1)
+ */
+ int occurrenceInfo = 1;
+ return occurrenceInfo;
+ }
+
+ @Override
+ protected long getIntervalTime() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.44
+ The Interval-Time AVP is of type Unsigned32 and it contains minimum time interval between area reports, in seconds.
+ */
+ long intervalTime = 3600L;
+ return intervalTime;
+ }
+
+ @Override
+ protected long getAreaType() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.41
+ "Country Code" 0
+ "PLMN ID" 1
+ "Location Area ID" 2
+ "Routing Area ID" 3
+ "Cell Global ID" 4
+ "UTRAN Cell ID" 5
+ */
+ long areaType = 3L;
+ return areaType;
+ }
+
+ @Override
+ protected byte[] getAreaIdentification() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.42
+ The Area-Identification AVP is of type OctetString and shall contain the identification of the area applicable
+ for the change of area event based deferred location reporting. Octets are coded as described in 3GPP TS 29.002 [24].
+ */
+ String areaId = "617265613531";
+ byte[] areaIdentification = areaId.getBytes();
+ return areaIdentification;
+ }
+
+ @Override
+ protected java.net.InetAddress getGMLCAddress() {
+
+ try {
+ java.net.InetAddress gmlcAddress = java.net.InetAddress.getLocalHost();
+ return gmlcAddress;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ protected long getPLRFLags() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.52
+ Bit Event Type Description
+ 0 MO-LR-ShortCircuit-Indicator This bit, when set, indicates that the MO-LR short circuit feature is requested
+ for the periodic location.This bit is applicable only when the deferred MT-LR procedure is
+ initiated for a periodic location event and when the message is sent over Lgd interface.
+ 1 Optimized-LCS-Proc-Req This bit, when set, indicates that the GMLC is requesting the optimized LCS procedure
+ for the combined MME/SGSN. This bit is applicable only when the MT-LR procedure is
+ initiated by the GMLC. The GMLC shall set this bit only when the HSS indicates the combined MME/SGSN
+ node supporting the optimized LCS procedure.
+ 2 Delayed-Location-Reporting-Support-Indicator This bit, when set, indicates that the GMLC supports delayed location reporting for UEs transiently
+ not reachable (e.g. UEs in extended idle mode DRX or Power Saving Mode) as specified in subclauses
+ 9.1.6 and 9.1.15 of 3GPP TS 23.271 [2], i.e. that the GMLC supports receiving a
+ PROVIDE SUBSCRIBER LOCATION RESPONSE with the UE-Transiently-Not-Reachable-Indicator set in the
+ PLA-Flags IE; and receiving the location information in a subsequent SUBSCRIBER LOCATION REPORT
+ when the UE becomes reachable.
+ */
+ long plrFlags = 4L;
+ return plrFlags;
+ }
+
+ @Override
+ protected long getReportingAmount() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.46
+ The Reporting-Amount AVP is of type Unsigned32 and it contains reporting frequency. Its minimum value shall be 1 and maximum value shall be 8639999.
+ */
+ long reportingAmount = 8639910L;
+ return reportingAmount;
+ }
+
+ @Override
+ protected long getReportingInterval() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.47
+ The Interval-Time AVP is of type Unsigned32 and it contains reporting frequency. Its minimum value shall be 1 and maximum value shall be 8639999.
+ */
+ long reportingInterval = 8639998L;
+ return reportingInterval;
+ }
+
+ @Override
+ protected int getPrioritizedListIndicator() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.51
+ The Prioritized-List-Indicator AVP is of type Enumerated and it indicates if the PLMN-ID-List is provided in prioritized order or not.
+ NOT_PRIORITIZED (0)
+ PRIORITIZED (1)
+ */
+ int prioritizedListIndicator = 0;
+ return prioritizedListIndicator;
+ }
+
+ @Override
+ protected byte[] getVisitedPLMNId() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.49
+ The PLMN-ID-List AVP is of type Grouped.
+ AVP format:
+ PLMN-ID-List ::=
+ { Visited-PLMN-Id }
+ [ Periodic-Location-Support-Indicator ]
+ *[ AVP ]
+ If not included, the default value of Periodic-Location-Support-Indicator shall be considered as "NOT_SUPPORTED" (0).
+ */
+ byte[] visitedPlmnIdList = hexStringToByteArray("473800");
+ return visitedPlmnIdList;
+ }
+
+ @Override
+ protected int getPeriodicLocationSupportIndicator() {
+ /*
+ 3GPP TS 29.172 v13.0.0 section 7.4.50
+ The Periodic-Location-Support-Indicator AVP is of type Enumerated and it indicates if the given PLMN-ID (indicated by Visited-PLMN-Id)
+ supports periodic location or not.
+ NOT_SUPPORTED (0)
+ SUPPORTED (1)
+ */
+ int periodicLocationSupportIndicator = 1;
+ return periodicLocationSupportIndicator;
+ }
+
+ public boolean isReceivedPLA() {
+ return receivedPLA;
+ }
+
+ public boolean isSentPLR() {
+ return sentPLR;
+ }
+
+}
\ No newline at end of file
diff --git a/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/base/SLgSessionBasicDefFlowTest.java b/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/base/SLgSessionBasicDefFlowTest.java
new file mode 100644
index 000000000..0c3f517f6
--- /dev/null
+++ b/testsuite/tests/src/test/java/org/mobicents/diameter/stack/functional/slg/base/SLgSessionBasicDefFlowTest.java
@@ -0,0 +1,225 @@
+/*
+ * TeleStax, Open Source Cloud Communications
+ * Copyright 2011-2016, TeleStax Inc. and individual contributors
+ * by the @authors tag.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007-2011, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+package org.mobicents.diameter.stack.functional.slg.base;
+
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.jdiameter.api.DisconnectCause;
+import org.jdiameter.api.Mode;
+import org.jdiameter.api.Peer;
+import org.jdiameter.api.PeerState;
+import org.jdiameter.api.PeerTable;
+import org.jdiameter.api.Stack;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ *
+ * @author Fernando Mendioroz
+ * @author Alexandre Mendonca
+ * @author Bartosz Baranowski
+ */
+@RunWith(Parameterized.class)
+public class SLgSessionBasicDefFlowTest {
+ // TODO: add test on replicated nodes ?
+ private ClientLRR clientNode;
+ private ServerLRA serverNode1;
+ private URI clientConfigURI;
+ private URI serverNode1ConfigURI;
+
+ /**
+ * @param clientConfigUrl
+ * // @param node1
+ * // @param node2
+ * @param serverNode1ConfigURL
+ */
+
+ public SLgSessionBasicDefFlowTest(String clientConfigUrl, String serverNode1ConfigURL) throws Exception {
+ super();
+ this.clientConfigURI = new URI(clientConfigUrl);
+ this.serverNode1ConfigURI = new URI(serverNode1ConfigURL);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ try {
+ this.clientNode = new ClientLRR();
+ this.serverNode1 = new ServerLRA();
+
+ this.serverNode1.init(new FileInputStream(new File(this.serverNode1ConfigURI)), "SERVER1");
+ this.serverNode1.start();
+
+ this.clientNode.init(new FileInputStream(new File(this.clientConfigURI)), "CLIENT");
+ this.clientNode.start(Mode.ANY_PEER, 10, TimeUnit.SECONDS);
+ Stack stack = this.clientNode.getStack();
+ List peers = stack.unwrap(PeerTable.class).getPeerTable();
+ if (peers.size() == 1) {
+ // ok
+ }
+ else if (peers.size() > 1) {
+ // works better with replicated, since disconnected peers are also listed
+ boolean foundConnected = false;
+ for (Peer p : peers) {
+ if (p.getState(PeerState.class).equals(PeerState.OKAY)) {
+ if (foundConnected) {
+ throw new Exception("Wrong number of connected peers: " + peers);
+ }
+ foundConnected = true;
+ }
+ }
+ }
+ else {
+ throw new Exception("Wrong number of connected peers: " + peers);
+ }
+ }
+ catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+ @After
+ public void tearDown() {
+ if (this.serverNode1 != null) {
+ try {
+ this.serverNode1.stop(DisconnectCause.REBOOTING);
+ }
+ catch (Exception e) {
+
+ }
+ this.serverNode1 = null;
+ }
+
+ if (this.clientNode != null) {
+ try {
+ this.clientNode.stop(DisconnectCause.REBOOTING);
+ }
+ catch (Exception e) {
+
+ }
+ this.clientNode = null;
+ }
+ }
+
+ @Test
+ public void testLocationReportBasicFlow() throws Exception {
+ try {
+ // pain of parameter tests :) ?
+ clientNode.sendLocationReportRequest();
+ waitForMessage();
+
+ serverNode1.sendLocationReportAnswer();
+ waitForMessage();
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ fail(e.toString());
+ }
+
+ if (!serverNode1.isReceivedLRR()) {
+ StringBuilder sb = new StringBuilder("Did not receive LRR! ");
+ sb.append("Server ER:\n").append(serverNode1.createErrorReport(this.serverNode1.getErrors()));
+
+ fail(sb.toString());
+ }
+ if (!clientNode.isReceivedLRA()) {
+ StringBuilder sb = new StringBuilder("Did not receive LRA! ");
+ sb.append("Client ER:\n").append(clientNode.createErrorReport(this.clientNode.getErrors()));
+
+ fail(sb.toString());
+ }
+
+ if (!clientNode.isPassed()) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Client ER:\n").append(clientNode.createErrorReport(this.clientNode.getErrors()));
+
+ fail(sb.toString());
+ }
+
+ if (!serverNode1.isPassed()) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Server ER:\n").append(serverNode1.createErrorReport(this.serverNode1.getErrors()));
+
+ fail(sb.toString());
+ }
+ }
+
+ @Parameters
+ public static Collection