Skip to content

Commit

Permalink
Add Idle Session Timeout check
Browse files Browse the repository at this point in the history
This allows to configure a new parameter, "SessionTimeOut" where it defines
how long a session can be idle before being forcefully terminated.

This can be configured by adding an optional `<SessionTimeOut value="86400000" />`
parameter to jdiameter-config.xml, after <MessageTimeOut> parameter. Default value is
`0` meaning there won't be a timeout for the sessions.

A test for this feature is included, RoSessionBasicFlowIdleTest.

Fixes RestComm#85
  • Loading branch information
brainslog committed Mar 15, 2017
1 parent 5054ee5 commit a719ece
Show file tree
Hide file tree
Showing 36 changed files with 558 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,6 @@ public interface BaseSession {
* @return session-id as String (Session-Id AVP)
*/
String getSessionId();

String IDLE_SESSION_TIMER_NAME = "IDLE_SESSION_TIMER";
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@
package org.jdiameter.client.impl;

import static org.jdiameter.client.impl.helpers.Parameters.MessageTimeOut;
import static org.jdiameter.client.impl.helpers.Parameters.SessionTimeOut;

import java.io.Serializable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
Expand All @@ -65,10 +67,14 @@
import org.jdiameter.api.OverloadException;
import org.jdiameter.api.Request;
import org.jdiameter.api.RouteException;
import org.jdiameter.client.api.IAssembler;
import org.jdiameter.client.api.IContainer;
import org.jdiameter.client.api.IEventListener;
import org.jdiameter.client.api.IMessage;
import org.jdiameter.client.api.parser.IMessageParser;
import org.jdiameter.common.api.timer.ITimerFacility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Implementation for {@link BaseSession}.
Expand All @@ -79,15 +85,21 @@
*/
public abstract class BaseSessionImpl implements BaseSession {

private static final Logger logger = LoggerFactory.getLogger(BaseSessionImpl.class);

protected final long creationTime = System.currentTimeMillis();
protected long lastAccessedTime = creationTime;
protected boolean isValid = true;
protected String sessionId;

protected long maxIdleTime = 0;

protected transient IContainer container;
protected transient IMessageParser parser;
protected NetworkReqListener reqListener;

private Serializable istTimerId;

@Override
public long getCreationTime() {
return creationTime;
Expand All @@ -98,6 +110,29 @@ public long getLastAccessedTime() {
return lastAccessedTime;
}

protected long setLastAccessTime() {
lastAccessedTime = System.currentTimeMillis();
maxIdleTime = container.getConfiguration().getLongValue(SessionTimeOut.ordinal(), (Long) SessionTimeOut.defValue());
if (maxIdleTime > 0) {
IAssembler assembler = container.getAssemblerFacility();
ITimerFacility timerFacility = assembler.getComponentInstance(ITimerFacility.class);
if (istTimerId != null) {
timerFacility.cancel(istTimerId);
}
istTimerId = timerFacility.schedule(this.getSessionId(), IDLE_SESSION_TIMER_NAME, maxIdleTime);
}
return lastAccessedTime;
}

public void onTimer(String timerName) {
if (timerName.equals(IDLE_SESSION_TIMER_NAME)) {
if (!isValid() || (maxIdleTime > 0 && System.currentTimeMillis() - getLastAccessedTime() > maxIdleTime)) {
logger.debug("Terminating idle/invalid application session [{}] with SID[{}]", this, getSessionId());
this.release();
}
}
}

@Override
public boolean isValid() {
return isValid;
Expand Down Expand Up @@ -138,7 +173,7 @@ protected void genericSend(Message message, EventListener listener)
protected void genericSend(Message aMessage, EventListener listener, long timeout, TimeUnit timeUnit)
throws InternalException, IllegalDiameterStateException, RouteException, OverloadException {
if (isValid) {
lastAccessedTime = System.currentTimeMillis();
setLastAccessTime();

IMessage message = (IMessage) aMessage;
IEventListener localListener = createListenerWrapper(listener);
Expand Down Expand Up @@ -402,7 +437,7 @@ public boolean isValid() {
@SuppressWarnings("unchecked")
public void receivedSuccessMessage(Request request, Answer answer) {
if (isValid) {
session.lastAccessedTime = System.currentTimeMillis();
session.setLastAccessTime();
listener.receivedSuccessMessage(request, answer);
}
}
Expand All @@ -411,7 +446,7 @@ public void receivedSuccessMessage(Request request, Answer answer) {
@SuppressWarnings("unchecked")
public void timeoutExpired(Request message) {
if (isValid) {
session.lastAccessedTime = System.currentTimeMillis();
session.setLastAccessTime();
listener.timeoutExpired(message);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public class RawSessionImpl extends BaseSessionImpl implements RawSession {
@Override
public Message createMessage(int commandCode, ApplicationId appId, Avp... avps) {
if ( isValid ) {
lastAccessedTime = System.currentTimeMillis();
setLastAccessTime();
IMessage m = parser.createEmptyMessage(commandCode, getAppId(appId));
m.getAvps().addAvp(avps);
appendAppId(appId, m);
Expand All @@ -88,7 +88,7 @@ public Message createMessage(int commandCode, ApplicationId appId, Avp... avps)
@Override
public Message createMessage(int commandCode, ApplicationId appId, long hopByHopIdentifier, long endToEndIdentifier, Avp... avps) {
if ( isValid ) {
lastAccessedTime = System.currentTimeMillis();
setLastAccessTime();
IMessage m = parser.createEmptyMessage(commandCode, getAppId(appId));
if (hopByHopIdentifier >= 0) {
m.setHopByHopIdentifier(-hopByHopIdentifier);
Expand All @@ -107,7 +107,7 @@ public Message createMessage(int commandCode, ApplicationId appId, long hopByHop
@Override
public Message createMessage(Message message, boolean copyAvps) {
if ( isValid ) {
lastAccessedTime = System.currentTimeMillis();
setLastAccessTime();
IMessage newMessage = null;
IMessage inner = (IMessage) message;
if (copyAvps) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public NetworkReqListener getReqListener() {
@Override
public Request createRequest(int commandCode, ApplicationId appId, String destRealm) {
if (isValid) {
lastAccessedTime = System.currentTimeMillis();
setLastAccessTime();
IRequest m = parser.createEmptyMessage(IRequest.class, commandCode, getAppId(appId));
m.setNetworkRequest(false);
m.setRequest(true);
Expand All @@ -135,7 +135,7 @@ public Request createRequest(int commandCode, ApplicationId appId, String destRe
@Override
public Request createRequest(int commandCode, ApplicationId appId, String destRealm, String destHost) {
if (isValid) {
lastAccessedTime = System.currentTimeMillis();
setLastAccessTime();
IRequest m = parser.createEmptyMessage(IRequest.class, commandCode, getAppId(appId));
m.setNetworkRequest(false);
m.setRequest(true);
Expand All @@ -158,7 +158,7 @@ public Request createRequest(int commandCode, ApplicationId appId, String destRe
@Override
public Request createRequest(Request prevRequest) {
if (isValid) {
lastAccessedTime = System.currentTimeMillis();
setLastAccessTime();
IRequest request = parser.createEmptyMessage(Request.class, (IMessage) prevRequest);
request.setRequest(true);
request.setNetworkRequest(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,10 @@ protected void processInterimIntervalAvp(StateEvent event) throws InternalExcept
*/
@Override
public void onTimer(String timerName) {
if (timerName.equals(TIMER_NAME_INTERIM)) {
if (timerName.equals(IDLE_SESSION_TIMER_NAME)) {
checkIdleAppSession();
}
else if (timerName.equals(TIMER_NAME_INTERIM)) {
if (context != null) {
try {
Request interimRecord = createInterimRecord();
Expand All @@ -641,7 +644,7 @@ public void onTimer(String timerName) {
}
}
else {
//....?
logger.warn("Received an unknown timer '{}' for Session-ID '{}'", timerName, getSessionId());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,10 @@ protected void cancelTsTimer() {
*/
@Override
public void onTimer(String timerName) {
if (timerName.equals(TIMER_NAME_TS)) {
if (timerName.equals(IDLE_SESSION_TIMER_NAME)) {
checkIdleAppSession();
}
else if (timerName.equals(TIMER_NAME_TS)) {
try {
sendAndStateLock.lock();
sessionData.setTsTimerId(null);
Expand All @@ -611,6 +614,9 @@ public void onTimer(String timerName) {
sendAndStateLock.unlock();
}
}
else {
logger.warn("Received an unknown timer '{}' for Session-ID '{}'", timerName, getSessionId());
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -623,9 +623,15 @@ protected void stopTx() {
*/
@Override
public void onTimer(String timerName) {
if (timerName.equals(TX_TIMER_NAME)) {
if (timerName.equals(IDLE_SESSION_TIMER_NAME)) {
checkIdleAppSession();
}
else if (timerName.equals(TX_TIMER_NAME)) {
new TxTimerTask(this, this.sessionData.getTxTimerRequest()).run();
}
else {
logger.warn("Received an unknown timer '{}' for Session-ID '{}'", timerName, getSessionId());
}
}

protected void setState(ClientCCASessionState newState) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,10 @@ protected void setState(CxDxSessionState newState) {
*/
@Override
public void onTimer(String timerName) {
if (timerName.equals(CxDxSession.TIMER_NAME_MSG_TIMEOUT)) {
if (timerName.equals(IDLE_SESSION_TIMER_NAME)) {
checkIdleAppSession();
}
else if (timerName.equals(CxDxSession.TIMER_NAME_MSG_TIMEOUT)) {
try {
sendAndStateLock.lock();
try {
Expand All @@ -385,6 +388,9 @@ public void onTimer(String timerName) {
sendAndStateLock.unlock();
}
}
else {
logger.warn("Received an unknown timer '{}' for Session-ID '{}'", timerName, getSessionId());
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,10 @@ protected void cancelTsTimer() {
*/
@Override
public void onTimer(String timerName) {
if (timerName.equals(TIMER_NAME_TS)) {
if (timerName.equals(IDLE_SESSION_TIMER_NAME)) {
checkIdleAppSession();
}
else if (timerName.equals(TIMER_NAME_TS)) {
try {
sendAndStateLock.lock();
sessionData.setTsTimerId(null);
Expand All @@ -579,6 +582,9 @@ public void onTimer(String timerName) {
sendAndStateLock.unlock();
}
}
else {
logger.warn("Received an unknown timer '{}' for Session-ID '{}'", timerName, getSessionId());
}
}

protected AbortSessionAnswer createAbortSessionAnswer(Answer answer) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -611,9 +611,15 @@ protected void stopTx() {
*/
@Override
public void onTimer(String timerName) {
if (timerName.equals(TX_TIMER_NAME)) {
if (timerName.equals(IDLE_SESSION_TIMER_NAME)) {
checkIdleAppSession();
}
else if (timerName.equals(TX_TIMER_NAME)) {
new TxTimerTask(this, this.sessionData.getTxTimerRequest()).run();
}
else {
logger.warn("Received an unknown timer '{}' for Session-ID '{}'", timerName, getSessionId());
}
}

protected void setState(ClientGxSessionState newState) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,10 @@ protected void processInterimIntervalAvp(StateEvent event) throws InternalExcept
*/
@Override
public void onTimer(String timerName) {
if (timerName.equals(TIMER_NAME_INTERIM)) {
if (timerName.equals(IDLE_SESSION_TIMER_NAME)) {
checkIdleAppSession();
}
else if (timerName.equals(TIMER_NAME_INTERIM)) {
if (context != null) {
try {
Request interimRecord = createInterimRecord();
Expand All @@ -626,6 +629,9 @@ public void onTimer(String timerName) {
}
}
}
else {
logger.warn("Received an unknown timer '{}' for Session-ID '{}'", timerName, getSessionId());
}
}

private void startInterimTimer(long v) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -639,9 +639,15 @@ protected void stopTx() {
*/
@Override
public void onTimer(String timerName) {
if (timerName.equals(TX_TIMER_NAME)) {
if (timerName.equals(IDLE_SESSION_TIMER_NAME)) {
checkIdleAppSession();
}
else if (timerName.equals(TX_TIMER_NAME)) {
new TxTimerTask(this, sessionData.getTxTimerRequest()).run();
}
else {
logger.warn("Received an unknown timer '{}' for Session-ID '{}'", timerName, getSessionId());
}
}

protected void setState(ClientRoSessionState newState) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -890,5 +890,11 @@ else if (!sessionData.getClientRxSessionState().equals(other.sessionData.getClie

@Override
public void onTimer(String timerName) {
if (timerName.equals(IDLE_SESSION_TIMER_NAME)) {
checkIdleAppSession();
}
else {
logger.warn("Received an unknown timer '{}' for Session-ID '{}'", timerName, getSessionId());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,10 @@ protected void setState(S13SessionState newState) {

@Override
public void onTimer(String timerName) {
if (timerName.equals(S13Session.TIMER_NAME_MSG_TIMEOUT)) {
if (timerName.equals(IDLE_SESSION_TIMER_NAME)) {
checkIdleAppSession();
}
else if (timerName.equals(S13Session.TIMER_NAME_MSG_TIMEOUT)) {
try {
sendAndStateLock.lock();
try {
Expand All @@ -223,6 +226,9 @@ public void onTimer(String timerName) {
sendAndStateLock.unlock();
}
}
else {
logger.warn("Received an unknown timer '{}' for Session-ID '{}'", timerName, getSessionId());
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,10 @@ protected void setState(S6aSessionState newState) {
*/
@Override
public void onTimer(String timerName) {
if (timerName.equals(S6aSession.TIMER_NAME_MSG_TIMEOUT)) {
if (timerName.equals(IDLE_SESSION_TIMER_NAME)) {
checkIdleAppSession();
}
else if (timerName.equals(S6aSession.TIMER_NAME_MSG_TIMEOUT)) {
try {
sendAndStateLock.lock();
try {
Expand All @@ -387,6 +390,9 @@ public void onTimer(String timerName) {
sendAndStateLock.unlock();
}
}
else {
logger.warn("Received an unknown timer '{}' for Session-ID '{}'", timerName, getSessionId());
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,12 @@ public boolean isReplicable() {

@Override
public void onTimer(String timerName) {
// TODO ...
if (timerName.equals(IDLE_SESSION_TIMER_NAME)) {
checkIdleAppSession();
}
else {
logger.warn("Received an unknown timer '{}' for Session-ID '{}'", timerName, getSessionId());
}
}

private class RequestDelivery implements Runnable {
Expand Down
Loading

0 comments on commit a719ece

Please sign in to comment.