294563 removed UpgradeConnectionException from websocket handling

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@1263 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2010-02-11 01:31:17 +00:00
parent 6047b7cad2
commit d208d55652
15 changed files with 69 additions and 105 deletions

View File

@ -133,7 +133,7 @@ public class HttpConnection implements Connection
} }
} }
public void handle() throws IOException public Connection handle() throws IOException
{ {
if (_exchange != null) if (_exchange != null)
_exchange.associate(this); _exchange.associate(this);
@ -171,7 +171,7 @@ public class HttpConnection implements Connection
Log.warn("Unexpected data received but no request sent"); Log.warn("Unexpected data received but no request sent");
close(); close();
} }
return; return this;
} }
} }
if (!_exchange.isAssociated()) if (!_exchange.isAssociated())
@ -251,7 +251,7 @@ public class HttpConnection implements Connection
if (_generator.flushBuffer()>0) if (_generator.flushBuffer()>0)
continue; continue;
} }
return; return this;
} }
} }
catch (Throwable e) catch (Throwable e)
@ -363,6 +363,8 @@ public class HttpConnection implements Connection
_exchange.disassociate(); _exchange.disassociate();
} }
} }
return this;
} }
public boolean isIdle() public boolean isIdle()

View File

@ -18,6 +18,7 @@ import java.net.Socket;
import javax.net.SocketFactory; import javax.net.SocketFactory;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.bio.SocketEndPoint; import org.eclipse.jetty.io.bio.SocketEndPoint;
import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.component.AbstractLifeCycle;
@ -67,7 +68,17 @@ class SocketConnector extends AbstractLifeCycle implements HttpClient.Connector
{ {
try try
{ {
connection.handle(); Connection con = connection;
while(true)
{
final Connection next = con.handle();
if (next!=con)
{
con=next;
continue;
}
break;
}
} }
catch (IOException e) catch (IOException e)
{ {

View File

@ -17,7 +17,13 @@ import java.io.IOException;
public interface Connection 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(); long getTimeStamp();

View File

@ -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;
}
}

View File

@ -24,7 +24,6 @@ import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.ConnectedEndPoint; import org.eclipse.jetty.io.ConnectedEndPoint;
import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.UpgradeConnectionException;
import org.eclipse.jetty.io.nio.SelectorManager.SelectSet; import org.eclipse.jetty.io.nio.SelectorManager.SelectSet;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.thread.Timeout; import org.eclipse.jetty.util.thread.Timeout;
@ -470,14 +469,16 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements Runnable,
{ {
try try
{ {
_connection.handle(); while(true)
} {
catch (UpgradeConnectionException e) final Connection next = _connection.handle();
{ if (next!=_connection)
Log.debug(e.toString()); {
Log.ignore(e); _connection=next;
setConnection(e.getConnection()); continue;
continue; }
break;
}
} }
catch (ClosedChannelException e) catch (ClosedChannelException e)
{ {

View File

@ -45,7 +45,6 @@ import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.io.UncheckedPrintWriter; import org.eclipse.jetty.io.UncheckedPrintWriter;
import org.eclipse.jetty.io.UpgradeConnectionException;
import org.eclipse.jetty.io.BufferCache.CachedBuffer; import org.eclipse.jetty.io.BufferCache.CachedBuffer;
import org.eclipse.jetty.io.nio.SelectChannelEndPoint; import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.util.QuotedStringTokenizer; 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 // Loop while more in buffer
boolean more_in_buffer =true; // assume true until proven otherwise boolean more_in_buffer =true; // assume true until proven otherwise
@ -428,7 +427,7 @@ public class HttpConnection implements Connection
} }
if (!progress) if (!progress)
return; return this;
} }
progress=false; progress=false;
} }
@ -452,6 +451,16 @@ public class HttpConnection implements Connection
if (_parser.isComplete() && _generator.isComplete() && !_endp.isBufferingOutput()) 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()) if (!_generator.isPersistent())
{ {
_parser.reset(true); _parser.reset(true);
@ -483,6 +492,7 @@ public class HttpConnection implements Connection
setCurrentConnection(null); setCurrentConnection(null);
_handling=false; _handling=false;
} }
return this;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -564,10 +574,6 @@ public class HttpConnection implements Connection
server.handleAsync(this); server.handleAsync(this);
} }
} }
catch (UpgradeConnectionException e)
{
throw e;
}
catch (ContinuationThrowable e) catch (ContinuationThrowable e)
{ {
Log.ignore(e); Log.ignore(e);

View File

@ -21,7 +21,6 @@ import java.util.concurrent.LinkedBlockingQueue;
import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.ByteArrayEndPoint; import org.eclipse.jetty.io.ByteArrayEndPoint;
import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.UpgradeConnectionException;
import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
@ -124,19 +123,16 @@ public class LocalConnector extends AbstractConnector
{ {
while (endPoint.getIn().length() > 0) while (endPoint.getIn().length() > 0)
{ {
while(true) while (true)
{ {
try final Connection con = endPoint.getConnection();
{ final Connection next = con.handle();
endPoint.getConnection().handle(); if (next!=con)
break; {
} endPoint.setConnection(next);
catch (UpgradeConnectionException e) continue;
{
Log.debug(e.toString());
Log.ignore(e);
endPoint.setConnection(e.getConnection());
} }
break;
} }
} }
} }

View File

@ -27,7 +27,6 @@ import org.eclipse.jetty.io.ConnectedEndPoint;
import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.UpgradeConnectionException;
import org.eclipse.jetty.io.bio.SocketEndPoint; import org.eclipse.jetty.io.bio.SocketEndPoint;
import org.eclipse.jetty.server.AbstractConnector; import org.eclipse.jetty.server.AbstractConnector;
import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.HttpConnection;
@ -239,25 +238,16 @@ public class SocketConnector extends AbstractConnector
{ {
if (isLowResources()) if (isLowResources())
{ {
int lrmit = getLowResourceMaxIdleTime(); int lrmit = getLowResourcesMaxIdleTime();
if (lrmit>=0 && _sotimeout!= lrmit) if (lrmit>=0 && _sotimeout!= lrmit)
{ {
_sotimeout=lrmit; _sotimeout=lrmit;
_socket.setSoTimeout(_sotimeout); _socket.setSoTimeout(_sotimeout);
} }
} }
} }
try
{ _connection=_connection.handle();
_connection.handle();
}
catch (UpgradeConnectionException e)
{
Log.debug(e.toString());
Log.ignore(e);
setConnection(e.getConnection());
continue;
}
} }
} }
catch (EofException e) catch (EofException e)

