Ejemplo n.º 1
0
 @Override
 public final boolean trySend(WebDataMessage message) {
   if (!message.isBinary()) ctx.writeAndFlush(new TextWebSocketFrame(message.getStringBody()));
   else
     ctx.writeAndFlush(
         new BinaryWebSocketFrame(Unpooled.wrappedBuffer(message.getByteBufferBody())));
   return true;
 }
Ejemplo n.º 2
0
  private void handleBlockRequest(final ChannelHandlerContext ctx, final RPCBlockRequest req)
      throws IOException {
    final long blockId = req.getBlockId();
    final long offset = req.getOffset();
    final long len = req.getLength();
    long lockId;
    try {
      // zd add logInfo
      LOG.info("Preparation for responding to remote block request for: " + blockId);
      lockId = mDataManager.lockBlock(Users.DATASERVER_USER_ID, blockId);
    } catch (IOException ioe) {
      LOG.error("Failed to lock block: " + blockId, ioe);
      RPCBlockResponse resp =
          RPCBlockResponse.createErrorResponse(req, RPCResponse.Status.BLOCK_LOCK_ERROR);
      ChannelFuture future = ctx.writeAndFlush(resp);
      future.addListener(ChannelFutureListener.CLOSE);
      return;
    }

    BlockReader reader = mDataManager.readBlockRemote(Users.DATASERVER_USER_ID, blockId, lockId);
    try {
      req.validate();
      final long fileLength = reader.getLength();
      validateBounds(req, fileLength);
      final long readLength = returnLength(offset, len, fileLength);
      RPCBlockResponse resp =
          new RPCBlockResponse(
              blockId,
              offset,
              readLength,
              getDataBuffer(req, reader, readLength),
              RPCResponse.Status.SUCCESS);
      ChannelFuture future = ctx.writeAndFlush(resp);
      future.addListener(ChannelFutureListener.CLOSE);
      future.addListener(new ClosableResourceChannelListener(reader));
      mDataManager.accessBlock(Users.DATASERVER_USER_ID, blockId);
      LOG.info("Preparation for responding to remote block request for: " + blockId + " done.");
    } catch (Exception e) {
      LOG.error("The file is not here : " + e.getMessage(), e);
      RPCBlockResponse resp =
          RPCBlockResponse.createErrorResponse(req, RPCResponse.Status.FILE_DNE);
      ChannelFuture future = ctx.writeAndFlush(resp);
      future.addListener(ChannelFutureListener.CLOSE);
      if (reader != null) {
        reader.close();
      }
    } finally {
      mDataManager.unlockBlock(lockId);
    }
  }
  public void finish() throws IOException {
    os.flush();
    ChannelFuture future;
    if (isCommitted()) {
      // if committed this means the output stream was used.
      future = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
    } else {
      future = ctx.writeAndFlush(getEmptyHttpResponse());
    }

    if (!isKeepAlive()) {
      future.addListener(ChannelFutureListener.CLOSE);
    }
  }
Ejemplo n.º 4
0
 @Override
 protected void doMessageReceived(ClientConnection conn, ChannelHandlerContext ctx, Object msg) {
   if (conn == null || conn.isClosed()) {
     return;
   }
   boolean valid = false;
   if (msg instanceof HttpResponse) {
     HttpResponse response = (HttpResponse) msg;
     conn.handleResponse(response);
     valid = true;
   }
   if (msg instanceof HttpContent) {
     HttpContent chunk = (HttpContent) msg;
     if (chunk.content().isReadable()) {
       Buffer buff = new Buffer(chunk.content().slice());
       conn.handleResponseChunk(buff);
     }
     if (chunk instanceof LastHttpContent) {
       conn.handleResponseEnd((LastHttpContent) chunk);
     }
     valid = true;
   } else if (msg instanceof WebSocketFrame) {
     WebSocketFrame frame = (WebSocketFrame) msg;
     switch (frame.getType()) {
       case BINARY:
       case TEXT:
         conn.handleWsFrame(frame);
         break;
       case PING:
         // Echo back the content of the PING frame as PONG frame as specified in RFC 6455
         // Section 5.5.2
         ctx.writeAndFlush(
             new DefaultWebSocketFrame(WebSocketFrame.FrameType.PONG, frame.getBinaryData()));
         break;
       case CLOSE:
         if (!closeFrameSent) {
           // Echo back close frame and close the connection once it was written.
           // This is specified in the WebSockets RFC 6455 Section  5.4.1
           ctx.writeAndFlush(frame).addListener(ChannelFutureListener.CLOSE);
           closeFrameSent = true;
         }
         break;
     }
     valid = true;
   }
   if (!valid) {
     throw new IllegalStateException("Invalid object " + msg);
   }
 }
Ejemplo n.º 5
0
  private void broadCast(ChannelHandlerContext ctx, String request) {
    String response = ManageSql(request.split(DELIMITER));

    response += DELIMITER;
    System.out.println("보내는 Data : " + response);
    ctx.writeAndFlush(Unpooled.copiedBuffer(response, CharsetUtil.UTF_8));
  }
  @Override
  public void sendError(int status, String message) throws IOException {
    if (committed) {
      throw new IllegalStateException();
    }

    final HttpResponseStatus responseStatus;
    if (message != null) {
      responseStatus = new HttpResponseStatus(status, message);
      setStatus(status);
    } else {
      responseStatus = HttpResponseStatus.valueOf(status);
      setStatus(status);
    }
    io.netty.handler.codec.http.HttpResponse response = null;
    if (message != null) {
      ByteBuf byteBuf = ctx.alloc().buffer();
      byteBuf.writeBytes(message.getBytes());

      response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, responseStatus, byteBuf);
    } else {
      response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, responseStatus);
    }
    if (keepAlive) {
      // Add keep alive and content length if needed
      response.headers().add(Names.CONNECTION, Values.KEEP_ALIVE);
      if (message == null) response.headers().add(Names.CONTENT_LENGTH, 0);
      else response.headers().add(Names.CONTENT_LENGTH, message.getBytes().length);
    }
    ctx.writeAndFlush(response);
    committed = true;
  }
  /**
   * Here we take in the message and respond with the appropriate message If we only have have
   * message defined, then we respond with this.message If we have messageMap defined, then see if
   * msg.message exists in messageMap, and respond with the value
   */
  @Override
  public void channelRead0(ChannelHandlerContext ctx, messageObject msg) {
    logger.info("Handling incoming message");
    String toSend = "";

    // If messageMap is null, then we only have the simple message to send
    if (null == this.messageMap) {
      logger.info("Using simple message");
      toSend = this.message;
    }
    // Otherwise figure out if messageMap has the key that's been sent in
    else {
      // If the map contains that key, broadcast the value
      if (this.messageMap.containsKey(msg.message)) {
        logger.info("Returning info for key:" + msg.message);
        toSend = this.messageMap.get(msg.message);
      }
      // Return ERROR if the key doesn't exist
      else {
        logger.info("key not found in message map: " + msg.message);
        toSend = "ERROR";
      }
    }

    logger.info("Packet payload is:" + toSend);
    ctx.writeAndFlush(
        new DatagramPacket(Unpooled.copiedBuffer(toSend, CharsetUtil.UTF_8), msg.address));
  }
Ejemplo n.º 8
0
  public void sendError() {
    if (request == null
        || status == null
        || shortDescription == null
        || detailedDescription == null
        || version == null
        || status == null) throw new IllegalStateException();

    StringBuffer sb = new StringBuffer();
    sb.append("Error ").append(status.code()).append(": ").append(shortDescription);
    sb.append("\n\n");
    sb.append(detailedDescription);
    sb.append("\n\n");
    sb.append("Request:\n").append(request.getUri());
    sb.append("\n\n");
    sb.append("Request Submitted:\n").append(FdsnwsDate.toString(new Date()));
    sb.append("\n\n");
    sb.append("Service version:\n").append(version);
    String html = sb.toString();

    FullHttpResponse response =
        new DefaultFullHttpResponse(
            request.getProtocolVersion(),
            status,
            Unpooled.copiedBuffer(html, Charset.forName("UTF-8")));
    response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, html.length());
    response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/plain; charset=UTF-8");

    if (HttpHeaders.isKeepAlive(request)) {
      response.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
    }
    ctx.writeAndFlush(response);
  }
Ejemplo n.º 9
0
 @Override
 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
   LOG.debug("Error ", cause);
   DefaultHttpResponse resp = ExceptionHandler.exceptionCaught(cause);
   resp.headers().set(CONNECTION, CLOSE);
   ctx.writeAndFlush(resp).addListener(ChannelFutureListener.CLOSE);
 }
  @Override
  public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
    System.out.println("Client Channel Registered");

    ctx.writeAndFlush(firstMessage);
    super.channelRegistered(ctx);
  }
Ejemplo n.º 11
0
  private void generateTraffic() {
    // Flush the outbound buffer to the socket.
    // Once flushed, generate the same amount of traffic again.
    ctx.writeAndFlush(content.duplicate().retain()).addListener(trafficGenerator);

    this.round++;
  }
Ejemplo n.º 12
0
 @Override
 public void channelActive(ChannelHandlerContext ctx) throws Exception {
   // TODO Auto-generated method stub
   System.out.println("RamoteAddress : " + ctx.channel().remoteAddress() + " active!");
   ctx.writeAndFlush("Welcome to " + InetAddress.getLocalHost().getHostName() + " service !\n");
   super.channelActive(ctx);
 }
Ejemplo n.º 13
0
  @Override
  public void send(final FileChannel channel) throws Exception {
    long len = channel.size();

    DefaultHttpResponse rsp = new DefaultHttpResponse(HttpVersion.HTTP_1_1, status);
    if (!headers.contains(HttpHeaderNames.CONTENT_LENGTH)) {
      headers.remove(HttpHeaderNames.TRANSFER_ENCODING);
      headers.set(HttpHeaderNames.CONTENT_LENGTH, len);
    }

    if (keepAlive) {
      headers.set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
    }

    // dump headers
    rsp.headers().set(headers);
    ChannelHandlerContext ctx = this.ctx;
    ctx.attr(NettyRequest.NEED_FLUSH).set(false);
    ctx.channel()
        .eventLoop()
        .execute(
            () -> {
              // send headers
              ctx.write(rsp);
              ctx.write(new DefaultFileRegion(channel, 0, len));
              keepAlive(ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT));
            });

    committed = true;
  }
  /**
   * When file timestamp is the same as what the browser is sending up, send a "304 Not Modified"
   *
   * @param ctx Context
   */
  private static void sendNotModified(ChannelHandlerContext ctx) {
    FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, NOT_MODIFIED);
    setDateHeader(response);

    // Close the connection as soon as the error message is sent.
    ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
  }
 @Override
 protected void encode(ChannelHandlerContext ctx, SingleResponse response, List<Object> out)
     throws WeixinException {
   String content = response.toContent();
   ctx.writeAndFlush(HttpUtil.createHttpResponse(content, ServerToolkits.CONTENTTYPE$TEXT_PLAIN));
   logger.debug("encode single response:{}", content);
 }
  private static void sendRedirect(ChannelHandlerContext ctx, String newUri) {
    FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, FOUND);
    response.headers().set(LOCATION, newUri);

    // Close the connection as soon as the error message is sent.
    ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
  }
Ejemplo n.º 17
0
  /**
   * 发送消息
   *
   * @param message
   * @param msg
   */
  public void send(final Payload message, final byte[] msg) {
    try {

      final ByteBuf data = context.alloc().buffer(msg.length); // (2)
      data.writeBytes(msg);

      final ChannelFuture cf = context.writeAndFlush(data);
      cf.addListener(
          new GenericFutureListener<Future<? super Void>>() {
            @Override
            public void operationComplete(Future<? super Void> future) throws Exception {
              if (cf.cause() != null) {
                logger.error("{}, Send Error.", context, cf.cause());
                PayloadServiceImpl.instance.updateSendStatus(
                    message,
                    userId,
                    new PushStatus(PushStatus.WriterError, cf.cause().getMessage()));
              } else {
                updateOpTime();
                PayloadServiceImpl.instance.updateSendStatus(
                    message, userId, new PushStatus(PushStatus.Success));
                ClientServiceImpl.instance.updateBadge(userId, 1);
                if (logger.isDebugEnabled()) {
                  logger.debug("Send Done, userId={}, messageId={}", userId, message.getId());
                }
              }
            }
          });

    } catch (Exception e) {
      message.setStatus(userId, new PushStatus(PushStatus.UnKnown, e.getMessage()));
      logger.error(e.getMessage(), e);
    }
  }
Ejemplo n.º 18
0
  /**
   * Calls {@link ChannelHandlerContext#fireChannelRead(Object)} to forward to the next {@link
   * ChannelHandler} in the {@link ChannelPipeline}.
   *
   * <p>Sub-classes may override this method to change behavior.
   */
  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    NettyMessage message = (NettyMessage) msg;

    // 如果是握手请求消息,处理,其它消息透传
    if (message.getHeader() != null
        && message.getHeader().getType() == MessageType.LOGIN_REQ.value()) {
      String nodeIndex = ctx.channel().remoteAddress().toString();
      NettyMessage loginResp = null;
      // 重复登陆,拒绝
      if (nodeCheck.containsKey(nodeIndex)) {
        loginResp = buildResponse((byte) -1);
      } else {
        InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
        String ip = address.getAddress().getHostAddress();
        boolean isOK = false;
        for (String WIP : whitekList) {
          if (WIP.equals(ip)) {
            isOK = true;
            break;
          }
        }
        loginResp = isOK ? buildResponse((byte) 0) : buildResponse((byte) -1);
        if (isOK) nodeCheck.put(nodeIndex, true);
      }
      System.out.println(
          "The login response is : " + loginResp + " body [" + loginResp.getBody() + "]");
      ctx.writeAndFlush(loginResp);
    } else {
      ctx.fireChannelRead(msg);
    }
  }
    @Override
    public void channelActive(@NotNull ChannelHandlerContext ctx) {
      startTime = System.nanoTime();
      ctx.writeAndFlush(firstMessage);

      System.out.print("Running throughput test ( for 10 seconds ) ");
    }
Ejemplo n.º 20
0
 /**
  * Writes response metadata to the channel if not already written previously and channel is
  * active.
  *
  * @param responseMetadata the {@link HttpResponse} that needs to be written.
  * @param listener the {@link GenericFutureListener} that needs to be attached to the write.
  * @return {@code true} if response metadata was written to the channel in this call. {@code
  *     false} otherwise.
  */
 private boolean maybeWriteResponseMetadata(
     HttpResponse responseMetadata, GenericFutureListener<ChannelFuture> listener) {
   long writeProcessingStartTime = System.currentTimeMillis();
   boolean writtenThisTime = false;
   if (responseMetadataWritten.compareAndSet(false, true)) {
     // we do some manipulation here for chunking. According to the HTTP spec, we can have either a
     // Content-Length
     // or Transfer-Encoding:chunked, never both. So we check for Content-Length - if it is not
     // there, we add
     // Transfer-Encoding:chunked. Note that sending HttpContent chunks data anyway - we are just
     // explicitly specifying
     // this in the header.
     if (!HttpHeaders.isContentLengthSet(responseMetadata)) {
       // This makes sure that we don't stomp on any existing transfer-encoding.
       HttpHeaders.setTransferEncodingChunked(responseMetadata);
     }
     logger.trace(
         "Sending response with status {} on channel {}",
         responseMetadata.getStatus(),
         ctx.channel());
     ChannelPromise writePromise = ctx.newPromise().addListener(listener);
     ctx.writeAndFlush(responseMetadata, writePromise);
     writtenThisTime = true;
     long writeProcessingTime = System.currentTimeMillis() - writeProcessingStartTime;
     nettyMetrics.responseMetadataProcessingTimeInMs.update(writeProcessingTime);
   }
   return writtenThisTime;
 }
Ejemplo n.º 21
0
 private void sendMessage(ChannelHandlerContext ctx, String config) {
   byte[] bytes = config.getBytes(charset);
   ByteBuf message = Unpooled.buffer(4 + bytes.length);
   message.writeInt(bytes.length);
   message.writeBytes(bytes);
   ctx.writeAndFlush(message);
 }
Ejemplo n.º 22
0
  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    if (msg instanceof EchoFile) {
      EchoFile ef = (EchoFile) msg;
      int SumCountPackage = ef.getSumCountPackage();
      int countPackage = ef.getCountPackage();
      byte[] bytes = ef.getBytes();
      String md5 = ef.getFile_md5(); // 文件名

      String path = file_dir + File.separator + md5;
      File file = new File(path);
      RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
      randomAccessFile.seek(countPackage * dataLength - dataLength);
      randomAccessFile.write(bytes);
      LOGGER.debug("总包数:" + ef.getSumCountPackage());
      LOGGER.debug("收到第" + countPackage + "包");
      LOGGER.debug("本包字节数:" + bytes.length);
      countPackage = countPackage + 1;

      if (countPackage <= SumCountPackage) {
        ef.setCountPackage(countPackage);
        ctx.writeAndFlush(ef);
        randomAccessFile.close();
      } else {
        randomAccessFile.close();
        ctx.close();
      }
    }
  }
Ejemplo n.º 23
0
  private void returnMessage(String info, ChannelHandlerContext ctx, String end) {
    byte[] b2 = HexString2Bytes(info);
    String checksum = Integer.toHexString(CRC_XModem(b2)).toUpperCase();
    System.out.println("checksum1:" + checksum);
    if (checksum.length() == 4) {

    } else if (checksum.length() == 3) {
      checksum = "0" + checksum;
    } else if (checksum.length() == 2) {
      checksum = "00" + checksum;
    } else if (checksum.length() == 1) {
      checksum = "000" + checksum;
    } else {
      checksum = checksum.substring(0, 4);
    }
    System.out.println("checksum2:" + checksum);
    byte b[] = HexString2Bytes(info + checksum + end);

    logger.info(String.format("primary sent:%s", info + checksum + end));

    /*
     * 下发一次
     * 服务器下行指令 @@ 35 30020000000001 0002 120.24.176.185:6666 77A6 0D0A
     * l 35 2字节根据实际下发的字节长度去计算
     * 404000233002000000000100023132302E32342E3137362E3138353A3636363677A60D0A
     */
    ctx.writeAndFlush(b);
  }
  private void sendServerError(final ChannelHandlerContext ctx, final ServerException cause)
      throws Exception {

    if (ctx.channel().isActive()) {

      final ByteBuf content = Unpooled.buffer();

      content.writeBytes(
          (cause.getStatus().code()
                  + " "
                  + cause.getStatus().reasonPhrase()
                  + " - "
                  + cause.getMessage())
              .getBytes());

      final FullHttpResponse response =
          new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, cause.getStatus());

      response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, content.readableBytes());

      response.content().writeBytes(content);

      ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
    }
  }
 private static void sendListing(ChannelHandlerContext ctx, File dir) {
   FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK);
   response.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8");
   StringBuilder buf = new StringBuilder();
   String dirPath = dir.getPath();
   buf.append("<!DOCTYPE html>\r\n");
   buf.append("<html><head><title>");
   buf.append(dirPath);
   buf.append(" 目录:");
   buf.append("</title></head><body>\r\n");
   buf.append("<h3>");
   buf.append(dirPath).append(" 目录:");
   buf.append("</h3>\r\n");
   buf.append("<ul>");
   buf.append("<li>链接:<a href=\"../\">..</a></li>\r\n");
   for (File f : dir.listFiles()) {
     if (f.isHidden() || !f.canRead()) {
       continue;
     }
     String name = f.getName();
     if (!ALLOWED_FILE_NAME.matcher(name).matches()) {
       continue;
     }
     buf.append("<li>链接:<a href=\"");
     buf.append(name);
     buf.append("\">");
     buf.append(name);
     buf.append("</a></li>\r\n");
   }
   buf.append("</ul></body></html>\r\n");
   ByteBuf buffer = Unpooled.copiedBuffer(buf, CharsetUtil.UTF_8);
   response.content().writeBytes(buffer);
   buffer.release();
   ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
 }
Ejemplo n.º 26
0
  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;
  }
Ejemplo n.º 27
0
  protected void doOnTerminate(
      ChannelHandlerContext ctx,
      ChannelFuture last,
      final ChannelPromise promise,
      final Throwable exception) {
    if (ctx.channel().isOpen()) {
      ChannelFutureListener listener =
          future -> {
            if (exception != null) {
              promise.tryFailure(exception);
            } else if (future.isSuccess()) {
              promise.trySuccess();
            } else {
              promise.tryFailure(future.cause());
            }
          };

      if (last != null) {
        ctx.flush();
        last.addListener(listener);
      } else {
        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(listener);
      }
    } else {
      if (exception != null) {
        promise.tryFailure(exception);
      } else {
        promise.trySuccess();
      }
    }
  }
Ejemplo n.º 28
0
 @Override
 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
   SubscribeReq req = (SubscribeReq) msg;
   if ("Administrator".equalsIgnoreCase(req.getUserName())) {
     System.out.println("Service accept client subscrib req : [" + req.toString() + "]");
     ctx.writeAndFlush(resp(req.getSubReqID()));
   }
 }
Ejemplo n.º 29
0
  @Override
  protected void channelRead0(ChannelHandlerContext ctx, LoginMessage message) throws Exception {
    String token = message.body.trim();
    User user = userDao.tokenManager.getUserByToken(token);

    if (user == null) {
      log.debug(
          "HardwareLogic token is invalid. Token '{}', '{}'", token, ctx.channel().remoteAddress());
      ctx.writeAndFlush(new ResponseMessage(message.id, Response.INVALID_TOKEN));
      return;
    }

    final Integer dashId = UserDao.getDashIdByToken(user.dashTokens, token, message.id);

    // todo find out why this happen
    DashBoard dash = user.profile.getDashById(dashId);
    if (dash == null) {
      log.error(
          "User : {} requested token {} for non-existing {} dash id.", user.name, token, dashId);
      ctx.writeAndFlush(new ResponseMessage(message.id, Response.INVALID_TOKEN));
      return;
    }

    ctx.pipeline().remove(this);
    ctx.pipeline().remove(UserNotLoggedHandler.class);
    ctx.pipeline()
        .addLast(
            new HardwareHandler(
                props,
                sessionDao,
                reportingDao,
                blockingIOProcessor,
                new HardwareStateHolder(dashId, user, token)));

    Session session = sessionDao.getSessionByUser(user, ctx.channel().eventLoop());

    if (session.initialEventLoop != ctx.channel().eventLoop()) {
      log.debug("Re registering hard channel. {}", ctx.channel());
      reRegisterChannel(
          ctx,
          session,
          channelFuture -> completeLogin(channelFuture.channel(), session, user, dash, message.id));
    } else {
      completeLogin(ctx.channel(), session, user, dash, message.id);
    }
  }
 private static void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {
   FullHttpResponse response =
       new DefaultFullHttpResponse(
           HTTP_1_1,
           status,
           Unpooled.copiedBuffer("失败: " + status.toString() + "\r\n", CharsetUtil.UTF_8));
   response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
   ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
 }