Used codec implementation of Base64 encoding. Thanks to Steven Osborn (steve918)

This commit is contained in:
Veebs 2011-10-16 21:02:14 +11:00
parent 6f9a886a36
commit 91796814eb
5 changed files with 35 additions and 118 deletions

View File

@ -1,115 +0,0 @@
/*
* Copyright 2010 Red Hat, Inc.
*
* Red Hat 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.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
/**
* Encodes binary data to plain text as Base64.
*
* Despite there being a gazillion other Base64 implementations out there, this
* has been written as part of XStream as it forms a core part but is too
* trivial to warrant an extra dependency.
*
* This meets the standard as described in RFC 1521, section 5.2
* <http://www.freesoft.org/CIE/RFC/1521/7.htm>, allowing other Base64 tools to
* manipulate the data.
*
* This code originally came from the XStream http://xstream.codehaus.org
* project by Joe Walnes. Relicensed to Webbit.
*/
public class Base64 {
// Here's how encoding works:
//
// 1) Incoming bytes are broken up into groups of 3 (each byte having 8
// bits).
//
// 2) The combined 24 bits (3 * 8) are split into 4 groups of 6 bits.
//
// input |------||------||------| (3 values each with 8 bits)
// 101010101010101010101010
// output |----||----||----||----| (4 values each with 6 bits)
//
// 3) Each of these 4 groups of 6 bits are converted back to a number, which
// will fall in the range of 0 - 63.
//
// 4) Each of these 4 numbers are converted to an alphanumeric char in a
// specified mapping table, to create
// a 4 character string.
//
// 5) This is repeated for all groups of three bytes.
//
// 6) Special padding is done at the end of the stream using the '=' char.
private static final char[] SIXTY_FOUR_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
.toCharArray();
private static final int[] REVERSE_MAPPING = new int[123];
static {
for (int i = 0; i < SIXTY_FOUR_CHARS.length; i++)
REVERSE_MAPPING[SIXTY_FOUR_CHARS[i]] = i + 1;
}
public static String encode(byte[] input) {
StringBuilder result = new StringBuilder();
int outputCharCount = 0;
for (int i = 0; i < input.length; i += 3) {
int remaining = Math.min(3, input.length - i);
int oneBigNumber = (input[i] & 0xff) << 16 | (remaining <= 1 ? 0 : input[i + 1] & 0xff) << 8
| (remaining <= 2 ? 0 : input[i + 2] & 0xff);
for (int j = 0; j < 4; j++)
result.append(remaining + 1 > j ? SIXTY_FOUR_CHARS[0x3f & oneBigNumber >> 6 * (3 - j)] : '=');
if ((outputCharCount += 4) % 76 == 0)
result.append('\n');
}
return result.toString();
}
public static byte[] decode(String input) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
StringReader in = new StringReader(input);
for (int i = 0; i < input.length(); i += 4) {
int a[] = { mapCharToInt(in), mapCharToInt(in), mapCharToInt(in), mapCharToInt(in) };
int oneBigNumber = (a[0] & 0x3f) << 18 | (a[1] & 0x3f) << 12 | (a[2] & 0x3f) << 6 | (a[3] & 0x3f);
for (int j = 0; j < 3; j++) {
if (a[j + 1] >= 0) {
out.write(0xff & oneBigNumber >> 8 * (2 - j));
}
}
}
return out.toByteArray();
} catch (IOException e) {
throw new Error(e + ": " + e.getMessage());
}
}
private static int mapCharToInt(Reader input) throws IOException {
int c;
while ((c = input.read()) != -1) {
int result = REVERSE_MAPPING[c];
if (result != 0)
return result - 1;
if (c == '=')
return -1;
}
return -1;
}
}

View File

@ -19,9 +19,13 @@ import java.net.URI;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.base64.Base64;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.util.CharsetUtil;
/**
* Base class for web socket client handshake implementations
@ -162,6 +166,18 @@ public abstract class WebSocketClientHandshaker {
}
}
/**
* Base 64 encoding
*
* @param bytes
* Bytes to encode
* @return encoded string
*/
protected String base64Encode(byte[] bytes) {
ChannelBuffer hashed = ChannelBuffers.wrappedBuffer(bytes);
return Base64.encode(hashed).toString(CharsetUtil.UTF_8);
}
/**
* Creates some random bytes
*

View File

@ -109,11 +109,11 @@ public class WebSocketClientHandshaker10 extends WebSocketClientHandshaker {
// Get 16 bit nonce and base 64 encode it
byte[] nonce = createRandomBytes(16);
String key = Base64.encode(nonce);
String key = base64Encode(nonce);
String acceptSeed = key + MAGIC_GUID;
byte[] sha1 = sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII));
this.expectedChallengeResponseString = Base64.encode(sha1);
this.expectedChallengeResponseString = base64Encode(sha1);
if (logger.isDebugEnabled()) {
logger.debug(String.format("HyBi10 Client Handshake key: %s. Expected response: %s.", key,

View File

@ -18,8 +18,12 @@ package org.jboss.netty.handler.codec.http.websocketx;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.base64.Base64;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.util.CharsetUtil;
/**
* Base class for server side web socket opening and closing handshakes
@ -146,6 +150,18 @@ public abstract class WebSocketServerHandshaker {
}
}
/**
* Base 64 encoding
*
* @param bytes
* Bytes to encode
* @return encoded string
*/
protected String base64Encode(byte[] bytes) {
ChannelBuffer hashed = ChannelBuffers.wrappedBuffer(bytes);
return Base64.encode(hashed).toString(CharsetUtil.UTF_8);
}
/**
* Selects the first matching supported sub protocol
*

View File

@ -125,7 +125,7 @@ public class WebSocketServerHandshaker10 extends WebSocketServerHandshaker {
}
String acceptSeed = key + WEBSOCKET_08_ACCEPT_GUID;
byte[] sha1 = sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII));
String accept = Base64.encode(sha1);
String accept = base64Encode(sha1);
if (logger.isDebugEnabled()) {
logger.debug(String.format("HyBi10 Server Handshake key: %s. Response: %s.", key, accept));