View File

@ -25,7 +25,6 @@ import org.eclipse.jetty.io.ConnectedEndPoint;
import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.UpgradeConnectionException;
import org.eclipse.jetty.io.nio.ChannelEndPoint; import org.eclipse.jetty.io.nio.ChannelEndPoint;
import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Request;
@ -167,14 +166,14 @@ public class BlockingChannelConnector extends AbstractNIOConnector
try try
{ {
connectionOpened(_connection); connectionOpened(_connection);
while (isOpen()) while (isOpen())
{ {
if (_connection.isIdle()) if (_connection.isIdle())
{ {
if (getServer().getThreadPool().isLowOnThreads()) if (getServer().getThreadPool().isLowOnThreads())
{ {
int lrmit = getLowResourceMaxIdleTime(); int lrmit = getLowResourcesMaxIdleTime();
if (lrmit>=0 && _sotimeout!= lrmit) if (lrmit>=0 && _sotimeout!= lrmit)
{ {
_sotimeout=lrmit; _sotimeout=lrmit;
@ -182,17 +181,8 @@ public class BlockingChannelConnector extends AbstractNIOConnector
} }
} }
} }
try
{ _connection = _connection.handle();
_connection.handle();
}
catch (UpgradeConnectionException e)
{
Log.debug(e.toString());
Log.ignore(e);
setConnection(e.getConnection());
continue;
}
} }
} }
catch (EofException e) catch (EofException e)

View File

@ -39,7 +39,6 @@ import org.eclipse.jetty.http.HttpException;
import org.eclipse.jetty.http.PathMap; import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.RuntimeIOException; import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.io.UpgradeConnectionException;
import org.eclipse.jetty.security.IdentityService; import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.SecurityHandler; import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.server.Dispatcher; import org.eclipse.jetty.server.Dispatcher;
@ -439,10 +438,6 @@ public class ServletHandler extends ScopedHandler
{ {
throw e; throw e;
} }
catch(UpgradeConnectionException e)
{
throw e;
}
catch(Exception e) catch(Exception e)
{ {
if (!(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type))) if (!(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type)))

View File

@ -84,7 +84,7 @@ public class WebSocketConnection implements Connection, WebSocket.Outbound
} }
} }
public void handle() throws IOException public Connection handle() throws IOException
{ {
boolean more=true; boolean more=true;
@ -120,6 +120,7 @@ public class WebSocketConnection implements Connection, WebSocket.Outbound
// TODO - not really the best way // TODO - not really the best way
_websocket.onDisconnect(); _websocket.onDisconnect();
} }
return this;
} }
public boolean isOpen() public boolean isOpen()

View File

@ -7,7 +7,6 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.io.ConnectedEndPoint; import org.eclipse.jetty.io.ConnectedEndPoint;
import org.eclipse.jetty.io.UpgradeConnectionException;
import org.eclipse.jetty.server.HttpConnection; import org.eclipse.jetty.server.HttpConnection;
@ -82,7 +81,7 @@ public class WebSocketFactory
* @throws IOException * @throws IOException
*/ */
public void upgrade(HttpServletRequest request,HttpServletResponse response, WebSocket websocket, String origin, String protocol) public void upgrade(HttpServletRequest request,HttpServletResponse response, WebSocket websocket, String origin, String protocol)
throws UpgradeConnectionException, IOException throws IOException
{ {
if (!"WebSocket".equals(request.getHeader("Upgrade"))) if (!"WebSocket".equals(request.getHeader("Upgrade")))
throw new IllegalStateException("!Upgrade:websocket"); throw new IllegalStateException("!Upgrade:websocket");
@ -109,6 +108,7 @@ public class WebSocketFactory
connection.fill(((HttpParser)http.getParser()).getBodyBuffer()); connection.fill(((HttpParser)http.getParser()).getBodyBuffer());
websocket.onConnect(connection); websocket.onConnect(connection);
throw new UpgradeConnectionException(connection); request.setAttribute("org.eclipse.jetty.io.Connection",connection);
response.flushBuffer();
} }
} }

View File

@ -6,10 +6,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; 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.Request;
import org.eclipse.jetty.server.handler.HandlerWrapper; import org.eclipse.jetty.server.handler.HandlerWrapper;

View File

@ -7,11 +7,6 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; 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;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**

View File

@ -90,6 +90,7 @@ public class WebSocketTest extends TestCase
ByteArrayBuffer out = _connector.getResponses(buffer,true); ByteArrayBuffer out = _connector.getResponses(buffer,true);
String response = StringUtil.printable(out.asArray()); String response = StringUtil.printable(out.asArray());
System.err.println(response);
assertTrue(response.startsWith("HTTP/1.1 101 Web Socket Protocol Handshake")); assertTrue(response.startsWith("HTTP/1.1 101 Web Socket Protocol Handshake"));
assertTrue(response.contains("Upgrade: WebSocket")); assertTrue(response.contains("Upgrade: WebSocket"));