Author: ngn
Date: Mon Aug 16 20:03:40 2010
New Revision: 986118
URL: http://svn.apache.org/viewvc?rev=986118&view=rev
Log:
Finished client ack implementation (VYSPER-239, 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/BoshResponse.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=986118&r1=986117&r2=986118&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:03:40 2010
@@ -56,6 +56,12 @@ public class BoshBackedSessionContext ex
private final int maximumSentResponses = 10;
/*
+ * The number of milliseconds that will have to pass for a response to be
reported missing to the client by
+ * responding with a report and time attributes. See Response
Acknowledgements in XEP-0124.
+ */
+ private final int brokenConnectionReportTimeout = 1000;
+
+ /*
* Keeps the suspended HTTP requests (does not respond to them) until the
server has an asynchronous message
* to send to the client. (Comet HTTP Long Polling technique - described
in XEP-0124)
*
@@ -211,9 +217,9 @@ public class BoshBackedSessionContext ex
private void error(BoshRequest br, String condition) {
requestsWindow.put(br.getRid(), br);
BoshRequest req = requestsWindow.remove(requestsWindow.firstKey());
- Stanza stanza = boshHandler.getTerminateResponse();
- stanza = boshHandler.addAttribute(stanza, "condition", condition);
- BoshResponse boshResponse = getBoshResponse(stanza, null);
+ Stanza body = boshHandler.getTerminateResponse();
+ body = boshHandler.addAttribute(body, "condition", condition);
+ BoshResponse boshResponse = getBoshResponse(body, null);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("BOSH writing response: {}", new
String(boshResponse.getContent()));
}
@@ -227,9 +233,17 @@ public class BoshBackedSessionContext ex
* Terminates the BOSH session
*/
synchronized public void close() {
- // respond to all the queued HTTP requests with empty responses
+ // respond to all the queued HTTP requests with termination responses
while (!requestsWindow.isEmpty()) {
- write0(boshHandler.getEmptyResponse());
+ BoshRequest req = requestsWindow.remove(requestsWindow.firstKey());
+ Stanza body = boshHandler.getTerminateResponse();
+ BoshResponse boshResponse = getBoshResponse(body, null);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("BOSH writing response: {}", new
String(boshResponse.getContent()));
+ }
+ Continuation continuation =
ContinuationSupport.getContinuation(req.getHttpServletRequest());
+ continuation.setAttribute("response", boshResponse);
+ continuation.resume();
}
serverRuntimeContext.getResourceRegistry().unbindSession(this);
@@ -434,10 +448,6 @@ public class BoshBackedSessionContext ex
}
latestEmptyPollingRequest = br;
}
- if (isClientAcknowledgements()) {
- // TODO: if received client ack is not the expected one, then send
a response report to the client informing him about this,
- // so that he could rerequest the missing responses.
- }
requestsWindow.put(br.getRid(), br);
if (highestReadRid == null) {
@@ -453,6 +463,27 @@ public class BoshBackedSessionContext ex
}
}
+ if (isClientAcknowledgements()) {
+ if (br.getBody().getAttribute("ack") == null) {
+ // if there is no ack attribute present then the client
confirmed it received all the responses to all the previous requests
+ // and we clear the cache
+ sentResponses.clear();
+ } else if (!sentResponses.isEmpty()) {
+ // After receiving a request with an 'ack' value less than the
'rid' of the last request that it has already responded to,
+ // the connection manager MAY inform the client of the
situation. In this case it SHOULD include a 'report' attribute set
+ // to one greater than the 'ack' attribute it received from
the client, and a 'time' attribute set to the number of milliseconds
+ // since it sent the response associated with the 'report'
attribute.
+ long ack =
Long.parseLong(br.getBody().getAttributeValue("ack"));
+ if (ack < sentResponses.lastKey() &&
sentResponses.containsKey(ack + 1)) {
+ long delta = System.currentTimeMillis() -
sentResponses.get(ack + 1).getTimestamp();
+ if (delta >= brokenConnectionReportTimeout) {
+ sendBrokenConnectionReport(ack + 1, delta);
+ 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;
@@ -472,6 +503,13 @@ public class BoshBackedSessionContext ex
}
}
+ private void sendBrokenConnectionReport(long report, long delta) {
+ Stanza body = boshHandler.getTerminateResponse();
+ body = boshHandler.addAttribute(body, "report", Long.toString(report));
+ body = boshHandler.addAttribute(body, "time", Long.toString(delta));
+ write0(body);
+ }
+
private void addContinuationExpirationListener(Continuation continuation) {
// listen the continuation to be notified when the request expires
continuation.addContinuationListener(new ContinuationListener() {
Modified:
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshResponse.java
URL:
http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshResponse.java?rev=986118&r1=986117&r2=986118&view=diff
==============================================================================
---
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshResponse.java
(original)
+++
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshResponse.java
Mon Aug 16 20:03:40 2010
@@ -30,9 +30,12 @@ public class BoshResponse {
private final byte[] content;
+ private final long timestamp;
+
public BoshResponse(String contentType, byte[] content) {
this.contentType = contentType;
this.content = content;
+ timestamp = System.currentTimeMillis();
}
public String getContentType() {
@@ -43,4 +46,8 @@ public class BoshResponse {
return content;
}
+ public long getTimestamp() {
+ return timestamp;
+ }
+
}