diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java index 04abb303f01..42d00c31ba6 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java @@ -133,7 +133,7 @@ public class HttpConnection implements Connection } } - public void handle() throws IOException + public Connection handle() throws IOException { if (_exchange != null) _exchange.associate(this); @@ -171,7 +171,7 @@ public class HttpConnection implements Connection Log.warn("Unexpected data received but no request sent"); close(); } - return; + return this; } } if (!_exchange.isAssociated()) @@ -251,7 +251,7 @@ public class HttpConnection implements Connection if (_generator.flushBuffer()>0) continue; } - return; + return this; } } catch (Throwable e) @@ -363,6 +363,8 @@ public class HttpConnection implements Connection _exchange.disassociate(); } } + + return this; } public boolean isIdle() diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/SocketConnector.java b/jetty-client/src/main/java/org/eclipse/jetty/client/SocketConnector.java index 358dff8f5f5..0da8617f904 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/SocketConnector.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/SocketConnector.java @@ -18,6 +18,7 @@ import java.net.Socket; import javax.net.SocketFactory; import javax.net.ssl.SSLContext; +import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.bio.SocketEndPoint; import org.eclipse.jetty.util.component.AbstractLifeCycle; @@ -67,7 +68,17 @@ class SocketConnector extends AbstractLifeCycle implements HttpClient.Connector { try { - connection.handle(); + Connection con = connection; + while(true) + { + final Connection next = con.handle(); + if (next!=con) + { + con=next; + continue; + } + break; + } } catch (IOException e) { diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java index fdb07d027c3..66381cb67dd 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java @@ -17,7 +17,13 @@ import java.io.IOException; public interface Connection { - void handle() throws IOException, UpgradeConnectionException; + /* ------------------------------------------------------------ */ + /** + * Handle the connection. + * @return The Connection to use for the next handling of the connection. This allows protocol upgrades. + * @throws IOException + */ + Connection handle() throws IOException; long getTimeStamp(); diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/UpgradeConnectionException.java b/jetty-io/src/main/java/org/eclipse/jetty/io/UpgradeConnectionException.java deleted file mode 100644 index 8b4c32e594f..00000000000 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/UpgradeConnectionException.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.eclipse.jetty.io; - -/* ------------------------------------------------------------ */ -/** Upgrade Connection Exception - * This exception is thrown when processing a protocol upgrade - * to exit all the current connection handling and to - * allow the {@link ConnectedEndPoint} to handle the new exception. - * - * Code that calls {@link org.eclipse.jetty.io.Connection#handle()} - * should catch this exception and call {@link ConnectedEndPoint#setConnection(org.eclipse.jetty.io.Connection)} - * with the new connection and then immediately call handle() again. - */ -public class UpgradeConnectionException extends RuntimeException -{ - Connection _connection; - - public UpgradeConnectionException(Connection newConnection) - { - _connection=newConnection; - } - - public Connection getConnection() - { - return _connection; - } -} diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java index b12fe6c1418..87c97a84ed3 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java @@ -24,7 +24,6 @@ import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.ConnectedEndPoint; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EofException; -import org.eclipse.jetty.io.UpgradeConnectionException; import org.eclipse.jetty.io.nio.SelectorManager.SelectSet; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.thread.Timeout; @@ -470,14 +469,16 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements Runnable, { try { - _connection.handle(); - } - catch (UpgradeConnectionException e) - { - Log.debug(e.toString()); - Log.ignore(e); - setConnection(e.getConnection()); - continue; + while(true) + { + final Connection next = _connection.handle(); + if (next!=_connection) + { + _connection=next; + continue; + } + break; + } } catch (ClosedChannelException e) { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java index dd54eefc7cc..bf126f29452 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java @@ -45,7 +45,6 @@ import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.io.UncheckedPrintWriter; -import org.eclipse.jetty.io.UpgradeConnectionException; import org.eclipse.jetty.io.BufferCache.CachedBuffer; import org.eclipse.jetty.io.nio.SelectChannelEndPoint; import org.eclipse.jetty.util.QuotedStringTokenizer; @@ -363,7 +362,7 @@ public class HttpConnection implements Connection } /* ------------------------------------------------------------ */ - public void handle() throws IOException + public Connection handle() throws IOException { // Loop while more in buffer boolean more_in_buffer =true; // assume true until proven otherwise @@ -428,7 +427,7 @@ public class HttpConnection implements Connection } if (!progress) - return; + return this; } progress=false; } @@ -452,6 +451,16 @@ public class HttpConnection implements Connection if (_parser.isComplete() && _generator.isComplete() && !_endp.isBufferingOutput()) { + if (_response.getStatus()==HttpStatus.SWITCHING_PROTOCOLS_101) + { + Connection connection = (Connection)_request.getAttribute("org.eclipse.jetty.io.Connection"); + if (connection!=null) + { + _parser.reset(true); + return connection; + } + } + if (!_generator.isPersistent()) { _parser.reset(true); @@ -483,6 +492,7 @@ public class HttpConnection implements Connection setCurrentConnection(null); _handling=false; } + return this; } /* ------------------------------------------------------------ */ @@ -564,10 +574,6 @@ public class HttpConnection implements Connection server.handleAsync(this); } } - catch (UpgradeConnectionException e) - { - throw e; - } catch (ContinuationThrowable e) { Log.ignore(e); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java index 0836a9ae39c..6385d2785ac 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java @@ -21,7 +21,6 @@ import java.util.concurrent.LinkedBlockingQueue; import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.io.ByteArrayEndPoint; import org.eclipse.jetty.io.Connection; -import org.eclipse.jetty.io.UpgradeConnectionException; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.Log; @@ -124,19 +123,16 @@ public class LocalConnector extends AbstractConnector { while (endPoint.getIn().length() > 0) { - while(true) + while (true) { - try - { - endPoint.getConnection().handle(); - break; - } - catch (UpgradeConnectionException e) - { - Log.debug(e.toString()); - Log.ignore(e); - endPoint.setConnection(e.getConnection()); + final Connection con = endPoint.getConnection(); + final Connection next = con.handle(); + if (next!=con) + { + endPoint.setConnection(next); + continue; } + break; } } } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/bio/SocketConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/bio/SocketConnector.java index 311a7a646cd..5a39e71f384 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/bio/SocketConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/bio/SocketConnector.java @@ -27,7 +27,6 @@ import org.eclipse.jetty.io.ConnectedEndPoint; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EofException; -import org.eclipse.jetty.io.UpgradeConnectionException; import org.eclipse.jetty.io.bio.SocketEndPoint; import org.eclipse.jetty.server.AbstractConnector; import org.eclipse.jetty.server.HttpConnection; @@ -239,25 +238,16 @@ public class SocketConnector extends AbstractConnector { if (isLowResources()) { - int lrmit = getLowResourceMaxIdleTime(); + int lrmit = getLowResourcesMaxIdleTime(); if (lrmit>=0 && _sotimeout!= lrmit) { _sotimeout=lrmit; _socket.setSoTimeout(_sotimeout); } } - } - try - { - _connection.handle(); - } - catch (UpgradeConnectionException e) - { - Log.debug(e.toString()); - Log.ignore(e); - setConnection(e.getConnection()); - continue; - } + } + + _connection=_connection.handle(); } } catch (EofException e) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/nio/BlockingChannelConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/nio/BlockingChannelConnector.java index 2039c8b94a7..1973e0a4d0d 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/nio/BlockingChannelConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/nio/BlockingChannelConnector.java @@ -25,7 +25,6 @@ import org.eclipse.jetty.io.ConnectedEndPoint; import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EofException; -import org.eclipse.jetty.io.UpgradeConnectionException; import org.eclipse.jetty.io.nio.ChannelEndPoint; import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.Request; @@ -167,14 +166,14 @@ public class BlockingChannelConnector extends AbstractNIOConnector try { connectionOpened(_connection); - + while (isOpen()) { if (_connection.isIdle()) { if (getServer().getThreadPool().isLowOnThreads()) { - int lrmit = getLowResourceMaxIdleTime(); + int lrmit = getLowResourcesMaxIdleTime(); if (lrmit>=0 && _sotimeout!= lrmit) { _sotimeout=lrmit; @@ -182,17 +181,8 @@ public class BlockingChannelConnector extends AbstractNIOConnector } } } - try - { - _connection.handle(); - } - catch (UpgradeConnectionException e) - { - Log.debug(e.toString()); - Log.ignore(e); - setConnection(e.getConnection()); - continue; - } + + _connection = _connection.handle(); } } catch (EofException e) diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java index 50669422784..a16cba5dc30 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java @@ -39,7 +39,6 @@ import org.eclipse.jetty.http.HttpException; import org.eclipse.jetty.http.PathMap; import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.io.RuntimeIOException; -import org.eclipse.jetty.io.UpgradeConnectionException; import org.eclipse.jetty.security.IdentityService; import org.eclipse.jetty.security.SecurityHandler; import org.eclipse.jetty.server.Dispatcher; @@ -439,10 +438,6 @@ public class ServletHandler extends ScopedHandler { throw e; } - catch(UpgradeConnectionException e) - { - throw e; - } catch(Exception e) { if (!(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type))) diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketConnection.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketConnection.java index ebd8715a5b1..4f76ceffd23 100644 --- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketConnection.java +++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketConnection.java @@ -84,7 +84,7 @@ public class WebSocketConnection implements Connection, WebSocket.Outbound } } - public void handle() throws IOException + public Connection handle() throws IOException { boolean more=true; @@ -120,6 +120,7 @@ public class WebSocketConnection implements Connection, WebSocket.Outbound // TODO - not really the best way _websocket.onDisconnect(); } + return this; } public boolean isOpen() diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketFactory.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketFactory.java index fc2b5eb41c2..cd8eb94748e 100644 --- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketFactory.java +++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketFactory.java @@ -7,7 +7,6 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.io.ConnectedEndPoint; -import org.eclipse.jetty.io.UpgradeConnectionException; import org.eclipse.jetty.server.HttpConnection; @@ -82,7 +81,7 @@ public class WebSocketFactory * @throws IOException */ public void upgrade(HttpServletRequest request,HttpServletResponse response, WebSocket websocket, String origin, String protocol) - throws UpgradeConnectionException, IOException + throws IOException { if (!"WebSocket".equals(request.getHeader("Upgrade"))) throw new IllegalStateException("!Upgrade:websocket"); @@ -109,6 +108,7 @@ public class WebSocketFactory connection.fill(((HttpParser)http.getParser()).getBodyBuffer()); websocket.onConnect(connection); - throw new UpgradeConnectionException(connection); + request.setAttribute("org.eclipse.jetty.io.Connection",connection); + response.flushBuffer(); } } diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketHandler.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketHandler.java index 4dc88bfe4d9..e91515d9dda 100644 --- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketHandler.java +++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketHandler.java @@ -6,10 +6,6 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.HttpParser; -import org.eclipse.jetty.io.ConnectedEndPoint; -import org.eclipse.jetty.io.UpgradeConnectionException; -import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.HandlerWrapper; diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketServlet.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketServlet.java index 2ff4e06e67a..e89d5f31d09 100644 --- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketServlet.java +++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketServlet.java @@ -7,11 +7,6 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.eclipse.jetty.http.HttpParser; -import org.eclipse.jetty.io.ConnectedEndPoint; -import org.eclipse.jetty.io.UpgradeConnectionException; -import org.eclipse.jetty.server.HttpConnection; - /* ------------------------------------------------------------ */ /** diff --git a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketTest.java b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketTest.java index 438acdbde08..292eb67e4be 100644 --- a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketTest.java +++ b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketTest.java @@ -90,6 +90,7 @@ public class WebSocketTest extends TestCase ByteArrayBuffer out = _connector.getResponses(buffer,true); String response = StringUtil.printable(out.asArray()); + System.err.println(response); assertTrue(response.startsWith("HTTP/1.1 101 Web Socket Protocol Handshake")); assertTrue(response.contains("Upgrade: WebSocket"));