private void send(final ByteBuf buffer) throws Exception { DefaultFullHttpResponse rsp = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, buffer); if (!headers.contains(HttpHeaderNames.CONTENT_LENGTH)) { headers .remove(HttpHeaderNames.TRANSFER_ENCODING) .set(HttpHeaderNames.CONTENT_LENGTH, buffer.readableBytes()); } if (keepAlive) { headers.set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE); } // dump headers rsp.headers().set(headers); Attribute<Boolean> async = ctx.attr(NettyRequest.ASYNC); boolean isAsync = async != null && async.get() == Boolean.TRUE; if (isAsync) { // we need flush, from async keepAlive(ctx.writeAndFlush(rsp)); } else { keepAlive(ctx.write(rsp)); } committed = true; }
@Override public void end() { if (ctx != null) { Attribute<NettyWebSocket> ws = ctx.attr(NettyWebSocket.KEY); if (ws != null && ws.get() != null) { status = HttpResponseStatus.SWITCHING_PROTOCOLS; ws.get().hankshake(); ctx = null; committed = true; return; } if (!committed) { DefaultHttpResponse rsp = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status); // dump headers rsp.headers().set(headers); keepAlive(ctx.write(rsp)); } committed = true; ctx = null; } }
@Override public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception { long size = calculateSize(msg); long curtime = System.currentTimeMillis(); if (trafficCounter != null) { trafficCounter.bytesRecvFlowControl(size); if (readLimit == 0) { // no action ctx.fireChannelRead(msg); return; } // compute the number of ms to wait before reopening the channel long wait = getTimeToWait( readLimit, trafficCounter.currentReadBytes(), trafficCounter.lastTime(), curtime); if (wait >= MINIMAL_WAIT) { // At least 10ms seems a minimal // time in order to // try to limit the traffic if (!isSuspended(ctx)) { ctx.attr(READ_SUSPENDED).set(true); // Create a Runnable to reactive the read if needed. If one was create before it will just // be // reused to limit object creation Attribute<Runnable> attr = ctx.attr(REOPEN_TASK); Runnable reopenTask = attr.get(); if (reopenTask == null) { reopenTask = new ReopenReadTimerTask(ctx); attr.set(reopenTask); } ctx.executor().schedule(reopenTask, wait, TimeUnit.MILLISECONDS); } else { // Create a Runnable to update the next handler in the chain. If one was create before it // will // just be reused to limit object creation Runnable bufferUpdateTask = new Runnable() { @Override public void run() { ctx.fireChannelRead(msg); } }; ctx.executor().schedule(bufferUpdateTask, wait, TimeUnit.MILLISECONDS); return; } } } ctx.fireChannelRead(msg); }
@Override public <X> X getAttribute(String key, Class<X> clz) { AttributeKey<X> attributeKey = AttributeKey.valueOf(key); Attribute<X> attribute = channel.attr(attributeKey); return attribute == null ? null : attribute.get(); }
@Override public void handle(NetworkContext context, MessageForgeHandshakeInOutAck message) { Session session = context.getSession(); Attribute<ForgeServerHandshakePhase> phase = context.getChannel().attr(ForgeHandshakePhase.PHASE); switch (phase.get()) { case WAITING_ACK: if (!message.getPhase().equals(ForgeClientHandshakePhase.WAITING_SERVER_DATA)) { session.disconnect( "Retrieved unexpected forge handshake ack message. (Got " + message.getPhase() + ", expected " + ForgeClientHandshakePhase.WAITING_SERVER_DATA + ")"); } else { List<MessageForgeHandshakeOutRegistryData.Entry> entries = Lists.newArrayList(); entries.add( new MessageForgeHandshakeOutRegistryData.Entry( "fml:items", Maps.newHashMap(), Lists.newArrayList())); entries.add( new MessageForgeHandshakeOutRegistryData.Entry( "fml:blocks", Maps.newHashMap(), Lists.newArrayList())); session.send(new MessageForgeHandshakeOutRegistryData(entries)); session.send(new MessageForgeHandshakeInOutAck(ForgeServerHandshakePhase.WAITING_ACK)); phase.set(ForgeServerHandshakePhase.COMPLETE); } LanternGame.log() .info( "{}: Forge handshake -> Received ack (waitingServerData) message.", session.getGameProfile().getName()); break; case COMPLETE: if (!message.getPhase().equals(ForgeClientHandshakePhase.WAITING_SERVER_COMPLETE)) { session.disconnect( "Retrieved unexpected forge handshake ack message. (Got " + message.getPhase() + ", expected " + ForgeClientHandshakePhase.WAITING_SERVER_COMPLETE + ")"); } else { session.send(new MessageForgeHandshakeInOutAck(ForgeServerHandshakePhase.COMPLETE)); phase.set(ForgeServerHandshakePhase.DONE); } LanternGame.log() .info( "{}: Forge handshake -> Received ack (waitingServerComplete) message.", session.getGameProfile().getName()); break; case DONE: if (!message.getPhase().equals(ForgeClientHandshakePhase.PENDING_COMPLETE) && !message.getPhase().equals(ForgeClientHandshakePhase.COMPLETE)) { session.disconnect( "Retrieved unexpected forge handshake ack message. (Got " + message.getPhase() + ", expected " + ForgeClientHandshakePhase.PENDING_COMPLETE + " or " + ForgeClientHandshakePhase.COMPLETE + ")"); } else { if (message.getPhase().equals(ForgeClientHandshakePhase.PENDING_COMPLETE)) { session.send(new MessageForgeHandshakeInOutAck(ForgeServerHandshakePhase.DONE)); LanternGame.log() .info( "{}: Forge handshake -> Received ack (pendingComplete) message.", session.getGameProfile().getName()); } else { session.setProtocolState(ProtocolState.PLAY); session.spawnPlayer(); LanternGame.log() .info( "{}: Forge handshake -> Received ack (complete) message.", session.getGameProfile().getName()); } } break; case ERROR: break; default: session.disconnect( "Retrieved unexpected forge handshake ack message. (Got " + message.getPhase() + ")"); } }