private synchronized int expelBuffer(long blockFor) throws IOException { if (_buffer == null) return 0; int result = flushBuffer(); _buffer.compact(); if (!_endp.isBlocking()) { while (_buffer.space() == 0) { boolean ready = _endp.blockWritable(blockFor); if (!ready) throw new IOException("Write timeout"); result += flushBuffer(); _buffer.compact(); } } return result; }
public synchronized void addFrame(byte flags, byte opcode, byte[] content, int offset, int length) throws IOException { // System.err.printf("<< %s %s // %s\n",TypeUtil.toHexString(flags),TypeUtil.toHexString(opcode),length); long blockFor = _endp.getMaxIdleTime(); if (_buffer == null) _buffer = (_maskGen != null) ? _buffers.getBuffer() : _buffers.getDirectBuffer(); boolean last = WebSocketConnectionD06.isLastFrame(flags); opcode = (byte) (((0xf & flags) << 4) + 0xf & opcode); int space = (_maskGen != null) ? 14 : 10; do { opcode = _opsent ? WebSocketConnectionD06.OP_CONTINUATION : opcode; _opsent = true; int payload = length; if (payload + space > _buffer.capacity()) { // We must fragement, so clear FIN bit opcode &= (byte) 0x7F; // Clear the FIN bit payload = _buffer.capacity() - space; } else if (last) opcode |= (byte) 0x80; // Set the FIN bit // ensure there is space for header if (_buffer.space() <= space) expelBuffer(blockFor); // write mask if ((_maskGen != null)) { _maskGen.genMask(_mask); _m = 0; _buffer.put(_mask); } // write the opcode and length if (payload > 0xffff) { bufferPut( new byte[] { opcode, (byte) 0x7f, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) ((payload >> 24) & 0xff), (byte) ((payload >> 16) & 0xff), (byte) ((payload >> 8) & 0xff), (byte) (payload & 0xff) }); } else if (payload >= 0x7e) { bufferPut(new byte[] {opcode, (byte) 0x7e, (byte) (payload >> 8), (byte) (payload & 0xff)}); } else { bufferPut(opcode); bufferPut((byte) payload); } // write payload int remaining = payload; while (remaining > 0) { _buffer.compact(); int chunk = remaining < _buffer.space() ? remaining : _buffer.space(); if ((_maskGen != null)) { for (int i = 0; i < chunk; i++) bufferPut(content[offset + (payload - remaining) + i]); } else _buffer.put(content, offset + (payload - remaining), chunk); remaining -= chunk; if (_buffer.space() > 0) { // Gently flush the data, issuing a non-blocking write flushBuffer(); } else { // Forcibly flush the data, issuing a blocking write expelBuffer(blockFor); if (remaining == 0) { // Gently flush the data, issuing a non-blocking write flushBuffer(); } } } offset += payload; length -= payload; } while (length > 0); _opsent = !last; }