| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.sdk.internal.websocket; | 5 package org.chromium.sdk.internal.websocket; |
| 6 | 6 |
| 7 import java.io.IOException; | 7 import java.io.IOException; |
| 8 import java.net.InetSocketAddress; | 8 import java.net.InetSocketAddress; |
| 9 import java.util.Random; | 9 import java.util.Random; |
| 10 import java.util.logging.Level; | 10 import java.util.logging.Level; |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 sendMessage(OpCode.TEXT, payload, false); | 140 sendMessage(OpCode.TEXT, payload, false); |
| 141 } | 141 } |
| 142 | 142 |
| 143 @Override | 143 @Override |
| 144 protected CloseReason runListenLoop(LoggableInput loggableReader) | 144 protected CloseReason runListenLoop(LoggableInput loggableReader) |
| 145 throws IOException, InterruptedException { | 145 throws IOException, InterruptedException { |
| 146 try { | 146 try { |
| 147 return runListenLoopImpl(loggableReader); | 147 return runListenLoopImpl(loggableReader); |
| 148 } catch (IOException e) { | 148 } catch (IOException e) { |
| 149 String stackTrace = BasicUtil.getStacktraceString(e); | 149 String stackTrace = BasicUtil.getStacktraceString(e); |
| 150 sendClosingMessage(StatusCode.PROTOCOL_ERROR, stackTrace); | 150 try { |
| 151 sendClosingMessage(StatusCode.PROTOCOL_ERROR, stackTrace); |
| 152 } catch (IOException e2) { |
| 153 // Connection may be closed by this time. We probably don't want to log
this exception. |
| 154 } |
| 151 throw new IOException(e); | 155 throw new IOException(e); |
| 152 } catch (IncomingProtocolException e) { | 156 } catch (IncomingProtocolException e) { |
| 153 String stackTrace = BasicUtil.getStacktraceString(e); | 157 String stackTrace = BasicUtil.getStacktraceString(e); |
| 154 sendClosingMessage(e.getStatusCode(), stackTrace); | 158 sendClosingMessage(e.getStatusCode(), stackTrace); |
| 155 throw new IOException(e); | 159 throw new IOException(e); |
| 156 } | 160 } |
| 157 } | 161 } |
| 158 | 162 |
| 159 private CloseReason runListenLoopImpl(LoggableInput loggableReader) | 163 private CloseReason runListenLoopImpl(LoggableInput loggableReader) |
| 160 throws IOException, InterruptedException, IncomingProtocolException { | 164 throws IOException, InterruptedException, IncomingProtocolException { |
| 161 while (true) { | 165 while (true) { |
| 162 loggableReader.markSeparatorForLog(); | 166 loggableReader.markSeparatorForLog(); |
| 163 int firstByte; | 167 int firstByte; |
| 164 try { | 168 try { |
| 165 firstByte = loggableReader.readByteOrEos(); | 169 firstByte = loggableReader.readByteOrEos(); |
| 166 } catch (IOException e) { | 170 } catch (IOException e) { |
| 167 if (isClosingGracefully()) { | 171 if (isClosingGracefully()) { |
| 168 return CloseReason.USER_REQUEST; | 172 return CloseReason.USER_REQUEST; |
| 169 } else { | 173 } else { |
| 170 throw e; | 174 throw e; |
| 171 } | 175 } |
| 172 } | 176 } |
| 173 if (firstByte == -1) { | 177 if (firstByte == -1) { |
| 174 if (isClosingGracefully()) { | 178 if (isClosingGracefully()) { |
| 175 return CloseReason.USER_REQUEST; | 179 return CloseReason.USER_REQUEST; |
| 176 } else { | 180 } else { |
| 177 throw new IOException("Unexpected end of stream"); | 181 return CloseReason.REMOTE_SILENTLY_CLOSED; |
| 178 } | 182 } |
| 179 } | 183 } |
| 180 | 184 |
| 181 if ((firstByte & FrameBits.FIN_BIT) == 0) { | 185 if ((firstByte & FrameBits.FIN_BIT) == 0) { |
| 182 throw new IncomingProtocolException("Fragments unsupported", | 186 throw new IncomingProtocolException("Fragments unsupported", |
| 183 StatusCode.CANNOT_ACCEPT, null); | 187 StatusCode.CANNOT_ACCEPT, null); |
| 184 } | 188 } |
| 185 if ((firstByte & FrameBits.RESERVED_MASK) != 0) { | 189 if ((firstByte & FrameBits.RESERVED_MASK) != 0) { |
| 186 throw new IncomingProtocolException("Unexpected reserved bits", | 190 throw new IncomingProtocolException("Unexpected reserved bits", |
| 187 StatusCode.PROTOCOL_ERROR, null); | 191 StatusCode.PROTOCOL_ERROR, null); |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 int length = loggablePayload.getLength(); | 384 int length = loggablePayload.getLength(); |
| 381 LoggableOutput output = getSocketWrapper().getLoggableOutput(); | 385 LoggableOutput output = getSocketWrapper().getLoggableOutput(); |
| 382 | 386 |
| 383 byte[] maskBytes = maskStrategy.generate(); | 387 byte[] maskBytes = maskStrategy.generate(); |
| 384 | 388 |
| 385 synchronized (this) { | 389 synchronized (this) { |
| 386 if (isOutputClosed()) { | 390 if (isOutputClosed()) { |
| 387 throw new IOException("WebSocket is already closed for output"); | 391 throw new IOException("WebSocket is already closed for output"); |
| 388 } | 392 } |
| 389 | 393 |
| 394 if (isClosingMessage) { |
| 395 // Close it before actually sending, because we can fail on it. |
| 396 setOutputClosed(true); |
| 397 } |
| 398 |
| 390 byte firstByte = (byte) (FrameBits.FIN_BIT | OpCode.TEXT); | 399 byte firstByte = (byte) (FrameBits.FIN_BIT | OpCode.TEXT); |
| 391 | 400 |
| 392 output.writeByte(firstByte); | 401 output.writeByte(firstByte); |
| 393 | 402 |
| 394 int maskFlag = maskBytes == null ? 0 : FrameBits.MASK_BIT; | 403 int maskFlag = maskBytes == null ? 0 : FrameBits.MASK_BIT; |
| 395 | 404 |
| 396 if (length <= 125) { | 405 if (length <= 125) { |
| 397 output.writeByte((byte) (length | maskFlag)); | 406 output.writeByte((byte) (length | maskFlag)); |
| 398 } else if (length <= FrameBits.MAX_TWO_BYTE_INT) { | 407 } else if (length <= FrameBits.MAX_TWO_BYTE_INT) { |
| 399 output.writeByte((byte) (FrameBits.LENGTH_2_BYTE_CODE | maskFlag)); | 408 output.writeByte((byte) (FrameBits.LENGTH_2_BYTE_CODE | maskFlag)); |
| 400 output.writeByte((byte) ((length >> 8) & 0xFF)); | 409 output.writeByte((byte) ((length >> 8) & 0xFF)); |
| 401 output.writeByte((byte) (length & 0xFF)); | 410 output.writeByte((byte) (length & 0xFF)); |
| 402 } else { | 411 } else { |
| 403 output.writeByte((byte) (FrameBits.LENGTH_8_BYTE_CODE | maskFlag)); | 412 output.writeByte((byte) (FrameBits.LENGTH_8_BYTE_CODE | maskFlag)); |
| 404 output.writeByte((byte) 0); | 413 output.writeByte((byte) 0); |
| 405 output.writeByte((byte) 0); | 414 output.writeByte((byte) 0); |
| 406 output.writeByte((byte) 0); | 415 output.writeByte((byte) 0); |
| 407 output.writeByte((byte) 0); | 416 output.writeByte((byte) 0); |
| 408 output.writeByte((byte) (length >>> 24)); | 417 output.writeByte((byte) (length >>> 24)); |
| 409 output.writeByte((byte) ((length >> 16) & 0xFF)); | 418 output.writeByte((byte) ((length >> 16) & 0xFF)); |
| 410 output.writeByte((byte) ((length >> 8) & 0xFF)); | 419 output.writeByte((byte) ((length >> 8) & 0xFF)); |
| 411 output.writeByte((byte) (length & 0xFF)); | 420 output.writeByte((byte) (length & 0xFF)); |
| 412 } | 421 } |
| 413 | 422 |
| 414 if (maskBytes != null) { | 423 if (maskBytes != null) { |
| 415 output.writeBytes(maskBytes); | 424 output.writeBytes(maskBytes); |
| 416 } | 425 } |
| 417 loggablePayload.send(output, maskBytes); | 426 loggablePayload.send(output, maskBytes); |
| 418 | |
| 419 if (isClosingMessage) { | |
| 420 setOutputClosed(true); | |
| 421 } | |
| 422 } | 427 } |
| 423 | 428 |
| 424 output.markSeparatorForLog(); | 429 output.markSeparatorForLog(); |
| 425 } | 430 } |
| 426 | 431 |
| 427 private static void performHandshakeOrFail(ManualLoggingSocketWrapper socket, | 432 private static void performHandshakeOrFail(ManualLoggingSocketWrapper socket, |
| 428 InetSocketAddress endpoint, String resourceId) throws IOException { | 433 InetSocketAddress endpoint, String resourceId) throws IOException { |
| 429 Hybi17Handshake.Result result = | 434 Hybi17Handshake.Result result = |
| 430 Hybi17Handshake.performHandshake(socket, endpoint, resourceId, RANDOM); | 435 Hybi17Handshake.performHandshake(socket, endpoint, resourceId, RANDOM); |
| 431 result.accept(HANDSHAKE_RESULT_VISITOR).get(); | 436 result.accept(HANDSHAKE_RESULT_VISITOR).get(); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 } | 513 } |
| 509 | 514 |
| 510 private interface StatusCode { | 515 private interface StatusCode { |
| 511 int NORMAL = 1000; | 516 int NORMAL = 1000; |
| 512 int PROTOCOL_ERROR = 1002; | 517 int PROTOCOL_ERROR = 1002; |
| 513 int CANNOT_ACCEPT = 1003; | 518 int CANNOT_ACCEPT = 1003; |
| 514 } | 519 } |
| 515 | 520 |
| 516 private static final int STATUS_CODE_LENTGH = 2; | 521 private static final int STATUS_CODE_LENTGH = 2; |
| 517 } | 522 } |
| OLD | NEW |