Commit 64c33cc9 authored by Alex Wenckus's avatar Alex Wenckus Committed by alex

fix for multiple simultaneous connection issues. JM-955

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@6984 b35dd754-fafc-0310-a699-88a17e54d16e
parent 4cc39134
......@@ -114,9 +114,17 @@ public class HttpBindServlet extends HttpServlet {
return false;
}
synchronized (session) {
try {
respond(response, session.getResponse((Long) request.getAttribute("request"))
.getBytes("utf-8"));
}
catch (HttpBindException e) {
response.sendError(e.getHttpError(), e.getMessage());
if(e.shouldCloseSession()) {
session.close();
}
}
}
return true;
}
......
......@@ -55,6 +55,13 @@ public class HttpSession extends ClientSession {
private long lastRequestID;
private int maxRequests;
private static final Comparator<HttpConnection> connectionComparator
= new Comparator<HttpConnection>() {
public int compare(HttpConnection o1, HttpConnection o2) {
return (int) (o1.getRequestId() - o2.getRequestId());
}
};
public HttpSession(String serverName, InetAddress address, StreamID streamID, long rid) {
super(serverName, null, streamID);
conn = new HttpVirtualConnection(address);
......@@ -311,9 +318,24 @@ public class HttpSession extends ClientSession {
}
}
public String getResponse(long requestID) {
public String getResponse(long requestID) throws HttpBindException {
for (HttpConnection connection : connectionQueue) {
if (connection.getRequestId() == requestID) {
if(requestID > lastRequestID + 1) {
throw new HttpBindException("Invalid RID error.", true, 404);
}
connectionQueue.remove(connection);
fireConnectionClosed(connection);
if(requestID > lastRequestID) {
lastRequestID = connection.getRequestId();
}
return getResponse(connection);
}
}
throw new InternalError("Could not locate connection: " + requestID);
}
private String getResponse(HttpConnection connection) {
String response;
try {
response = connection.getResponse();
......@@ -321,13 +343,8 @@ public class HttpSession extends ClientSession {
catch (HttpBindTimeoutException e) {
response = createEmptyBody();
}
connectionQueue.remove(connection);
fireConnectionClosed(connection);
return response;
}
}
throw new InternalError("Could not locate connection: " + requestID);
}
/**
* Sets whether the initial request on the session was secure.
......@@ -348,8 +365,9 @@ public class HttpSession extends ClientSession {
* @param isSecure true if the connection was secured using HTTPS.
* @return the created {@link org.jivesoftware.wildfire.http.HttpConnection} which represents
* the connection.
* @throws HttpConnectionClosedException if the connection was closed before a response could
* be delivered.
*
* @throws HttpConnectionClosedException if the connection was closed before a response could be
* delivered.
* @throws HttpBindException if the connection has violated a facet of the HTTP binding
* protocol.
*/
......@@ -402,12 +420,13 @@ public class HttpSession extends ClientSession {
connection.setSession(this);
// We aren't supposed to hold connections open or we already have some packets waiting
// to be sent to the client.
if (hold <= 0 || pendingElements.size() > 0) {
if (hold <= 0 || (pendingElements.size() > 0 && connection.getRequestId()
== lastRequestID + 1)) {
String deliverable = createDeliverable(pendingElements);
try {
fireConnectionOpened(connection);
deliver(connection, deliverable);
fireConnectionClosed(connection);
lastRequestID = connection.getRequestId();
pendingElements.clear();
}
catch (HttpConnectionClosedException he) {
......@@ -417,15 +436,18 @@ public class HttpSession extends ClientSession {
else {
// With this connection we need to check if we will have too many connections open,
// closing any extras.
while (connectionQueue.size() >= hold) {
HttpConnection toClose = connectionQueue.remove(0);
// Number of current connections open plus the current one tells us how many that
// we need to close.
int connectionsToClose = (connectionQueue.size() + 1) - hold;
for (int i = 0; i < connectionsToClose; i++) {
HttpConnection toClose = connectionQueue.get(i);
toClose.close();
fireConnectionClosed(toClose);
}
connectionQueue.add(connection);
Collections.sort(connectionQueue, connectionComparator);
fireConnectionOpened(connection);
}
lastRequestID = connection.getRequestId();
}
private void deliver(HttpConnection connection, String deliverable)
......@@ -471,10 +493,13 @@ public class HttpSession extends ClientSession {
boolean delivered = false;
for (HttpConnection connection : connectionQueue) {
try {
if (connection.getRequestId() == lastRequestID + 1) {
deliver(connection, deliverable);
delivered = true;
lastRequestID = connection.getRequestId();
break;
}
}
catch (HttpConnectionClosedException e) {
/* Connection was closed, try the next one */
}
......@@ -609,24 +634,4 @@ public class HttpSession extends ClientSession {
return (int) (o.getRequestID() - requestID);
}
}
/**
* A queue of all current connections. Connections are dealt with in order of their request
* IDs.
*/
private class ConnectionQueue {
private final HttpConnection[] connections;
private final String[] requestIds;
private int pointer = 0;
public ConnectionQueue(int size) {
this.connections = new HttpConnection[size];
this.requestIds = new String[size];
}
}
}
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