Ejemplo n.º 1
0
  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() + ")");
   }
 }