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 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 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() + ")"); } }