public synchronized void addFrame(byte flags, byte opcode, byte[] content, int offset, int length) throws IOException { long blockFor = _endp.getMaxIdleTime(); if (_buffer == null) _buffer = _buffers.getDirectBuffer(); if (_buffer.space() == 0) expelBuffer(blockFor); bufferPut(opcode, blockFor); if (isLengthFrame(opcode)) { // Send a length delimited frame // How many bytes we need for the length ? // We have 7 bits available, so log2(length) / 7 + 1 // For example, 50000 bytes is 2 8-bytes: 11000011 01010000 // but we need to write it in 3 7-bytes 0000011 0000110 1010000 // 65536 == 1 00000000 00000000 => 100 0000000 0000000 int lengthBytes = new BigInteger(String.valueOf(length)).bitLength() / 7 + 1; for (int i = lengthBytes - 1; i > 0; --i) { byte lengthByte = (byte) (0x80 | (0x7F & (length >> 7 * i))); bufferPut(lengthByte, blockFor); } bufferPut((byte) (0x7F & length), blockFor); } int remaining = length; while (remaining > 0) { int chunk = remaining < _buffer.space() ? remaining : _buffer.space(); _buffer.put(content, offset + (length - remaining), chunk); remaining -= chunk; if (_buffer.space() > 0) { if (!isLengthFrame(opcode)) _buffer.put((byte) 0xFF); // Gently flush the data, issuing a non-blocking write flushBuffer(); } else { // Forcibly flush the data, issuing a blocking write expelBuffer(blockFor); if (remaining == 0) { if (!isLengthFrame(opcode)) _buffer.put((byte) 0xFF); // Gently flush the data, issuing a non-blocking write flushBuffer(); } } } }
@Test public void testReuse() throws Exception { HttpFields header = new HttpFields(); Buffer n1 = new ByteArrayBuffer("name1"); Buffer va = new ByteArrayBuffer("value1"); Buffer vb = new ByteArrayBuffer(10); vb.put((byte) 'v'); vb.put((byte) 'a'); vb.put((byte) 'l'); vb.put((byte) 'u'); vb.put((byte) 'e'); vb.put((byte) '1'); header.put("name0", "value0"); header.put(n1, va); header.put("name2", "value2"); assertEquals("value0", header.getStringField("name0")); assertEquals("value1", header.getStringField("name1")); assertEquals("value2", header.getStringField("name2")); assertNull(header.getStringField("name3")); header.remove(n1); assertNull(header.getStringField("name1")); header.put(n1, vb); assertEquals("value1", header.getStringField("name1")); int matches = 0; Enumeration e = header.getFieldNames(); while (e.hasMoreElements()) { Object o = e.nextElement(); if ("name0".equals(o)) matches++; if ("name1".equals(o)) matches++; if ("name2".equals(o)) matches++; } assertEquals(3, matches); e = header.getValues("name1"); assertEquals(true, e.hasMoreElements()); assertEquals(e.nextElement(), "value1"); assertEquals(false, e.hasMoreElements()); }
/* ------------------------------------------------------------ */ public void putTo(Buffer buffer) throws IOException { int o = (_name instanceof CachedBuffer) ? ((CachedBuffer) _name).getOrdinal() : -1; if (o >= 0) buffer.put(_name); else { int s = _name.getIndex(); int e = _name.putIndex(); while (s < e) { byte b = _name.peek(s++); switch (b) { case '\r': case '\n': case ':': continue; default: buffer.put(b); } } } buffer.put((byte) ':'); buffer.put((byte) ' '); o = (_value instanceof CachedBuffer) ? ((CachedBuffer) _value).getOrdinal() : -1; if (o >= 0) buffer.put(_value); else { int s = _value.getIndex(); int e = _value.putIndex(); while (s < e) { byte b = _value.peek(s++); switch (b) { case '\r': case '\n': continue; default: buffer.put(b); } } } BufferUtil.putCRLF(buffer); }
private synchronized void bufferPut(byte datum, long blockFor) throws IOException { if (_buffer == null) _buffer = _buffers.getDirectBuffer(); _buffer.put(datum); if (_buffer.space() == 0) expelBuffer(blockFor); }
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; }
private synchronized void bufferPut(byte data) throws IOException { _buffer.put((byte) (data ^ _mask[+_m++ % 4])); }
private synchronized void bufferPut(byte[] data) throws IOException { if (_maskGen != null) for (int i = 0; i < data.length; i++) data[i] ^= _mask[+_m++ % 4]; _buffer.put(data); }