Bug 365973 - Websocket client on android causes many VFY errors and

warnings.

+ Splitting out WebSocketConnection#handshake() into new
  WebSocketServletConnection interface and refactoring accordingly,
  in order to remove servlet-api dep on WebSocketConnection for
  appropriate websocket client use.
This commit is contained in:
Joakim Erdfelt 2011-12-12 09:02:40 -07:00
parent 2c650a5fdd
commit 004fa1ce1c
13 changed files with 263 additions and 153 deletions

View File

@ -7,6 +7,7 @@ import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.Map;
import java.util.Random;
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.http.HttpFields;
@ -141,7 +142,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
/* ------------------------------------------------------------ */
/**
* @return the shared mask generator, or null if no shared mask generator is used
* @see {@link WebSocketClient#getMaskGen()}
* @see WebSocketClient#getMaskGen()
*/
public MaskGen getMaskGen()
{
@ -151,7 +152,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
/* ------------------------------------------------------------ */
/**
* @param maskGen the shared mask generator, or null if no shared mask generator is used
* @see {@link WebSocketClient#setMaskGen(MaskGen)}
* @see WebSocketClient#setMaskGen(MaskGen)
*/
public void setMaskGen(MaskGen maskGen)
{

View File

@ -1,12 +1,8 @@
package org.eclipse.jetty.websocket;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.nio.AsyncConnection;
@ -14,8 +10,6 @@ public interface WebSocketConnection extends AsyncConnection
{
void fillBuffersFrom(Buffer buffer);
void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException;
List<Extension> getExtensions();
WebSocket.Connection getConnection();

View File

@ -19,10 +19,6 @@ import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffer;
@ -30,7 +26,6 @@ import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -340,54 +335,6 @@ public class WebSocketConnectionD00 extends AbstractConnection implements WebSoc
}
}
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
{
String uri=request.getRequestURI();
String query=request.getQueryString();
if (query!=null && query.length()>0)
uri+="?"+query;
uri=new HttpURI(uri).toString();
String host=request.getHeader("Host");
String origin=request.getHeader("Sec-WebSocket-Origin");
if (origin==null)
origin=request.getHeader("Origin");
if (origin!=null)
origin= QuotedStringTokenizer.quoteIfNeeded(origin, "\r\n");
String key1 = request.getHeader("Sec-WebSocket-Key1");
if (key1!=null)
{
String key2 = request.getHeader("Sec-WebSocket-Key2");
setHixieKeys(key1,key2);
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
if (origin!=null)
response.addHeader("Sec-WebSocket-Origin",origin);
response.addHeader("Sec-WebSocket-Location",(request.isSecure()?"wss://":"ws://")+host+uri);
if (subprotocol!=null)
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
response.sendError(101,"WebSocket Protocol Handshake");
}
else
{
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
response.addHeader("WebSocket-Origin",origin);
response.addHeader("WebSocket-Location",(request.isSecure()?"wss://":"ws://")+host+uri);
if (subprotocol!=null)
response.addHeader("WebSocket-Protocol",subprotocol);
response.sendError(101,"Web Socket Protocol Handshake");
response.flushBuffer();
if (_websocket instanceof OnFrame)
((OnFrame)_websocket).onHandshake(this);
_websocket.onOpen(this);
}
}
public void setMaxTextMessageSize(int size)
{
}

View File

@ -19,9 +19,6 @@ import java.security.MessageDigest;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffer;
@ -77,8 +74,8 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
private final static byte[] MAGIC;
private final WebSocketParser _parser;
private final WebSocketGenerator _generator;
private final WebSocket _webSocket;
private final OnFrame _onFrame;
protected final WebSocket _webSocket;
protected final OnFrame _onFrame;
private final OnBinaryMessage _onBinaryMessage;
private final OnTextMessage _onTextMessage;
private final OnControl _onControl;
@ -101,11 +98,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
}
private final WebSocketParser.FrameHandler _frameHandler= new FrameHandlerD06();
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
private final WebSocket.FrameConnection _connection = new FrameConnectionD06();
protected final WebSocket.FrameConnection _connection = new FrameConnectionD06();
/* ------------------------------------------------------------ */
@ -487,6 +480,7 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
}
/* ------------------------------------------------------------ */
@Override
public String toString()
{
return this.getClass().getSimpleName()+"@"+_endp.getLocalAddr()+":"+_endp.getLocalPort()+"<->"+_endp.getRemoteAddr()+":"+_endp.getRemotePort();
@ -693,29 +687,13 @@ public class WebSocketConnectionD06 extends AbstractConnection implements WebSoc
_connection.close(code,message);
}
@Override
public String toString()
{
return WebSocketConnectionD06.this.toString()+"FH";
}
}
/* ------------------------------------------------------------ */
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
{
String key = request.getHeader("Sec-WebSocket-Key");
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
if (subprotocol!=null)
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
response.sendError(101);
if (_onFrame!=null)
_onFrame.onHandshake(_connection);
_webSocket.onOpen(_connection);
}
/* ------------------------------------------------------------ */
public static String hashKey(String key)
{

View File

@ -19,9 +19,6 @@ import java.security.MessageDigest;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffer;
@ -77,13 +74,13 @@ public class WebSocketConnectionD08 extends AbstractConnection implements WebSoc
}
private final static byte[] MAGIC;
private final List<Extension> _extensions;
protected final List<Extension> _extensions;
private final WebSocketParserD08 _parser;
private final WebSocketParser.FrameHandler _inbound;
private final WebSocketGeneratorD08 _generator;
private final WebSocketGenerator _outbound;
private final WebSocket _webSocket;
private final OnFrame _onFrame;
protected final WebSocket _webSocket;
protected final OnFrame _onFrame;
private final OnBinaryMessage _onBinaryMessage;
private final OnTextMessage _onTextMessage;
private final OnControl _onControl;
@ -110,8 +107,7 @@ public class WebSocketConnectionD08 extends AbstractConnection implements WebSoc
}
private final WebSocketParser.FrameHandler _frameHandler= new WSFrameHandler();
private final WebSocket.FrameConnection _connection = new WSFrameConnection();
protected final WebSocket.FrameConnection _connection = new WSFrameConnection();
/* ------------------------------------------------------------ */
@ -800,27 +796,6 @@ public class WebSocketConnectionD08 extends AbstractConnection implements WebSoc
}
}
/* ------------------------------------------------------------ */
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
{
String key = request.getHeader("Sec-WebSocket-Key");
response.setHeader("Upgrade", "WebSocket");
response.addHeader("Connection","Upgrade");
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
if (subprotocol!=null)
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
for(Extension ext : _extensions)
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
response.sendError(101);
if (_onFrame!=null)
_onFrame.onHandshake(_connection);
_webSocket.onOpen(_connection);
}
/* ------------------------------------------------------------ */
public static String hashKey(String key)
{

View File

@ -19,9 +19,6 @@ import java.security.MessageDigest;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffer;
@ -106,12 +103,12 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
}
private final static byte[] MAGIC;
private final List<Extension> _extensions;
protected final List<Extension> _extensions;
private final WebSocketParserD13 _parser;
private final WebSocketGeneratorD13 _generator;
private final WebSocketGenerator _outbound;
private final WebSocket _webSocket;
private final OnFrame _onFrame;
protected final WebSocket _webSocket;
protected final OnFrame _onFrame;
private final OnBinaryMessage _onBinaryMessage;
private final OnTextMessage _onTextMessage;
private final OnControl _onControl;
@ -137,7 +134,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
}
}
private final WebSocket.FrameConnection _connection = new WSFrameConnection();
protected final WebSocket.FrameConnection _connection = new WSFrameConnection();
/* ------------------------------------------------------------ */
@ -918,27 +915,6 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
}
}
/* ------------------------------------------------------------ */
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
{
String key = request.getHeader("Sec-WebSocket-Key");
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
if (subprotocol!=null)
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
for(Extension ext : _extensions)
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
response.sendError(101);
if (_onFrame!=null)
_onFrame.onHandshake(_connection);
_webSocket.onOpen(_connection);
}
/* ------------------------------------------------------------ */
public static String hashKey(String key)
{

View File

@ -201,22 +201,25 @@ public class WebSocketFactory
ConnectedEndPoint endp = (ConnectedEndPoint)http.getEndPoint();
List<String> extensions_requested = new ArrayList<String>();
for (Enumeration e=request.getHeaders("Sec-WebSocket-Extensions");e.hasMoreElements();)
@SuppressWarnings("unchecked")
Enumeration<String> e = request.getHeaders("Sec-WebSocket-Extensions");
while (e.hasMoreElements())
{
QuotedStringTokenizer tok = new QuotedStringTokenizer((String)e.nextElement(),",");
QuotedStringTokenizer tok = new QuotedStringTokenizer(e.nextElement(),",");
while (tok.hasMoreTokens())
{
extensions_requested.add(tok.nextToken());
}
}
final WebSocketConnection connection;
final WebSocketServletConnection connection;
final List<Extension> extensions;
switch (draft)
{
case -1:
case 0:
extensions=Collections.emptyList();
connection = new WebSocketConnectionD00(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
connection = new WebSocketServletConnectionD00(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
break;
case 1:
case 2:
@ -225,16 +228,16 @@ public class WebSocketFactory
case 5:
case 6:
extensions=Collections.emptyList();
connection = new WebSocketConnectionD06(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
connection = new WebSocketServletConnectionD06(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol);
break;
case 7:
case 8:
extensions= initExtensions(extensions_requested,8-WebSocketConnectionD08.OP_EXT_DATA, 16-WebSocketConnectionD08.OP_EXT_CTRL,3);
connection = new WebSocketConnectionD08(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
connection = new WebSocketServletConnectionD08(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
break;
case 13:
extensions= initExtensions(extensions_requested,8-WebSocketConnectionD13.OP_EXT_DATA, 16-WebSocketConnectionD13.OP_EXT_CTRL,3);
connection = new WebSocketConnectionD13(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
connection = new WebSocketServletConnectionD13(websocket, endp, _buffers, http.getTimeStamp(), _maxIdleTime, protocol,extensions,draft);
break;
default:
LOG.warn("Unsupported Websocket version: "+draft);
@ -293,6 +296,7 @@ public class WebSocketFactory
// Try each requested protocol
WebSocket websocket = null;
@SuppressWarnings("unchecked")
Enumeration<String> protocols = request.getHeaders("Sec-WebSocket-Protocol");
String protocol=null;
while (protocol==null && protocols!=null && protocols.hasMoreElements())

View File

@ -41,6 +41,7 @@ import javax.servlet.http.HttpServletResponse;
* that a websocket may be accept before closing.
*
*/
@SuppressWarnings("serial")
public abstract class WebSocketServlet extends HttpServlet implements WebSocketFactory.Acceptor
{
WebSocketFactory _webSocketFactory;

View File

@ -0,0 +1,11 @@
package org.eclipse.jetty.websocket;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface WebSocketServletConnection extends WebSocketConnection
{
void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException;
}

View File

@ -0,0 +1,81 @@
package org.eclipse.jetty.websocket;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.websocket.WebSocket.OnFrame;
public class WebSocketServletConnectionD00 extends WebSocketConnectionD00 implements WebSocketServletConnection
{
public WebSocketServletConnectionD00(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol)
throws IOException
{
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol);
}
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
{
String uri = request.getRequestURI();
String query = request.getQueryString();
if (query != null && query.length() > 0)
{
uri += "?" + query;
}
uri = new HttpURI(uri).toString();
String host = request.getHeader("Host");
String origin = request.getHeader("Sec-WebSocket-Origin");
if (origin == null)
{
origin = request.getHeader("Origin");
}
if (origin != null)
{
origin = QuotedStringTokenizer.quoteIfNeeded(origin,"\r\n");
}
String key1 = request.getHeader("Sec-WebSocket-Key1");
if (key1 != null)
{
String key2 = request.getHeader("Sec-WebSocket-Key2");
setHixieKeys(key1,key2);
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
if (origin != null)
{
response.addHeader("Sec-WebSocket-Origin",origin);
}
response.addHeader("Sec-WebSocket-Location",(request.isSecure()?"wss://":"ws://") + host + uri);
if (subprotocol != null)
{
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
}
response.sendError(101,"WebSocket Protocol Handshake");
}
else
{
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
response.addHeader("WebSocket-Origin",origin);
response.addHeader("WebSocket-Location",(request.isSecure()?"wss://":"ws://") + host + uri);
if (subprotocol != null)
{
response.addHeader("WebSocket-Protocol",subprotocol);
}
response.sendError(101,"Web Socket Protocol Handshake");
response.flushBuffer();
if (_websocket instanceof OnFrame)
{
((OnFrame)_websocket).onHandshake(this);
}
_websocket.onOpen(this);
}
}
}

View File

@ -0,0 +1,39 @@
package org.eclipse.jetty.websocket;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.EndPoint;
public class WebSocketServletConnectionD06 extends WebSocketConnectionD06 implements WebSocketServletConnection
{
public WebSocketServletConnectionD06(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol)
throws IOException
{
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol);
}
/* ------------------------------------------------------------ */
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
{
String key = request.getHeader("Sec-WebSocket-Key");
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
if (subprotocol!=null)
{
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
}
response.sendError(101);
if (_onFrame!=null)
{
_onFrame.onHandshake(_connection);
}
_webSocket.onOpen(_connection);
}
}

View File

@ -0,0 +1,51 @@
package org.eclipse.jetty.websocket;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.EndPoint;
public class WebSocketServletConnectionD08 extends WebSocketConnectionD08 implements WebSocketServletConnection
{
public WebSocketServletConnectionD08(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
List<Extension> extensions, int draft, MaskGen maskgen) throws IOException
{
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft,maskgen);
}
public WebSocketServletConnectionD08(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
List<Extension> extensions, int draft) throws IOException
{
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft);
}
/* ------------------------------------------------------------ */
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
{
String key = request.getHeader("Sec-WebSocket-Key");
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
if (subprotocol != null)
{
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
}
for (Extension ext : _extensions)
{
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
}
response.sendError(101);
if (_onFrame != null)
{
_onFrame.onHandshake(_connection);
}
_webSocket.onOpen(_connection);
}
}

View File

@ -0,0 +1,52 @@
package org.eclipse.jetty.websocket;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.EndPoint;
public class WebSocketServletConnectionD13 extends WebSocketConnectionD13 implements WebSocketServletConnection
{
public WebSocketServletConnectionD13(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
List<Extension> extensions, int draft, MaskGen maskgen) throws IOException
{
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft,maskgen);
}
public WebSocketServletConnectionD13(WebSocket websocket, EndPoint endpoint, WebSocketBuffers buffers, long timestamp, int maxIdleTime, String protocol,
List<Extension> extensions, int draft) throws IOException
{
super(websocket,endpoint,buffers,timestamp,maxIdleTime,protocol,extensions,draft);
}
/* ------------------------------------------------------------ */
public void handshake(HttpServletRequest request, HttpServletResponse response, String subprotocol) throws IOException
{
String key = request.getHeader("Sec-WebSocket-Key");
response.setHeader("Upgrade","WebSocket");
response.addHeader("Connection","Upgrade");
response.addHeader("Sec-WebSocket-Accept",hashKey(key));
if (subprotocol != null)
{
response.addHeader("Sec-WebSocket-Protocol",subprotocol);
}
for (Extension ext : _extensions)
{
response.addHeader("Sec-WebSocket-Extensions",ext.getParameterizedName());
}
response.sendError(101);
if (_onFrame != null)
{
_onFrame.onHandshake(_connection);
}
_webSocket.onOpen(_connection);
}
}