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).
*
- * Sends the opening request to the server:
- *
+ * Sends the opening request to the server:
+ *
- * Process server response:
- *
+ * Process server response:
+ *
+ * Performs client side opening and closing handshakes for web socket
+ * specification version draft-ietf-hybi-thewebsocketprotocol- 10
+ *
+ * Sends the opening request to the server:
+ *
+ * Process server response:
+ *
- * Performs client side opening and closing handshakes for web socket
- * specification version draft-ietf-hybi-thewebsocketprotocol- 10
- *
- * Sends the opening request to the server:
- *
- * Process server response:
- *
+ * Performs client side opening and closing handshakes for RFC 6455. This was originally
+ * draft-ietf-hybi-thewebsocketprotocol- 17
+ *
+ * Sends the opening request to the server:
+ *
+ * Process server response:
+ *
- * Performs client side opening and closing handshakes for web socket
- * specification version draft-ietf-hybi-thewebsocketprotocol- 17
- *
- * Sends the opening request to the server:
- *
- * Process server response:
- *
+ * Performs server side opening and closing handshakes for web socket
+ * specification version draft-ietf-hybi-thewebsocketprotocol- 10
+ *
+ * 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:
+ *
+ * Server response:
+ *
- * Performs server side opening and closing handshakes for web socket
- * specification version draft-ietf-hybi-thewebsocketprotocol- 10
- *
- * 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:
- *
- * Server response:
- *
+ * Performs server side opening and closing handshakes for RFC 6455. This was originally
+ * draft-ietf-hybi-thewebsocketprotocol- 17
+ *
+ * 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:
+ *
+ * Server response:
+ *
- * Performs server side opening and closing handshakes for web socket
- * specification version draft-ietf-hybi-thewebsocketprotocol- 17
- *
- * 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:
- *
- * Server response:
- *
- * 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.
- *
+ * Version of the web socket wire protocol.
+ *
* {
* "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..785054850a 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
@@ -18,6 +18,7 @@ package org.jboss.netty.example.http.websocketx.client;
import java.net.URI;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -28,7 +29,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
@@ -55,31 +56,34 @@ public class App {
MyCallbackHandler callbackHandler = new MyCallbackHandler();
WebSocketClientFactory factory = new WebSocketClientFactory();
- // Connect with spec version 17. You can change it to V10 or V00.
- // 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);
+ HashMap
- * GET /demo HTTP/1.1
- * Upgrade: WebSocket
- * Connection: Upgrade
- * Host: example.com
- * Origin: http://example.com
- * Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5
- * Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
- *
- * ^n:ds[4U
- *
- *
- * @param channel
- * Channel into which we can write our request
- */
- @Override
- public void performOpeningHandshake(Channel channel) {
- // Make keys
- int spaces1 = createRandomNumber(1, 12);
- int spaces2 = createRandomNumber(1, 12);
+ /**
+ *
+ * GET /demo HTTP/1.1
+ * Upgrade: WebSocket
+ * Connection: Upgrade
+ * Host: example.com
+ * Origin: http://example.com
+ * Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5
+ * Sec-WebSocket-Key2: 12998 5 Y3 1 .P00
+ *
+ * ^n:ds[4U
+ *
+ *
+ * @param channel
+ * Channel into which we can write our request
+ */
+ @Override
+ public void performOpeningHandshake(Channel channel) {
+ // Make keys
+ int spaces1 = createRandomNumber(1, 12);
+ int spaces2 = createRandomNumber(1, 12);
- int max1 = Integer.MAX_VALUE / spaces1;
- int max2 = Integer.MAX_VALUE / spaces2;
+ int max1 = Integer.MAX_VALUE / spaces1;
+ int max2 = Integer.MAX_VALUE / spaces2;
- int number1 = createRandomNumber(0, max1);
- int number2 = createRandomNumber(0, max2);
+ int number1 = createRandomNumber(0, max1);
+ int number2 = createRandomNumber(0, max2);
- int product1 = number1 * spaces1;
- int product2 = number2 * spaces2;
+ int product1 = number1 * spaces1;
+ int product2 = number2 * spaces2;
- String key1 = Integer.toString(product1);
- String key2 = Integer.toString(product2);
+ String key1 = Integer.toString(product1);
+ String key2 = Integer.toString(product2);
- key1 = insertRandomCharacters(key1);
- key2 = insertRandomCharacters(key2);
+ key1 = insertRandomCharacters(key1);
+ key2 = insertRandomCharacters(key2);
- key1 = insertSpaces(key1, spaces1);
- key2 = insertSpaces(key2, spaces2);
+ key1 = insertSpaces(key1, spaces1);
+ key2 = insertSpaces(key2, spaces2);
- byte[] key3 = createRandomBytes(8);
+ byte[] key3 = createRandomBytes(8);
- ByteBuffer buffer = ByteBuffer.allocate(4);
- buffer.putInt(number1);
- byte[] number1Array = buffer.array();
- buffer = ByteBuffer.allocate(4);
- buffer.putInt(number2);
- byte[] number2Array = buffer.array();
+ ByteBuffer buffer = ByteBuffer.allocate(4);
+ buffer.putInt(number1);
+ byte[] number1Array = buffer.array();
+ buffer = ByteBuffer.allocate(4);
+ buffer.putInt(number2);
+ byte[] number2Array = buffer.array();
- byte[] challenge = new byte[16];
- 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);
+ byte[] challenge = new byte[16];
+ 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);
- // Get path
- URI wsURL = this.getWebSocketURL();
- String path = wsURL.getPath();
- if (wsURL.getQuery() != null && wsURL.getQuery().length() > 0) {
- path = wsURL.getPath() + "?" + wsURL.getQuery();
- }
+ // Get path
+ URI wsURL = this.getWebSocketURL();
+ String path = wsURL.getPath();
+ if (wsURL.getQuery() != null && wsURL.getQuery().length() > 0) {
+ path = wsURL.getPath() + "?" + wsURL.getQuery();
+ }
- // Format request
- HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path);
- request.addHeader(Names.UPGRADE, Values.WEBSOCKET);
- request.addHeader(Names.CONNECTION, Values.UPGRADE);
- request.addHeader(Names.HOST, wsURL.getHost());
- 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());
- }
- request.setContent(ChannelBuffers.copiedBuffer(key3));
+ // Format request
+ HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, path);
+ request.addHeader(Names.UPGRADE, Values.WEBSOCKET);
+ request.addHeader(Names.CONNECTION, Values.UPGRADE);
+ request.addHeader(Names.HOST, wsURL.getHost());
+ 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 (customHeaders != null) {
+ for (String header : customHeaders.keySet()) {
+ request.addHeader(header, customHeaders.get(header));
+ }
+ }
+ request.setContent(ChannelBuffers.copiedBuffer(key3));
- channel.write(request);
+ channel.write(request);
- channel.getPipeline().replace(HttpRequestEncoder.class, "ws-encoder", new WebSocket00FrameEncoder());
- }
+ channel.getPipeline().replace(HttpRequestEncoder.class, "ws-encoder", new WebSocket00FrameEncoder());
+ }
- /**
- *
- * HTTP/1.1 101 WebSocket Protocol Handshake
- * Upgrade: WebSocket
- * Connection: Upgrade
- * Sec-WebSocket-Origin: http://example.com
- * Sec-WebSocket-Location: ws://example.com/demo
- * Sec-WebSocket-Protocol: sample
- *
- * 8jKS'y:G*Co,Wxa-
- *
- *
- * @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, "WebSocket Protocol Handshake");
+ /**
+ *
+ * HTTP/1.1 101 WebSocket Protocol Handshake
+ * Upgrade: WebSocket
+ * Connection: Upgrade
+ * Sec-WebSocket-Origin: http://example.com
+ * Sec-WebSocket-Location: ws://example.com/demo
+ * Sec-WebSocket-Protocol: sample
+ *
+ * 8jKS'y:G*Co,Wxa-
+ *
+ *
+ * @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, "WebSocket Protocol Handshake");
- if (!response.getStatus().equals(status)) {
- throw new WebSocketHandshakeException("Invalid handshake response status: " + response.getStatus());
- }
+ 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)) {
- throw new WebSocketHandshakeException("Invalid handshake response upgrade: " + response.getHeader(Names.UPGRADE));
- }
+ String upgrade = response.getHeader(Names.UPGRADE);
+ if (upgrade == null || !upgrade.equals(Values.WEBSOCKET)) {
+ 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 connection = response.getHeader(Names.CONNECTION);
+ if (connection == null || !connection.equals(Values.UPGRADE)) {
+ throw new WebSocketHandshakeException("Invalid handshake response connection: "
+ + response.getHeader(Names.CONNECTION));
+ }
- byte[] challenge = response.getContent().array();
- if (!Arrays.equals(challenge, expectedChallengeResponseBytes)) {
- throw new WebSocketHandshakeException("Invalid challenge");
- }
+ byte[] challenge = response.getContent().array();
+ if (!Arrays.equals(challenge, expectedChallengeResponseBytes)) {
+ throw new WebSocketHandshakeException("Invalid challenge");
+ }
- String protocol = response.getHeader(Names.SEC_WEBSOCKET_PROTOCOL);
- this.setSubProtocolResponse(protocol);
+ String protocol = response.getHeader(Names.SEC_WEBSOCKET_PROTOCOL);
+ this.setSubProtocolResponse(protocol);
- channel.getPipeline().replace(HttpResponseDecoder.class, "ws-decoder", new WebSocket00FrameDecoder());
+ channel.getPipeline().replace(HttpResponseDecoder.class, "ws-decoder", new WebSocket00FrameDecoder());
- this.setOpenningHandshakeCompleted(true);
- }
+ this.setOpenningHandshakeCompleted(true);
+ }
- private String insertRandomCharacters(String key) {
- int count = createRandomNumber(1, 12);
+ private String insertRandomCharacters(String key) {
+ int count = createRandomNumber(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))) {
- randomChars[randCount] = (char) rand;
- randCount += 1;
- }
- }
+ 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))) {
+ randomChars[randCount] = (char) rand;
+ randCount += 1;
+ }
+ }
- for (int i = 0; i < count; i++) {
- int split = createRandomNumber(0, key.length());
- String part1 = key.substring(0, split);
- String part2 = key.substring(split);
- key = part1 + randomChars[i] + part2;
- }
+ for (int i = 0; i < count; i++) {
+ int split = createRandomNumber(0, key.length());
+ String part1 = key.substring(0, split);
+ String part2 = key.substring(split);
+ key = part1 + randomChars[i] + part2;
+ }
- return key;
- }
+ return key;
+ }
- private String insertSpaces(String key, int spaces) {
- for (int i = 0; i < spaces; i++) {
- int split = createRandomNumber(1, key.length() - 1);
- String part1 = key.substring(0, split);
- String part2 = key.substring(split);
- key = part1 + " " + part2;
- }
+ private String insertSpaces(String key, int spaces) {
+ for (int i = 0; i < spaces; i++) {
+ int split = createRandomNumber(1, key.length() - 1);
+ String part1 = key.substring(0, split);
+ String part2 = key.substring(split);
+ key = part1 + " " + part2;
+ }
- return key;
- }
+ return key;
+ }
}
\ No newline at end of file
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..62bfbc7fef
--- /dev/null
+++ b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker08.java
@@ -0,0 +1,197 @@
+/*
+ * 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 java.util.Map;
+
+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;
+
+/**
+ *
+ * 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");
+ if (customHeaders != null) {
+ for (String header : customHeaders.keySet()) {
+ request.addHeader(header, customHeaders.get(header));
+ }
+ }
+
+ channel.write(request);
+
+ channel.getPipeline().replace(HttpRequestEncoder.class, "ws-encoder", new WebSocket08FrameEncoder(true));
+ }
+
+ /**
+ *
+ * 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;
-
-/**
- *
- * 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));
- }
-
- /**
- *
- * 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..d7dc30267f
--- /dev/null
+++ b/src/main/java/org/jboss/netty/handler/codec/http/websocketx/WebSocketClientHandshaker13.java
@@ -0,0 +1,197 @@
+/*
+ * 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 java.util.Map;
+
+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;
+
+/**
+ *
+ * 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");
+ if (customHeaders != null) {
+ for (String header : customHeaders.keySet()) {
+ request.addHeader(header, customHeaders.get(header));
+ }
+ }
+
+ channel.write(request);
+
+ channel.getPipeline().replace(HttpRequestEncoder.class, "ws-encoder", new WebSocket13FrameEncoder(true));
+ }
+
+ /**
+ *
+ * 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;
-
-/**
- *
- * 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));
- }
-
- /**
- *
- * 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..6ec12a3393 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
@@ -16,42 +16,46 @@
package org.jboss.netty.handler.codec.http.websocketx;
import java.net.URI;
+import java.util.Map;
/**
* Instances the appropriate handshake class to use for clients
*/
public class WebSocketClientHandshakerFactory {
- /**
- * Instances a new handshaker
- *
- * @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. Null if no
- * sub-protocol support is required.
- * @param allowExtensions
- * Allow extensions to be used in the reserved bits of the web
- * 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);
- }
- if (version == WebSocketSpecificationVersion.V10) {
- return new WebSocketClientHandshaker10(webSocketURL, version, subProtocol, allowExtensions);
- }
- if (version == WebSocketSpecificationVersion.V00) {
- return new WebSocketClientHandshaker00(webSocketURL, version, subProtocol);
- }
+ /**
+ * Instances a new handshaker
+ *
+ * @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. Null if no
+ * sub-protocol support is required.
+ * @param allowExtensions
+ * Allow extensions to be used in the reserved bits of the web
+ * socket frame
+ * @param customHeaders
+ * custom HTTP headers
+ * @throws WebSocketHandshakeException
+ */
+ public WebSocketClientHandshaker newHandshaker(URI webSocketURL, WebSocketVersion version, String subProtocol,
+ boolean allowExtensions, Map
+ * 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
+ *
+ *
+ *
+ * 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;
-
-/**
- *
- * 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
- *
- *
- *
- * 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;
+
+/**
+ *
+ * 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
+ *
+ *
+ *
+ * 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;
-
-/**
- *
- * 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
- *
- *
- *
- * 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;
-
-/**
- *