You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by ng...@apache.org on 2010/08/16 22:28:52 UTC
svn commit: r986126 - in
/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124:
BoshBackedSessionContext.java BoshHandler.java
Author: ngn
Date: Mon Aug 16 20:28:52 2010
New Revision: 986126
URL: http://svn.apache.org/viewvc?rev=986126&view=rev
Log:
Adding support for detecting inactivity (VYSPER-240, by Bogdan Pistol)
Adding support for pause (VYSPER-241, by Bogdan Pistol)
Modified:
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java
Modified: mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java?rev=986126&r1=986125&r2=986126&view=diff
==============================================================================
--- mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java (original)
+++ mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContext.java Mon Aug 16 20:28:52 2010
@@ -22,6 +22,8 @@ package org.apache.vysper.xmpp.extension
import java.util.LinkedList;
import java.util.Queue;
import java.util.SortedMap;
+import java.util.Timer;
+import java.util.TimerTask;
import java.util.TreeMap;
import org.apache.vysper.xml.fragment.Renderer;
@@ -48,6 +50,8 @@ public class BoshBackedSessionContext ex
private final static Logger LOGGER = LoggerFactory.getLogger(BoshBackedSessionContext.class);
private final BoshHandler boshHandler;
+
+ private final int maxpause = 120;
private final int inactivity = 60;
@@ -91,6 +95,8 @@ public class BoshBackedSessionContext ex
private int hold = 1;
+ private int currentInactivity = inactivity;
+
/*
* The highest RID that can be read and processed, this is the highest (rightmost) contiguous RID.
* The requests from the client can come theoretically with missing updates:
@@ -107,6 +113,14 @@ public class BoshBackedSessionContext ex
* attribute in any request is meaningful.
*/
private boolean clientAcknowledgements;
+
+ /*
+ * The timestamp of the latest response wrote to the client is used to measure the inactivity period.
+ * When reaching the maximum inactivity the session will automatically close.
+ */
+ private long latestWriteTimestamp = System.currentTimeMillis();
+
+ private Timer inactivityChecker = new Timer(true);
/**
* Creates a new context for a session
@@ -126,6 +140,25 @@ public class BoshBackedSessionContext ex
}
/**
+ * Periodically checks if the session reached the maximum inactivity period.
+ */
+ public void startInactivityChecker() {
+ inactivityChecker.schedule(new TimerTask() {
+
+ @Override
+ public void run() {
+ synchronized (BoshBackedSessionContext.this) {
+ if (System.currentTimeMillis() - latestWriteTimestamp >= currentInactivity * 1000 && requestsWindow.isEmpty()) {
+ LOGGER.info("BOSH session reached maximum inactivity period, closing session...");
+ close();
+ }
+ }
+ }
+
+ }, 1000, 1000);
+ }
+
+ /**
* Returns the highest RID that is received in a continuous (uninterrupted) sequence of RIDs.
* Higher RIDs can exist with gaps separating them from the highestReadRid.
* @return the highest continuous RID received so far
@@ -189,6 +222,7 @@ public class BoshBackedSessionContext ex
Continuation continuation = ContinuationSupport.getContinuation(req.getHttpServletRequest());
continuation.setAttribute("response", boshResponse);
continuation.resume();
+ latestWriteTimestamp = System.currentTimeMillis();
}
private boolean isResponseSavable(BoshRequest req, Stanza response) {
@@ -249,6 +283,8 @@ public class BoshBackedSessionContext ex
serverRuntimeContext.getResourceRegistry().unbindSession(this);
sessionStateHolder.setState(SessionState.CLOSED);
+ inactivityChecker.cancel();
+
LOGGER.info("BOSH session {} closed", getSessionId());
}
@@ -272,6 +308,14 @@ public class BoshBackedSessionContext ex
public String getContentType() {
return contentType;
}
+
+ /**
+ * Getter for the maximum length of a temporary session pause (in seconds) that a client can request
+ * @return
+ */
+ public int getMaxPause() {
+ return maxpause;
+ }
/**
* Setter for the BOSH 'wait' parameter, the longest time (in seconds) that the connection manager is allowed to
@@ -404,6 +448,9 @@ public class BoshBackedSessionContext ex
* @param req the HTTP request
*/
public void insertRequest(BoshRequest br) {
+ // reset the inactivity
+ currentInactivity = inactivity;
+
Continuation continuation = ContinuationSupport.getContinuation(br.getHttpServletRequest());
addContinuationExpirationListener(continuation);
continuation.setTimeout(wait * 1000);
@@ -484,6 +531,21 @@ public class BoshBackedSessionContext ex
}
}
+ // we cannot pause if there are missing requests, this is tested with
+ // br.getRid().equals(requestsWindow.lastKey()) && highestReadRid.equals(br.getRid())
+ if (br.getBody().getAttribute("pause") != null && br.getRid().equals(requestsWindow.lastKey()) && highestReadRid.equals(br.getRid())) {
+ int pause = Integer.parseInt(br.getBody().getAttributeValue("pause"));
+ if (pause > maxpause) {
+ // do not allow to pause more than maxpause
+ pause = maxpause;
+ }
+ if (pause < 0) {
+ pause = 0;
+ }
+ respondToPause(pause);
+ return;
+ }
+
// If there are delayed responses waiting to be sent to the BOSH client, then we wrap them all in
// a <body/> element and send them as a HTTP response to the current HTTP request.
Stanza delayedResponse;
@@ -503,6 +565,18 @@ public class BoshBackedSessionContext ex
}
}
+ private void respondToPause(int pause) {
+ LOGGER.debug("Setting inactivity period to {}", pause);
+ currentInactivity = pause;
+ for (;;) {
+ BoshRequest boshRequest = getNextRequest();
+ if (boshRequest == null) {
+ break;
+ }
+ write0(boshHandler.getEmptyResponse());
+ }
+ }
+
private void sendBrokenConnectionReport(long report, long delta) {
Stanza body = boshHandler.getTerminateResponse();
body = boshHandler.addAttribute(body, "report", Long.toString(report));
@@ -533,6 +607,7 @@ public class BoshBackedSessionContext ex
Continuation continuation = ContinuationSupport.getContinuation(br.getHttpServletRequest());
continuation.setAttribute("response", boshResponse);
continuation.resume();
+ latestWriteTimestamp = System.currentTimeMillis();
}
private BoshResponse getBoshResponse(Stanza stanza, Long ack) {
Modified: mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java
URL: http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java?rev=986126&r1=986125&r2=986126&view=diff
==============================================================================
--- mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java (original)
+++ mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandler.java Mon Aug 16 20:28:52 2010
@@ -196,6 +196,7 @@ public class BoshHandler {
if ("1".equals(br.getBody().getAttributeValue("ack"))) {
session.setClientAcknowledgements(true);
}
+ session.startInactivityChecker();
session.insertRequest(br);
sessions.put(session.getSessionId(), session);
@@ -213,6 +214,7 @@ public class BoshHandler {
body.addAttribute("ver", session.getBoshVersion());
body.addAttribute("from", session.getServerJID().getFullQualifiedName());
body.addAttribute("secure", "true");
+ body.addAttribute("maxpause", Integer.toString(session.getMaxPause()));
// adding the ack attribute here is needed because when responding to o request with the same RID (as is the case here)
// the ack would not be included on BoshBackedSessionContext#write0, but this first ack is required.