private void handleHTTP(OutPacketMessage msg, ChannelHandlerContext ctx, ChannelPromise promise) throws IOException { Channel channel = ctx.channel(); Attribute<Boolean> attr = channel.attr(WRITE_ONCE); Queue<Packet> queue = msg.getClientHead().getPacketsQueue(msg.getTransport()); if (!channel.isActive() || queue.isEmpty() || !attr.compareAndSet(null, true)) { promise.setSuccess(); return; } ByteBuf out = encoder.allocateBuffer(ctx.alloc()); Boolean b64 = ctx.channel().attr(EncoderHandler.B64).get(); if (b64 != null && b64) { Integer jsonpIndex = ctx.channel().attr(EncoderHandler.JSONP_INDEX).get(); encoder.encodeJsonP(jsonpIndex, queue, out, ctx.alloc(), 50); String type = "application/javascript"; if (jsonpIndex == null) { type = "text/plain"; } sendMessage(msg, channel, out, type, promise); } else { encoder.encodePackets(queue, out, ctx.alloc(), 50); sendMessage(msg, channel, out, "application/octet-stream", promise); } }
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 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); }
public boolean decode( ChannelHandlerContext ctx, final ByteBuf buf, InetSocketAddress recipient, final InetSocketAddress sender) { LOG.debug("Decoding of TomP2P starts now. Readable: {}.", buf.readableBytes()); try { final int readerBefore = buf.readerIndex(); // set the sender of this message for handling timeout final Attribute<InetSocketAddress> attributeInet = ctx.attr(INET_ADDRESS_KEY); attributeInet.set(sender); if (message == null && !headerDone) { headerDone = decodeHeader(buf, recipient, sender); if (headerDone) { // store the sender as an attribute final Attribute<PeerAddress> attributePeerAddress = ctx.attr(PEER_ADDRESS_KEY); attributePeerAddress.set(message.sender()); message.udp(ctx.channel() instanceof DatagramChannel); if (message.isFireAndForget() && message.isUdp()) { TimeoutFactory.removeTimeout(ctx); } } else { return false; } } final boolean donePayload = decodePayload(buf); decodeSignature(buf, readerBefore, donePayload); if (donePayload) { boolean isRelay = message.sender().isRelayed(); if (isRelay && !message.peerSocketAddresses().isEmpty()) { PeerAddress tmpSender = message.sender().changePeerSocketAddresses(message.peerSocketAddresses()); message.sender(tmpSender); } } // see https://github.com/netty/netty/issues/1976 buf.discardSomeReadBytes(); return donePayload; } catch (Exception e) { ctx.fireExceptionCaught(e); e.printStackTrace(); return 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 <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() + ")"); } }