/** * Adds the data to the buffer for binary data. If a textual message is currently in progress that * message will be completed and a new binary message started. If the buffer for binary data is * full, the buffer will be flushed and a new binary continuation fragment started. * * @param b The byte (only the least significant byte is used) of data to send to the client. * @throws IOException If a flush is required and an error occurs writing the WebSocket frame to * the client */ public void writeBinaryData(int b) throws IOException { try { synchronized (stateLock) { if (closed) { throw new IOException(sm.getString("outbound.closed")); } if (bb.position() == bb.capacity()) { doFlush(false); } if (text == null) { text = Boolean.FALSE; } else if (text == Boolean.TRUE) { // Flush the character data flush(); text = Boolean.FALSE; } bb.put((byte) (b & 0xFF)); } } catch (IOException ioe) { // Any IOException is terminal. Make sure the inbound side knows // that something went wrong. // The exception handling needs to be outside of the sync to avoid // possible deadlocks (e.g. BZ55524) when triggering the inbound // close as that will execute user code streamInbound.doOnClose(Constants23.getStatusClosedUnexpectedly()); throw ioe; } }
/** * Generic function to send either a ping or a pong. * * @param data Optional message. * @param opcode The byte to include as the opcode. * @throws IOException If an error occurs writing to the client */ private void sendControlMessage(ByteBuffer data, byte opcode) throws IOException { try { synchronized (stateLock) { if (closed) { throw new IOException(sm.getString("outbound.closed")); } doFlush(false); upgradeOutbound.write(0x80 | opcode); if (data == null) { upgradeOutbound.write(0); } else { upgradeOutbound.write(data.limit() - data.position()); upgradeOutbound.write(data.array(), data.position(), data.limit() - data.position()); } upgradeOutbound.flush(); } } catch (IOException ioe) { // Any IOException is terminal. Make sure the Inbound side knows // that something went wrong. // The exception handling needs to be outside of the sync to avoid // possible deadlocks (e.g. BZ55524) when triggering the inbound // close as that will execute user code streamInbound.doOnClose(Constants23.getStatusClosedUnexpectedly()); throw ioe; } }
/** * Flush any message (binary or textual) that may be buffered and then send a WebSocket text * message as a single frame with the provided buffer as the payload of the message. * * @param msgCb The buffer containing the payload * @throws IOException If an error occurs writing to the client */ public void writeTextMessage(CharBuffer msgCb) throws IOException { try { synchronized (stateLock) { if (closed) { throw new IOException(sm.getString("outbound.closed")); } if (text != null) { // Empty the buffer flush(); } text = Boolean.TRUE; doWriteText(msgCb, true); } } catch (IOException ioe) { // Any IOException is terminal. Make sure the Inbound side knows // that something went wrong. // The exception handling needs to be outside of the sync to avoid // possible deadlocks (e.g. BZ55524) when triggering the inbound // close as that will execute user code streamInbound.doOnClose(Constants23.getStatusClosedUnexpectedly()); throw ioe; } }
/** * Flush any message (binary or textual) that may be buffered. * * @throws IOException If an error occurs writing to the client */ public void flush() throws IOException { try { synchronized (stateLock) { if (closed) { throw new IOException(sm.getString("outbound.closed")); } doFlush(true); } } catch (IOException ioe) { // Any IOException is terminal. Make sure the Inbound side knows // that something went wrong. // The exception handling needs to be outside of the sync to avoid // possible deadlocks (e.g. BZ55524) when triggering the inbound // close as that will execute user code streamInbound.doOnClose(Constants23.getStatusClosedUnexpectedly()); throw ioe; } }
/** * Send a close message to the client * * @param status Must be a valid status code or zero to send no code * @param data Optional message. If message is defined, a valid status code must be provided. * @throws IOException If an error occurs writing to the client */ public void close(int status, ByteBuffer data) throws IOException { try { synchronized (stateLock) { if (closed) { return; } // Send any partial data we have try { doFlush(false); } finally { closed = true; } upgradeOutbound.write(0x88); if (status == 0) { upgradeOutbound.write(0); } else if (data == null || data.position() == data.limit()) { upgradeOutbound.write(2); upgradeOutbound.write(status >>> 8); upgradeOutbound.write(status); } else { upgradeOutbound.write(2 + data.limit() - data.position()); upgradeOutbound.write(status >>> 8); upgradeOutbound.write(status); upgradeOutbound.write(data.array(), data.position(), data.limit() - data.position()); } upgradeOutbound.flush(); bb = null; cb = null; upgradeOutbound = null; } } catch (IOException ioe) { // Any IOException is terminal. Make sure the Inbound side knows // that something went wrong. // The exception handling needs to be outside of the sync to avoid // possible deadlocks (e.g. BZ55524) when triggering the inbound // close as that will execute user code streamInbound.doOnClose(Constants23.getStatusClosedUnexpectedly()); throw ioe; } }