From cedbfba07d96d100f8cc04bf0fe4491eb8502616 Mon Sep 17 00:00:00 2001 From: vibul Date: Thu, 15 Dec 2011 14:34:20 +1100 Subject: [PATCH] Change use of specification version to wire protocol version --- .../websocketx/autobahn/package-info.java | 2 +- .../example/http/websocketx/client/App.java | 4 +- .../client/WebSocketClientFactory.java | 4 +- .../client/WebSocketClientHandler.java | 6 +- .../websocketx/WebSocketClientHandshaker.java | 8 +- .../WebSocketClientHandshaker00.java | 2 +- .../WebSocketClientHandshaker08.java | 202 ++++++++++++++++++ .../WebSocketClientHandshaker10.java | 183 ---------------- .../WebSocketClientHandshaker13.java | 202 ++++++++++++++++++ .../WebSocketClientHandshaker17.java | 183 ---------------- .../WebSocketClientHandshakerFactory.java | 12 +- .../websocketx/WebSocketServerHandshaker.java | 6 +- .../WebSocketServerHandshaker00.java | 2 +- .../WebSocketServerHandshaker08.java | 180 ++++++++++++++++ .../WebSocketServerHandshaker10.java | 169 --------------- .../WebSocketServerHandshaker13.java | 180 ++++++++++++++++ .../WebSocketServerHandshaker17.java | 169 --------------- .../WebSocketServerHandshakerFactory.java | 10 +- .../WebSocketSpecificationVersion.java | 51 ----- .../http/websocketx/WebSocketVersion.java | 58 +++++ .../codec/http/websocketx/package-info.java | 2 +- 21 files changed, 851 insertions(+), 784 deletions(-) create mode 100644 src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java delete mode 100644 src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker10.java create mode 100644 src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java delete mode 100644 src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker17.java create mode 100644 src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java delete mode 100644 src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker10.java create mode 100644 src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java delete mode 100644 src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker17.java delete mode 100644 src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketSpecificationVersion.java create mode 100644 src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketVersion.java diff --git a/src/main/java/org/jboss/netty/example/http/websocketx/autobahn/package-info.java b/src/main/java/org/jboss/netty/example/http/websocketx/autobahn/package-info.java index f2041cab7c..ae6ea1d20a 100644 --- a/src/main/java/org/jboss/netty/example/http/websocketx/autobahn/package-info.java +++ b/src/main/java/org/jboss/netty/example/http/websocketx/autobahn/package-info.java @@ -36,7 +36,7 @@ * *

08. Go to test suite directory: cd testsuite/websockets * - *

09. Edit fuzzing_clinet_spec.json and set the version to 10 or 17. + *

