Commit b1884cd9 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

BOSH updated to version 1.6. JM-1033. Thanks to Safa Sofuoğlu.

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/trunk@10657 b35dd754-fafc-0310-a699-88a17e54d16e
parent c41ff947
...@@ -45,7 +45,7 @@ public enum BoshBindingError { ...@@ -45,7 +45,7 @@ public enum BoshBindingError {
/** /**
* (1) 'sid' is not valid, (2) 'stream' is not valid, (3) 'rid' is larger than the upper limit * (1) 'sid' is not valid, (2) 'stream' is not valid, (3) 'rid' is larger than the upper limit
* of the expected window, (4) connection manager is unable to resend response, (5) 'key' * of the expected window, (4) connection manager is unable to resend response, (5) 'key'
* sequence is invalid * sequence is invalid (6) script syntax is not enabled
*/ */
itemNotFound(Type.terminal, "item-not-found", HttpServletResponse.SC_NOT_FOUND), itemNotFound(Type.terminal, "item-not-found", HttpServletResponse.SC_NOT_FOUND),
/** /**
......
...@@ -19,8 +19,8 @@ import org.dom4j.Element; ...@@ -19,8 +19,8 @@ import org.dom4j.Element;
import org.dom4j.io.XMPPPacketReader; import org.dom4j.io.XMPPPacketReader;
import org.jivesoftware.openfire.auth.UnauthorizedException; import org.jivesoftware.openfire.auth.UnauthorizedException;
import org.jivesoftware.openfire.net.MXParser; import org.jivesoftware.openfire.net.MXParser;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.JiveGlobals; import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.mortbay.util.ajax.ContinuationSupport; import org.mortbay.util.ajax.ContinuationSupport;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory; import org.xmlpull.v1.XmlPullParserFactory;
...@@ -182,7 +182,8 @@ public class HttpBindServlet extends HttpServlet { ...@@ -182,7 +182,8 @@ public class HttpBindServlet extends HttpServlet {
System.out.println(new Date()+": HTTP ERR("+session.getStreamID().getID() + "): " + bindingError.getErrorType().getType() + ", " + bindingError.getCondition() + "."); System.out.println(new Date()+": HTTP ERR("+session.getStreamID().getID() + "): " + bindingError.getErrorType().getType() + ", " + bindingError.getCondition() + ".");
} }
try { try {
if (session.getVersion() >= 1.6) { if ((session.getMajorVersion() == 1 && session.getMinorVersion() >= 6) ||
session.getMajorVersion() > 1) {
respond(session, response, createErrorBody(bindingError.getErrorType().getType(), respond(session, response, createErrorBody(bindingError.getErrorType().getType(),
bindingError.getCondition()), request.getMethod()); bindingError.getCondition()), request.getMethod());
} }
...@@ -241,11 +242,19 @@ public class HttpBindServlet extends HttpServlet { ...@@ -241,11 +242,19 @@ public class HttpBindServlet extends HttpServlet {
} }
String type = rootNode.attributeValue("type"); String type = rootNode.attributeValue("type");
int pauseDuration = getIntAttribue(rootNode.attributeValue("pause"), -1);
if ("terminate".equals(type)) { if ("terminate".equals(type)) {
session.close(); session.close();
respond(session, response, createEmptyBody(), request.getMethod()); respond(session, response, createEmptyBody(), request.getMethod());
} }
else if (pauseDuration > 0 && pauseDuration <= session.getMaxPause()) {
session.pause(pauseDuration);
respond(session, response, createEmptyBody(), request.getMethod());
session.setLastResponseEmpty(true);
}
else { else {
session.resetInactivityTimeout();
connection.setContinuation(ContinuationSupport.getContinuation(request, connection)); connection.setContinuation(ContinuationSupport.getContinuation(request, connection));
request.setAttribute("request-session", connection.getSession()); request.setAttribute("request-session", connection.getSession());
request.setAttribute("request", connection.getRequestId()); request.setAttribute("request", connection.getRequestId());
...@@ -301,6 +310,7 @@ public class HttpBindServlet extends HttpServlet { ...@@ -301,6 +310,7 @@ public class HttpBindServlet extends HttpServlet {
} }
catch (HttpBindTimeoutException e) { catch (HttpBindTimeoutException e) {
content = createEmptyBody(); content = createEmptyBody();
connection.getSession().setLastResponseEmpty(true);
} }
respond(connection.getSession(), response, content, method); respond(connection.getSession(), response, content, method);
...@@ -313,6 +323,10 @@ public class HttpBindServlet extends HttpServlet { ...@@ -313,6 +323,10 @@ public class HttpBindServlet extends HttpServlet {
response.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8");
if ("GET".equals(method)) { if ("GET".equals(method)) {
// Prevent caching of responses
response.addHeader("Cache-Control", "no-store");
response.addHeader("Cache-Control", "no-cache");
response.addHeader("Pragma", "no-cache");
content = "_BOSH_(\"" + StringEscapeUtils.escapeJavaScript(content) + "\")"; content = "_BOSH_(\"" + StringEscapeUtils.escapeJavaScript(content) + "\")";
} }
...@@ -343,6 +357,18 @@ public class HttpBindServlet extends HttpServlet { ...@@ -343,6 +357,18 @@ public class HttpBindServlet extends HttpServlet {
} }
} }
private int getIntAttribue(String value, int defaultValue) {
if (value == null || "".equals(value)) {
return defaultValue;
}
try {
return Integer.valueOf(value);
}
catch (Exception ex) {
return defaultValue;
}
}
private XMPPPacketReader getPacketReader() { private XMPPPacketReader getPacketReader() {
// Reader is associated with a new XMPPPacketReader // Reader is associated with a new XMPPPacketReader
XMPPPacketReader reader = localReader.get(); XMPPPacketReader reader = localReader.get();
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
package org.jivesoftware.openfire.http; package org.jivesoftware.openfire.http;
import org.jivesoftware.util.JiveConstants;
import org.mortbay.util.ajax.Continuation; import org.mortbay.util.ajax.Continuation;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
...@@ -185,7 +186,7 @@ public class HttpConnection { ...@@ -185,7 +186,7 @@ public class HttpConnection {
} }
private String waitForResponse() throws HttpBindTimeoutException { private String waitForResponse() throws HttpBindTimeoutException {
if (continuation.suspend(session.getWait() * 1000)) { if (continuation.suspend(session.getWait() * JiveConstants.SECOND)) {
String deliverable = (String) continuation.getObject(); String deliverable = (String) continuation.getObject();
// This will occur when the hold attribute of a session has been exceded. // This will occur when the hold attribute of a session has been exceded.
this.isDelivered = true; this.isDelivered = true;
......
...@@ -119,7 +119,11 @@ public class HttpSessionManager { ...@@ -119,7 +119,11 @@ public class HttpSessionManager {
int wait = getIntAttribute(rootNode.attributeValue("wait"), 60); int wait = getIntAttribute(rootNode.attributeValue("wait"), 60);
int hold = getIntAttribute(rootNode.attributeValue("hold"), 1); int hold = getIntAttribute(rootNode.attributeValue("hold"), 1);
double version = getDoubleAttribute(rootNode.attributeValue("ver"), 1.5);
String version = rootNode.attributeValue("ver");
if (version == null || "".equals(version)) {
version = "1.5";
}
HttpSession session = createSession(connection.getRequestId(), address, connection); HttpSession session = createSession(connection.getRequestId(), address, connection);
session.setWait(Math.min(wait, getMaxWait())); session.setWait(Math.min(wait, getMaxWait()));
...@@ -127,10 +131,23 @@ public class HttpSessionManager { ...@@ -127,10 +131,23 @@ public class HttpSessionManager {
session.setSecure(connection.isSecure()); session.setSecure(connection.isSecure());
session.setMaxPollingInterval(getPollingInterval()); session.setMaxPollingInterval(getPollingInterval());
session.setMaxRequests(getMaxRequests()); session.setMaxRequests(getMaxRequests());
session.setInactivityTimeout(getInactivityTimeout()); session.setMaxPause(getMaxPause());
if(session.isPollingSession()) {
session.setDefaultInactivityTimeout(getPollingInactivityTimeout());
}
else {
session.setDefaultInactivityTimeout(getInactivityTimeout());
}
session.resetInactivityTimeout();
// Store language and version information in the connection. // Store language and version information in the connection.
session.setLanaguage(language); session.setLanguage(language);
session.setVersion(version);
String [] versionString = version.split("\\.");
session.setMajorVersion(Integer.parseInt(versionString[0]));
session.setMinorVersion(Integer.parseInt(versionString[1]));
try { try {
connection.deliverBody(createSessionCreationResponse(session)); connection.deliverBody(createSessionCreationResponse(session));
} }
...@@ -146,6 +163,17 @@ public class HttpSessionManager { ...@@ -146,6 +163,17 @@ public class HttpSessionManager {
} }
/**
* Returns the maximum length of a temporary session pause (in seconds) that the client MAY
* request.
*
* @return the maximum length of a temporary session pause (in seconds) that the client MAY
* request.
*/
public int getMaxPause() {
return JiveGlobals.getIntProperty("xmpp.httpbind.client.maxpause", 300);
}
/** /**
* Returns the longest time (in seconds) that Openfire is allowed to wait before responding to * Returns the longest time (in seconds) that Openfire is allowed to wait before responding to
* any request during the session. This enables the client to prevent its TCP connection from * any request during the session. This enables the client to prevent its TCP connection from
...@@ -188,7 +216,7 @@ public class HttpSessionManager { ...@@ -188,7 +216,7 @@ public class HttpSessionManager {
} }
/** /**
* Seconds a session has to be idle to be closed. Default is 30 minutes. Sending stanzas to the * Seconds a session has to be idle to be closed. Default is 30. Sending stanzas to the
* client is not considered as activity. We are only considering the connection active when the * client is not considered as activity. We are only considering the connection active when the
* client sends some data or hearbeats (i.e. whitespaces) to the server. The reason for this is * client sends some data or hearbeats (i.e. whitespaces) to the server. The reason for this is
* that sending data will fail if the connection is closed. And if the thread is blocked while * that sending data will fail if the connection is closed. And if the thread is blocked while
...@@ -201,6 +229,20 @@ public class HttpSessionManager { ...@@ -201,6 +229,20 @@ public class HttpSessionManager {
return JiveGlobals.getIntProperty("xmpp.httpbind.client.idle", 30); return JiveGlobals.getIntProperty("xmpp.httpbind.client.idle", 30);
} }
/**
* Seconds a polling session has to be idle to be closed. Default is 60. Sending stanzas to the
* client is not considered as activity. We are only considering the connection active when the
* client sends some data or hearbeats (i.e. whitespaces) to the server. The reason for this is
* that sending data will fail if the connection is closed. And if the thread is blocked while
* sending data (because the socket is closed) then the clean up thread will close the socket
* anyway.
*
* @return Seconds a polling session has to be idle to be closed.
*/
public int getPollingInactivityTimeout() {
return JiveGlobals.getIntProperty("xmpp.httpbind.client.idle.polling", 60);
}
/** /**
* Forwards a client request, which is related to a session, to the server. A connection is * Forwards a client request, which is related to a session, to the server. A connection is
* created and queued up in the provided session. When a connection reaches the top of a queue * created and queued up in the provided session. When a connection reaches the top of a queue
...@@ -278,8 +320,13 @@ public class HttpSessionManager { ...@@ -278,8 +320,13 @@ public class HttpSessionManager {
response.addAttribute("inactivity", String.valueOf(session.getInactivityTimeout())); response.addAttribute("inactivity", String.valueOf(session.getInactivityTimeout()));
response.addAttribute("polling", String.valueOf(session.getMaxPollingInterval())); response.addAttribute("polling", String.valueOf(session.getMaxPollingInterval()));
response.addAttribute("wait", String.valueOf(session.getWait())); response.addAttribute("wait", String.valueOf(session.getWait()));
if(session.getVersion() >= 1.6) { if ((session.getMajorVersion() == 1 && session.getMinorVersion() >= 6) ||
response.addAttribute("ver", String.valueOf(session.getVersion())); session.getMajorVersion() > 1) {
response.addAttribute("hold", String.valueOf(session.getHold()));
response.addAttribute("ack", String.valueOf(session.getLastAcknowledged()));
response.addAttribute("maxpause", String.valueOf(session.getMaxPause()));
response.addAttribute("ver", String.valueOf(session.getMajorVersion())
+ "." + String.valueOf(session.getMinorVersion()));
} }
Element features = response.addElement("stream:features"); Element features = response.addElement("stream:features");
...@@ -295,8 +342,8 @@ public class HttpSessionManager { ...@@ -295,8 +342,8 @@ public class HttpSessionManager {
public void run() { public void run() {
long currentTime = System.currentTimeMillis(); long currentTime = System.currentTimeMillis();
for (HttpSession session : sessionMap.values()) { for (HttpSession session : sessionMap.values()) {
long lastActive = (currentTime - session.getLastActivity()) / 1000; long lastActive = currentTime - session.getLastActivity();
if (lastActive > session.getInactivityTimeout()) { if (lastActive > session.getInactivityTimeout() * JiveConstants.SECOND) {
session.close(); session.close();
} }
} }
...@@ -304,7 +351,7 @@ public class HttpSessionManager { ...@@ -304,7 +351,7 @@ public class HttpSessionManager {
} }
/** /**
* A runner that gurantees that the packets per a session will be sent and * A runner that guarantees that the packets per a session will be sent and
* processed in the order in which they were received. * processed in the order in which they were received.
*/ */
private class HttpPacketSender implements Runnable { private class HttpPacketSender implements Runnable {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment