All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fisco.bcos.channel.handler.ChannelHandler Maven / Gradle / Ivy

package org.fisco.bcos.channel.handler;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateEvent;
import java.util.concurrent.RejectedExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

public class ChannelHandler extends SimpleChannelInboundHandler {
  private static Logger logger = LoggerFactory.getLogger(ChannelHandler.class);

  @Override
  public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
    String host = ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress();
    Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort();

    if (evt instanceof IdleStateEvent) {
      IdleStateEvent e = (IdleStateEvent) evt;
      switch (e.state()) {
        case READER_IDLE:
        case WRITER_IDLE:
        case ALL_IDLE:
          logger.error(
              "event:{} connect{}:{} long time Inactive,disconnect", e.state(), host, port);
          channelInactive(ctx);
          ctx.disconnect();
          ctx.close();
          break;
        default:
          break;
      }
    }
  }

  @Override
  public void channelActive(ChannelHandlerContext ctx) throws Exception {
    try {
      // 已连上,获取ip信息
      String host = ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress();
      Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort();

      logger.debug(
          "success,connected["
              + host
              + "]:["
              + String.valueOf(port)
              + "],"
              + String.valueOf(ctx.channel().isActive()));

      if (isServer) {
        logger.debug("server accept new connect: {}:{}", host, port);
        // 将此新连接增加到connections
        ConnectionInfo info = new ConnectionInfo();
        info.setHost(host);
        info.setPort(port);

        connections.getConnections().add(info);
        connections.setNetworkConnectionByHost(info.getHost(), info.getPort(), ctx);
        connections.getCallback().onConnect(ctx);
      } else {
        // 更新ctx信息
        ChannelHandlerContext connection = connections.getNetworkConnectionByHost(host, port);
        if (connection != null && connection.channel().isActive()) {
          logger.debug("connect available, close reconnect: {}:{}", host, port);

          ctx.channel().disconnect();
          ctx.channel().close();
        } else {
          logger.debug("client connect success {}:{}", host, port);
          connections.setNetworkConnectionByHost(host, port, ctx);
          connections.getCallback().onConnect(ctx);
        }
      }
    } catch (Exception e) {
      logger.error("error", e);
    }
  }

  @Override
  public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    try {
      logger.debug("disconnect");
      // 已断连,获取ip信息
      String host = ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress();
      Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort();

      logger.debug(
          "disconnect "
              + host
              + ":"
              + String.valueOf(port)
              + " ,"
              + String.valueOf(ctx.channel().isActive()));

      if (isServer) {
        // server模式下,移除该connectionInfo
        for (Integer i = 0; i < connections.getConnections().size(); ++i) {
          ConnectionInfo info = connections.getConnections().get(i);

          if (info.getHost().equals(host) && info.getPort().equals(port)) {
            connections.getConnections().remove(i);
          }
        }

        // 移除该networkConnection
        connections.removeNetworkConnectionByHost(host, port);
      } else {
        // 无需将连接置为null
        // connections.setNetworkConnection(host, port, null);
      }

      connections.getCallback().onDisconnect(ctx);
    } catch (Exception e) {
      logger.error("error ", e);
    }
  }

  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) {
    String host = ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress();
    Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort();

    final ChannelHandlerContext ctxF = ctx;
    final ByteBuf in = (ByteBuf) msg;

    logger.trace("receive,from" + host + ":" + port + " in:" + in.readableBytes());
    logger.trace("threadPool:{}", threadPool == null);

    try {
      if (threadPool == null) {
        connections.onReceiveMessage(ctx, in);
      } else {
        threadPool.execute(
            new Runnable() {
              @Override
              public void run() {
                connections.onReceiveMessage(ctxF, in);
              }
            });
      }
    } catch (RejectedExecutionException e) {
      logger.error("threadPool is full,reject to request", e);
    }
  }

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
    logger.error("network error ", cause);
    // 已断连,获取ip信息
    String host = ((SocketChannel) ctx.channel()).remoteAddress().getAddress().getHostAddress();
    Integer port = ((SocketChannel) ctx.channel()).remoteAddress().getPort();

    logger.debug(
        "disconnect "
            + host
            + ":"
            + String.valueOf(port)
            + " ,"
            + String.valueOf(ctx.channel().isActive()));

    if (isServer) {
      // server模式下,移除该connection
      connections.removeNetworkConnectionByHost(host, port);
    } else {
      // 将该连接置为不可用
      // connections.setNetworkConnection(host, port, null);
    }

    ctx.disconnect();
    ctx.close();
  }

  @Override
  protected void channelRead0(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
    channelRead(ctx, in);
  }

  public void checkAvailable(ChannelHandlerContext ctx) {}

  public ChannelConnections getConnections() {
    return connections;
  }

  public void setConnections(ChannelConnections connections) {
    this.connections = connections;
  }

  public Boolean getIsServer() {
    return isServer;
  }

  public void setIsServer(Boolean isServer) {
    this.isServer = isServer;
  }

  public ThreadPoolTaskExecutor getThreadPool() {
    return threadPool;
  }

  public void setThreadPool(ThreadPoolTaskExecutor threadPool) {
    this.threadPool = threadPool;

    logger.debug("set threadPool:{}", threadPool == null);
  }

  private ChannelConnections connections;
  private Boolean isServer = false;
  private ThreadPoolTaskExecutor threadPool;
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy