diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/BinaryWebSocketFrame.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/BinaryWebSocketFrame.java index ed9f87dbe0..983879e980 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/BinaryWebSocketFrame.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/BinaryWebSocketFrame.java @@ -27,7 +27,7 @@ public class BinaryWebSocketFrame extends WebSocketFrame { * Creates a new empty binary frame. */ public BinaryWebSocketFrame() { - this.setBinaryData(ChannelBuffers.EMPTY_BUFFER); + setBinaryData(ChannelBuffers.EMPTY_BUFFER); } /** @@ -37,7 +37,7 @@ public class BinaryWebSocketFrame extends WebSocketFrame { * the content of the frame. */ public BinaryWebSocketFrame(ChannelBuffer binaryData) { - this.setBinaryData(binaryData); + setBinaryData(binaryData); } /** @@ -51,9 +51,9 @@ public class BinaryWebSocketFrame extends WebSocketFrame { * the content of the frame. */ public BinaryWebSocketFrame(boolean finalFragment, int rsv, ChannelBuffer binaryData) { - this.setFinalFragment(finalFragment); - this.setRsv(rsv); - this.setBinaryData(binaryData); + setFinalFragment(finalFragment); + setRsv(rsv); + setBinaryData(binaryData); } @Override diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/CloseWebSocketFrame.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/CloseWebSocketFrame.java index 67a61f8199..1f8ed46028 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/CloseWebSocketFrame.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/CloseWebSocketFrame.java @@ -26,7 +26,7 @@ public class CloseWebSocketFrame extends WebSocketFrame { * Creates a new empty close frame. */ public CloseWebSocketFrame() { - this.setBinaryData(ChannelBuffers.EMPTY_BUFFER); + setBinaryData(ChannelBuffers.EMPTY_BUFFER); } /** @@ -38,8 +38,8 @@ public class CloseWebSocketFrame extends WebSocketFrame { * reserved bits used for protocol extensions */ public CloseWebSocketFrame(boolean finalFragment, int rsv) { - this.setFinalFragment(finalFragment); - this.setRsv(rsv); + setFinalFragment(finalFragment); + setRsv(rsv); } @Override diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/ContinuationWebSocketFrame.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/ContinuationWebSocketFrame.java index bb2df42aa5..cb373dabe6 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/ContinuationWebSocketFrame.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/ContinuationWebSocketFrame.java @@ -31,7 +31,7 @@ public class ContinuationWebSocketFrame extends WebSocketFrame { * Creates a new empty continuation frame. */ public ContinuationWebSocketFrame() { - this.setBinaryData(ChannelBuffers.EMPTY_BUFFER); + setBinaryData(ChannelBuffers.EMPTY_BUFFER); } /** @@ -41,7 +41,7 @@ public class ContinuationWebSocketFrame extends WebSocketFrame { * the content of the frame. */ public ContinuationWebSocketFrame(ChannelBuffer binaryData) { - this.setBinaryData(binaryData); + setBinaryData(binaryData); } /** @@ -55,9 +55,9 @@ public class ContinuationWebSocketFrame extends WebSocketFrame { * the content of the frame. */ public ContinuationWebSocketFrame(boolean finalFragment, int rsv, ChannelBuffer binaryData) { - this.setFinalFragment(finalFragment); - this.setRsv(rsv); - this.setBinaryData(binaryData); + setFinalFragment(finalFragment); + setRsv(rsv); + setBinaryData(binaryData); } /** @@ -73,9 +73,9 @@ public class ContinuationWebSocketFrame extends WebSocketFrame { * Aggregated text set by decoder on the final continuation frame of a fragmented text message */ public ContinuationWebSocketFrame(boolean finalFragment, int rsv, ChannelBuffer binaryData, String aggregatedText) { - this.setFinalFragment(finalFragment); - this.setRsv(rsv); - this.setBinaryData(binaryData); + setFinalFragment(finalFragment); + setRsv(rsv); + setBinaryData(binaryData); this.aggregatedText = aggregatedText; } @@ -90,19 +90,19 @@ public class ContinuationWebSocketFrame extends WebSocketFrame { * text content of the frame. */ public ContinuationWebSocketFrame(boolean finalFragment, int rsv, String text) { - this.setFinalFragment(finalFragment); - this.setRsv(rsv); - this.setText(text); + setFinalFragment(finalFragment); + setRsv(rsv); + setText(text); } /** * Returns the text data in this frame */ public String getText() { - if (this.getBinaryData() == null) { + if (getBinaryData() == null) { return null; } - return this.getBinaryData().toString(CharsetUtil.UTF_8); + return getBinaryData().toString(CharsetUtil.UTF_8); } /** @@ -113,9 +113,9 @@ public class ContinuationWebSocketFrame extends WebSocketFrame { */ public void setText(String text) { if (text == null || text.isEmpty()) { - this.setBinaryData(ChannelBuffers.EMPTY_BUFFER); + setBinaryData(ChannelBuffers.EMPTY_BUFFER); } else { - this.setBinaryData(ChannelBuffers.copiedBuffer(text, CharsetUtil.UTF_8)); + setBinaryData(ChannelBuffers.copiedBuffer(text, CharsetUtil.UTF_8)); } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/PingWebSocketFrame.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/PingWebSocketFrame.java index 5815faad97..0923e1fb47 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/PingWebSocketFrame.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/PingWebSocketFrame.java @@ -27,8 +27,8 @@ public class PingWebSocketFrame extends WebSocketFrame { * Creates a new empty ping frame. */ public PingWebSocketFrame() { - this.setFinalFragment(true); - this.setBinaryData(ChannelBuffers.EMPTY_BUFFER); + setFinalFragment(true); + setBinaryData(ChannelBuffers.EMPTY_BUFFER); } /** @@ -38,7 +38,7 @@ public class PingWebSocketFrame extends WebSocketFrame { * the content of the frame. */ public PingWebSocketFrame(ChannelBuffer binaryData) { - this.setBinaryData(binaryData); + setBinaryData(binaryData); } /** @@ -52,9 +52,9 @@ public class PingWebSocketFrame extends WebSocketFrame { * the content of the frame. */ public PingWebSocketFrame(boolean finalFragment, int rsv, ChannelBuffer binaryData) { - this.setFinalFragment(finalFragment); - this.setRsv(rsv); - this.setBinaryData(binaryData); + setFinalFragment(finalFragment); + setRsv(rsv); + setBinaryData(binaryData); } @Override diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/PongWebSocketFrame.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/PongWebSocketFrame.java index ee3fd861b4..8cd3eb51ab 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/PongWebSocketFrame.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/PongWebSocketFrame.java @@ -27,7 +27,7 @@ public class PongWebSocketFrame extends WebSocketFrame { * Creates a new empty pong frame. */ public PongWebSocketFrame() { - this.setBinaryData(ChannelBuffers.EMPTY_BUFFER); + setBinaryData(ChannelBuffers.EMPTY_BUFFER); } /** @@ -37,7 +37,7 @@ public class PongWebSocketFrame extends WebSocketFrame { * the content of the frame. */ public PongWebSocketFrame(ChannelBuffer binaryData) { - this.setBinaryData(binaryData); + setBinaryData(binaryData); } /** @@ -51,9 +51,9 @@ public class PongWebSocketFrame extends WebSocketFrame { * the content of the frame. */ public PongWebSocketFrame(boolean finalFragment, int rsv, ChannelBuffer binaryData) { - this.setFinalFragment(finalFragment); - this.setRsv(rsv); - this.setBinaryData(binaryData); + setFinalFragment(finalFragment); + setRsv(rsv); + setBinaryData(binaryData); } @Override diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/TextWebSocketFrame.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/TextWebSocketFrame.java index 0087ced4e2..a9f89e6518 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/TextWebSocketFrame.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/TextWebSocketFrame.java @@ -28,7 +28,7 @@ public class TextWebSocketFrame extends WebSocketFrame { * Creates a new empty text frame. */ public TextWebSocketFrame() { - this.setBinaryData(ChannelBuffers.EMPTY_BUFFER); + setBinaryData(ChannelBuffers.EMPTY_BUFFER); } /** @@ -39,9 +39,9 @@ public class TextWebSocketFrame extends WebSocketFrame { */ public TextWebSocketFrame(String text) { if (text == null || text.isEmpty()) { - this.setBinaryData(ChannelBuffers.EMPTY_BUFFER); + setBinaryData(ChannelBuffers.EMPTY_BUFFER); } else { - this.setBinaryData(ChannelBuffers.copiedBuffer(text, CharsetUtil.UTF_8)); + setBinaryData(ChannelBuffers.copiedBuffer(text, CharsetUtil.UTF_8)); } } @@ -52,7 +52,7 @@ public class TextWebSocketFrame extends WebSocketFrame { * the content of the frame. Must be UTF-8 encoded */ public TextWebSocketFrame(ChannelBuffer binaryData) { - this.setBinaryData(binaryData); + setBinaryData(binaryData); } /** @@ -66,12 +66,12 @@ public class TextWebSocketFrame extends WebSocketFrame { * String to put in the frame */ public TextWebSocketFrame(boolean finalFragment, int rsv, String text) { - this.setFinalFragment(finalFragment); - this.setRsv(rsv); + setFinalFragment(finalFragment); + setRsv(rsv); if (text == null || text.isEmpty()) { - this.setBinaryData(ChannelBuffers.EMPTY_BUFFER); + setBinaryData(ChannelBuffers.EMPTY_BUFFER); } else { - this.setBinaryData(ChannelBuffers.copiedBuffer(text, CharsetUtil.UTF_8)); + setBinaryData(ChannelBuffers.copiedBuffer(text, CharsetUtil.UTF_8)); } } @@ -86,19 +86,19 @@ public class TextWebSocketFrame extends WebSocketFrame { * the content of the frame. Must be UTF-8 encoded */ public TextWebSocketFrame(boolean finalFragment, int rsv, ChannelBuffer binaryData) { - this.setFinalFragment(finalFragment); - this.setRsv(rsv); - this.setBinaryData(binaryData); + setFinalFragment(finalFragment); + setRsv(rsv); + setBinaryData(binaryData); } /** * Returns the text data in this frame */ public String getText() { - if (this.getBinaryData() == null) { + if (getBinaryData() == null) { return null; } - return this.getBinaryData().toString(CharsetUtil.UTF_8); + return getBinaryData().toString(CharsetUtil.UTF_8); } /** @@ -111,7 +111,7 @@ public class TextWebSocketFrame extends WebSocketFrame { if (text == null) { throw new NullPointerException("text"); } - this.setBinaryData(ChannelBuffers.copiedBuffer(text, CharsetUtil.UTF_8)); + setBinaryData(ChannelBuffers.copiedBuffer(text, CharsetUtil.UTF_8)); } @Override diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/UTF8Output.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/UTF8Output.java index 4477699fbc..dfeeba553b 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/UTF8Output.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/UTF8Output.java @@ -60,7 +60,7 @@ final class UTF8Output { public void write(int b) { byte type = TYPES[b & 0xFF]; - codep = (state != UTF8_ACCEPT) ? (b & 0x3f) | (codep << 6) : (0xff >> type) & b; + codep = state != UTF8_ACCEPT ? b & 0x3f | codep << 6 : 0xff >> type & b; state = STATES[state + type]; diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameDecoder.java index 59f1722289..69ca9776cf 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket00FrameDecoder.java @@ -33,7 +33,7 @@ import io.netty.handler.codec.replay.VoidEnum; */ public class WebSocket00FrameDecoder extends ReplayingDecoder { - public static final int DEFAULT_MAX_FRAME_SIZE = 16384; + private static final int DEFAULT_MAX_FRAME_SIZE = 16384; private final int maxFrameSize; private boolean receivedClosingHandshake; @@ -70,7 +70,7 @@ public class WebSocket00FrameDecoder extends ReplayingDecoder { return decodeBinaryFrame(type, buffer); } else { // Decode a 0xff terminated UTF-8 string - return decodeTextFrame(type, buffer); + return decodeTextFrame(buffer); } } @@ -92,7 +92,7 @@ public class WebSocket00FrameDecoder extends ReplayingDecoder { } } while ((b & 0x80) == 0x80); - if (type == ((byte) 0xFF) && frameSize == 0) { + if (type == (byte) 0xFF && frameSize == 0) { receivedClosingHandshake = true; return new CloseWebSocketFrame(); } @@ -100,7 +100,7 @@ public class WebSocket00FrameDecoder extends ReplayingDecoder { return new BinaryWebSocketFrame(buffer.readBytes((int) frameSize)); } - private WebSocketFrame decodeTextFrame(byte type, ChannelBuffer buffer) throws TooLongFrameException { + private WebSocketFrame decodeTextFrame(ChannelBuffer buffer) throws TooLongFrameException { int ridx = buffer.readerIndex(); int rbytes = actualReadableBytes(); int delimPos = buffer.indexOf(ridx, ridx + rbytes, (byte) 0xFF); diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.java index 518567c8bc..e7d76db0b9 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocket08FrameDecoder.java @@ -75,8 +75,8 @@ public class WebSocket08FrameDecoder extends ReplayingDecoder>> 8) & 0xFF); + header.writeByte(maskPayload ? 0xFE : 126); + header.writeByte(length >>> 8 & 0xFF); header.writeByte(length & 0xFF); } else { header = ChannelBuffers.buffer(10 + maskLength); header.writeByte(b0); - header.writeByte(this.maskPayload ? 0xFF : 127); + header.writeByte(maskPayload ? 0xFF : 127); header.writeLong(length); } // Write payload - if (this.maskPayload) { + if (maskPayload) { Integer random = (int) (Math.random() * Integer.MAX_VALUE); mask = ByteBuffer.allocate(4).putInt(random).array(); header.writeBytes(mask); diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java index 23a4d7263c..18ad9ec051 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java @@ -23,6 +23,7 @@ import java.util.Map; import io.netty.buffer.ChannelBuffer; import io.netty.buffer.ChannelBuffers; import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; import io.netty.handler.codec.base64.Base64; import io.netty.handler.codec.http.HttpResponse; import io.netty.util.CharsetUtil; @@ -32,35 +33,44 @@ import io.netty.util.CharsetUtil; */ public abstract class WebSocketClientHandshaker { - private URI webSocketURL; + private final URI webSocketUrl; - private WebSocketVersion version = WebSocketVersion.UNKNOWN; + private final WebSocketVersion version; - private boolean openingHandshakeCompleted; + private boolean handshakeComplete; - private String subProtocolRequest; + private final String expectedSubprotocol; - private String subProtocolResponse; + private String actualSubprotocol; - protected Map customHeaders; + protected final Map customHeaders; - public WebSocketClientHandshaker(URI webSocketURL, WebSocketVersion version, String subProtocol, + /** + * Base constructor + * + * @param webSocketUrl + * URL for web socket communications. e.g "ws://myhost.com/mypath". Subsequent web socket frames will be + * sent to this URL. + * @param version + * Version of web socket specification to use to connect to the server + * @param subprotocol + * Sub protocol request sent to the server. + * @param customHeaders + * Map of custom headers to add to the client request + */ + public WebSocketClientHandshaker(URI webSocketUrl, WebSocketVersion version, String subprotocol, Map customHeaders) { - this.webSocketURL = webSocketURL; + this.webSocketUrl = webSocketUrl; this.version = version; - this.subProtocolRequest = subProtocol; + expectedSubprotocol = subprotocol; this.customHeaders = customHeaders; } /** * Returns the URI to the web socket. e.g. "ws://myhost.com/path" */ - public URI getWebSocketURL() { - return webSocketURL; - } - - protected void setWebSocketURL(URI webSocketURL) { - this.webSocketURL = webSocketURL; + public URI getWebSocketUrl() { + return webSocketUrl; } /** @@ -70,133 +80,50 @@ public abstract class WebSocketClientHandshaker { return version; } - protected void setVersion(WebSocketVersion version) { - this.version = version; - } - /** * Flag to indicate if the opening handshake is complete */ - public boolean isOpeningHandshakeCompleted() { - return openingHandshakeCompleted; + public boolean isHandshakeComplete() { + return handshakeComplete; } - protected void setOpenningHandshakeCompleted(boolean openningHandshakeCompleted) { - this.openingHandshakeCompleted = openningHandshakeCompleted; + protected void setHandshakeComplete() { + handshakeComplete = true; } /** * Returns the sub protocol request sent to the server as specified in the constructor */ - public String getSubProtocolRequest() { - return subProtocolRequest; - } - - protected void setSubProtocolRequest(String subProtocolRequest) { - this.subProtocolRequest = subProtocolRequest; + public String getExpectedSubprotocol() { + return expectedSubprotocol; } /** * Returns the sub protocol response and sent by the server. Only available after end of handshake. */ - public String getSubProtocolResponse() { - return subProtocolResponse; + public String getActualSubprotocol() { + return actualSubprotocol; } - protected void setSubProtocolResponse(String subProtocolResponse) { - this.subProtocolResponse = subProtocolResponse; + protected void setActualSubprotocol(String actualSubprotocol) { + this.actualSubprotocol = actualSubprotocol; } /** - * Performs the opening handshake + * Begins the opening handshake * * @param channel * Channel */ - public abstract void performOpeningHandshake(Channel channel); + public abstract ChannelFuture handshake(Channel channel); /** - * Performs the closing handshake + * Validates and finishes the opening handshake initiated by {@link #handshake}}. * * @param channel * Channel * @param response * HTTP response containing the closing handshake details */ - public abstract void performClosingHandshake(Channel channel, HttpResponse response) - throws WebSocketHandshakeException; - - /** - * Performs an MD5 hash - * - * @param bytes - * Data to hash - * @return Hashed data - */ - protected byte[] md5(byte[] bytes) { - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - return md.digest(bytes); - } catch (NoSuchAlgorithmException e) { - throw new InternalError("MD5 not supported on this platform"); - } - } - - /** - * Performs an SHA-1 hash - * - * @param bytes - * Data to hash - * @return Hashed data - */ - protected byte[] sha1(byte[] bytes) { - try { - MessageDigest md = MessageDigest.getInstance("SHA1"); - return md.digest(bytes); - } catch (NoSuchAlgorithmException e) { - throw new InternalError("SHA-1 not supported on this platform"); - } - } - - /** - * Base 64 encoding - * - * @param bytes - * Bytes to encode - * @return encoded string - */ - protected String base64Encode(byte[] bytes) { - ChannelBuffer hashed = ChannelBuffers.wrappedBuffer(bytes); - return Base64.encode(hashed).toString(CharsetUtil.UTF_8); - } - - /** - * Creates some random bytes - * - * @param size - * Number of random bytes to create - * @return random bytes - */ - protected byte[] createRandomBytes(int size) { - byte[] bytes = new byte[size]; - - for (int i = 0; i < size; i++) { - bytes[i] = (byte) createRandomNumber(0, 255); - } - - return bytes; - } - - /** - * Generates a random number - * - * @param min - * Minimum value - * @param max - * Maximum value - * @return Random number - */ - protected int createRandomNumber(int min, int max) { - return (int) (Math.random() * max + min); - } + public abstract void finishHandshake(Channel channel, HttpResponse response); } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java index cfe0b69b05..d4d26e45a6 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java @@ -22,6 +22,7 @@ import java.util.Map; import io.netty.buffer.ChannelBuffers; import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; import io.netty.handler.codec.http.DefaultHttpRequest; import io.netty.handler.codec.http.HttpHeaders.Names; import io.netty.handler.codec.http.HttpHeaders.Values; @@ -55,14 +56,14 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker { * sent to this URL. * @param version * Version of web socket specification to use to connect to the server - * @param subProtocol + * @param subprotocol * Sub protocol request sent to the server. * @param customHeaders * Map of custom headers to add to the client request */ - public WebSocketClientHandshaker00(URI webSocketURL, WebSocketVersion version, String subProtocol, + public WebSocketClientHandshaker00(URI webSocketURL, WebSocketVersion version, String subprotocol, Map customHeaders) { - super(webSocketURL, version, subProtocol, customHeaders); + super(webSocketURL, version, subprotocol, customHeaders); } @@ -87,16 +88,16 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker { * Channel into which we can write our request */ @Override - public void performOpeningHandshake(Channel channel) { + public ChannelFuture handshake(Channel channel) { // Make keys - int spaces1 = createRandomNumber(1, 12); - int spaces2 = createRandomNumber(1, 12); + int spaces1 = WebSocketUtil.randomNumber(1, 12); + int spaces2 = WebSocketUtil.randomNumber(1, 12); int max1 = Integer.MAX_VALUE / spaces1; int max2 = Integer.MAX_VALUE / spaces2; - int number1 = createRandomNumber(0, max1); - int number2 = createRandomNumber(0, max2); + int number1 = WebSocketUtil.randomNumber(0, max1); + int number2 = WebSocketUtil.randomNumber(0, max2); int product1 = number1 * spaces1; int product2 = number2 * spaces2; @@ -110,7 +111,7 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker { key1 = insertSpaces(key1, spaces1); key2 = insertSpaces(key2, spaces2); - byte[] key3 = createRandomBytes(8); + byte[] key3 = WebSocketUtil.randomBytes(8); ByteBuffer buffer = ByteBuffer.allocate(4); buffer.putInt(number1); @@ -123,10 +124,10 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker { System.arraycopy(number1Array, 0, challenge, 0, 4); System.arraycopy(number2Array, 0, challenge, 4, 4); System.arraycopy(key3, 0, challenge, 8, 8); - this.expectedChallengeResponseBytes = md5(challenge); + expectedChallengeResponseBytes = WebSocketUtil.md5(challenge); // Get path - URI wsURL = this.getWebSocketURL(); + URI wsURL = getWebSocketUrl(); String path = wsURL.getPath(); if (wsURL.getQuery() != null && wsURL.getQuery().length() > 0) { path = wsURL.getPath() + "?" + wsURL.getQuery(); @@ -140,8 +141,8 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker { request.addHeader(Names.ORIGIN, "http://" + wsURL.getHost()); request.addHeader(Names.SEC_WEBSOCKET_KEY1, key1); request.addHeader(Names.SEC_WEBSOCKET_KEY2, key2); - if (this.getSubProtocolRequest() != null && !this.getSubProtocolRequest().equals("")) { - request.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, this.getSubProtocolRequest()); + if (getExpectedSubprotocol() != null && !getExpectedSubprotocol().equals("")) { + request.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, getExpectedSubprotocol()); } if (customHeaders != null) { @@ -152,9 +153,11 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker { request.setContent(ChannelBuffers.copiedBuffer(key3)); - channel.write(request); + ChannelFuture future = channel.write(request); channel.getPipeline().replace(HttpRequestEncoder.class, "ws-encoder", new WebSocket00FrameEncoder()); + + return future; } /** @@ -180,7 +183,7 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker { * @throws WebSocketHandshakeException */ @Override - public void performClosingHandshake(Channel channel, HttpResponse response) throws WebSocketHandshakeException { + public void finishHandshake(Channel channel, HttpResponse response) throws WebSocketHandshakeException { final HttpResponseStatus status = new HttpResponseStatus(101, "WebSocket Protocol Handshake"); if (!response.getStatus().equals(status)) { @@ -205,28 +208,28 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker { } String protocol = response.getHeader(Names.SEC_WEBSOCKET_PROTOCOL); - this.setSubProtocolResponse(protocol); + setActualSubprotocol(protocol); channel.getPipeline().replace(HttpResponseDecoder.class, "ws-decoder", new WebSocket00FrameDecoder()); - this.setOpenningHandshakeCompleted(true); + setHandshakeComplete(); } private String insertRandomCharacters(String key) { - int count = createRandomNumber(1, 12); + int count = WebSocketUtil.randomNumber(1, 12); char[] randomChars = new char[count]; int randCount = 0; while (randCount < count) { int rand = (int) (Math.random() * 0x7e + 0x21); - if (((0x21 < rand) && (rand < 0x2f)) || ((0x3a < rand) && (rand < 0x7e))) { + if (0x21 < rand && rand < 0x2f || 0x3a < rand && rand < 0x7e) { randomChars[randCount] = (char) rand; randCount += 1; } } for (int i = 0; i < count; i++) { - int split = createRandomNumber(0, key.length()); + int split = WebSocketUtil.randomNumber(0, key.length()); String part1 = key.substring(0, split); String part2 = key.substring(split); key = part1 + randomChars[i] + part2; @@ -237,7 +240,7 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker { private String insertSpaces(String key, int spaces) { for (int i = 0; i < spaces; i++) { - int split = createRandomNumber(1, key.length() - 1); + int split = WebSocketUtil.randomNumber(1, key.length() - 1); String part1 = key.substring(0, split); String part2 = key.substring(split); key = part1 + " " + part2; diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java index 5ee0c635fd..f9d122903a 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java @@ -19,6 +19,7 @@ import java.net.URI; import java.util.Map; import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; import io.netty.handler.codec.http.DefaultHttpRequest; import io.netty.handler.codec.http.HttpHeaders.Names; import io.netty.handler.codec.http.HttpHeaders.Values; @@ -50,7 +51,7 @@ public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker { private static final String protocol = null; - private boolean allowExtensions; + private final boolean allowExtensions; /** * Constructor specifying the destination web socket location and version to initiate @@ -60,16 +61,16 @@ public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker { * sent to this URL. * @param version * Version of web socket specification to use to connect to the server - * @param subProtocol + * @param subprotocol * Sub protocol request sent to the server. * @param allowExtensions * Allow extensions to be used in the reserved bits of the web socket frame * @param customHeaders * Map of custom headers to add to the client request */ - public WebSocketClientHandshaker08(URI webSocketURL, WebSocketVersion version, String subProtocol, + public WebSocketClientHandshaker08(URI webSocketURL, WebSocketVersion version, String subprotocol, boolean allowExtensions, Map customHeaders) { - super(webSocketURL, version, subProtocol, customHeaders); + super(webSocketURL, version, subprotocol, customHeaders); this.allowExtensions = allowExtensions; } @@ -94,25 +95,25 @@ public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker { * Channel into which we can write our request */ @Override - public void performOpeningHandshake(Channel channel) { + public ChannelFuture handshake(Channel channel) { // Get path - URI wsURL = this.getWebSocketURL(); + URI wsURL = getWebSocketUrl(); String path = wsURL.getPath(); if (wsURL.getQuery() != null && wsURL.getQuery().length() > 0) { path = wsURL.getPath() + "?" + wsURL.getQuery(); } // Get 16 bit nonce and base 64 encode it - byte[] nonce = createRandomBytes(16); - String key = base64Encode(nonce); + byte[] nonce = WebSocketUtil.randomBytes(16); + String key = WebSocketUtil.base64(nonce); String acceptSeed = key + MAGIC_GUID; - byte[] sha1 = sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII)); - this.expectedChallengeResponseString = base64Encode(sha1); + byte[] sha1 = WebSocketUtil.sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII)); + expectedChallengeResponseString = WebSocketUtil.base64(sha1); if (logger.isDebugEnabled()) { logger.debug(String.format("WS Version 08 Client Handshake key: %s. Expected response: %s.", key, - this.expectedChallengeResponseString)); + expectedChallengeResponseString)); } // Format request @@ -133,9 +134,11 @@ public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker { } } - channel.write(request); + ChannelFuture future = channel.write(request); channel.getPipeline().replace(HttpRequestEncoder.class, "ws-encoder", new WebSocket08FrameEncoder(true)); + + return future; } /** @@ -158,8 +161,8 @@ public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker { * @throws WebSocketHandshakeException */ @Override - public void performClosingHandshake(Channel channel, HttpResponse response) throws WebSocketHandshakeException { - final HttpResponseStatus status = new HttpResponseStatus(101, "Switching Protocols"); + public void finishHandshake(Channel channel, HttpResponse response) { + final HttpResponseStatus status = HttpResponseStatus.SWITCHING_PROTOCOLS; if (!response.getStatus().equals(status)) { throw new WebSocketHandshakeException("Invalid handshake response status: " + response.getStatus()); @@ -178,15 +181,14 @@ public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker { } String accept = response.getHeader(Names.SEC_WEBSOCKET_ACCEPT); - if (accept == null || !accept.equals(this.expectedChallengeResponseString)) { + if (accept == null || !accept.equals(expectedChallengeResponseString)) { throw new WebSocketHandshakeException(String.format("Invalid challenge. Actual: %s. Expected: %s", accept, - this.expectedChallengeResponseString)); + expectedChallengeResponseString)); } channel.getPipeline().replace(HttpResponseDecoder.class, "ws-decoder", - new WebSocket08FrameDecoder(false, this.allowExtensions)); + new WebSocket08FrameDecoder(false, allowExtensions)); - this.setOpenningHandshakeCompleted(true); + setHandshakeComplete(); } - } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java index 82a79514e8..19cfd1abbb 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java @@ -19,6 +19,7 @@ import java.net.URI; import java.util.Map; import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; import io.netty.handler.codec.http.DefaultHttpRequest; import io.netty.handler.codec.http.HttpHeaders.Names; import io.netty.handler.codec.http.HttpHeaders.Values; @@ -50,7 +51,7 @@ public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker { private static final String protocol = null; - private boolean allowExtensions; + private final boolean allowExtensions; /** * Constructor specifying the destination web socket location and version to initiate @@ -60,16 +61,16 @@ public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker { * sent to this URL. * @param version * Version of web socket specification to use to connect to the server - * @param subProtocol + * @param subprotocol * Sub protocol request sent to the server. * @param allowExtensions * Allow extensions to be used in the reserved bits of the web socket frame * @param customHeaders * Map of custom headers to add to the client request */ - public WebSocketClientHandshaker13(URI webSocketURL, WebSocketVersion version, String subProtocol, + public WebSocketClientHandshaker13(URI webSocketURL, WebSocketVersion version, String subprotocol, boolean allowExtensions, Map customHeaders) { - super(webSocketURL, version, subProtocol, customHeaders); + super(webSocketURL, version, subprotocol, customHeaders); this.allowExtensions = allowExtensions; } @@ -94,25 +95,25 @@ public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker { * Channel into which we can write our request */ @Override - public void performOpeningHandshake(Channel channel) { + public ChannelFuture handshake(Channel channel) { // Get path - URI wsURL = this.getWebSocketURL(); + URI wsURL = getWebSocketUrl(); String path = wsURL.getPath(); if (wsURL.getQuery() != null && wsURL.getQuery().length() > 0) { path = wsURL.getPath() + "?" + wsURL.getQuery(); } // Get 16 bit nonce and base 64 encode it - byte[] nonce = createRandomBytes(16); - String key = base64Encode(nonce); + byte[] nonce = WebSocketUtil.randomBytes(16); + String key = WebSocketUtil.base64(nonce); String acceptSeed = key + MAGIC_GUID; - byte[] sha1 = sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII)); - this.expectedChallengeResponseString = base64Encode(sha1); + byte[] sha1 = WebSocketUtil.sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII)); + expectedChallengeResponseString = WebSocketUtil.base64(sha1); if (logger.isDebugEnabled()) { logger.debug(String.format("WS Version 13 Client Handshake key: %s. Expected response: %s.", key, - this.expectedChallengeResponseString)); + expectedChallengeResponseString)); } // Format request @@ -132,9 +133,12 @@ public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker { request.addHeader(header, customHeaders.get(header)); } } - channel.write(request); + + ChannelFuture future = channel.write(request); channel.getPipeline().replace(HttpRequestEncoder.class, "ws-encoder", new WebSocket13FrameEncoder(true)); + + return future; } /** @@ -157,8 +161,8 @@ public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker { * @throws WebSocketHandshakeException */ @Override - public void performClosingHandshake(Channel channel, HttpResponse response) throws WebSocketHandshakeException { - final HttpResponseStatus status = new HttpResponseStatus(101, "Switching Protocols"); + public void finishHandshake(Channel channel, HttpResponse response) throws WebSocketHandshakeException { + final HttpResponseStatus status = HttpResponseStatus.SWITCHING_PROTOCOLS; if (!response.getStatus().equals(status)) { throw new WebSocketHandshakeException("Invalid handshake response status: " + response.getStatus()); @@ -177,15 +181,14 @@ public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker { } String accept = response.getHeader(Names.SEC_WEBSOCKET_ACCEPT); - if (accept == null || !accept.equals(this.expectedChallengeResponseString)) { + if (accept == null || !accept.equals(expectedChallengeResponseString)) { throw new WebSocketHandshakeException(String.format("Invalid challenge. Actual: %s. Expected: %s", accept, - this.expectedChallengeResponseString)); + expectedChallengeResponseString)); } channel.getPipeline().replace(HttpResponseDecoder.class, "ws-decoder", - new WebSocket13FrameDecoder(false, this.allowExtensions)); + new WebSocket13FrameDecoder(false, allowExtensions)); - this.setOpenningHandshakeCompleted(true); + setHandshakeComplete(); } - } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshakerFactory.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshakerFactory.java index 23fdce8162..a199299411 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshakerFactory.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketClientHandshakerFactory.java @@ -31,7 +31,7 @@ public class WebSocketClientHandshakerFactory { * sent to this URL. * @param version * Version of web socket specification to use to connect to the server - * @param subProtocol + * @param subprotocol * Sub protocol request sent to the server. Null if no sub-protocol support is required. * @param allowExtensions * Allow extensions to be used in the reserved bits of the web socket frame @@ -39,16 +39,16 @@ public class WebSocketClientHandshakerFactory { * Custom HTTP headers to send during the handshake * @throws WebSocketHandshakeException */ - public WebSocketClientHandshaker newHandshaker(URI webSocketURL, WebSocketVersion version, String subProtocol, + public WebSocketClientHandshaker newHandshaker(URI webSocketURL, WebSocketVersion version, String subprotocol, boolean allowExtensions, Map customHeaders) throws WebSocketHandshakeException { if (version == WebSocketVersion.V13) { - return new WebSocketClientHandshaker13(webSocketURL, version, subProtocol, allowExtensions, customHeaders); + return new WebSocketClientHandshaker13(webSocketURL, version, subprotocol, allowExtensions, customHeaders); } if (version == WebSocketVersion.V08) { - return new WebSocketClientHandshaker08(webSocketURL, version, subProtocol, allowExtensions, customHeaders); + return new WebSocketClientHandshaker08(webSocketURL, version, subprotocol, allowExtensions, customHeaders); } if (version == WebSocketVersion.V00) { - return new WebSocketClientHandshaker00(webSocketURL, version, subProtocol, customHeaders); + return new WebSocketClientHandshaker00(webSocketURL, version, subprotocol, customHeaders); } throw new WebSocketHandshakeException("Protocol version " + version.toString() + " not supported."); diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketHandshakeException.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketHandshakeException.java index 815d330fb1..459aa2dae6 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketHandshakeException.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketHandshakeException.java @@ -18,7 +18,7 @@ package io.netty.handler.codec.http.websocketx; /** * Exception during handshaking process */ -public class WebSocketHandshakeException extends Exception { +public class WebSocketHandshakeException extends RuntimeException { private static final long serialVersionUID = 1L; diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java index fd7d29e884..5cbe843429 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java @@ -17,10 +17,13 @@ package io.netty.handler.codec.http.websocketx; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.LinkedHashSet; +import java.util.Set; import io.netty.buffer.ChannelBuffer; import io.netty.buffer.ChannelBuffers; import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; import io.netty.handler.codec.base64.Base64; import io.netty.handler.codec.http.HttpRequest; import io.netty.util.CharsetUtil; @@ -30,55 +33,54 @@ import io.netty.util.CharsetUtil; */ public abstract class WebSocketServerHandshaker { - private String webSocketURL; + private final String webSocketUrl; - private String subProtocols; + private final String[] subprotocols; - private String[] subProtocolsArray; - - private WebSocketVersion version = WebSocketVersion.UNKNOWN; + private final WebSocketVersion version; /** * Constructor specifying the destination web socket location * - * @param webSocketURL + * @param version + * the protocol version + * @param webSocketUrl * URL for web socket communications. e.g "ws://myhost.com/mypath". Subsequent web socket frames will be * sent to this URL. - * @param subProtocols + * @param subprotocols * CSV of supported protocols. Null if sub protocols not supported. */ - public WebSocketServerHandshaker(String webSocketURL, String subProtocols) { - this.webSocketURL = webSocketURL; - this.subProtocols = subProtocols; - - if (this.subProtocols != null) { - this.subProtocolsArray = subProtocols.split(","); - for (int i = 0; i < this.subProtocolsArray.length; i++) { - this.subProtocolsArray[i] = this.subProtocolsArray[i].trim(); + protected WebSocketServerHandshaker( + WebSocketVersion version, String webSocketUrl, String subprotocols) { + this.version = version; + this.webSocketUrl = webSocketUrl; + if (subprotocols != null) { + String[] subprotocolArray = subprotocols.split(","); + for (int i = 0; i < subprotocolArray.length; i++) { + subprotocolArray[i] = subprotocolArray[i].trim(); } + this.subprotocols = subprotocolArray; + } else { + this.subprotocols = new String[0]; } } /** * Returns the URL of the web socket */ - public String getWebSocketURL() { - return webSocketURL; - } - - public void setWebSocketURL(String webSocketURL) { - this.webSocketURL = webSocketURL; + public String getWebSocketUrl() { + return webSocketUrl; } /** * Returns the CSV of supported sub protocols */ - public String getSubProtocols() { - return subProtocols; - } - - public void setSubProtocols(String subProtocols) { - this.subProtocols = subProtocols; + public Set getSubprotocols() { + Set ret = new LinkedHashSet(); + for (String p: this.subprotocols) { + ret.add(p); + } + return ret; } /** @@ -88,10 +90,6 @@ public abstract class WebSocketServerHandshaker { return version; } - public void setVersion(WebSocketVersion version) { - this.version = version; - } - /** * Performs the opening handshake * @@ -99,9 +97,8 @@ public abstract class WebSocketServerHandshaker { * Channel * @param req * HTTP Request - * @throws NoSuchAlgorithmException */ - public abstract void performOpeningHandshake(Channel channel, HttpRequest req); + public abstract ChannelFuture handshake(Channel channel, HttpRequest req); /** * Performs the closing handshake @@ -111,71 +108,27 @@ public abstract class WebSocketServerHandshaker { * @param frame * Closing Frame that was received */ - public abstract void performClosingHandshake(Channel channel, CloseWebSocketFrame frame); - - /** - * Performs an MD5 hash - * - * @param bytes - * Data to hash - * @return Hashed data - */ - protected byte[] md5(byte[] bytes) { - try { - MessageDigest md = MessageDigest.getInstance("MD5"); - return md.digest(bytes); - } catch (NoSuchAlgorithmException e) { - throw new InternalError("MD5 not supported on this platform"); - } - } - - /** - * SHA-1 hashing. Instance this we think it is not thread safe - * - * @param bytes - * byte to hash - * @return hashed - */ - protected byte[] sha1(byte[] bytes) { - try { - MessageDigest md = MessageDigest.getInstance("SHA1"); - return md.digest(bytes); - } catch (NoSuchAlgorithmException e) { - throw new InternalError("SHA-1 not supported on this platform"); - } - } - - /** - * Base 64 encoding - * - * @param bytes - * Bytes to encode - * @return encoded string - */ - protected String base64Encode(byte[] bytes) { - ChannelBuffer hashed = ChannelBuffers.wrappedBuffer(bytes); - return Base64.encode(hashed).toString(CharsetUtil.UTF_8); - } + public abstract ChannelFuture close(Channel channel, CloseWebSocketFrame frame); /** * Selects the first matching supported sub protocol * - * @param requestedSubProtocol + * @param requestedSubprotocols * CSV of protocols to be supported. e.g. "chat, superchat" * @return First matching supported sub protocol. Null if not found. */ - protected String selectSubProtocol(String requestedSubProtocol) { - if (requestedSubProtocol == null || this.subProtocolsArray == null) { + protected String selectSubprotocol(String requestedSubprotocols) { + if (requestedSubprotocols == null || subprotocols.length == 0) { return null; } - String[] requesteSubProtocolsArray = requestedSubProtocol.split(","); - for (int i = 0; i < requesteSubProtocolsArray.length; i++) { - String requesteSubProtocol = requesteSubProtocolsArray[i].trim(); + String[] requesteSubprotocolArray = requestedSubprotocols.split(","); + for (String p: requesteSubprotocolArray) { + String requestedSubprotocol = p.trim(); - for (String supportedSubProtocol : this.subProtocolsArray) { - if (requesteSubProtocol.equals(supportedSubProtocol)) { - return requesteSubProtocol; + for (String supportedSubprotocol: subprotocols) { + if (requestedSubprotocol.equals(supportedSubprotocol)) { + return requestedSubprotocol; } } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00.java index e4c51e7f68..da6aee631e 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00.java @@ -15,34 +15,24 @@ */ package io.netty.handler.codec.http.websocketx; -import static io.netty.handler.codec.http.HttpHeaders.Names.CONNECTION; -import static io.netty.handler.codec.http.HttpHeaders.Names.ORIGIN; -import static io.netty.handler.codec.http.HttpHeaders.Names.SEC_WEBSOCKET_KEY1; -import static io.netty.handler.codec.http.HttpHeaders.Names.SEC_WEBSOCKET_KEY2; -import static io.netty.handler.codec.http.HttpHeaders.Names.SEC_WEBSOCKET_LOCATION; -import static io.netty.handler.codec.http.HttpHeaders.Names.SEC_WEBSOCKET_ORIGIN; -import static io.netty.handler.codec.http.HttpHeaders.Names.SEC_WEBSOCKET_PROTOCOL; -import static io.netty.handler.codec.http.HttpHeaders.Names.WEBSOCKET_LOCATION; -import static io.netty.handler.codec.http.HttpHeaders.Names.WEBSOCKET_ORIGIN; -import static io.netty.handler.codec.http.HttpHeaders.Names.WEBSOCKET_PROTOCOL; -import static io.netty.handler.codec.http.HttpHeaders.Values.WEBSOCKET; -import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; - -import java.security.NoSuchAlgorithmException; +import static io.netty.handler.codec.http.HttpHeaders.Names.*; +import static io.netty.handler.codec.http.HttpHeaders.Values.*; +import static io.netty.handler.codec.http.HttpVersion.*; import io.netty.buffer.ChannelBuffer; import io.netty.buffer.ChannelBuffers; import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelPipeline; -import io.netty.handler.codec.http.HttpChunkAggregator; import io.netty.handler.codec.http.DefaultHttpResponse; +import io.netty.handler.codec.http.HttpChunkAggregator; +import io.netty.handler.codec.http.HttpHeaders.Names; +import io.netty.handler.codec.http.HttpHeaders.Values; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpRequestDecoder; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseEncoder; import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpHeaders.Names; -import io.netty.handler.codec.http.HttpHeaders.Values; import io.netty.logging.InternalLogger; import io.netty.logging.InternalLoggerFactory; @@ -66,11 +56,11 @@ public class WebSocketServerHandshaker00 extends WebSocketServerHandshaker { * @param webSocketURL * URL for web socket communications. e.g "ws://myhost.com/mypath". Subsequent web socket frames will be * sent to this URL. - * @param subProtocols + * @param subprotocols * CSV of supported protocols */ - public WebSocketServerHandshaker00(String webSocketURL, String subProtocols) { - super(webSocketURL, subProtocols); + public WebSocketServerHandshaker00(String webSocketURL, String subprotocols) { + super(WebSocketVersion.V00, webSocketURL, subprotocols); } /** @@ -117,20 +107,18 @@ public class WebSocketServerHandshaker00 extends WebSocketServerHandshaker { * Channel * @param req * HTTP request - * @throws NoSuchAlgorithmException */ @Override - public void performOpeningHandshake(Channel channel, HttpRequest req) { + public ChannelFuture handshake(Channel channel, HttpRequest req) { if (logger.isDebugEnabled()) { logger.debug(String.format("Channel %s WS Version 00 server handshake", channel.getId())); } - this.setVersion(WebSocketVersion.V00); // Serve the WebSocket handshake request. if (!Values.UPGRADE.equalsIgnoreCase(req.getHeader(CONNECTION)) || !WEBSOCKET.equalsIgnoreCase(req.getHeader(Names.UPGRADE))) { - return; + throw new WebSocketHandshakeException("not a WebSocket handshake request: missing upgrade"); } // Hixie 75 does not contain these headers while Hixie 76 does @@ -146,10 +134,10 @@ public class WebSocketServerHandshaker00 extends WebSocketServerHandshaker { if (isHixie76) { // New handshake method with a challenge: res.addHeader(SEC_WEBSOCKET_ORIGIN, req.getHeader(ORIGIN)); - res.addHeader(SEC_WEBSOCKET_LOCATION, this.getWebSocketURL()); + res.addHeader(SEC_WEBSOCKET_LOCATION, getWebSocketUrl()); String protocol = req.getHeader(SEC_WEBSOCKET_PROTOCOL); if (protocol != null) { - res.addHeader(SEC_WEBSOCKET_PROTOCOL, selectSubProtocol(protocol)); + res.addHeader(SEC_WEBSOCKET_PROTOCOL, selectSubprotocol(protocol)); } // Calculate the answer of the challenge. @@ -162,15 +150,15 @@ public class WebSocketServerHandshaker00 extends WebSocketServerHandshaker { input.writeInt(a); input.writeInt(b); input.writeLong(c); - ChannelBuffer output = ChannelBuffers.wrappedBuffer(this.md5(input.array())); + ChannelBuffer output = ChannelBuffers.wrappedBuffer(WebSocketUtil.md5(input.array())); res.setContent(output); } else { // Old Hixie 75 handshake method with no challenge: res.addHeader(WEBSOCKET_ORIGIN, req.getHeader(ORIGIN)); - res.addHeader(WEBSOCKET_LOCATION, this.getWebSocketURL()); + res.addHeader(WEBSOCKET_LOCATION, getWebSocketUrl()); String protocol = req.getHeader(WEBSOCKET_PROTOCOL); if (protocol != null) { - res.addHeader(WEBSOCKET_PROTOCOL, selectSubProtocol(protocol)); + res.addHeader(WEBSOCKET_PROTOCOL, selectSubprotocol(protocol)); } } @@ -179,9 +167,11 @@ public class WebSocketServerHandshaker00 extends WebSocketServerHandshaker { p.remove(HttpChunkAggregator.class); p.replace(HttpRequestDecoder.class, "wsdecoder", new WebSocket00FrameDecoder()); - channel.write(res); + ChannelFuture future = channel.write(res); p.replace(HttpResponseEncoder.class, "wsencoder", new WebSocket00FrameEncoder()); + + return future; } /** @@ -193,7 +183,7 @@ public class WebSocketServerHandshaker00 extends WebSocketServerHandshaker { * Web Socket frame that was received */ @Override - public void performClosingHandshake(Channel channel, CloseWebSocketFrame frame) { - channel.write(frame); + public ChannelFuture close(Channel channel, CloseWebSocketFrame frame) { + return channel.write(frame); } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java index 755ea7c992..e188798a7e 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java @@ -15,23 +15,21 @@ */ package io.netty.handler.codec.http.websocketx; -import static io.netty.handler.codec.http.HttpHeaders.Values.WEBSOCKET; -import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; - -import java.security.NoSuchAlgorithmException; +import static io.netty.handler.codec.http.HttpHeaders.Values.*; +import static io.netty.handler.codec.http.HttpVersion.*; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelPipeline; -import io.netty.handler.codec.http.HttpChunkAggregator; import io.netty.handler.codec.http.DefaultHttpResponse; +import io.netty.handler.codec.http.HttpChunkAggregator; +import io.netty.handler.codec.http.HttpHeaders.Names; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpRequestDecoder; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseEncoder; import io.netty.handler.codec.http.HttpResponseStatus; -import io.netty.handler.codec.http.HttpHeaders.Names; import io.netty.logging.InternalLogger; import io.netty.logging.InternalLoggerFactory; import io.netty.util.CharsetUtil; @@ -49,7 +47,7 @@ public class WebSocketServerHandshaker08 extends WebSocketServerHandshaker { public static final String WEBSOCKET_08_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - private boolean allowExtensions; + private final boolean allowExtensions; /** * Constructor specifying the destination web socket location @@ -57,13 +55,13 @@ public class WebSocketServerHandshaker08 extends WebSocketServerHandshaker { * @param webSocketURL * URL for web socket communications. e.g "ws://myhost.com/mypath". Subsequent web socket frames will be * sent to this URL. - * @param subProtocols + * @param subprotocols * CSV of supported protocols * @param allowExtensions * Allow extensions to be used in the reserved bits of the web socket frame */ - public WebSocketServerHandshaker08(String webSocketURL, String subProtocols, boolean allowExtensions) { - super(webSocketURL, subProtocols); + public WebSocketServerHandshaker08(String webSocketURL, String subprotocols, boolean allowExtensions) { + super(WebSocketVersion.V08, webSocketURL, subprotocols); this.allowExtensions = allowExtensions; } @@ -105,48 +103,46 @@ public class WebSocketServerHandshaker08 extends WebSocketServerHandshaker { * Channel * @param req * HTTP request - * @throws NoSuchAlgorithmException */ @Override - public void performOpeningHandshake(Channel channel, HttpRequest req) { + public ChannelFuture handshake(Channel channel, HttpRequest req) { if (logger.isDebugEnabled()) { logger.debug(String.format("Channel %s WS Version 8 server handshake", channel.getId())); } - HttpResponse res = new DefaultHttpResponse(HTTP_1_1, new HttpResponseStatus(101, "Switching Protocols")); - this.setVersion(WebSocketVersion.V08); + HttpResponse res = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.SWITCHING_PROTOCOLS); String key = req.getHeader(Names.SEC_WEBSOCKET_KEY); if (key == null) { - res.setStatus(HttpResponseStatus.BAD_REQUEST); - return; + throw new WebSocketHandshakeException("not a WebSocket request: missing key"); } String acceptSeed = key + WEBSOCKET_08_ACCEPT_GUID; - byte[] sha1 = sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII)); - String accept = base64Encode(sha1); + byte[] sha1 = WebSocketUtil.sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII)); + String accept = WebSocketUtil.base64(sha1); if (logger.isDebugEnabled()) { logger.debug(String.format("WS Version 8 Server Handshake key: %s. Response: %s.", key, accept)); } - res.setStatus(new HttpResponseStatus(101, "Switching Protocols")); + res.setStatus(HttpResponseStatus.SWITCHING_PROTOCOLS); res.addHeader(Names.UPGRADE, WEBSOCKET.toLowerCase()); res.addHeader(Names.CONNECTION, Names.UPGRADE); res.addHeader(Names.SEC_WEBSOCKET_ACCEPT, accept); String protocol = req.getHeader(Names.SEC_WEBSOCKET_PROTOCOL); if (protocol != null) { - res.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, this.selectSubProtocol(protocol)); + res.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, selectSubprotocol(protocol)); } - channel.write(res); + ChannelFuture future = channel.write(res); // Upgrade the connection and send the handshake response. ChannelPipeline p = channel.getPipeline(); p.remove(HttpChunkAggregator.class); - p.replace(HttpRequestDecoder.class, "wsdecoder", new WebSocket08FrameDecoder(true, this.allowExtensions)); + p.replace(HttpRequestDecoder.class, "wsdecoder", new WebSocket08FrameDecoder(true, allowExtensions)); p.replace(HttpResponseEncoder.class, "wsencoder", new WebSocket08FrameEncoder(false)); + return future; } /** @@ -158,9 +154,10 @@ public class WebSocketServerHandshaker08 extends WebSocketServerHandshaker { * Web Socket frame that was received */ @Override - public void performClosingHandshake(Channel channel, CloseWebSocketFrame frame) { + public ChannelFuture close(Channel channel, CloseWebSocketFrame frame) { ChannelFuture f = channel.write(frame); f.addListener(ChannelFutureListener.CLOSE); + return f; } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java index b87fc20b58..d93f581604 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java @@ -18,8 +18,6 @@ package io.netty.handler.codec.http.websocketx; import static io.netty.handler.codec.http.HttpHeaders.Values.WEBSOCKET; import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; -import java.security.NoSuchAlgorithmException; - import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; @@ -50,7 +48,7 @@ public class WebSocketServerHandshaker13 extends WebSocketServerHandshaker { public static final String WEBSOCKET_13_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - private boolean allowExtensions; + private final boolean allowExtensions; /** * Constructor specifying the destination web socket location @@ -58,13 +56,13 @@ public class WebSocketServerHandshaker13 extends WebSocketServerHandshaker { * @param webSocketURL * URL for web socket communications. e.g "ws://myhost.com/mypath". Subsequent web socket frames will be * sent to this URL. - * @param subProtocols + * @param subprotocols * CSV of supported protocols * @param allowExtensions * Allow extensions to be used in the reserved bits of the web socket frame */ - public WebSocketServerHandshaker13(String webSocketURL, String subProtocols, boolean allowExtensions) { - super(webSocketURL, subProtocols); + public WebSocketServerHandshaker13(String webSocketURL, String subprotocols, boolean allowExtensions) { + super(WebSocketVersion.V13, webSocketURL, subprotocols); this.allowExtensions = allowExtensions; } @@ -106,48 +104,46 @@ public class WebSocketServerHandshaker13 extends WebSocketServerHandshaker { * Channel * @param req * HTTP request - * @throws NoSuchAlgorithmException */ @Override - public void performOpeningHandshake(Channel channel, HttpRequest req) { + public ChannelFuture handshake(Channel channel, HttpRequest req) { if (logger.isDebugEnabled()) { logger.debug(String.format("Channel %s WS Version 13 server handshake", channel.getId())); } - HttpResponse res = new DefaultHttpResponse(HTTP_1_1, new HttpResponseStatus(101, "Switching Protocols")); - this.setVersion(WebSocketVersion.V13); + HttpResponse res = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.SWITCHING_PROTOCOLS); String key = req.getHeader(Names.SEC_WEBSOCKET_KEY); if (key == null) { - res.setStatus(HttpResponseStatus.BAD_REQUEST); - return; + throw new WebSocketHandshakeException("not a WebSocket request: missing key"); } String acceptSeed = key + WEBSOCKET_13_ACCEPT_GUID; - byte[] sha1 = sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII)); - String accept = base64Encode(sha1); + byte[] sha1 = WebSocketUtil.sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII)); + String accept = WebSocketUtil.base64(sha1); if (logger.isDebugEnabled()) { logger.debug(String.format("WS Version 13 Server Handshake key: %s. Response: %s.", key, accept)); } - res.setStatus(new HttpResponseStatus(101, "Switching Protocols")); + res.setStatus(HttpResponseStatus.SWITCHING_PROTOCOLS); res.addHeader(Names.UPGRADE, WEBSOCKET.toLowerCase()); res.addHeader(Names.CONNECTION, Names.UPGRADE); res.addHeader(Names.SEC_WEBSOCKET_ACCEPT, accept); String protocol = req.getHeader(Names.SEC_WEBSOCKET_PROTOCOL); if (protocol != null) { - res.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, this.selectSubProtocol(protocol)); + res.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, selectSubprotocol(protocol)); } - channel.write(res); + ChannelFuture future = channel.write(res); // Upgrade the connection and send the handshake response. ChannelPipeline p = channel.getPipeline(); p.remove(HttpChunkAggregator.class); - p.replace(HttpRequestDecoder.class, "wsdecoder", new WebSocket13FrameDecoder(true, this.allowExtensions)); + p.replace(HttpRequestDecoder.class, "wsdecoder", new WebSocket13FrameDecoder(true, allowExtensions)); p.replace(HttpResponseEncoder.class, "wsencoder", new WebSocket13FrameEncoder(false)); + return future; } /** @@ -159,9 +155,10 @@ public class WebSocketServerHandshaker13 extends WebSocketServerHandshaker { * Web Socket frame that was received */ @Override - public void performClosingHandshake(Channel channel, CloseWebSocketFrame frame) { + public ChannelFuture close(Channel channel, CloseWebSocketFrame frame) { ChannelFuture f = channel.write(frame); f.addListener(ChannelFutureListener.CLOSE); + return f; } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshakerFactory.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshakerFactory.java index 9badcd0d45..4428bc5ea0 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshakerFactory.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshakerFactory.java @@ -30,9 +30,9 @@ public class WebSocketServerHandshakerFactory { private final String webSocketURL; - private final String subProtocols; + private final String subprotocols; - private boolean allowExtensions; + private final boolean allowExtensions; /** * Constructor specifying the destination web socket location @@ -40,14 +40,14 @@ public class WebSocketServerHandshakerFactory { * @param webSocketURL * URL for web socket communications. e.g "ws://myhost.com/mypath". Subsequent web socket frames will be * sent to this URL. - * @param subProtocols + * @param subprotocols * CSV of supported protocols. Null if sub protocols not supported. * @param allowExtensions * Allow extensions to be used in the reserved bits of the web socket frame */ - public WebSocketServerHandshakerFactory(String webSocketURL, String subProtocols, boolean allowExtensions) { + public WebSocketServerHandshakerFactory(String webSocketURL, String subprotocols, boolean allowExtensions) { this.webSocketURL = webSocketURL; - this.subProtocols = subProtocols; + this.subprotocols = subprotocols; this.allowExtensions = allowExtensions; } @@ -63,16 +63,16 @@ public class WebSocketServerHandshakerFactory { if (version != null) { if (version.equals(WebSocketVersion.V13.toHttpHeaderValue())) { // Version 13 of the wire protocol - RFC 6455 (version 17 of the draft hybi specification). - return new WebSocketServerHandshaker13(webSocketURL, subProtocols, this.allowExtensions); + return new WebSocketServerHandshaker13(webSocketURL, subprotocols, allowExtensions); } else if (version.equals(WebSocketVersion.V08.toHttpHeaderValue())) { // Version 8 of the wire protocol - version 10 of the draft hybi specification. - return new WebSocketServerHandshaker08(webSocketURL, subProtocols, this.allowExtensions); + return new WebSocketServerHandshaker08(webSocketURL, subprotocols, allowExtensions); } else { return null; } } else { // Assume version 00 where version header was not specified - return new WebSocketServerHandshaker00(webSocketURL, subProtocols); + return new WebSocketServerHandshaker00(webSocketURL, subprotocols); } } @@ -83,8 +83,9 @@ public class WebSocketServerHandshakerFactory { * Channel */ public void sendUnsupportedWebSocketVersionResponse(Channel channel) { - HttpResponse res = new DefaultHttpResponse(HttpVersion.HTTP_1_1, new HttpResponseStatus(101, - "Switching Protocols")); + HttpResponse res = new DefaultHttpResponse( + HttpVersion.HTTP_1_1, + HttpResponseStatus.SWITCHING_PROTOCOLS); res.setStatus(HttpResponseStatus.UPGRADE_REQUIRED); res.setHeader(Names.SEC_WEBSOCKET_VERSION, WebSocketVersion.V13.toHttpHeaderValue()); channel.write(res); diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketUtil.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketUtil.java new file mode 100644 index 0000000000..ffe7efcfbd --- /dev/null +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketUtil.java @@ -0,0 +1,109 @@ +/* + * Copyright 2011 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.handler.codec.http.websocketx; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import io.netty.buffer.ChannelBuffer; +import io.netty.buffer.ChannelBuffers; +import io.netty.handler.codec.base64.Base64; +import io.netty.util.CharsetUtil; + +/** + * TODO Document me. + */ +final class WebSocketUtil { + + /** + * Performs an MD5 hash + * + * @param bytes + * Data to hash + * @return Hashed data + */ + static byte[] md5(byte[] bytes) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + return md.digest(bytes); + } catch (NoSuchAlgorithmException e) { + throw new InternalError("MD5 not supported on this platform"); + } + } + + /** + * Performs an SHA-1 hash + * + * @param bytes + * Data to hash + * @return Hashed data + */ + static byte[] sha1(byte[] bytes) { + try { + MessageDigest md = MessageDigest.getInstance("SHA1"); + return md.digest(bytes); + } catch (NoSuchAlgorithmException e) { + throw new InternalError("SHA-1 not supported on this platform"); + } + } + + /** + * Base 64 encoding + * + * @param bytes + * Bytes to encode + * @return encoded string + */ + static String base64(byte[] bytes) { + ChannelBuffer hashed = ChannelBuffers.wrappedBuffer(bytes); + return Base64.encode(hashed).toString(CharsetUtil.UTF_8); + } + + /** + * Creates some random bytes + * + * @param size + * Number of random bytes to create + * @return random bytes + */ + static byte[] randomBytes(int size) { + byte[] bytes = new byte[size]; + + for (int i = 0; i < size; i++) { + bytes[i] = (byte) randomNumber(0, 255); + } + + return bytes; + } + + /** + * Generates a random number + * + * @param min + * Minimum value + * @param max + * Maximum value + * @return Random number + */ + static int randomNumber(int min, int max) { + return (int) (Math.random() * max + min); + } + + + private WebSocketUtil() { + // Unused + } +} diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketVersion.java b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketVersion.java index 3c7e842a3b..b538e7e805 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketVersion.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/websocketx/WebSocketVersion.java @@ -57,6 +57,6 @@ public enum WebSocketVersion { } else if (this == V13) { return "13"; } - throw new IllegalArgumentException(this.toString() + " does not have a HttpHeaderValue."); + throw new IllegalStateException("Unknown web socket version: " + this); } } diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00Test.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00Test.java index b4f92c3834..8e98282542 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00Test.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00Test.java @@ -76,7 +76,7 @@ public class WebSocketServerHandshaker00Test { req.setContent(buffer); WebSocketServerHandshaker00 handsaker = new WebSocketServerHandshaker00("ws://example.com/chat", "chat"); - handsaker.performOpeningHandshake(channelMock, req); + handsaker.handshake(channelMock, req); Assert.assertEquals("ws://example.com/chat", res.getValue().getHeader(Names.SEC_WEBSOCKET_LOCATION)); Assert.assertEquals("chat", res.getValue().getHeader(Names.SEC_WEBSOCKET_PROTOCOL)); diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08Test.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08Test.java index aa3470b745..6ca8a495d1 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08Test.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08Test.java @@ -69,7 +69,7 @@ public class WebSocketServerHandshaker08Test { req.setHeader(Names.SEC_WEBSOCKET_VERSION, "8"); WebSocketServerHandshaker08 handsaker = new WebSocketServerHandshaker08("ws://example.com/chat", "chat", false); - handsaker.performOpeningHandshake(channelMock, req); + handsaker.handshake(channelMock, req); Assert.assertEquals("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", res.getValue().getHeader(Names.SEC_WEBSOCKET_ACCEPT)); Assert.assertEquals("chat", res.getValue().getHeader(Names.SEC_WEBSOCKET_PROTOCOL)); diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13Test.java b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13Test.java index c38ae478c4..257e484fa5 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13Test.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13Test.java @@ -68,7 +68,7 @@ public class WebSocketServerHandshaker13Test { req.setHeader(Names.SEC_WEBSOCKET_PROTOCOL, "chat, superchat"); req.setHeader(Names.SEC_WEBSOCKET_VERSION, "13"); WebSocketServerHandshaker13 handsaker = new WebSocketServerHandshaker13("ws://example.com/chat", "chat", false); - handsaker.performOpeningHandshake(channelMock, req); + handsaker.handshake(channelMock, req); Assert.assertEquals("s3pPLMBiTxaQ9kYGzzhZRbK+xOo=", res.getValue().getHeader(Names.SEC_WEBSOCKET_ACCEPT)); Assert.assertEquals("chat", res.getValue().getHeader(Names.SEC_WEBSOCKET_PROTOCOL)); diff --git a/example/src/main/java/io/netty/example/http/websocketx/autobahn/AutobahnServerHandler.java b/example/src/main/java/io/netty/example/http/websocketx/autobahn/AutobahnServerHandler.java index b1edbca325..83d54025bc 100644 --- a/example/src/main/java/io/netty/example/http/websocketx/autobahn/AutobahnServerHandler.java +++ b/example/src/main/java/io/netty/example/http/websocketx/autobahn/AutobahnServerHandler.java @@ -76,7 +76,7 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler { if (this.handshaker == null) { wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel()); } else { - this.handshaker.performOpeningHandshake(ctx.getChannel(), req); + this.handshaker.handshake(ctx.getChannel(), req); } } @@ -85,7 +85,7 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler { .format("Channel %s received %s", ctx.getChannel().getId(), frame.getClass().getSimpleName())); if (frame instanceof CloseWebSocketFrame) { - this.handshaker.performClosingHandshake(ctx.getChannel(), (CloseWebSocketFrame) frame); + this.handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame); } else if (frame instanceof PingWebSocketFrame) { ctx.getChannel().write( new PongWebSocketFrame(frame.isFinalFragment(), frame.getRsv(), frame.getBinaryData())); diff --git a/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClient.java b/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClient.java index 58041cfdb1..5ed8cbefe7 100644 --- a/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClient.java +++ b/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClient.java @@ -97,21 +97,17 @@ public class WebSocketClient { Channel ch = future.getChannel(); - handshaker.performOpeningHandshake(ch); - - Thread.sleep(1000); + handshaker.handshake(ch).awaitUninterruptibly(); // Send 10 messages and wait for responses System.out.println("WebSocket Client sending message"); for (int i = 0; i < 10; i++) { ch.write(new TextWebSocketFrame("Message #" + i)); } - Thread.sleep(1000); // Ping System.out.println("WebSocket Client sending ping"); - ch.write(new PingWebSocketFrame(ChannelBuffers.copiedBuffer(new byte[] { 1, 2, 3, 4, 5, 6 }))); - Thread.sleep(1000); + ch.write(new PingWebSocketFrame(ChannelBuffers.copiedBuffer(new byte[]{1, 2, 3, 4, 5, 6}))); // Close System.out.println("WebSocket Client sending close"); diff --git a/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClientHandler.java b/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClientHandler.java index 063fd7a6a8..7555b992ba 100644 --- a/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClientHandler.java +++ b/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClientHandler.java @@ -52,8 +52,8 @@ public class WebSocketClientHandler extends SimpleChannelUpstreamHandler { @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { Channel ch = ctx.getChannel(); - if (!handshaker.isOpeningHandshakeCompleted()) { - handshaker.performClosingHandshake(ch, (HttpResponse) e.getMessage()); + if (!handshaker.isHandshakeComplete()) { + handshaker.finishHandshake(ch, (HttpResponse) e.getMessage()); System.out.println("WebSocket Client connected!"); return; } diff --git a/example/src/main/java/io/netty/example/http/websocketx/server/WebSocketServerHandler.java b/example/src/main/java/io/netty/example/http/websocketx/server/WebSocketServerHandler.java index af9b2431ea..64fdcc6000 100644 --- a/example/src/main/java/io/netty/example/http/websocketx/server/WebSocketServerHandler.java +++ b/example/src/main/java/io/netty/example/http/websocketx/server/WebSocketServerHandler.java @@ -96,7 +96,7 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler { if (this.handshaker == null) { wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel()); } else { - this.handshaker.performOpeningHandshake(ctx.getChannel(), req); + this.handshaker.handshake(ctx.getChannel(), req); } } @@ -104,7 +104,7 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler { // Check for closing frame if (frame instanceof CloseWebSocketFrame) { - this.handshaker.performClosingHandshake(ctx.getChannel(), (CloseWebSocketFrame) frame); + this.handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame); return; } else if (frame instanceof PingWebSocketFrame) { ctx.getChannel().write(new PongWebSocketFrame(frame.getBinaryData())); diff --git a/example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServerHandler.java b/example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServerHandler.java index 2fd0f235af..c2a6bf6289 100644 --- a/example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServerHandler.java +++ b/example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServerHandler.java @@ -96,7 +96,7 @@ public class WebSocketSslServerHandler extends SimpleChannelUpstreamHandler { if (this.handshaker == null) { wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel()); } else { - this.handshaker.performOpeningHandshake(ctx.getChannel(), req); + this.handshaker.handshake(ctx.getChannel(), req); } } @@ -104,7 +104,7 @@ public class WebSocketSslServerHandler extends SimpleChannelUpstreamHandler { // Check for closing frame if (frame instanceof CloseWebSocketFrame) { - this.handshaker.performClosingHandshake(ctx.getChannel(), (CloseWebSocketFrame) frame); + this.handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame); return; } else if (frame instanceof PingWebSocketFrame) { ctx.getChannel().write(new PongWebSocketFrame(frame.getBinaryData()));