private void encodeFrame(WsURLConnectionImpl connection, Frame frame) throws IOException { OutputStream out = connection.getTcpOutputStream(); int offset = frame.offset(); ByteBuffer buf = frame.buffer(); int payloadLength = frame.payloadLength(); int payloadOffset = frame.payloadOffset(); int mask = 0; if (payloadLength > 0) { mask = 1 + connection.getRandom().nextInt(Integer.MAX_VALUE); } int metadataLength = payloadOffset - offset; switch (metadataLength) { case 2: frameBuffer.putShort(buf.getShort(offset)); break; case 4: frameBuffer.putInt(buf.getInt(offset)); break; case 10: frameBuffer.putShort(buf.getShort(offset)); frameBuffer.putLong(buf.getLong(offset + 2)); break; default: throw new IllegalStateException(format(MSG_INVALID_METADATA_LENGTH, metadataLength)); } // Set the mask bit. byte maskByte = frameBuffer.get(1); frameBuffer.put(1, (byte) (maskByte | 0x80)); encodeMaskAndPayload(buf, payloadOffset, payloadLength, mask); out.write(frameBuffer.array(), 0, frameBuffer.position()); frameBuffer.rewind(); }
private void validateAndEncodeCloseFrame(WsURLConnectionImpl connection, Frame frame) throws IOException { OutputStream out = connection.getTcpOutputStream(); int len = 0; int code = 0; int closeCode = 0; ByteBuffer buffer = frame.buffer(); int closePayloadLen = frame.payloadLength(); int payloadOffset = frame.payloadOffset(); IOException exception = null; closePayloadRO.wrap(buffer, payloadOffset, payloadOffset + closePayloadLen); if (closePayloadLen >= 2) { closeCode = closePayloadRO.statusCode(); } if (closeCode != 0) { switch (closeCode) { case WS_MISSING_STATUS_CODE: case WS_ABNORMAL_CLOSE: case WS_UNSUCCESSFUL_TLS_HANDSHAKE: len += 2; code = WS_PROTOCOL_ERROR; exception = new IOException(format(MSG_CLOSE_FRAME_VIOLATION, closeCode, closePayloadLen)); break; case WS_NORMAL_CLOSE: case WS_ENDPOINT_GOING_AWAY: case WS_PROTOCOL_ERROR: case WS_INCORRECT_MESSAGE_TYPE: case WS_INCONSISTENT_DATA_MESSAGE_TYPE: case WS_VIOLATE_POLICY: case WS_MESSAGE_TOO_BIG: case WS_UNSUCCESSFUL_EXTENSION_NEGOTIATION: case WS_SERVER_TERMINATED_CONNECTION: len += 2; code = closeCode; break; default: if ((closeCode >= 3000) && (closeCode <= 4999)) { len += 2; code = closeCode; } throw new IOException(format("Invalid CLOSE code %d", closeCode)); } if ((code != WS_PROTOCOL_ERROR) && (closePayloadLen > 2)) { int reasonLength = closePayloadLen - 2; assert reasonLength == closePayloadRO.reasonLength(); if (reasonLength > 0) { if (!validBytesUTF8(buffer, closePayloadRO.reasonOffset(), reasonLength)) { code = WS_PROTOCOL_ERROR; exception = new IOException(format(MSG_CLOSE_FRAME_VIOLATION, closeCode, reasonLength)); } else if (reasonLength > 123) { code = WS_PROTOCOL_ERROR; exception = new IOException(format(MSG_CLOSE_FRAME_VIOLATION, closeCode, reasonLength)); len += reasonLength; } else { if (code != WS_NORMAL_CLOSE) { reasonLength = 0; } len += reasonLength; } } } } frameBuffer.put((byte) 0x88); encodePayloadLength(len); if (len == 0) { frameBuffer.putInt(0); } else { assert len >= 2; int mask = 1 + connection.getRandom().nextInt(Integer.MAX_VALUE); int reasonOffset = closePayloadRO.reasonOffset(); int roffset = reasonOffset; closePayload.putShort(0, (short) code); if (len > 2) { for (int i = 2; i < len; i++) { closePayload.put(i, frame.buffer().get(roffset++)); } } encodeMaskAndPayload(closePayload, 0, len, mask); } out.write(frameBuffer.array(), 0, frameBuffer.position()); frameBuffer.rewind(); out.flush(); out.close(); if (exception != null) { throw exception; } }