Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(134)

Unified Diff: plugins/org.chromium.sdk.wipbackend.wk118685/src/org/chromium/sdk/internal/websocket/Hybi17WsConnection.java

Issue 11829027: drop old backends (Closed) Base URL: https://chromedevtools.googlecode.com/svn/trunk
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: plugins/org.chromium.sdk.wipbackend.wk118685/src/org/chromium/sdk/internal/websocket/Hybi17WsConnection.java
diff --git a/plugins/org.chromium.sdk.wipbackend.wk118685/src/org/chromium/sdk/internal/websocket/Hybi17WsConnection.java b/plugins/org.chromium.sdk.wipbackend.wk118685/src/org/chromium/sdk/internal/websocket/Hybi17WsConnection.java
deleted file mode 100644
index b1d13f928fea14acdf63d7d0e3db4b926175427d..0000000000000000000000000000000000000000
--- a/plugins/org.chromium.sdk.wipbackend.wk118685/src/org/chromium/sdk/internal/websocket/Hybi17WsConnection.java
+++ /dev/null
@@ -1,522 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.sdk.internal.websocket;
-
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.util.Random;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import org.chromium.sdk.ConnectionLogger;
-import org.chromium.sdk.internal.websocket.ManualLoggingSocketWrapper.LoggableInput;
-import org.chromium.sdk.internal.websocket.ManualLoggingSocketWrapper.LoggableOutput;
-import org.chromium.sdk.util.BasicUtil;
-
-/**
- * WebSocket connection. Sends and receives messages. Implements HyBi-17 protocol specification.
- * @see http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17
- */
-public class Hybi17WsConnection extends AbstractWsConnection<LoggableInput, LoggableOutput> {
- private static final Logger LOGGER = Logger.getLogger(Hybi17WsConnection.class.getName());
- private static final Random RANDOM = new Random();
-
- /**
- * Specifies how outgoing frames get masked. While protocol specification requires that every
- * outgoing frame must be masked (to disable provocative content that socket client may send),
- * this doesn't really make sense when the client is trusted. On the other hand, transparent mask
- * makes debug sniffering easier.
- */
- public enum MaskStrategy {
- /**
- * Directs to use no mask at all. This is explicitly against protocol specification, peer
- * is expected to terminate connection in response.
- */
- NO_MASK() {
- @Override public byte[] generate() {
- return null;
- }
-
- @Override
- ManualLoggingSocketWrapper.FactoryBase getLogWrapperFactory() {
- return ManualLoggingSocketWrapper.PLAIN_ASCII;
- }
- },
- /**
- * Directs to always use transparent mask (i.e. all zeroes). This makes all frames clear-text.
- * Not suitable when untrusted client uses the WebSocket.
- */
- TRANSPARENT_MASK() {
- private final byte[] bytes = new byte[4];
-
- @Override public byte[] generate() {
- return bytes;
- }
-
- @Override
- ManualLoggingSocketWrapper.FactoryBase getLogWrapperFactory() {
- return ManualLoggingSocketWrapper.PLAIN_ASCII;
- }
- },
- /**
- * Directs to use randomly generated masks as specified by specification. As a by-product makes
- * traffic hard to sniff.
- */
- NORMAL_MASK() {
- @Override
- byte[] generate() {
- byte[] result = new byte[4];
- RANDOM.nextBytes(result);
- return result;
- }
-
- @Override
- ManualLoggingSocketWrapper.FactoryBase getLogWrapperFactory() {
- return ManualLoggingSocketWrapper.ANNOTATED;
- }
- };
-
- /** @return 4-byte array or null */
- abstract byte[] generate();
-
- abstract ManualLoggingSocketWrapper.FactoryBase getLogWrapperFactory();
- }
-
- public static Hybi17WsConnection connect(InetSocketAddress endpoint, int timeout,
- String resourceId, MaskStrategy maskStrategy, ConnectionLogger connectionLogger)
- throws IOException {
- ManualLoggingSocketWrapper socketWrapper = new ManualLoggingSocketWrapper(endpoint, timeout,
- connectionLogger, maskStrategy.getLogWrapperFactory());
-
- boolean handshakeDone = false;
- Exception handshakeException = null;
- try {
- performHandshakeOrFail(socketWrapper, endpoint, resourceId);
- handshakeDone = true;
- } catch (RuntimeException e) {
- handshakeException = e;
- throw e;
- } catch (IOException e) {
- handshakeException = e;
- throw e;
- } finally {
- if (!handshakeDone) {
- socketWrapper.getShutdownRelay().sendSignal(null, handshakeException);
- }
- }
-
- return new Hybi17WsConnection(socketWrapper, maskStrategy, connectionLogger);
- }
-
- private final MaskStrategy maskStrategy;
-
- private Hybi17WsConnection(ManualLoggingSocketWrapper socketWrapper, MaskStrategy maskStrategy,
- ConnectionLogger connectionLogger) {
- super(socketWrapper, connectionLogger);
- this.maskStrategy = maskStrategy;
- }
-
- @Override
- public void sendTextualMessage(final String message) throws IOException {
- final byte[] bytes = message.getBytes(UTF_8_CHARSET);
-
- LoggablePayload payload = new LoggablePayload() {
- @Override void send(LoggableOutput output, byte[] maskBytes) throws IOException {
- output.writeToLog(message, "utf-8 demasked");
- if (maskBytes != null) {
- for (int i = 0; i < bytes.length; i++) {
- bytes[i] = (byte) (bytes[i] ^ maskBytes[i % 4]);
- }
- }
- output.writeBytesNoLogging(bytes);
- }
- @Override int getLength() {
- return bytes.length;
- }
- };
-
- sendMessage(OpCode.TEXT, payload, false);
- }
-
- @Override
- protected CloseReason runListenLoop(LoggableInput loggableReader)
- throws IOException, InterruptedException {
- try {
- return runListenLoopImpl(loggableReader);
- } catch (IOException e) {
- String stackTrace = BasicUtil.getStacktraceString(e);
- try {
- sendClosingMessage(StatusCode.PROTOCOL_ERROR, stackTrace);
- } catch (IOException e2) {
- // Connection may be closed by this time. We probably don't want to log this exception.
- }
- throw new IOException(e);
- } catch (IncomingProtocolException e) {
- String stackTrace = BasicUtil.getStacktraceString(e);
- sendClosingMessage(e.getStatusCode(), stackTrace);
- throw new IOException(e);
- }
- }
-
- private CloseReason runListenLoopImpl(LoggableInput loggableReader)
- throws IOException, InterruptedException, IncomingProtocolException {
- while (true) {
- loggableReader.markSeparatorForLog();
- int firstByte;
- try {
- firstByte = loggableReader.readByteOrEos();
- } catch (IOException e) {
- if (isClosingGracefully()) {
- return CloseReason.USER_REQUEST;
- } else {
- throw e;
- }
- }
- if (firstByte == -1) {
- if (isClosingGracefully()) {
- return CloseReason.USER_REQUEST;
- } else {
- return CloseReason.REMOTE_SILENTLY_CLOSED;
- }
- }
-
- if ((firstByte & FrameBits.FIN_BIT) == 0) {
- throw new IncomingProtocolException("Fragments unsupported",
- StatusCode.CANNOT_ACCEPT, null);
- }
- if ((firstByte & FrameBits.RESERVED_MASK) != 0) {
- throw new IncomingProtocolException("Unexpected reserved bits",
- StatusCode.PROTOCOL_ERROR, null);
- }
-
- int opcode = firstByte & FrameBits.OPCODE_MASK;
-
- IncomingFrameHandler frameHandler;
-
- switch (opcode) {
- case OpCode.CONTINUATION:
- throw new IncomingProtocolException("Continuation is not supported",
- StatusCode.CANNOT_ACCEPT, null);
- case OpCode.TEXT:
- frameHandler = IncomingFrameHandler.TEXT_MESSAGE;
- break;
- case OpCode.BINARY:
- throw new IncomingProtocolException("Binary is not supported",
- StatusCode.CANNOT_ACCEPT, null);
- case OpCode.CLOSE:
- sendClosingMessage(StatusCode.NORMAL, null);
- return CloseReason.REMOTE_CLOSE_REQUEST;
- case OpCode.PING:
- frameHandler = IncomingFrameHandler.PING;
- break;
- case OpCode.PONG:
- frameHandler = IncomingFrameHandler.PONG;
- break;
- default:
- throw new IncomingProtocolException("Unsupported opcode " + opcode,
- StatusCode.CANNOT_ACCEPT, null);
- }
-
- int secondByte = readByteOfFail(loggableReader);
-
- boolean hasMask = (secondByte & FrameBits.MASK_BIT) != 0;
-
- if (hasMask) {
- throw new IncomingProtocolException("Masked server-to-client message is not supported",
- StatusCode.PROTOCOL_ERROR, null);
- }
-
- int payloadLenByte = secondByte & FrameBits.LENGTH_MASK;
- int payloadLen;
- if (payloadLenByte == FrameBits.LENGTH_2_BYTE_CODE) {
- int lengthTemp = readByteOfFail(loggableReader);
- lengthTemp <<= 8;
- lengthTemp += readByteOfFail(loggableReader);
- payloadLen = lengthTemp;
- } else if (payloadLenByte == FrameBits.LENGTH_8_BYTE_CODE) {
- for (int i = 0; i < 4; i++) {
- int b = readByteOfFail(loggableReader);
- if (b != 0) {
- throw new IncomingProtocolException("Payload length is too large",
- StatusCode.CANNOT_ACCEPT, null);
- }
- }
- int lengthTemp = readByteOfFail(loggableReader);
- if ((lengthTemp & FrameBits.HIGH_BIT) != 0) {
- throw new IncomingProtocolException("Payload length is too large",
- StatusCode.CANNOT_ACCEPT, null);
- }
- for (int i = 0; i < 3; i++) {
- lengthTemp <<= 8;
- lengthTemp += readByteOfFail(loggableReader);
- }
- payloadLen = lengthTemp;
- } else {
- payloadLen = payloadLenByte;
- }
-
- byte [] bytes = loggableReader.readBytes(payloadLen);
- frameHandler.process(bytes, this);
- }
- }
-
- private static class IncomingProtocolException extends Exception {
- private final int statusCode;
-
- private IncomingProtocolException(String message, int statusCode, Throwable cause) {
- super(message, cause);
- this.statusCode = statusCode;
- }
-
- int getStatusCode() {
- return statusCode;
- }
- }
-
- private static abstract class IncomingFrameHandler {
- abstract void process(byte[] bytes, Hybi17WsConnection hybiWsConnection);
-
- static final IncomingFrameHandler TEXT_MESSAGE = new IncomingFrameHandler() {
- @Override
- void process(byte[] bytes, Hybi17WsConnection hybiWsConnection) {
- final String text = new String(bytes, UTF_8_CHARSET);
- hybiWsConnection.getDispatchQueue().add(new MessageDispatcher() {
- @Override
- boolean dispatch(Listener userListener) {
- userListener.textMessageRecieved(text);
- return false;
- }
- });
- }
- };
-
- static final IncomingFrameHandler PING = new IncomingFrameHandler() {
- @Override
- void process(final byte[] bytes, Hybi17WsConnection hybiWsConnection) {
- LoggablePayload payload = new LoggablePayload() {
- @Override
- void send(LoggableOutput output, byte[] maskBytes) throws IOException {
- output.writeBytesToLog(bytes);
- if (maskBytes != null) {
- for (int i = 0; i < bytes.length; i++) {
- bytes[i] = (byte) (bytes[i] ^ maskBytes[i % 4]);
- }
- }
- output.writeBytes(bytes);
- output.markSeparatorForLog();
- }
- @Override int getLength() {
- return bytes.length;
- }
- };
- try {
- // Should we do in this thread or relay it to Dispatch thread?
- hybiWsConnection.sendMessage(OpCode.PONG, payload, false);
- } catch (IOException e) {
- LOGGER.log(Level.WARNING, "Failed to send pong", e);
- }
- }
- };
-
- static final IncomingFrameHandler PONG = new IncomingFrameHandler() {
- @Override
- void process(byte[] bytes, Hybi17WsConnection hybiWsConnection) {
- // Ignore
- }
- };
- }
-
- /**
- * Payload that can send and properly log itself. Good logging requires that the body
- * is not masked.
- */
- private static abstract class LoggablePayload {
- abstract void send(LoggableOutput output, byte[] maskBytes) throws IOException;
- abstract int getLength();
- }
-
- private void sendClosingMessage(final int statusCode, final String message) throws IOException {
- final byte[] bytes;
- if (message == null) {
- bytes = new byte[0];
- } else {
- bytes = message.getBytes(UTF_8_CHARSET);
- }
-
- LoggablePayload payload = new LoggablePayload() {
- @Override
- void send(LoggableOutput output, byte[] maskBytes) throws IOException {
- byte codeByte1 = (byte) ((statusCode >> 8) & 0xFF);
- byte codeByte2 = (byte) (statusCode & 0xFF);
-
- byte codeByteMasked1 = codeByte1;
- byte codeByteMasked2 = codeByte2;
- if (maskBytes != null) {
- codeByteMasked1 ^= maskBytes[0];
- codeByteMasked2 ^= maskBytes[1];
-
- for (int i = 0; i < bytes.length; i++) {
- bytes[i] = (byte) (bytes[i] ^ maskBytes[(i + STATUS_CODE_LENTGH) % 4]);
- }
- }
- output.writeByteNoLogging(codeByteMasked1);
- output.writeByteNoLogging(codeByteMasked2);
-
- output.writeByteToLog(codeByte1);
- output.writeByteToLog(codeByte2);
-
- output.writeBytesNoLogging(bytes);
- output.writeToLog(message, "utf-8 demasked");
- }
-
- @Override int getLength() {
- return STATUS_CODE_LENTGH + bytes.length;
- }
- };
-
- sendMessage(OpCode.CLOSE, payload, true);
- }
-
- private void sendMessage(int opCode, LoggablePayload loggablePayload, boolean isClosingMessage)
- throws IOException {
- int length = loggablePayload.getLength();
- LoggableOutput output = getSocketWrapper().getLoggableOutput();
-
- byte[] maskBytes = maskStrategy.generate();
-
- synchronized (this) {
- if (isOutputClosed()) {
- throw new IOException("WebSocket is already closed for output");
- }
-
- if (isClosingMessage) {
- // Close it before actually sending, because we can fail on it.
- setOutputClosed(true);
- }
-
- byte firstByte = (byte) (FrameBits.FIN_BIT | OpCode.TEXT);
-
- output.writeByte(firstByte);
-
- int maskFlag = maskBytes == null ? 0 : FrameBits.MASK_BIT;
-
- if (length <= 125) {
- output.writeByte((byte) (length | maskFlag));
- } else if (length <= FrameBits.MAX_TWO_BYTE_INT) {
- output.writeByte((byte) (FrameBits.LENGTH_2_BYTE_CODE | maskFlag));
- output.writeByte((byte) ((length >> 8) & 0xFF));
- output.writeByte((byte) (length & 0xFF));
- } else {
- output.writeByte((byte) (FrameBits.LENGTH_8_BYTE_CODE | maskFlag));
- output.writeByte((byte) 0);
- output.writeByte((byte) 0);
- output.writeByte((byte) 0);
- output.writeByte((byte) 0);
- output.writeByte((byte) (length >>> 24));
- output.writeByte((byte) ((length >> 16) & 0xFF));
- output.writeByte((byte) ((length >> 8) & 0xFF));
- output.writeByte((byte) (length & 0xFF));
- }
-
- if (maskBytes != null) {
- output.writeBytes(maskBytes);
- }
- loggablePayload.send(output, maskBytes);
- }
-
- output.markSeparatorForLog();
- }
-
- private static void performHandshakeOrFail(ManualLoggingSocketWrapper socket,
- InetSocketAddress endpoint, String resourceId) throws IOException {
- Hybi17Handshake.Result result =
- Hybi17Handshake.performHandshake(socket, endpoint, resourceId, RANDOM);
- result.accept(HANDSHAKE_RESULT_VISITOR).get();
- }
-
- private static final Hybi17Handshake.Result.Visitor<DataOrException<Void>>
- HANDSHAKE_RESULT_VISITOR =
- new Hybi17Handshake.Result.Visitor<DataOrException<Void>>() {
- @Override
- public DataOrException<Void> visitConnected() {
- return new DataOrException<Void>() {
- @Override Void get() throws IOException {
- return null;
- }
- };
- }
-
- @Override
- public DataOrException<Void> visitUnknownError(final Exception exception) {
- return new DataOrException<Void>() {
- @Override Void get() throws IOException {
- throw new IOException("Failed to establish WebSocket connection", exception);
- }
- };
- }
-
- @Override
- public DataOrException<Void> visitErrorMessage(final int code,
- final String errorName, final String text) {
- return new DataOrException<Void>() {
- @Override Void get() throws IOException {
- throw new IOException("Failed to establish WebSocket connection: " + code + " " +
- errorName + " | " + text);
- }
- };
- }
- };
-
- /**
- * This class is used solely to put IOException through Visitor.
- */
- private static abstract class DataOrException<T> {
- abstract T get() throws IOException;
- }
-
- private static int readByteOfFail(LoggableInput loggableReader) throws IOException {
- int b = loggableReader.readByteOrEos();
- if (b == -1) {
- throw new IOException("Unexpected EOS");
- }
- return b;
- }
-
- private interface FrameBits {
- // First byte bits.
- int FIN_BIT = 1 << 7;
- int MASK_BIT = 1 << 7;
-
- // Second byte bits.
- int OPCODE_LENGTH = 4;
- int OPCODE_MASK = (1 << OPCODE_LENGTH) - 1;
- int RESERVED_MASK = ((1 << 3) - 1) << OPCODE_LENGTH ;
-
- int LENGTH_MASK = (1 << 7) - 1;
- int LENGTH_2_BYTE_CODE = 126;
- int LENGTH_8_BYTE_CODE = 127;
-
- // Length bytes.
- int HIGH_BIT = 1 << 7;
- int MAX_TWO_BYTE_INT = 1 << 16 - 1;
- }
-
- private interface OpCode {
- int CONTINUATION = 0x0;
- int TEXT = 0x1;
- int BINARY = 0x2;
- int CLOSE = 0x8;
- int PING = 0x9;
- int PONG = 0xA;
- }
-
- private interface StatusCode {
- int NORMAL = 1000;
- int PROTOCOL_ERROR = 1002;
- int CANNOT_ACCEPT = 1003;
- }
-
- private static final int STATUS_CODE_LENTGH = 2;
-}

Powered by Google App Engine
This is Rietveld 408576698