09. Edit fuzzing_clinet_spec.json and set the hybi specification version to 10 or 17 (RFC 6455). * * { * "options": {"failByDrop": false}, diff --git a/src/main/java/org/jboss/netty/example/http/websocketx/client/App.java b/src/main/java/org/jboss/netty/example/http/websocketx/client/App.java index c5171aedc0..196a9fc673 100644 --- a/src/main/java/org/jboss/netty/example/http/websocketx/client/App.java +++ b/src/main/java/org/jboss/netty/example/http/websocketx/client/App.java @@ -28,7 +28,7 @@ import org.jboss.netty.handler.codec.http.websocketx.PingWebSocketFrame; import org.jboss.netty.handler.codec.http.websocketx.PongWebSocketFrame; import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame; import org.jboss.netty.handler.codec.http.websocketx.WebSocketFrame; -import org.jboss.netty.handler.codec.http.websocketx.WebSocketSpecificationVersion; +import org.jboss.netty.handler.codec.http.websocketx.WebSocketVersion; /** * A HTTP client demo app @@ -59,7 +59,7 @@ public class App { // If you change it to V00, ping is not supported and remember to change HttpResponseDecoder to // WebSocketHttpResponseDecoder in the pipeline. WebSocketClient client = factory.newClient(new URI("ws://localhost:8080/websocket"), - WebSocketSpecificationVersion.V17, callbackHandler); + WebSocketVersion.V13, callbackHandler); // Connect System.out.println("WebSocket Client connecting"); diff --git a/src/main/java/org/jboss/netty/example/http/websocketx/client/WebSocketClientFactory.java b/src/main/java/org/jboss/netty/example/http/websocketx/client/WebSocketClientFactory.java index 112c10d40a..e88a75db89 100644 --- a/src/main/java/org/jboss/netty/example/http/websocketx/client/WebSocketClientFactory.java +++ b/src/main/java/org/jboss/netty/example/http/websocketx/client/WebSocketClientFactory.java @@ -29,7 +29,7 @@ import org.jboss.netty.channel.Channels; import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; import org.jboss.netty.handler.codec.http.HttpRequestEncoder; import org.jboss.netty.handler.codec.http.HttpResponseDecoder; -import org.jboss.netty.handler.codec.http.websocketx.WebSocketSpecificationVersion; +import org.jboss.netty.handler.codec.http.websocketx.WebSocketVersion; import java.net.URI; import java.util.concurrent.Executors; @@ -57,7 +57,7 @@ public class WebSocketClientFactory { * @return A WebSocket client. Call {@link WebSocketClient#connect()} to connect. */ public WebSocketClient newClient(final URI url, - final WebSocketSpecificationVersion version, + final WebSocketVersion version, final WebSocketCallback callback) { ClientBootstrap bootstrap = new ClientBootstrap(socketChannelFactory); diff --git a/src/main/java/org/jboss/netty/example/http/websocketx/client/WebSocketClientHandler.java b/src/main/java/org/jboss/netty/example/http/websocketx/client/WebSocketClientHandler.java index 5c12363abd..844e1767d1 100644 --- a/src/main/java/org/jboss/netty/example/http/websocketx/client/WebSocketClientHandler.java +++ b/src/main/java/org/jboss/netty/example/http/websocketx/client/WebSocketClientHandler.java @@ -37,7 +37,7 @@ import org.jboss.netty.handler.codec.http.HttpResponse; import org.jboss.netty.handler.codec.http.websocketx.WebSocketClientHandshaker; import org.jboss.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory; import org.jboss.netty.handler.codec.http.websocketx.WebSocketFrame; -import org.jboss.netty.handler.codec.http.websocketx.WebSocketSpecificationVersion; +import org.jboss.netty.handler.codec.http.websocketx.WebSocketVersion; import org.jboss.netty.util.CharsetUtil; /** @@ -53,9 +53,9 @@ public class WebSocketClientHandler extends SimpleChannelUpstreamHandler impleme private final WebSocketCallback callback; private Channel channel; private WebSocketClientHandshaker handshaker = null; - private final WebSocketSpecificationVersion version; + private final WebSocketVersion version; - public WebSocketClientHandler(ClientBootstrap bootstrap, URI url, WebSocketSpecificationVersion version, WebSocketCallback callback) { + public WebSocketClientHandler(ClientBootstrap bootstrap, URI url, WebSocketVersion version, WebSocketCallback callback) { this.bootstrap = bootstrap; this.url = url; this.version = version; diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java index 792d5c6357..1155192148 100644 --- a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java +++ b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker.java @@ -33,7 +33,7 @@ public abstract class WebSocketClientHandshaker { private URI webSocketURL; - private WebSocketSpecificationVersion version = WebSocketSpecificationVersion.UNKNOWN; + private WebSocketVersion version = WebSocketVersion.UNKNOWN; private boolean openingHandshakeCompleted = false; @@ -47,7 +47,7 @@ public abstract class WebSocketClientHandshaker { * @param version * @param subProtocol */ - public WebSocketClientHandshaker(URI webSocketURL, WebSocketSpecificationVersion version, String subProtocol) { + public WebSocketClientHandshaker(URI webSocketURL, WebSocketVersion version, String subProtocol) { this.webSocketURL = webSocketURL; this.version = version; this.subProtocolRequest = subProtocol; @@ -67,11 +67,11 @@ public abstract class WebSocketClientHandshaker { /** * Version of the web socket specification that is being used */ - public WebSocketSpecificationVersion getVersion() { + public WebSocketVersion getVersion() { return version; } - protected void setVersion(WebSocketSpecificationVersion version) { + protected void setVersion(WebSocketVersion version) { this.version = version; } diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java index 127ad2edc5..d2ff48d983 100644 --- a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java +++ b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker00.java @@ -61,7 +61,7 @@ public class WebSocketClientHandshaker00 extends WebSocketClientHandshaker { * @param subProtocol * Sub protocol request sent to the server. */ - public WebSocketClientHandshaker00(URI webSocketURL, WebSocketSpecificationVersion version, String subProtocol) { + public WebSocketClientHandshaker00(URI webSocketURL, WebSocketVersion version, String subProtocol) { super(webSocketURL, version, subProtocol); } diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java new file mode 100644 index 0000000000..6c99bfffe8 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java @@ -0,0 +1,202 @@ +/* + * 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 org.jboss.netty.handler.codec.http.websocketx; + +import java.net.URI; + +import org.jboss.netty.channel.Channel; +import org.jboss.netty.handler.codec.http.DefaultHttpRequest; +import org.jboss.netty.handler.codec.http.HttpHeaders.Names; +import org.jboss.netty.handler.codec.http.HttpHeaders.Values; +import org.jboss.netty.handler.codec.http.HttpMethod; +import org.jboss.netty.handler.codec.http.HttpRequest; +import org.jboss.netty.handler.codec.http.HttpRequestEncoder; +import org.jboss.netty.handler.codec.http.HttpResponse; +import org.jboss.netty.handler.codec.http.HttpResponseDecoder; +import org.jboss.netty.handler.codec.http.HttpResponseStatus; +import org.jboss.netty.handler.codec.http.HttpVersion; +import org.jboss.netty.logging.InternalLogger; +import org.jboss.netty.logging.InternalLoggerFactory; +import org.jboss.netty.util.CharsetUtil; + +/** + *

+ * Performs client side opening and closing handshakes for web socket + * specification version draft-ietf-hybi-thewebsocketprotocol- 10 + *

+ */ +public class WebSocketClientHandshaker08 extends WebSocketClientHandshaker { + + private static final InternalLogger logger = InternalLoggerFactory + .getInstance(WebSocketClientHandshaker08.class); + + public static final String MAGIC_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + + private String expectedChallengeResponseString = null; + + private static final String protocol = null; + + private boolean allowExtensions = false; + + /** + * Constructor specifying the destination web socket location and version to + * initiate + * + * @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 allowExtensions + * Allow extensions to be used in the reserved bits of the web + * socket frame + */ + public WebSocketClientHandshaker08(URI webSocketURL, + WebSocketVersion version, String subProtocol, + boolean allowExtensions) { + super(webSocketURL, version, subProtocol); + this.allowExtensions = allowExtensions; + } + + /** + * /** + *

+ * Sends the opening request to the server: + *

+ * + *
+	 * GET /chat HTTP/1.1
+	 * Host: server.example.com
+	 * Upgrade: websocket
+	 * Connection: Upgrade
+	 * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+	 * Sec-WebSocket-Origin: http://example.com
+	 * Sec-WebSocket-Protocol: chat, superchat
+	 * Sec-WebSocket-Version: 8
+	 * 
+ * + * @param channel + * Channel into which we can write our request + */ + @Override + public void performOpeningHandshake(Channel channel) { + // Get path + URI wsURL = this.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); + + String acceptSeed = key + MAGIC_GUID; + byte[] sha1 = sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII)); + this.expectedChallengeResponseString = base64Encode(sha1); + + if (logger.isDebugEnabled()) { + logger.debug(String + .format("WS Version 08 Client Handshake key: %s. Expected response: %s.", + key, this.expectedChallengeResponseString)); + } + + // Format request + HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, + HttpMethod.GET, path); + request.addHeader(Names.UPGRADE, Values.WEBSOCKET.toLowerCase()); + request.addHeader(Names.CONNECTION, Values.UPGRADE); + request.addHeader(Names.SEC_WEBSOCKET_KEY, key); + request.addHeader(Names.HOST, wsURL.getHost()); + request.addHeader(Names.ORIGIN, "http://" + wsURL.getHost()); + if (protocol != null && !protocol.equals("")) { + request.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, protocol); + } + request.addHeader(Names.SEC_WEBSOCKET_VERSION, "8"); + + channel.write(request); + + channel.getPipeline().replace(HttpRequestEncoder.class, "ws-encoder", + new WebSocket08FrameEncoder(true)); + } + + /** + *

+ * Process server response: + *

+ * + *
+	 * HTTP/1.1 101 Switching Protocols
+	 * Upgrade: websocket
+	 * Connection: Upgrade
+	 * Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
+	 * Sec-WebSocket-Protocol: chat
+	 * 
+ * + * @param channel + * Channel + * @param response + * HTTP response returned from the server for the request sent by + * beginOpeningHandshake00(). + * @throws WebSocketHandshakeException + */ + @Override + public void performClosingHandshake(Channel channel, HttpResponse response) + throws WebSocketHandshakeException { + final HttpResponseStatus status = new HttpResponseStatus(101, + "Switching Protocols"); + + if (!response.getStatus().equals(status)) { + throw new WebSocketHandshakeException( + "Invalid handshake response status: " + + response.getStatus()); + } + + String upgrade = response.getHeader(Names.UPGRADE); + if (upgrade == null || !upgrade.equals(Values.WEBSOCKET.toLowerCase())) { + throw new WebSocketHandshakeException( + "Invalid handshake response upgrade: " + + response.getHeader(Names.UPGRADE)); + } + + String connection = response.getHeader(Names.CONNECTION); + if (connection == null || !connection.equals(Values.UPGRADE)) { + throw new WebSocketHandshakeException( + "Invalid handshake response connection: " + + response.getHeader(Names.CONNECTION)); + } + + String accept = response.getHeader(Names.SEC_WEBSOCKET_ACCEPT); + if (accept == null + || !accept.equals(this.expectedChallengeResponseString)) { + throw new WebSocketHandshakeException(String.format( + "Invalid challenge. Actual: %s. Expected: %s", accept, + this.expectedChallengeResponseString)); + } + + channel.getPipeline().replace(HttpResponseDecoder.class, "ws-decoder", + new WebSocket08FrameDecoder(false, this.allowExtensions)); + + this.setOpenningHandshakeCompleted(true); + } + +} \ No newline at end of file diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker10.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker10.java deleted file mode 100644 index 879aede004..0000000000 --- a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker10.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * 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 org.jboss.netty.handler.codec.http.websocketx; - -import java.net.URI; - -import org.jboss.netty.channel.Channel; -import org.jboss.netty.handler.codec.http.DefaultHttpRequest; -import org.jboss.netty.handler.codec.http.HttpHeaders.Names; -import org.jboss.netty.handler.codec.http.HttpHeaders.Values; -import org.jboss.netty.handler.codec.http.HttpMethod; -import org.jboss.netty.handler.codec.http.HttpRequest; -import org.jboss.netty.handler.codec.http.HttpRequestEncoder; -import org.jboss.netty.handler.codec.http.HttpResponse; -import org.jboss.netty.handler.codec.http.HttpResponseDecoder; -import org.jboss.netty.handler.codec.http.HttpResponseStatus; -import org.jboss.netty.handler.codec.http.HttpVersion; -import org.jboss.netty.logging.InternalLogger; -import org.jboss.netty.logging.InternalLoggerFactory; -import org.jboss.netty.util.CharsetUtil; - -/** - *

- * Performs client side opening and closing handshakes for web socket - * specification version draft-ietf-hybi-thewebsocketprotocol- 10 - *

- */ -public class WebSocketClientHandshaker10 extends WebSocketClientHandshaker { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketClientHandshaker10.class); - - public static final String MAGIC_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - - private String expectedChallengeResponseString = null; - - private static final String protocol = null; - - private boolean allowExtensions = false; - - /** - * Constructor specifying the destination web socket location and version to - * initiate - * - * @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 allowExtensions - * Allow extensions to be used in the reserved bits of the web - * socket frame - */ - public WebSocketClientHandshaker10(URI webSocketURL, WebSocketSpecificationVersion version, String subProtocol, boolean allowExtensions) { - super(webSocketURL, version, subProtocol); - this.allowExtensions = allowExtensions; - } - - /** - * /** - *

- * Sends the opening request to the server: - *

- * - *
-     * GET /chat HTTP/1.1
-     * Host: server.example.com
-     * Upgrade: websocket
-     * Connection: Upgrade
-     * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
-     * Sec-WebSocket-Origin: http://example.com
-     * Sec-WebSocket-Protocol: chat, superchat
-     * Sec-WebSocket-Version: 8
-     * 
- * - * @param channel - * Channel into which we can write our request - */ - @Override - public void performOpeningHandshake(Channel channel) { - // Get path - URI wsURL = this.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); - - String acceptSeed = key + MAGIC_GUID; - byte[] sha1 = sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII)); - this.expectedChallengeResponseString = base64Encode(sha1); - - if (logger.isDebugEnabled()) { - logger.debug(String.format("HyBi10 Client Handshake key: %s. Expected response: %s.", key, this.expectedChallengeResponseString)); - } - - // Format request - HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); - request.addHeader(Names.UPGRADE, Values.WEBSOCKET.toLowerCase()); - request.addHeader(Names.CONNECTION, Values.UPGRADE); - request.addHeader(Names.SEC_WEBSOCKET_KEY, key); - request.addHeader(Names.HOST, wsURL.getHost()); - request.addHeader(Names.ORIGIN, "http://" + wsURL.getHost()); - if (protocol != null && !protocol.equals("")) { - request.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, protocol); - } - request.addHeader(Names.SEC_WEBSOCKET_VERSION, "8"); - - channel.write(request); - - channel.getPipeline().replace(HttpRequestEncoder.class, "ws-encoder", new WebSocket08FrameEncoder(true)); - } - - /** - *

- * Process server response: - *

- * - *
-     * HTTP/1.1 101 Switching Protocols
-     * Upgrade: websocket
-     * Connection: Upgrade
-     * Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
-     * Sec-WebSocket-Protocol: chat
-     * 
- * - * @param channel - * Channel - * @param response - * HTTP response returned from the server for the request sent by - * beginOpeningHandshake00(). - * @throws WebSocketHandshakeException - */ - @Override - public void performClosingHandshake(Channel channel, HttpResponse response) throws WebSocketHandshakeException { - final HttpResponseStatus status = new HttpResponseStatus(101, "Switching Protocols"); - - if (!response.getStatus().equals(status)) { - throw new WebSocketHandshakeException("Invalid handshake response status: " + response.getStatus()); - } - - String upgrade = response.getHeader(Names.UPGRADE); - if (upgrade == null || !upgrade.equals(Values.WEBSOCKET.toLowerCase())) { - throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + response.getHeader(Names.UPGRADE)); - } - - String connection = response.getHeader(Names.CONNECTION); - if (connection == null || !connection.equals(Values.UPGRADE)) { - throw new WebSocketHandshakeException("Invalid handshake response connection: " + response.getHeader(Names.CONNECTION)); - } - - String accept = response.getHeader(Names.SEC_WEBSOCKET_ACCEPT); - if (accept == null || !accept.equals(this.expectedChallengeResponseString)) { - throw new WebSocketHandshakeException(String.format("Invalid challenge. Actual: %s. Expected: %s", accept, this.expectedChallengeResponseString)); - } - - channel.getPipeline().replace(HttpResponseDecoder.class, "ws-decoder", new WebSocket08FrameDecoder(false, this.allowExtensions)); - - this.setOpenningHandshakeCompleted(true); - } - -} \ No newline at end of file diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java new file mode 100644 index 0000000000..892668bdc4 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java @@ -0,0 +1,202 @@ +/* + * 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 org.jboss.netty.handler.codec.http.websocketx; + +import java.net.URI; + +import org.jboss.netty.channel.Channel; +import org.jboss.netty.handler.codec.http.DefaultHttpRequest; +import org.jboss.netty.handler.codec.http.HttpHeaders.Names; +import org.jboss.netty.handler.codec.http.HttpHeaders.Values; +import org.jboss.netty.handler.codec.http.HttpMethod; +import org.jboss.netty.handler.codec.http.HttpRequest; +import org.jboss.netty.handler.codec.http.HttpRequestEncoder; +import org.jboss.netty.handler.codec.http.HttpResponse; +import org.jboss.netty.handler.codec.http.HttpResponseDecoder; +import org.jboss.netty.handler.codec.http.HttpResponseStatus; +import org.jboss.netty.handler.codec.http.HttpVersion; +import org.jboss.netty.logging.InternalLogger; +import org.jboss.netty.logging.InternalLoggerFactory; +import org.jboss.netty.util.CharsetUtil; + +/** + *

+ * Performs client side opening and closing handshakes for RFC 6455. This was originally + * draft-ietf-hybi-thewebsocketprotocol- 17 + *

+ */ +public class WebSocketClientHandshaker13 extends WebSocketClientHandshaker { + + private static final InternalLogger logger = InternalLoggerFactory + .getInstance(WebSocketClientHandshaker13.class); + + public static final String MAGIC_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + + private String expectedChallengeResponseString = null; + + private static final String protocol = null; + + private boolean allowExtensions = false; + + /** + * Constructor specifying the destination web socket location and version to + * initiate + * + * @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 allowExtensions + * Allow extensions to be used in the reserved bits of the web + * socket frame + */ + public WebSocketClientHandshaker13(URI webSocketURL, + WebSocketVersion version, String subProtocol, + boolean allowExtensions) { + super(webSocketURL, version, subProtocol); + this.allowExtensions = allowExtensions; + } + + /** + * /** + *

+ * Sends the opening request to the server: + *

+ * + *
+	 * GET /chat HTTP/1.1
+	 * Host: server.example.com
+	 * Upgrade: websocket
+	 * Connection: Upgrade
+	 * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+	 * Sec-WebSocket-Origin: http://example.com
+	 * Sec-WebSocket-Protocol: chat, superchat
+	 * Sec-WebSocket-Version: 13
+	 * 
+ * + * @param channel + * Channel into which we can write our request + */ + @Override + public void performOpeningHandshake(Channel channel) { + // Get path + URI wsURL = this.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); + + String acceptSeed = key + MAGIC_GUID; + byte[] sha1 = sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII)); + this.expectedChallengeResponseString = base64Encode(sha1); + + if (logger.isDebugEnabled()) { + logger.debug(String.format( + "WS Version 13 Client Handshake key: %s. Expected response: %s.", + key, this.expectedChallengeResponseString)); + } + + // Format request + HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, + HttpMethod.GET, path); + request.addHeader(Names.UPGRADE, Values.WEBSOCKET.toLowerCase()); + request.addHeader(Names.CONNECTION, Values.UPGRADE); + request.addHeader(Names.SEC_WEBSOCKET_KEY, key); + request.addHeader(Names.HOST, wsURL.getHost()); + request.addHeader(Names.ORIGIN, "http://" + wsURL.getHost()); + if (protocol != null && !protocol.equals("")) { + request.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, protocol); + } + request.addHeader(Names.SEC_WEBSOCKET_VERSION, "13"); + + channel.write(request); + + channel.getPipeline().replace(HttpRequestEncoder.class, "ws-encoder", + new WebSocket13FrameEncoder(true)); + } + + /** + *

+ * Process server response: + *

+ * + *
+	 * HTTP/1.1 101 Switching Protocols
+	 * Upgrade: websocket
+	 * Connection: Upgrade
+	 * Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
+	 * Sec-WebSocket-Protocol: chat
+	 * 
+ * + * @param channel + * Channel + * @param response + * HTTP response returned from the server for the request sent by + * beginOpeningHandshake00(). + * @throws WebSocketHandshakeException + */ + @Override + public void performClosingHandshake(Channel channel, HttpResponse response) + throws WebSocketHandshakeException { + final HttpResponseStatus status = new HttpResponseStatus(101, + "Switching Protocols"); + + if (!response.getStatus().equals(status)) { + throw new WebSocketHandshakeException( + "Invalid handshake response status: " + + response.getStatus()); + } + + String upgrade = response.getHeader(Names.UPGRADE); + if (upgrade == null || !upgrade.equals(Values.WEBSOCKET.toLowerCase())) { + throw new WebSocketHandshakeException( + "Invalid handshake response upgrade: " + + response.getHeader(Names.UPGRADE)); + } + + String connection = response.getHeader(Names.CONNECTION); + if (connection == null || !connection.equals(Values.UPGRADE)) { + throw new WebSocketHandshakeException( + "Invalid handshake response connection: " + + response.getHeader(Names.CONNECTION)); + } + + String accept = response.getHeader(Names.SEC_WEBSOCKET_ACCEPT); + if (accept == null + || !accept.equals(this.expectedChallengeResponseString)) { + throw new WebSocketHandshakeException(String.format( + "Invalid challenge. Actual: %s. Expected: %s", accept, + this.expectedChallengeResponseString)); + } + + channel.getPipeline().replace(HttpResponseDecoder.class, "ws-decoder", + new WebSocket13FrameDecoder(false, this.allowExtensions)); + + this.setOpenningHandshakeCompleted(true); + } + +} \ No newline at end of file diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker17.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker17.java deleted file mode 100644 index 83c4aeee2d..0000000000 --- a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker17.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * 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 org.jboss.netty.handler.codec.http.websocketx; - -import java.net.URI; - -import org.jboss.netty.channel.Channel; -import org.jboss.netty.handler.codec.http.DefaultHttpRequest; -import org.jboss.netty.handler.codec.http.HttpHeaders.Names; -import org.jboss.netty.handler.codec.http.HttpHeaders.Values; -import org.jboss.netty.handler.codec.http.HttpMethod; -import org.jboss.netty.handler.codec.http.HttpRequest; -import org.jboss.netty.handler.codec.http.HttpRequestEncoder; -import org.jboss.netty.handler.codec.http.HttpResponse; -import org.jboss.netty.handler.codec.http.HttpResponseDecoder; -import org.jboss.netty.handler.codec.http.HttpResponseStatus; -import org.jboss.netty.handler.codec.http.HttpVersion; -import org.jboss.netty.logging.InternalLogger; -import org.jboss.netty.logging.InternalLoggerFactory; -import org.jboss.netty.util.CharsetUtil; - -/** - *

- * Performs client side opening and closing handshakes for web socket - * specification version draft-ietf-hybi-thewebsocketprotocol- 17 - *

- */ -public class WebSocketClientHandshaker17 extends WebSocketClientHandshaker { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketClientHandshaker17.class); - - public static final String MAGIC_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - - private String expectedChallengeResponseString = null; - - private static final String protocol = null; - - private boolean allowExtensions = false; - - /** - * Constructor specifying the destination web socket location and version to - * initiate - * - * @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 allowExtensions - * Allow extensions to be used in the reserved bits of the web - * socket frame - */ - public WebSocketClientHandshaker17(URI webSocketURL, WebSocketSpecificationVersion version, String subProtocol, boolean allowExtensions) { - super(webSocketURL, version, subProtocol); - this.allowExtensions = allowExtensions; - } - - /** - * /** - *

- * Sends the opening request to the server: - *

- * - *
-     * GET /chat HTTP/1.1
-     * Host: server.example.com
-     * Upgrade: websocket
-     * Connection: Upgrade
-     * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
-     * Sec-WebSocket-Origin: http://example.com
-     * Sec-WebSocket-Protocol: chat, superchat
-     * Sec-WebSocket-Version: 13
-     * 
- * - * @param channel - * Channel into which we can write our request - */ - @Override - public void performOpeningHandshake(Channel channel) { - // Get path - URI wsURL = this.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); - - String acceptSeed = key + MAGIC_GUID; - byte[] sha1 = sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII)); - this.expectedChallengeResponseString = base64Encode(sha1); - - if (logger.isDebugEnabled()) { - logger.debug(String.format("HyBi17 Client Handshake key: %s. Expected response: %s.", key, this.expectedChallengeResponseString)); - } - - // Format request - HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path); - request.addHeader(Names.UPGRADE, Values.WEBSOCKET.toLowerCase()); - request.addHeader(Names.CONNECTION, Values.UPGRADE); - request.addHeader(Names.SEC_WEBSOCKET_KEY, key); - request.addHeader(Names.HOST, wsURL.getHost()); - request.addHeader(Names.ORIGIN, "http://" + wsURL.getHost()); - if (protocol != null && !protocol.equals("")) { - request.addHeader(Names.SEC_WEBSOCKET_PROTOCOL, protocol); - } - request.addHeader(Names.SEC_WEBSOCKET_VERSION, "13"); - - channel.write(request); - - channel.getPipeline().replace(HttpRequestEncoder.class, "ws-encoder", new WebSocket13FrameEncoder(true)); - } - - /** - *

- * Process server response: - *

- * - *
-     * HTTP/1.1 101 Switching Protocols
-     * Upgrade: websocket
-     * Connection: Upgrade
-     * Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
-     * Sec-WebSocket-Protocol: chat
-     * 
- * - * @param channel - * Channel - * @param response - * HTTP response returned from the server for the request sent by - * beginOpeningHandshake00(). - * @throws WebSocketHandshakeException - */ - @Override - public void performClosingHandshake(Channel channel, HttpResponse response) throws WebSocketHandshakeException { - final HttpResponseStatus status = new HttpResponseStatus(101, "Switching Protocols"); - - if (!response.getStatus().equals(status)) { - throw new WebSocketHandshakeException("Invalid handshake response status: " + response.getStatus()); - } - - String upgrade = response.getHeader(Names.UPGRADE); - if (upgrade == null || !upgrade.equals(Values.WEBSOCKET.toLowerCase())) { - throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + response.getHeader(Names.UPGRADE)); - } - - String connection = response.getHeader(Names.CONNECTION); - if (connection == null || !connection.equals(Values.UPGRADE)) { - throw new WebSocketHandshakeException("Invalid handshake response connection: " + response.getHeader(Names.CONNECTION)); - } - - String accept = response.getHeader(Names.SEC_WEBSOCKET_ACCEPT); - if (accept == null || !accept.equals(this.expectedChallengeResponseString)) { - throw new WebSocketHandshakeException(String.format("Invalid challenge. Actual: %s. Expected: %s", accept, this.expectedChallengeResponseString)); - } - - channel.getPipeline().replace(HttpResponseDecoder.class, "ws-decoder", new WebSocket13FrameDecoder(false, this.allowExtensions)); - - this.setOpenningHandshakeCompleted(true); - } - -} \ No newline at end of file diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshakerFactory.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshakerFactory.java index 31bea2973c..852c1f3d5f 100644 --- a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshakerFactory.java +++ b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshakerFactory.java @@ -40,14 +40,14 @@ public class WebSocketClientHandshakerFactory { * socket frame * @throws WebSocketHandshakeException */ - public WebSocketClientHandshaker newHandshaker(URI webSocketURL, WebSocketSpecificationVersion version, String subProtocol, boolean allowExtensions) throws WebSocketHandshakeException { - if (version == WebSocketSpecificationVersion.V17) { - return new WebSocketClientHandshaker17(webSocketURL, version, subProtocol, allowExtensions); + public WebSocketClientHandshaker newHandshaker(URI webSocketURL, WebSocketVersion version, String subProtocol, boolean allowExtensions) throws WebSocketHandshakeException { + if (version == WebSocketVersion.V13) { + return new WebSocketClientHandshaker13(webSocketURL, version, subProtocol, allowExtensions); } - if (version == WebSocketSpecificationVersion.V10) { - return new WebSocketClientHandshaker10(webSocketURL, version, subProtocol, allowExtensions); + if (version == WebSocketVersion.V08) { + return new WebSocketClientHandshaker08(webSocketURL, version, subProtocol, allowExtensions); } - if (version == WebSocketSpecificationVersion.V00) { + if (version == WebSocketVersion.V00) { return new WebSocketClientHandshaker00(webSocketURL, version, subProtocol); } diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java index 4871416fc0..f0cd27eaa0 100644 --- a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java +++ b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker.java @@ -33,7 +33,7 @@ public abstract class WebSocketServerHandshaker { private String[] subProtocolsArray = null; - private WebSocketSpecificationVersion version = WebSocketSpecificationVersion.UNKNOWN; + private WebSocketVersion version = WebSocketVersion.UNKNOWN; /** * Constructor specifying the destination web socket location @@ -83,11 +83,11 @@ public abstract class WebSocketServerHandshaker { /** * Returns the version of the specification being supported */ - public WebSocketSpecificationVersion getVersion() { + public WebSocketVersion getVersion() { return version; } - public void setVersion(WebSocketSpecificationVersion version) { + public void setVersion(WebSocketVersion version) { this.version = version; } diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00.java index cb902dbd84..2a8fde99db 100644 --- a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00.java +++ b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker00.java @@ -129,7 +129,7 @@ public class WebSocketServerHandshaker00 extends WebSocketServerHandshaker { if (logger.isDebugEnabled()) { logger.debug(String.format("Channel %s web socket spec version 00 handshake", channel.getId())); } - this.setVersion(WebSocketSpecificationVersion.V00); + this.setVersion(WebSocketVersion.V00); // Serve the WebSocket handshake request. if (!Values.UPGRADE.equalsIgnoreCase(req.getHeader(CONNECTION)) || !WEBSOCKET.equalsIgnoreCase(req.getHeader(Names.UPGRADE))) { diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java new file mode 100644 index 0000000000..4acab1b4bd --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker08.java @@ -0,0 +1,180 @@ +/* + * 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 org.jboss.netty.handler.codec.http.websocketx; + +import static org.jboss.netty.handler.codec.http.HttpHeaders.Values.WEBSOCKET; +import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1; + +import java.security.NoSuchAlgorithmException; + +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelFuture; +import org.jboss.netty.channel.ChannelFutureListener; +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.handler.codec.http.DefaultHttpResponse; +import org.jboss.netty.handler.codec.http.HttpChunkAggregator; +import org.jboss.netty.handler.codec.http.HttpRequest; +import org.jboss.netty.handler.codec.http.HttpRequestDecoder; +import org.jboss.netty.handler.codec.http.HttpResponse; +import org.jboss.netty.handler.codec.http.HttpResponseEncoder; +import org.jboss.netty.handler.codec.http.HttpResponseStatus; +import org.jboss.netty.handler.codec.http.HttpHeaders.Names; +import org.jboss.netty.logging.InternalLogger; +import org.jboss.netty.logging.InternalLoggerFactory; +import org.jboss.netty.util.CharsetUtil; + +/** + *

+ * Performs server side opening and closing handshakes for web socket + * specification version draft-ietf-hybi-thewebsocketprotocol- 10 + *

+ */ +public class WebSocketServerHandshaker08 extends WebSocketServerHandshaker { + + private static final InternalLogger logger = InternalLoggerFactory + .getInstance(WebSocketServerHandshaker08.class); + + public static final String WEBSOCKET_08_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + + private boolean allowExtensions = false; + + /** + * Constructor specifying the destination web socket location + * + * @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 + * 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); + this.allowExtensions = allowExtensions; + } + + /** + *

+ * Handle the web socket handshake for the web socket specification HyBi + * version 8 to 10. Version 8, 9 and 10 share the same wire protocol. + *

+ * + *

+ * Browser request to the server: + *

+ * + *
+	 * GET /chat HTTP/1.1
+	 * Host: server.example.com
+	 * Upgrade: websocket
+	 * Connection: Upgrade
+	 * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+	 * Sec-WebSocket-Origin: http://example.com
+	 * Sec-WebSocket-Protocol: chat, superchat
+	 * Sec-WebSocket-Version: 8
+	 * 
+ * + *

+ * Server response: + *

+ * + *
+	 * HTTP/1.1 101 Switching Protocols
+	 * Upgrade: websocket
+	 * Connection: Upgrade
+	 * Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
+	 * Sec-WebSocket-Protocol: chat
+	 * 
+ * + * @param channel + * Channel + * @param req + * HTTP request + * @throws NoSuchAlgorithmException + */ + @Override + public void performOpeningHandshake(Channel channel, HttpRequest req) { + + if (logger.isDebugEnabled()) { + logger.debug(String.format( + "Channel %s WS version 08 handshake", + channel.getId())); + } + + HttpResponse res = new DefaultHttpResponse(HTTP_1_1, + new HttpResponseStatus(101, "Switching Protocols")); + this.setVersion(WebSocketVersion.V08); + + String key = req.getHeader(Names.SEC_WEBSOCKET_KEY); + if (key == null) { + res.setStatus(HttpResponseStatus.BAD_REQUEST); + return; + } + String acceptSeed = key + WEBSOCKET_08_ACCEPT_GUID; + byte[] sha1 = sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII)); + String accept = base64Encode(sha1); + + if (logger.isDebugEnabled()) { + logger.debug(String.format( + "WS Version 08 Server Handshake key: %s. Response: %s.", + key, accept)); + } + + res.setStatus(new HttpResponseStatus(101, "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)); + } + + 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(HttpResponseEncoder.class, "wsencoder", + new WebSocket08FrameEncoder(false)); + + } + + /** + * Echo back the closing frame and close the connection + * + * @param channel + * Channel + * @param frame + * Web Socket frame that was received + */ + @Override + public void performClosingHandshake(Channel channel, + CloseWebSocketFrame frame) { + ChannelFuture f = channel.write(frame); + f.addListener(ChannelFutureListener.CLOSE); + } + +} \ No newline at end of file diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker10.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker10.java deleted file mode 100644 index 3ca89d686e..0000000000 --- a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker10.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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 org.jboss.netty.handler.codec.http.websocketx; - -import static org.jboss.netty.handler.codec.http.HttpHeaders.Values.WEBSOCKET; -import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1; - -import java.security.NoSuchAlgorithmException; - -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelFuture; -import org.jboss.netty.channel.ChannelFutureListener; -import org.jboss.netty.channel.ChannelPipeline; -import org.jboss.netty.handler.codec.http.DefaultHttpResponse; -import org.jboss.netty.handler.codec.http.HttpChunkAggregator; -import org.jboss.netty.handler.codec.http.HttpRequest; -import org.jboss.netty.handler.codec.http.HttpRequestDecoder; -import org.jboss.netty.handler.codec.http.HttpResponse; -import org.jboss.netty.handler.codec.http.HttpResponseEncoder; -import org.jboss.netty.handler.codec.http.HttpResponseStatus; -import org.jboss.netty.handler.codec.http.HttpHeaders.Names; -import org.jboss.netty.logging.InternalLogger; -import org.jboss.netty.logging.InternalLoggerFactory; -import org.jboss.netty.util.CharsetUtil; - -/** - *

- * Performs server side opening and closing handshakes for web socket - * specification version draft-ietf-hybi-thewebsocketprotocol- 10 - *

- */ -public class WebSocketServerHandshaker10 extends WebSocketServerHandshaker { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketServerHandshaker10.class); - - public static final String WEBSOCKET_08_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - - private boolean allowExtensions = false; - - /** - * Constructor specifying the destination web socket location - * - * @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 - * CSV of supported protocols - * @param allowExtensions - * Allow extensions to be used in the reserved bits of the web - * socket frame - */ - public WebSocketServerHandshaker10(String webSocketURL, String subProtocols, boolean allowExtensions) { - super(webSocketURL, subProtocols); - this.allowExtensions = allowExtensions; - } - - /** - *

- * Handle the web socket handshake for the web socket specification HyBi - * version 8 to 10. Version 8, 9 and 10 share the same wire protocol. - *

- * - *

- * Browser request to the server: - *

- * - *
-     * GET /chat HTTP/1.1
-     * Host: server.example.com
-     * Upgrade: websocket
-     * Connection: Upgrade
-     * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
-     * Sec-WebSocket-Origin: http://example.com
-     * Sec-WebSocket-Protocol: chat, superchat
-     * Sec-WebSocket-Version: 8
-     * 
- * - *

- * Server response: - *

- * - *
-     * HTTP/1.1 101 Switching Protocols
-     * Upgrade: websocket
-     * Connection: Upgrade
-     * Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
-     * Sec-WebSocket-Protocol: chat
-     * 
- * - * @param channel - * Channel - * @param req - * HTTP request - * @throws NoSuchAlgorithmException - */ - @Override - public void performOpeningHandshake(Channel channel, HttpRequest req) { - - if (logger.isDebugEnabled()) { - logger.debug(String.format("Channel %s web socket spec version 10 handshake", channel.getId())); - } - - HttpResponse res = new DefaultHttpResponse(HTTP_1_1, new HttpResponseStatus(101, "Switching Protocols")); - this.setVersion(WebSocketSpecificationVersion.V10); - - String key = req.getHeader(Names.SEC_WEBSOCKET_KEY); - if (key == null) { - res.setStatus(HttpResponseStatus.BAD_REQUEST); - return; - } - String acceptSeed = key + WEBSOCKET_08_ACCEPT_GUID; - byte[] sha1 = sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII)); - String accept = base64Encode(sha1); - - if (logger.isDebugEnabled()) { - logger.debug(String.format("HyBi10 Server Handshake key: %s. Response: %s.", key, accept)); - } - - res.setStatus(new HttpResponseStatus(101, "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)); - } - - 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(HttpResponseEncoder.class, "wsencoder", new WebSocket08FrameEncoder(false)); - - } - - /** - * Echo back the closing frame and close the connection - * - * @param channel - * Channel - * @param frame - * Web Socket frame that was received - */ - @Override - public void performClosingHandshake(Channel channel, CloseWebSocketFrame frame) { - ChannelFuture f = channel.write(frame); - f.addListener(ChannelFutureListener.CLOSE); - } - -} \ No newline at end of file diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java new file mode 100644 index 0000000000..9928743e55 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker13.java @@ -0,0 +1,180 @@ +/* + * 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 org.jboss.netty.handler.codec.http.websocketx; + +import static org.jboss.netty.handler.codec.http.HttpHeaders.Values.WEBSOCKET; +import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1; + +import java.security.NoSuchAlgorithmException; + +import org.jboss.netty.channel.Channel; +import org.jboss.netty.channel.ChannelFuture; +import org.jboss.netty.channel.ChannelFutureListener; +import org.jboss.netty.channel.ChannelPipeline; +import org.jboss.netty.handler.codec.http.DefaultHttpResponse; +import org.jboss.netty.handler.codec.http.HttpChunkAggregator; +import org.jboss.netty.handler.codec.http.HttpRequest; +import org.jboss.netty.handler.codec.http.HttpRequestDecoder; +import org.jboss.netty.handler.codec.http.HttpResponse; +import org.jboss.netty.handler.codec.http.HttpResponseEncoder; +import org.jboss.netty.handler.codec.http.HttpResponseStatus; +import org.jboss.netty.handler.codec.http.HttpHeaders.Names; +import org.jboss.netty.logging.InternalLogger; +import org.jboss.netty.logging.InternalLoggerFactory; +import org.jboss.netty.util.CharsetUtil; + +/** + *

+ * Performs server side opening and closing handshakes for RFC 6455. This was originally + * draft-ietf-hybi-thewebsocketprotocol- 17 + *

+ */ +public class WebSocketServerHandshaker13 extends WebSocketServerHandshaker { + + private static final InternalLogger logger = InternalLoggerFactory + .getInstance(WebSocketServerHandshaker13.class); + + public static final String WEBSOCKET_17_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + + private boolean allowExtensions = false; + + /** + * Constructor specifying the destination web socket location + * + * @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 + * 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); + this.allowExtensions = allowExtensions; + } + + /** + *

+ * Handle the web socket handshake for the web socket specification HyBi + * versions 13-17. Versions 13-17 share the same wire protocol. + *

+ * + *

+ * Browser request to the server: + *

+ * + *
+	 * GET /chat HTTP/1.1
+	 * Host: server.example.com
+	 * Upgrade: websocket
+	 * Connection: Upgrade
+	 * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
+	 * Sec-WebSocket-Origin: http://example.com
+	 * Sec-WebSocket-Protocol: chat, superchat
+	 * Sec-WebSocket-Version: 13
+	 * 
+ * + *

+ * Server response: + *

+ * + *
+	 * HTTP/1.1 101 Switching Protocols
+	 * Upgrade: websocket
+	 * Connection: Upgrade
+	 * Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
+	 * Sec-WebSocket-Protocol: chat
+	 * 
+ * + * @param channel + * Channel + * @param req + * HTTP request + * @throws NoSuchAlgorithmException + */ + @Override + public void performOpeningHandshake(Channel channel, HttpRequest req) { + + if (logger.isDebugEnabled()) { + logger.debug(String.format( + "Channel %s WS version 13 handshake", + channel.getId())); + } + + HttpResponse res = new DefaultHttpResponse(HTTP_1_1, + new HttpResponseStatus(101, "Switching Protocols")); + this.setVersion(WebSocketVersion.V13); + + String key = req.getHeader(Names.SEC_WEBSOCKET_KEY); + if (key == null) { + res.setStatus(HttpResponseStatus.BAD_REQUEST); + return; + } + String acceptSeed = key + WEBSOCKET_17_ACCEPT_GUID; + byte[] sha1 = sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII)); + String accept = base64Encode(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.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)); + } + + 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(HttpResponseEncoder.class, "wsencoder", + new WebSocket13FrameEncoder(false)); + + } + + /** + * Echo back the closing frame and close the connection + * + * @param channel + * Channel + * @param frame + * Web Socket frame that was received + */ + @Override + public void performClosingHandshake(Channel channel, + CloseWebSocketFrame frame) { + ChannelFuture f = channel.write(frame); + f.addListener(ChannelFutureListener.CLOSE); + } + +} \ No newline at end of file diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker17.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker17.java deleted file mode 100644 index aec5088797..0000000000 --- a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshaker17.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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 org.jboss.netty.handler.codec.http.websocketx; - -import static org.jboss.netty.handler.codec.http.HttpHeaders.Values.WEBSOCKET; -import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1; - -import java.security.NoSuchAlgorithmException; - -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelFuture; -import org.jboss.netty.channel.ChannelFutureListener; -import org.jboss.netty.channel.ChannelPipeline; -import org.jboss.netty.handler.codec.http.DefaultHttpResponse; -import org.jboss.netty.handler.codec.http.HttpChunkAggregator; -import org.jboss.netty.handler.codec.http.HttpRequest; -import org.jboss.netty.handler.codec.http.HttpRequestDecoder; -import org.jboss.netty.handler.codec.http.HttpResponse; -import org.jboss.netty.handler.codec.http.HttpResponseEncoder; -import org.jboss.netty.handler.codec.http.HttpResponseStatus; -import org.jboss.netty.handler.codec.http.HttpHeaders.Names; -import org.jboss.netty.logging.InternalLogger; -import org.jboss.netty.logging.InternalLoggerFactory; -import org.jboss.netty.util.CharsetUtil; - -/** - *

- * Performs server side opening and closing handshakes for web socket - * specification version draft-ietf-hybi-thewebsocketprotocol- 17 - *

- */ -public class WebSocketServerHandshaker17 extends WebSocketServerHandshaker { - - private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketServerHandshaker17.class); - - public static final String WEBSOCKET_17_ACCEPT_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - - private boolean allowExtensions = false; - - /** - * Constructor specifying the destination web socket location - * - * @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 - * CSV of supported protocols - * @param allowExtensions - * Allow extensions to be used in the reserved bits of the web - * socket frame - */ - public WebSocketServerHandshaker17(String webSocketURL, String subProtocols, boolean allowExtensions) { - super(webSocketURL, subProtocols); - this.allowExtensions = allowExtensions; - } - - /** - *

- * Handle the web socket handshake for the web socket specification HyBi - * versions 13-17. Versions 13-17 share the same wire protocol. - *

- * - *

- * Browser request to the server: - *

- * - *
-     * GET /chat HTTP/1.1
-     * Host: server.example.com
-     * Upgrade: websocket
-     * Connection: Upgrade
-     * Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
-     * Sec-WebSocket-Origin: http://example.com
-     * Sec-WebSocket-Protocol: chat, superchat
-     * Sec-WebSocket-Version: 13
-     * 
- * - *

- * Server response: - *

- * - *
-     * HTTP/1.1 101 Switching Protocols
-     * Upgrade: websocket
-     * Connection: Upgrade
-     * Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
-     * Sec-WebSocket-Protocol: chat
-     * 
- * - * @param channel - * Channel - * @param req - * HTTP request - * @throws NoSuchAlgorithmException - */ - @Override - public void performOpeningHandshake(Channel channel, HttpRequest req) { - - if (logger.isDebugEnabled()) { - logger.debug(String.format("Channel %s web socket spec version 17 handshake", channel.getId())); - } - - HttpResponse res = new DefaultHttpResponse(HTTP_1_1, new HttpResponseStatus(101, "Switching Protocols")); - this.setVersion(WebSocketSpecificationVersion.V17); - - String key = req.getHeader(Names.SEC_WEBSOCKET_KEY); - if (key == null) { - res.setStatus(HttpResponseStatus.BAD_REQUEST); - return; - } - String acceptSeed = key + WEBSOCKET_17_ACCEPT_GUID; - byte[] sha1 = sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII)); - String accept = base64Encode(sha1); - - if (logger.isDebugEnabled()) { - logger.debug(String.format("HyBi17 Server Handshake key: %s. Response: %s.", key, accept)); - } - - res.setStatus(new HttpResponseStatus(101, "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)); - } - - 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(HttpResponseEncoder.class, "wsencoder", new WebSocket13FrameEncoder(false)); - - } - - /** - * Echo back the closing frame and close the connection - * - * @param channel - * Channel - * @param frame - * Web Socket frame that was received - */ - @Override - public void performClosingHandshake(Channel channel, CloseWebSocketFrame frame) { - ChannelFuture f = channel.write(frame); - f.addListener(ChannelFutureListener.CLOSE); - } - -} \ No newline at end of file diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshakerFactory.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshakerFactory.java index a64ff99f75..e46cde796a 100644 --- a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshakerFactory.java +++ b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketServerHandshakerFactory.java @@ -64,14 +64,14 @@ public class WebSocketServerHandshakerFactory { String version = req.getHeader(Names.SEC_WEBSOCKET_VERSION); if (version != null) { - if (version.equals("13")) { + if (version.equals(WebSocketVersion.V13.toHttpHeaderValue())) { // Version 13 of the wire protocol - assume version 17 of the // specification. - return new WebSocketServerHandshaker17(webSocketURL, subProtocols, this.allowExtensions); - } else if (version.equals("8")) { + return new WebSocketServerHandshaker13(webSocketURL, subProtocols, this.allowExtensions); + } else if (version.equals(WebSocketVersion.V08.toHttpHeaderValue())) { // Version 8 of the wire protocol - assume version 10 of the // specification. - return new WebSocketServerHandshaker10(webSocketURL, subProtocols, this.allowExtensions); + return new WebSocketServerHandshaker08(webSocketURL, subProtocols, this.allowExtensions); } else { return null; } @@ -91,7 +91,7 @@ public class WebSocketServerHandshakerFactory { HttpResponse res = new DefaultHttpResponse(HttpVersion.HTTP_1_1, new HttpResponseStatus(101, "Switching Protocols")); res.setStatus(HttpResponseStatus.UPGRADE_REQUIRED); - res.setHeader(Names.SEC_WEBSOCKET_VERSION, "13"); + res.setHeader(Names.SEC_WEBSOCKET_VERSION, WebSocketVersion.V13.toHttpHeaderValue()); channel.write(res); } diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketSpecificationVersion.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketSpecificationVersion.java deleted file mode 100644 index 9e2b3d19b8..0000000000 --- a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketSpecificationVersion.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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 org.jboss.netty.handler.codec.http.websocketx; - -/** - *

- * Versions of the web socket specification. - *

- *

- * A specification is tied to one wire protocol version but a protocol version - * may have use by more than 1 version of the specification. - *

- */ -public enum WebSocketSpecificationVersion { - UNKNOWN, - - /** - * draft-ietf-hybi-thewebsocketprotocol- 00. - */ - V00, - - /** - * draft-ietf-hybi-thewebsocketprotocol- 10 - */ - V10, - - /** - * draft-ietf-hybi-thewebsocketprotocol- 17 - */ - V17 - -} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketVersion.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketVersion.java new file mode 100644 index 0000000000..d0d4c7e506 --- /dev/null +++ b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketVersion.java @@ -0,0 +1,58 @@ +/* + * 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 org.jboss.netty.handler.codec.http.websocketx; + +/** + *

+ * Version of the web socket wire protocol. + *

+ */ +public enum WebSocketVersion { + UNKNOWN, + + /** + * draft-ietf-hybi-thewebsocketprotocol- 00. + */ + V00, + + /** + * draft-ietf-hybi-thewebsocketprotocol- 10 + */ + V08, + + /** + * RFC 6455. This was + * originally draft-ietf-hybi-thewebsocketprotocol- 17 + */ + V13; + + public String toHttpHeaderValue() { + if (this == V00) { + return "0"; + } else if (this == V08) { + return "8"; + } else if (this == V13) { + return "13"; + } + throw new IllegalArgumentException(this.toString() + " cannot be converted to a string."); + } +} diff --git a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/package-info.java b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/package-info.java index 90e1af55ea..a550146468 100644 --- a/src/main/java/org/jboss/netty/handler/codec/http/websocketx/package-info.java +++ b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/package-info.java @@ -23,7 +23,7 @@ * *

*