@Test public void iternext() { Iternext dut = new Iternext(transcoder, transcoder); ChannelBuffer request = ChannelBuffers.buffer(2); request.writeBytes(new byte[] {(byte) 0xC8, (byte) 0x51}); ChannelBuffer actual = ChannelBuffers.buffer(request.capacity()); dut.encode(actual); assertEquals(request, actual); ChannelBuffer response = ChannelBuffers.buffer(1 + 4 + value.length); assertFalse(dut.decode(response)); response.writeByte(BinaryCommand.ESUCCESS); assertFalse(dut.decode(response)); response.resetReaderIndex(); response.writeInt(value.length); response.writeBytes(value); assertTrue(dut.decode(response)); assertArrayEquals(value, (byte[]) dut.getReturnValue()); // error response.clear(); response.writeByte(BinaryCommand.EUNKNOWN); assertTrue(dut.decode(response)); assertNull(dut.getReturnValue()); }
@Test public void setmst() { String host = "host"; int port = 1978; long timestamp = System.currentTimeMillis(); int opts = RDB.ROCHKCON; Setmst dut = new Setmst(host, port, timestamp, opts); ChannelBuffer request = ChannelBuffers.buffer(2 + 4 + 4 + 8 + 4 + host.getBytes().length); request.writeBytes(new byte[] {(byte) 0xC8, (byte) 0x78}); request.writeInt(host.getBytes().length); request.writeInt(port); request.writeLong(timestamp); request.writeInt(opts); request.writeBytes(host.getBytes()); ChannelBuffer actual = ChannelBuffers.buffer(request.capacity()); dut.encode(actual); assertEquals(request, actual); ChannelBuffer response = ChannelBuffers.buffer(1); assertFalse(dut.decode(response)); response.writeByte(Command.ESUCCESS); assertTrue(dut.decode(response)); assertTrue(dut.getReturnValue()); // error response.clear(); response.writeByte(Command.EUNKNOWN); assertTrue(dut.decode(response)); assertFalse(dut.getReturnValue()); }
/** * 自动缩小超长的帧数据缓存 * * @param ctx * @return */ protected void shrinkCumulation(ChannelHandlerContext ctx) { ChannelBuffer c = cumulation; if (this.cumulation != null) { if (cumulation.readableBytes() < this.minShrinkCapacity && cumulation.capacity() > this.minShrinkCapacity) { c = ChannelBuffers.dynamicBuffer( this.minShrinkCapacity, ctx.getChannel().getConfig().getBufferFactory()); c.writeBytes(cumulation); this.cumulation = c; } } }
public void handleJsRequest(String path, HttpRequest req, HttpResponse resp) { if (req.containsHeader(IF_NONE_MATCH) || req.containsHeader(IF_MODIFIED_SINCE)) { resp.setStatus(HttpResponseStatus.NOT_MODIFIED); return; } String jsName = path.substring(1); ChannelBuffer buf = jsBufferMap.get(jsName); if (buf == null) { tryReloadJs(); if (jsName == null) { log.error("需要访问的JS名称为空。[req: " + req.getUri() + "]"); } buf = jsBufferMap.get(jsName); } if (buf != null) { resp.setContent(buf); resp.setHeader(CONTENT_LENGTH, buf.capacity()); resp.setHeader(CONTENT_TYPE, "text/javascript; charset=UTF-8"); resp.setHeader(CONTENT_ENCODING, "gzip"); // resp.setHeader(EXPIRES, System.currentTimeMillis() + expired); StringBuilder etagBuilder = new StringBuilder("W/\"") .append(buf.capacity()) .append("-") .append(System.currentTimeMillis()) .append("\""); resp.setHeader(ETAG, etagBuilder.toString()); LogRequestParser lrp = logRequestParserThreadLocal.get(); if (lrp == null) { lrp = new LogRequestParser(); } lrp.cdate.setTime(System.currentTimeMillis() + expired); resp.setHeader(EXPIRES, lrp.sdf.format(lrp.cdate)); } else { resp.setStatus(HttpResponseStatus.NOT_FOUND); } }
/** * From the current context (currentBuffer and currentData), returns the next HttpChunk (if * possible) trying to get sizeleft bytes more into the currentBuffer. This is the Multipart * version. * * @param sizeleft the number of bytes to try to get from currentData * @return the next HttpChunk or null if not enough bytes were found * @throws ErrorDataEncoderException if the encoding is in error */ private HttpChunk encodeNextChunkMultipart(int sizeleft) throws ErrorDataEncoderException { if (currentData == null) { return null; } ChannelBuffer buffer; if (currentData instanceof InternalAttribute) { String internal = ((InternalAttribute) currentData).toString(); byte[] bytes; try { bytes = internal.getBytes("ASCII"); } catch (UnsupportedEncodingException e) { throw new ErrorDataEncoderException(e); } buffer = ChannelBuffers.wrappedBuffer(bytes); currentData = null; } else { if (currentData instanceof Attribute) { try { buffer = ((Attribute) currentData).getChunk(sizeleft); } catch (IOException e) { throw new ErrorDataEncoderException(e); } } else { try { buffer = ((FileUpload) currentData).getChunk(sizeleft); } catch (IOException e) { throw new ErrorDataEncoderException(e); } } if (buffer.capacity() == 0) { // end for current InterfaceHttpData, need more data currentData = null; return null; } } if (currentBuffer == null) { currentBuffer = buffer; } else { currentBuffer = ChannelBuffers.wrappedBuffer(currentBuffer, buffer); } if (currentBuffer.readableBytes() < HttpPostBodyUtil.chunkSize) { currentData = null; return null; } buffer = fillChannelBuffer(); return new DefaultHttpChunk(buffer); }
/** * Decodes bytes from a channel buffer * * @param ctx a channel handler context * @param channel a channel * @param msg a message * @return a byte array */ @Override protected Object decode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception { if (!(msg instanceof ChannelBuffer)) { return msg; } ChannelBuffer buf = (ChannelBuffer) msg; byte[] array; if (buf.hasArray()) { if (buf.arrayOffset() == 0 && buf.readableBytes() == buf.capacity()) { array = buf.array(); } else { array = new byte[buf.readableBytes()]; buf.getBytes(0, array); } } else { array = new byte[buf.readableBytes()]; buf.getBytes(0, array); } return array; }
@SuppressWarnings("unchecked") @Override protected Object encode(ChannelHandlerContext ctx, Channel c, Object msg) throws Exception { if (msg instanceof Message) { Message message = (Message) msg; Class<? extends Message> clazz = message.getClass(); MessageCodec<Message> codec = (MessageCodec<Message>) CodecLookupService.find(clazz); if (codec == null) { throw new IOException("Unknown message type: " + clazz + "."); } ChannelBuffer opcodeBuf = ChannelBuffers.buffer(3); opcodeBuf.writeByte(codec.getOpcode()); ChannelBuffer codecBuf = codec.encode(message); opcodeBuf.writeInt(codecBuf.capacity()); return ChannelBuffers.wrappedBuffer(opcodeBuf, codecBuf); } return msg; }
@Test public void protocol() { double num = 4; Adddouble dut = new Adddouble(transcoder, transcoder, key, num); ChannelBuffer request = ChannelBuffers.buffer(2 + 4 + 8 + 8 + key.length); request.writeBytes(new byte[] {(byte) 0xC8, (byte) 0x61}); request.writeInt(key.length); request.writeLong(dut._integ(num)); request.writeLong(dut._fract(num)); request.writeBytes(key); ChannelBuffer actual = ChannelBuffers.buffer(request.capacity()); dut.encode(actual); assertEquals(request, actual); ChannelBuffer response = ChannelBuffers.buffer(1 + 8 + 8); assertFalse(dut.decode(response)); response.writeByte(Command.ESUCCESS); assertFalse(dut.decode(response)); response.resetReaderIndex(); response.writeLong(dut._integ(3.0 + num)); assertFalse(dut.decode(response)); response.resetReaderIndex(); response.writeLong(dut._fract(3.0 + num)); assertTrue(dut.decode(response)); assertEquals(3.0 + num, (double) dut.getReturnValue(), 0.0); // error response.clear(); response.writeByte(Command.EUNKNOWN); assertTrue(dut.decode(response)); assertEquals(Double.NaN, (double) dut.getReturnValue(), 0.0); }
private ChannelBuffer unwrap( ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer, int offset, int length) throws SSLException { ByteBuffer inNetBuf = buffer.toByteBuffer(offset, length); ByteBuffer outAppBuf = bufferPool.acquire(); try { boolean needsWrap = false; loop: for (; ; ) { SSLEngineResult result; synchronized (handshakeLock) { if (!handshaken && !handshaking && !engine.getUseClientMode() && !engine.isInboundDone() && !engine.isOutboundDone()) { handshake(); } try { result = engine.unwrap(inNetBuf, outAppBuf); } catch (SSLException e) { throw e; } final HandshakeStatus handshakeStatus = result.getHandshakeStatus(); handleRenegotiation(handshakeStatus); switch (handshakeStatus) { case NEED_UNWRAP: if (inNetBuf.hasRemaining() && !engine.isInboundDone()) { break; } else { break loop; } case NEED_WRAP: wrapNonAppData(ctx, channel); break; case NEED_TASK: runDelegatedTasks(); break; case FINISHED: setHandshakeSuccess(channel); needsWrap = true; break loop; case NOT_HANDSHAKING: needsWrap = true; break loop; default: throw new IllegalStateException("Unknown handshake status: " + handshakeStatus); } } } if (needsWrap) { // wrap() acquires pendingUnencryptedWrites first and then // handshakeLock. If handshakeLock is already hold by the // current thread, calling wrap() will lead to a dead lock // i.e. pendingUnencryptedWrites -> handshakeLock vs. // handshakeLock -> pendingUnencryptedLock -> handshakeLock // // There is also a same issue between pendingEncryptedWrites // and pendingUnencryptedWrites. if (!Thread.holdsLock(handshakeLock) && !pendingEncryptedWritesLock.isHeldByCurrentThread()) { wrap(ctx, channel); } } outAppBuf.flip(); if (outAppBuf.hasRemaining()) { ChannelBuffer frame = ChannelBuffers.buffer(outAppBuf.remaining()); frame.writeBytes(outAppBuf.array(), 0, frame.capacity()); return frame; } else { return null; } } catch (SSLException e) { setHandshakeFailure(channel, e); throw e; } finally { bufferPool.release(outAppBuf); } }
private ChannelFuture wrapNonAppData(ChannelHandlerContext ctx, Channel channel) throws SSLException { ChannelFuture future = null; ByteBuffer outNetBuf = bufferPool.acquire(); SSLEngineResult result; try { for (; ; ) { synchronized (handshakeLock) { result = engine.wrap(EMPTY_BUFFER, outNetBuf); } if (result.bytesProduced() > 0) { outNetBuf.flip(); ChannelBuffer msg = ChannelBuffers.buffer(outNetBuf.remaining()); msg.writeBytes(outNetBuf.array(), 0, msg.capacity()); outNetBuf.clear(); future = future(channel); future.addListener( new ChannelFutureListener() { public void operationComplete(ChannelFuture future) throws Exception { if (future.getCause() instanceof ClosedChannelException) { synchronized (ignoreClosedChannelExceptionLock) { ignoreClosedChannelException++; } } } }); write(ctx, future, msg); } final HandshakeStatus handshakeStatus = result.getHandshakeStatus(); handleRenegotiation(handshakeStatus); switch (handshakeStatus) { case FINISHED: setHandshakeSuccess(channel); runDelegatedTasks(); break; case NEED_TASK: runDelegatedTasks(); break; case NEED_UNWRAP: if (!Thread.holdsLock(handshakeLock)) { // unwrap shouldn't be called when this method was // called by unwrap - unwrap will keep running after // this method returns. unwrap(ctx, channel, ChannelBuffers.EMPTY_BUFFER, 0, 0); } break; case NOT_HANDSHAKING: case NEED_WRAP: break; default: throw new IllegalStateException("Unexpected handshake status: " + handshakeStatus); } if (result.bytesProduced() == 0) { break; } } } catch (SSLException e) { setHandshakeFailure(channel, e); throw e; } finally { bufferPool.release(outNetBuf); } if (future == null) { future = succeededFuture(channel); } return future; }
private ChannelFuture wrap(ChannelHandlerContext context, Channel channel) throws SSLException { ChannelFuture future = null; ChannelBuffer msg; ByteBuffer outNetBuf = bufferPool.acquire(); boolean success = true; boolean offered = false; boolean needsUnwrap = false; try { loop: for (; ; ) { // Acquire a lock to make sure unencrypted data is polled // in order and their encrypted counterpart is offered in // order. synchronized (pendingUnencryptedWrites) { PendingWrite pendingWrite = pendingUnencryptedWrites.peek(); if (pendingWrite == null) { break; } ByteBuffer outAppBuf = pendingWrite.outAppBuf; if (outAppBuf == null) { // A write request with an empty buffer pendingUnencryptedWrites.remove(); offerEncryptedWriteRequest( new DownstreamMessageEvent( channel, pendingWrite.future, ChannelBuffers.EMPTY_BUFFER, channel.getRemoteAddress())); offered = true; } else { SSLEngineResult result = null; try { synchronized (handshakeLock) { result = engine.wrap(outAppBuf, outNetBuf); } } finally { if (!outAppBuf.hasRemaining()) { pendingUnencryptedWrites.remove(); } } if (result.bytesProduced() > 0) { outNetBuf.flip(); msg = ChannelBuffers.buffer(outNetBuf.remaining()); msg.writeBytes(outNetBuf.array(), 0, msg.capacity()); outNetBuf.clear(); if (pendingWrite.outAppBuf.hasRemaining()) { // pendingWrite's future shouldn't be notified if // only partial data is written. future = succeededFuture(channel); } else { future = pendingWrite.future; } MessageEvent encryptedWrite = new DownstreamMessageEvent(channel, future, msg, channel.getRemoteAddress()); offerEncryptedWriteRequest(encryptedWrite); offered = true; } else { final HandshakeStatus handshakeStatus = result.getHandshakeStatus(); handleRenegotiation(handshakeStatus); switch (handshakeStatus) { case NEED_WRAP: if (outAppBuf.hasRemaining()) { break; } else { break loop; } case NEED_UNWRAP: needsUnwrap = true; break loop; case NEED_TASK: runDelegatedTasks(); break; case FINISHED: case NOT_HANDSHAKING: if (handshakeStatus == HandshakeStatus.FINISHED) { setHandshakeSuccess(channel); } if (result.getStatus() == Status.CLOSED) { success = false; } break loop; default: throw new IllegalStateException("Unknown handshake status: " + handshakeStatus); } } } } } } catch (SSLException e) { success = false; setHandshakeFailure(channel, e); throw e; } finally { bufferPool.release(outNetBuf); if (offered) { flushPendingEncryptedWrites(context); } if (!success) { IllegalStateException cause = new IllegalStateException("SSLEngine already closed"); // Mark all remaining pending writes as failure if anything // wrong happened before the write requests are wrapped. // Please note that we do not call setFailure while a lock is // acquired, to avoid a potential dead lock. for (; ; ) { PendingWrite pendingWrite; synchronized (pendingUnencryptedWrites) { pendingWrite = pendingUnencryptedWrites.poll(); if (pendingWrite == null) { break; } } pendingWrite.future.setFailure(cause); } } } if (needsUnwrap) { unwrap(context, channel, ChannelBuffers.EMPTY_BUFFER, 0, 0); } if (future == null) { future = succeededFuture(channel); } return future; }
public static void main(String[] args) { final int payloadSize = 100; int CYCLE_SIZE = 50000; final long NUMBER_OF_ITERATIONS = 500000; ChannelBuffer message = ChannelBuffers.buffer(100); for (int i = 0; i < message.capacity(); i++) { message.writeByte((byte) i); } // Configure the server. ServerBootstrap serverBootstrap = new ServerBootstrap( new NioServerSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); // Set up the pipeline factory. serverBootstrap.setPipelineFactory( new ChannelPipelineFactory() { @Override public ChannelPipeline getPipeline() throws Exception { return Channels.pipeline(new EchoServerHandler()); } }); // Bind and start to accept incoming connections. serverBootstrap.bind(new InetSocketAddress(9000)); ClientBootstrap clientBootstrap = new ClientBootstrap( new NioClientSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); // ClientBootstrap clientBootstrap = new ClientBootstrap( // new OioClientSocketChannelFactory(Executors.newCachedThreadPool())); // Set up the pipeline factory. final EchoClientHandler clientHandler = new EchoClientHandler(); clientBootstrap.setPipelineFactory( new ChannelPipelineFactory() { @Override public ChannelPipeline getPipeline() throws Exception { return Channels.pipeline(clientHandler); } }); // Start the connection attempt. ChannelFuture future = clientBootstrap.connect(new InetSocketAddress("localhost", 9000)); future.awaitUninterruptibly(); Channel clientChannel = future.getChannel(); System.out.println("Warming up..."); for (long i = 0; i < 10000; i++) { clientHandler.latch = new CountDownLatch(1); clientChannel.write(message); try { clientHandler.latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("Warmed up"); long start = System.currentTimeMillis(); long cycleStart = System.currentTimeMillis(); for (long i = 1; i < NUMBER_OF_ITERATIONS; i++) { clientHandler.latch = new CountDownLatch(1); clientChannel.write(message); try { clientHandler.latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } if ((i % CYCLE_SIZE) == 0) { long cycleEnd = System.currentTimeMillis(); System.out.println( "Ran 50000, TPS " + (CYCLE_SIZE / ((double) (cycleEnd - cycleStart) / 1000))); cycleStart = cycleEnd; } } long end = System.currentTimeMillis(); long seconds = (end - start) / 1000; System.out.println( "Ran [" + NUMBER_OF_ITERATIONS + "] iterations, payload [" + payloadSize + "]: took [" + seconds + "], TPS: " + ((double) NUMBER_OF_ITERATIONS) / seconds); clientChannel.close().awaitUninterruptibly(); clientBootstrap.releaseExternalResources(); serverBootstrap.releaseExternalResources(); }
/** * From the current context (currentBuffer and currentData), returns the next HttpChunk (if * possible) trying to get sizeleft bytes more into the currentBuffer. This is the UrlEncoded * version. * * @param sizeleft the number of bytes to try to get from currentData * @return the next HttpChunk or null if not enough bytes were found * @throws ErrorDataEncoderException if the encoding is in error */ private HttpChunk encodeNextChunkUrlEncoded(int sizeleft) throws ErrorDataEncoderException { if (currentData == null) { return null; } int size = sizeleft; ChannelBuffer buffer; if (isKey) { // get name String key = currentData.getName(); buffer = ChannelBuffers.wrappedBuffer(key.getBytes()); isKey = false; if (currentBuffer == null) { currentBuffer = ChannelBuffers.wrappedBuffer(buffer, ChannelBuffers.wrappedBuffer("=".getBytes())); // continue size -= buffer.readableBytes() + 1; } else { currentBuffer = ChannelBuffers.wrappedBuffer( currentBuffer, buffer, ChannelBuffers.wrappedBuffer("=".getBytes())); // continue size -= buffer.readableBytes() + 1; } if (currentBuffer.readableBytes() >= HttpPostBodyUtil.chunkSize) { buffer = fillChannelBuffer(); return new DefaultHttpChunk(buffer); } } try { buffer = ((Attribute) currentData).getChunk(size); } catch (IOException e) { throw new ErrorDataEncoderException(e); } ChannelBuffer delimiter = null; if (buffer.readableBytes() < size) { // delimiter isKey = true; delimiter = iterator.hasNext() ? ChannelBuffers.wrappedBuffer("&".getBytes()) : null; } if (buffer.capacity() == 0) { // end for current InterfaceHttpData, need potentially more data currentData = null; if (currentBuffer == null) { currentBuffer = delimiter; } else { if (delimiter != null) { currentBuffer = ChannelBuffers.wrappedBuffer(currentBuffer, delimiter); } } if (currentBuffer.readableBytes() >= HttpPostBodyUtil.chunkSize) { buffer = fillChannelBuffer(); return new DefaultHttpChunk(buffer); } return null; } if (currentBuffer == null) { if (delimiter != null) { currentBuffer = ChannelBuffers.wrappedBuffer(buffer, delimiter); } else { currentBuffer = buffer; } } else { if (delimiter != null) { currentBuffer = ChannelBuffers.wrappedBuffer(currentBuffer, buffer, delimiter); } else { currentBuffer = ChannelBuffers.wrappedBuffer(currentBuffer, buffer); } } if (currentBuffer.readableBytes() < HttpPostBodyUtil.chunkSize) { // end for current InterfaceHttpData, need more data currentData = null; isKey = true; return null; } buffer = fillChannelBuffer(); // size = 0 return new DefaultHttpChunk(buffer); }