Author: berndf
Date: Wed Apr 18 14:36:32 2012
New Revision: 1327524
URL: http://svn.apache.org/viewvc?rev=1327524&view=rev
Log:
VYSPER-304, VYSPER-305: BOSH: guard central context state fields against race
conditions, make some methods and var names more expressive, add debug logging,
use static final object for empty stanza, do not queue empty stanzas
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
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshServlet.java
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/test/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContextTest.java
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/test/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandlerTest.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=1327524&r1=1327523&r2=1327524&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
Wed Apr 18 14:36:32 2012
@@ -24,6 +24,7 @@ import java.util.Queue;
import java.util.SortedMap;
import java.util.TreeMap;
+import org.apache.commons.lang.StringUtils;
import org.apache.vysper.xml.fragment.Renderer;
import org.apache.vysper.xml.fragment.XMLElement;
import org.apache.vysper.xmpp.protocol.SessionStateHolder;
@@ -69,19 +70,19 @@ public class BoshBackedSessionContext ex
*
* The BOSH requests are sorted by their RIDs.
*/
- private final SortedMap<Long, BoshRequest> requestsWindow;
+ private final SortedMap<Long, BoshRequest> requestsWindow = new
TreeMap<Long, BoshRequest>();
/*
* Keeps the asynchronous messages sent from server that cannot be
delivered to the client because there are
* no available HTTP requests to respond to (requestsWindow is empty).
*/
- private final Queue<Stanza> delayedResponseQueue;
+ private final Queue<Stanza> delayedResponseQueue = new
LinkedList<Stanza>();
/*
* A cache of sent responses to the BOSH client, kept in the event of
delivery failure and retransmission requests.
* See Broken Connections in XEP-0124.
*/
- private final SortedMap<Long, BoshResponse> sentResponses;
+ private final SortedMap<Long, BoshResponse> sentResponses = new
TreeMap<Long, BoshResponse>();
private int requests = 2;
@@ -99,11 +100,20 @@ public class BoshBackedSessionContext ex
* 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:
* rid_1, rid_2, rid_4 (missing rid_3, highestReadRid is rid_2)
+ *
+ * must be synchronized along with requestsWindow
*/
private Long highestReadRid = null;
-
+
+ /**
+ *
+ * must be synchronized along with requestsWindow
+ */
private Long currentProcessingRequest = null;
-
+
+ /**
+ * must be synchronized along with requestsWindow
+ */
private BoshRequest latestEmptyPollingRequest = null;
/*
@@ -137,10 +147,7 @@ public class BoshBackedSessionContext ex
sessionStateHolder.setState(SessionState.ENCRYPTED);
this.boshHandler = boshHandler;
- requestsWindow = new TreeMap<Long, BoshRequest>();
- delayedResponseQueue = new LinkedList<Stanza>();
- sentResponses = new TreeMap<Long, BoshResponse>();
-
+
this.inactivityChecker = inactivityChecker;
updateInactivityChecker();
}
@@ -149,11 +156,11 @@ public class BoshBackedSessionContext ex
return isWatchedByInactivityChecker;
}
- private void updateInactivityChecker() {
+ private synchronized void updateInactivityChecker() {
Long newInactivityExpireTime = null;
if (requestsWindow.isEmpty()) {
newInactivityExpireTime = latestWriteTimestamp +
currentInactivity * 1000;
- if (newInactivityExpireTime == lastInactivityExpireTime) {
+ if (newInactivityExpireTime.equals(lastInactivityExpireTime)) {
return;
}
} else if (!isWatchedByInactivityChecker) {
@@ -189,7 +196,9 @@ public class BoshBackedSessionContext ex
* This method is synchronized on the session object to prevent
concurrent writes to the same BOSH client
*/
synchronized public void write(Stanza stanza) {
- write0(boshHandler.wrapStanza(stanza));
+ if (stanza == null) throw new IllegalArgumentException("stanza must not be
null.");
+ LOGGER.debug("adding server stanza for writing to BOSH client");
+ writeBOSHResponse(boshHandler.wrapStanza(stanza));
}
/**
@@ -198,29 +207,43 @@ public class BoshBackedSessionContext ex
*<p>
* (package access)
*
- * @param response The BOSH response to write
+ * @param responseStanza The BOSH response to write
*/
- void write0(Stanza response) {
+ /*package*/ void writeBOSHResponse(Stanza responseStanza) {
+ if (responseStanza == null) throw new IllegalArgumentException();
+ final boolean isEmtpyResponse = responseStanza ==
BoshHandler.EMPTY_BOSH_RESPONSE;
+
BoshRequest req;
- if (requestsWindow.isEmpty() || requestsWindow.firstKey()>
highestReadRid) {
- delayedResponseQueue.offer(response);
- return;
- } else {
+ BoshResponse boshResponse;
+ synchronized (requestsWindow) {
+ if (requestsWindow.isEmpty() || requestsWindow.firstKey()>
highestReadRid) {
+ if (isEmtpyResponse) return; // do not delay empty responses
+ final boolean accepted =
delayedResponseQueue.offer(responseStanza);
+ if (!accepted) {
+ LOGGER.debug("rid = {} - request not queued. BOSH
delayedResponseQueue is full: {}",
+ requestsWindow.firstKey(),
delayedResponseQueue.size());
+ // TODO do not silently drop this stanza
+ }
+ return;
+ }
req = requestsWindow.remove(requestsWindow.firstKey());
+ boshResponse = getBoshResponse(responseStanza,
req.getRid().equals(highestReadRid) ? null : highestReadRid);
+ if (LOGGER.isDebugEnabled()) {
+ String emptyHint = isEmtpyResponse ? "empty " :
StringUtils.EMPTY;
+ LOGGER.debug("rid = " + req.getRid() + " - BOSH writing {}response:
{}", emptyHint, new String(boshResponse.getContent()));
+ }
}
- BoshResponse boshResponse = getBoshResponse(response,
req.getRid().equals(highestReadRid) ? null : highestReadRid);
- if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("BOSH writing response: {}", new
String(boshResponse.getContent()));
- }
-
- if (isResponseSavable(req, response)) {
- sentResponses.put(req.getRid(), boshResponse);
- // The number of responses to non-pause requests kept in the
buffer SHOULD be either the same as the maximum
- // number of simultaneous requests allowed or, if Acknowledgements
are being used, the number of responses
- // that have not yet been acknowledged (this part is handled in
insertRequest(BoshRequest)), or
- // the hard limit maximumSentResponses (not in the specification)
that prevents excessive memory consumption.
- if (sentResponses.size()> maximumSentResponses ||
(!isClientAcknowledgements()&& sentResponses.size()> requests)) {
- sentResponses.remove(sentResponses.firstKey());
+
+ if (isResponseSavable(req, responseStanza)) {
+ synchronized (sentResponses) {
+ sentResponses.put(req.getRid(), boshResponse);
+ // The number of responses to non-pause requests kept in the
buffer SHOULD be either the same as the maximum
+ // number of simultaneous requests allowed or, if
Acknowledgements are being used, the number of responses
+ // that have not yet been acknowledged (this part is handled
in insertRequest(BoshRequest)), or
+ // the hard limit maximumSentResponses (not in the
specification) that prevents excessive memory consumption.
+ if (sentResponses.size()> maximumSentResponses ||
(!isClientAcknowledgements()&& sentResponses.size()> requests)) {
+ sentResponses.remove(sentResponses.firstKey());
+ }
}
}
@@ -231,7 +254,7 @@ public class BoshBackedSessionContext ex
updateInactivityChecker();
}
- private boolean isResponseSavable(BoshRequest req, Stanza response) {
+ private static boolean isResponseSavable(BoshRequest req, Stanza response)
{
// responses to pause requests are not saved
if (req.getBody().getAttributeValue("pause") != null) {
return false;
@@ -255,13 +278,14 @@ public class BoshBackedSessionContext ex
* @param condition the error condition
*/
private void error(BoshRequest br, String condition) {
- requestsWindow.put(br.getRid(), br);
+ final Long rid = br.getRid();
+ requestsWindow.put(rid, br);
BoshRequest req = requestsWindow.remove(requestsWindow.firstKey());
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()));
+ LOGGER.debug("rid = {} - BOSH writing response: {}", rid, new
String(boshResponse.getContent()));
}
Continuation continuation =
ContinuationSupport.getContinuation(req.getHttpServletRequest());
continuation.setAttribute("response", boshResponse);
@@ -279,7 +303,7 @@ public class BoshBackedSessionContext ex
Stanza body = boshHandler.getTerminateResponse();
BoshResponse boshResponse = getBoshResponse(body, null);
if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("BOSH writing response: {}", new
String(boshResponse.getContent()));
+ LOGGER.debug("rid = {} - BOSH writing response: {}",
req.getRid(), new String(boshResponse.getContent()));
}
Continuation continuation =
ContinuationSupport.getContinuation(req.getHttpServletRequest());
continuation.setAttribute("response", boshResponse);
@@ -443,8 +467,9 @@ public class BoshBackedSessionContext ex
LOGGER.warn("Continuation expired without having an associated
request!");
return;
}
+ LOGGER.debug("rid = {} - BOSH request expired", req.getRid());
while (!requestsWindow.isEmpty()&& requestsWindow.firstKey()<=
req.getRid()) {
- write0(boshHandler.getEmptyResponse());
+ writeBOSHResponse(BoshHandler.EMPTY_BOSH_RESPONSE);
}
}
@@ -455,6 +480,10 @@ public class BoshBackedSessionContext ex
* @param req the HTTP request
*/
public void insertRequest(BoshRequest br) {
+
+ final Long rid = br.getRid();
+ LOGGER.debug("rid = {} - inserting new BOSH request", rid);
+
// reset the inactivity
currentInactivity = inactivity;
@@ -463,78 +492,87 @@ public class BoshBackedSessionContext ex
continuation.setTimeout(wait * 1000);
continuation.setAttribute("request", br);
continuation.suspend();
-
- if (highestReadRid != null&& highestReadRid + requests< br.getRid())
{
- LOGGER.warn("BOSH received RID greater than the permitted window of
concurrent requests");
- error(br, "item-not-found");
- return;
- }
- if (highestReadRid != null&& br.getRid()<= highestReadRid) {
- if (sentResponses.containsKey(br.getRid())) {
- // Resending the old response
- resendResponse(br);
- } else {
- LOGGER.warn("BOSH response not in buffer error");
+
+ final int currentRequests = requests;
+ synchronized (requestsWindow) {
+ if (highestReadRid != null&& highestReadRid + currentRequests<
rid) {
+ LOGGER.warn("rid = {} - received RID>= the permitted window of
concurrent requests ({})",
+ rid, highestReadRid);
error(br, "item-not-found");
+ return;
}
- return;
- }
- if (requestsWindow.size() + 1> requests&&
!"terminate".equals(br.getBody().getAttributeValue("type"))
-&& br.getBody().getAttributeValue("pause") == null) {
- LOGGER.warn("BOSH Overactivity: Too many simultaneous requests");
- error(br, "policy-violation");
- return;
- }
- if (requestsWindow.size() + 1 == requests&&
!"terminate".equals(br.getBody().getAttributeValue("type"))
-&& br.getBody().getAttributeValue("pause") == null&&
br.getBody().getInnerElements().isEmpty()) {
- if (!requestsWindow.isEmpty()
-&& br.getTimestamp() -
requestsWindow.get(requestsWindow.lastKey()).getTimestamp()< polling * 1000) {
- LOGGER.warn("BOSH Overactivity: Too frequent requests");
- error(br, "policy-violation");
+ if (highestReadRid != null&& rid<= highestReadRid) {
+ synchronized (sentResponses) {
+ if (sentResponses.containsKey(rid)) {
+ // Resending the old response
+ resendResponse(br);
+ } else {
+ LOGGER.warn("rid = {} - BOSH response not in buffer
error");
+ error(br, "item-not-found");
+ }
+ }
return;
}
- }
- if ((wait == 0 || hold == 0)&&
br.getBody().getInnerElements().isEmpty()) {
- if (latestEmptyPollingRequest != null&& br.getTimestamp() -
latestEmptyPollingRequest.getTimestamp()< polling * 1000) {
- LOGGER.warn("BOSH Overactivity for polling: Too frequent
requests");
+ if (requestsWindow.size() + 1> currentRequests&&
!"terminate".equals(br.getBody().getAttributeValue("type"))
+&& br.getBody().getAttributeValue("pause") == null) {
+ LOGGER.warn("BOSH Overactivity: Too many simultaneous
requests");
error(br, "policy-violation");
return;
}
- latestEmptyPollingRequest = br;
- }
-
- requestsWindow.put(br.getRid(), br);
- updateInactivityChecker();
-
- if (highestReadRid == null) {
- highestReadRid = br.getRid();
- }
- for (;;) {
- // update the highestReadRid to the latest value
- // it is possible to have higher RIDs than the highestReadRid with
a gap between them (e.g. lost client request)
- if (requestsWindow.containsKey(highestReadRid + 1)) {
- highestReadRid++;
- } else {
- break;
+ if (requestsWindow.size() + 1 == currentRequests&&
!"terminate".equals(br.getBody().getAttributeValue("type"))
+&& br.getBody().getAttributeValue("pause") == null&&
br.getBody().getInnerElements().isEmpty()) {
+ if (!requestsWindow.isEmpty()
+&& br.getTimestamp() -
requestsWindow.get(requestsWindow.lastKey()).getTimestamp()< polling * 1000) {
+ LOGGER.warn("BOSH Overactivity: Too frequent requests");
+ error(br, "policy-violation");
+ return;
+ }
+ }
+ if ((wait == 0 || hold == 0)&&
br.getBody().getInnerElements().isEmpty()) {
+ if (latestEmptyPollingRequest != null&& br.getTimestamp() -
latestEmptyPollingRequest.getTimestamp()< polling * 1000) {
+ LOGGER.warn("BOSH Overactivity for polling: Too frequent
requests");
+ error(br, "policy-violation");
+ return;
+ }
+ latestEmptyPollingRequest = br;
+ }
+
+ requestsWindow.put(rid, br);
+ updateInactivityChecker();
+
+ if (highestReadRid == null) {
+ highestReadRid = rid;
+ }
+ for (;;) {
+ // update the highestReadRid to the latest value
+ // it is possible to have higher RIDs than the highestReadRid
with a gap between them (e.g. lost client request)
+ if (requestsWindow.containsKey(highestReadRid + 1)) {
+ highestReadRid++;
+ } else {
+ break;
+ }
}
}
-
+
+
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;
+ synchronized (sentResponses) {
+ 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;
+ }
}
}
}
@@ -542,19 +580,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;
+ synchronized (requestsWindow) {
+ if (br.getBody().getAttribute("pause") != null&&
rid.equals(requestsWindow.lastKey())&& highestReadRid.equals(rid)) {
+ 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;
}
- 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;
@@ -563,14 +603,14 @@ public class BoshBackedSessionContext ex
mergedResponse = boshHandler.mergeResponses(mergedResponse,
delayedResponse);
}
if (mergedResponse != null) {
- write0(mergedResponse);
+ writeBOSHResponse(mergedResponse);
return;
}
// If there are more suspended enqueued requests than it is allowed
by the BOSH 'hold' parameter,
// than we release the oldest one by sending an empty response.
if (requestsWindow.size()> hold) {
- write0(boshHandler.getEmptyResponse());
+ writeBOSHResponse(BoshHandler.EMPTY_BOSH_RESPONSE);
}
}
@@ -582,7 +622,7 @@ public class BoshBackedSessionContext ex
if (boshRequest == null) {
break;
}
- write0(boshHandler.getEmptyResponse());
+ writeBOSHResponse(BoshHandler.EMPTY_BOSH_RESPONSE);
}
}
@@ -590,7 +630,7 @@ public class BoshBackedSessionContext ex
Stanza body = boshHandler.getTerminateResponse();
body = boshHandler.addAttribute(body, "report",
Long.toString(report));
body = boshHandler.addAttribute(body, "time", Long.toString(delta));
- write0(body);
+ writeBOSHResponse(body);
}
private void addContinuationExpirationListener(Continuation continuation)
{
@@ -609,9 +649,14 @@ public class BoshBackedSessionContext ex
}
private void resendResponse(BoshRequest br) {
- BoshResponse boshResponse = sentResponses.get(br.getRid());
+ final Long rid = br.getRid();
+ BoshResponse boshResponse = sentResponses.get(rid);
+ if (boshResponse == null) {
+ LOGGER.debug("rid = {} - BOSH response could not (no longer) be
retrieved for resending.", rid);
+ return;
+ }
if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("BOSH writing response: {}", new
String(boshResponse.getContent()));
+ LOGGER.debug("rid = {} - BOSH writing response (resending): {}",
rid, new String(boshResponse.getContent()));
}
Continuation continuation =
ContinuationSupport.getContinuation(br.getHttpServletRequest());
continuation.setAttribute("response", boshResponse);
@@ -634,17 +679,19 @@ public class BoshBackedSessionContext ex
* @return the next (by RID order) body to process
*/
public BoshRequest getNextRequest() {
- if (requestsWindow.isEmpty()) {
- return null;
- }
- if (currentProcessingRequest == null || currentProcessingRequest<
requestsWindow.firstKey()) {
- currentProcessingRequest = requestsWindow.firstKey();
- }
- if (currentProcessingRequest> highestReadRid) {
- return null;
- } else {
- currentProcessingRequest++;
- return requestsWindow.get(currentProcessingRequest - 1);
+ synchronized (requestsWindow) {
+ if (requestsWindow.isEmpty()) {
+ return null;
+ }
+ if (currentProcessingRequest == null || currentProcessingRequest<
requestsWindow.firstKey()) {
+ currentProcessingRequest = requestsWindow.firstKey();
+ }
+ if (currentProcessingRequest> highestReadRid) {
+ return null;
+ } else {
+ currentProcessingRequest++;
+ return requestsWindow.get(currentProcessingRequest - 1);
+ }
}
}
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=1327524&r1=1327523&r2=1327524&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
Wed Apr 18 14:36:32 2012
@@ -46,6 +46,13 @@ import org.slf4j.LoggerFactory;
public class BoshHandler {
private static final Logger LOGGER =
LoggerFactory.getLogger(BoshHandler.class);
+
+ /**
+ * the empty BOSH response.
+ *<p>
+ * Looks like<code><body
xmlns='http://jabber.org/protocol/httpbind'/></code>
+ */
+ protected static final Stanza EMPTY_BOSH_RESPONSE = new
StanzaBuilder("body", NamespaceURIs.XEP0124_BOSH).build();
private ServerRuntimeContext serverRuntimeContext;
@@ -143,7 +150,7 @@ public class BoshHandler {
} else if (session.getState() == SessionState.AUTHENTICATED) {
if
("true".equals(br.getBody().getAttributeValue(NamespaceURIs.URN_XMPP_XBOSH,
"restart"))) {
// restart request
- session.write0(getRestartResponse());
+ session.writeBOSHResponse(getRestartResponse());
} else {
// any other request
for (XMLElement element : br.getBody().getInnerElements()) {
@@ -160,7 +167,7 @@ public class BoshHandler {
private void terminateSession(BoshBackedSessionContext session) {
sessions.remove(session.getSessionId());
- session.write0(getTerminateResponse());
+ session.writeBOSHResponse(getTerminateResponse());
session.close();
}
@@ -203,7 +210,7 @@ public class BoshHandler {
session.insertRequest(br);
sessions.put(session.getSessionId(), session);
- session.write0(getSessionCreationResponse(session));
+ session.writeBOSHResponse(getSessionCreationResponse(session));
}
private Stanza getSessionCreationResponse(BoshBackedSessionContext
session) {
@@ -230,17 +237,6 @@ public class BoshHandler {
}
/**
- * Creates an empty BOSH response.
- *<p>
- * The empty BOSH response looks like<code><body
xmlns='http://jabber.org/protocol/httpbind'/></code>
- * @return the empty BOSH response
- */
- public Stanza getEmptyResponse() {
- StanzaBuilder stanzaBuilder = new StanzaBuilder("body",
NamespaceURIs.XEP0124_BOSH);
- return stanzaBuilder.build();
- }
-
- /**
* Creates a BOSH response by wrapping a stanza in a<body/> element
* @param stanza the XMPP stanza to wrap
* @return the BOSH response
Modified:
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshServlet.java
URL:
http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshServlet.java?rev=1327524&r1=1327523&r2=1327524&view=diff
==============================================================================
---
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshServlet.java
(original)
+++
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/main/java/org/apache/vysper/xmpp/extension/xep0124/BoshServlet.java
Wed Apr 18 14:36:32 2012
@@ -52,7 +52,7 @@ public class BoshServlet extends HttpSer
private static final String INFO_GET = "This is an XMPP BOSH connection
manager, only POST is allowed";
- private static final String SERVER_IDENTIFICATION = "Vysper/0.5";
+ private static final String SERVER_IDENTIFICATION = "Vysper/0.8";
private final Logger logger = LoggerFactory.getLogger(BoshServlet.class);
Modified:
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/test/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContextTest.java
URL:
http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/test/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContextTest.java?rev=1327524&r1=1327523&r2=1327524&view=diff
==============================================================================
---
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/test/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContextTest.java
(original)
+++
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/test/java/org/apache/vysper/xmpp/extension/xep0124/BoshBackedSessionContextTest.java
Wed Apr 18 14:36:32 2012
@@ -88,7 +88,7 @@ public class BoshBackedSessionContextTes
BoshBackedSessionContext boshBackedSessionContext = new
BoshBackedSessionContext(boshHandler, serverRuntimeContext, inactivityChecker);
Stanza body = new StanzaBuilder("body",
NamespaceURIs.XEP0124_BOSH).build();
boshBackedSessionContext.insertRequest(new
BoshRequest(httpServletRequest, body, 1L));
- boshBackedSessionContext.write0(body);
+ boshBackedSessionContext.writeBOSHResponse(body);
mocksControl.verify();
BoshResponse boshResponse = captured.getValue();
@@ -116,7 +116,7 @@ public class BoshBackedSessionContextTes
@Test
public void testRequestExpired() {
- Stanza body = new StanzaBuilder("body",
NamespaceURIs.XEP0124_BOSH).build();
+ Stanza emtpyStanza = new StanzaBuilder("body",
NamespaceURIs.XEP0124_BOSH).build();
// addRequest
HttpServletRequest httpServletRequest =
mocksControl.createMock(HttpServletRequest.class);
@@ -130,16 +130,13 @@ public class BoshBackedSessionContextTes
Capture<ContinuationListener> listenerCaptured = new
Capture<ContinuationListener>();
continuation.addContinuationListener(EasyMock.<ContinuationListener>
capture(listenerCaptured));
- BoshRequest br = new BoshRequest(httpServletRequest, body, 1L);
+ BoshRequest br = new BoshRequest(httpServletRequest, emtpyStanza, 1L);
// requestExpired
expect(continuation.getAttribute("request")).andReturn(br);
Capture<BoshResponse> responseCaptured = new Capture<BoshResponse>();
continuation.setAttribute(eq("response"), EasyMock.<BoshResponse>
capture(responseCaptured));
- expect(boshHandler.getEmptyResponse()).andReturn(body);
- expectLastCall().atLeastOnce();
-
// write0
continuation.resume();
@@ -150,7 +147,7 @@ public class BoshBackedSessionContextTes
listenerCaptured.getValue().onTimeout(continuation);
mocksControl.verify();
- assertEquals(new Renderer(body).getComplete(), new
String(responseCaptured.getValue().getContent()));
+ assertEquals(new Renderer(emtpyStanza).getComplete(), new
String(responseCaptured.getValue().getContent()));
assertEquals(BoshServlet.XML_CONTENT_TYPE,
responseCaptured.getValue().getContentType());
}
@@ -191,7 +188,7 @@ public class BoshBackedSessionContextTes
// consecutive writes with RID 1 and 2
boshBackedSessionContext.insertRequest(new
BoshRequest(httpServletRequest1, body, 1L));
boshBackedSessionContext.insertRequest(new
BoshRequest(httpServletRequest2, body, 2L));
- boshBackedSessionContext.write0(body);
+ boshBackedSessionContext.writeBOSHResponse(body);
mocksControl.verify();
assertEquals(httpServletRequest1,
br1.getValue().getHttpServletRequest());
@@ -227,8 +224,8 @@ public class BoshBackedSessionContextTes
BoshBackedSessionContext boshBackedSessionContext = new
BoshBackedSessionContext(boshHandler,
serverRuntimeContext, inactivityChecker);
- boshBackedSessionContext.write0(body1);
- boshBackedSessionContext.write0(body2);
+ boshBackedSessionContext.writeBOSHResponse(body1);
+ boshBackedSessionContext.writeBOSHResponse(body2);
boshBackedSessionContext.insertRequest(new
BoshRequest(httpServletRequest, body, 1L));
mocksControl.verify();
}
Modified:
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/test/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandlerTest.java
URL:
http://svn.apache.org/viewvc/mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/test/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandlerTest.java?rev=1327524&r1=1327523&r2=1327524&view=diff
==============================================================================
---
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/test/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandlerTest.java
(original)
+++
mina/vysper/trunk/server/extensions/xep0124-xep0206-bosh/src/test/java/org/apache/vysper/xmpp/extension/xep0124/BoshHandlerTest.java
Wed Apr 18 14:36:32 2012
@@ -155,7 +155,7 @@ public class BoshHandlerTest {
@Test
public void testGetEmptyResponse() {
- Stanza response = boshHandler.getEmptyResponse();
+ Stanza response = BoshHandler.EMPTY_BOSH_RESPONSE;
assertNotNull(response);
assertEquals("body", response.getName());
assertEquals(NamespaceURIs.XEP0124_BOSH, response.getNamespaceURI());