/*
  * Create an HTTP 400 bad request response.
  */
 public static FullHttpResponse badRequest(String msg) {
   DefaultFullHttpResponse resp = new DefaultFullHttpResponse(HTTP_1_1, BAD_REQUEST);
   resp.content().writeBytes(msg.getBytes());
   resp.headers().set(CONTENT_TYPE, "text/plain");
   resp.headers().set(CONTENT_LENGTH, resp.content().readableBytes());
   return resp;
 }
 /**
  * Respond to errors occurring on a Reactor by redirecting them to the client via an HTTP 500
  * error response.
  *
  * @param channel the channel on which to send an HTTP response
  * @return a consumer to handle HTTP requests
  */
 public static Consumer<Throwable> errorHandler(
     NetChannel<FullHttpRequest, FullHttpResponse> channel) {
   return ev -> {
     DefaultFullHttpResponse resp =
         new DefaultFullHttpResponse(
             HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR);
     resp.content().writeBytes(ev.getMessage().getBytes());
     resp.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/plain");
     resp.headers().set(HttpHeaders.Names.CONTENT_LENGTH, resp.content().readableBytes());
     channel.send(resp);
   };
 }
  /*
   * Create an HTTP 200 response that contains the data of the thumbnailed image.
   */
  public static FullHttpResponse serveImage(Path path) throws IOException {
    DefaultFullHttpResponse resp = new DefaultFullHttpResponse(HTTP_1_1, OK);

    RandomAccessFile f = new RandomAccessFile(path.toString(), "r");
    resp.headers().set(CONTENT_TYPE, "image/jpeg");
    resp.headers().set(CONTENT_LENGTH, f.length());

    byte[] bytes = Files.readAllBytes(path);
    resp.content().writeBytes(bytes);

    return resp;
  }
  private static void sendHttpResponse(
      ChannelHandlerContext ctx, FullHttpRequest req, DefaultFullHttpResponse res) {

    // ����Ӧ����ͻ���
    if (res.getStatus().code() != 200) {
      ByteBuf buf = Unpooled.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8);
      res.content().writeBytes(buf);
      buf.release();
    }

    // ����Ƿ�Keep-Alive���ر�����
    ChannelFuture f = ctx.channel().writeAndFlush(res);
    if (!isKeepAlive(req) || res.getStatus().code() != 200) {
      f.addListener(ChannelFutureListener.CLOSE);
    }
  }
  private void respondAsLeader(ChannelHandlerContext ctx, Routed routed, ActorGateway jobManager) {
    DefaultFullHttpResponse response;

    try {
      // we only pass the first element in the list to the handlers.
      Map<String, String> queryParams = new HashMap<>();
      for (String key : routed.queryParams().keySet()) {
        queryParams.put(key, routed.queryParam(key));
      }

      InetSocketAddress address = (InetSocketAddress) ctx.channel().localAddress();
      queryParams.put(WEB_MONITOR_ADDRESS_KEY, address.getHostName() + ":" + address.getPort());

      String result = handler.handleRequest(routed.pathParams(), queryParams, jobManager);
      byte[] bytes = result.getBytes(ENCODING);

      response =
          new DefaultFullHttpResponse(
              HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer(bytes));

      response.headers().set(HttpHeaders.Names.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
      response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "application/json");
    } catch (NotFoundException e) {
      // this should result in a 404 error code (not found)
      ByteBuf message =
          e.getMessage() == null
              ? Unpooled.buffer(0)
              : Unpooled.wrappedBuffer(e.getMessage().getBytes(ENCODING));
      response =
          new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND, message);
      response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/plain");
      LOG.warn("Error while handling request", e);
    } catch (Exception e) {
      byte[] bytes = ExceptionUtils.stringifyException(e).getBytes(ENCODING);
      response =
          new DefaultFullHttpResponse(
              HttpVersion.HTTP_1_1,
              HttpResponseStatus.INTERNAL_SERVER_ERROR,
              Unpooled.wrappedBuffer(bytes));
      response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/plain");
      LOG.warn("Error while handling request", e);
    }

    response.headers().set(HttpHeaders.Names.CONTENT_ENCODING, "utf-8");
    response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, response.content().readableBytes());
    KeepAliveWrite.flush(ctx, routed.request(), response);
  }
 @Override
 protected void decode(ChannelHandlerContext ctx, DefaultFullHttpResponse msg, List<Object> out)
     throws Exception {
   HttpXmlResponse resHttpXmlResponse = new HttpXmlResponse(msg, decode0(ctx, msg.content()));
   out.add(resHttpXmlResponse);
 }
  private void messageReceive(ChannelHandlerContext ctx, DefaultFullHttpResponse response) {
    /** send next cmd * */
    switch (state) {
      case PLAY:
        String rtpInfo = response.headers().get("RTP-Info");

        setState(RTSP.PLAYING);
        break;
      case SETUP:
        // session
        String sessionId = response.headers().get("Session");
        if (null != sessionId) {
          Matcher matcher = Pattern.compile("([^;]+)").matcher(sessionId);
          if (matcher.find()) {
            rtspStack.setSession(matcher.group(1));
          } else {
            rtspStack.setSession(sessionId);
          }
        }

        // transport
        InetSocketAddress remoteHost = (InetSocketAddress) ctx.channel().remoteAddress();
        String transport = response.headers().get("Transport");
        RtpSessionExt rtp = rtspStack.getLastRtpSession();
        Matcher matcher = Pattern.compile("([^\\s=;]+)=(([^-;]+)(-([^;]+))?)").matcher(transport);
        while (matcher.find()) {
          String key = matcher.group(1).toLowerCase();
          if ("server_port".equals(key)) {
            rtp.connectRtp(
                new InetSocketAddress(
                    remoteHost.getHostString(), Integer.valueOf(matcher.group(3))));
            rtp.connectRtcp(
                new InetSocketAddress(
                    remoteHost.getHostString(), Integer.valueOf(matcher.group(5))));
          } else if ("ssrc".equals(key)) {
            rtp.setSsrc(Long.parseLong(matcher.group(2).trim(), 16));
          } else if ("interleaved".equals(key)) {
            rtp.setRtpChunk(Integer.valueOf(matcher.group(3)));
            rtp.setRtcpChunk(Integer.valueOf(matcher.group(5)));
          } else {
            logger.warn("ignored [{}={}]", key, matcher.group(2));
          }
        }

        // next action
        boolean finish = setup(sd, mediaIndex++);
        if (finish) {
          sendPlay();
          setState(RTSP.PLAY);
        }

        break;
      case DESCRIBE:
        if (response.getStatus().code() == HttpResponseStatus.UNAUTHORIZED.code()) {
          sendDescribe(buildAuthorizationString(response));
          break;
        }

        String desciptor = response.content().toString(Charset.forName("UTF8"));
        SessionDescriptionImpl sd = new SessionDescriptionImpl();
        StringTokenizer tokenizer = new StringTokenizer(desciptor);
        while (tokenizer.hasMoreChars()) {
          String line = tokenizer.nextToken();

          try {
            SDPParser paser = ParserFactory.createParser(line);
            if (null != paser) {
              SDPField obj = paser.parse();
              sd.addField(obj);
            }
          } catch (ParseException e) {
            logger.warn("fail parse [{}]", line, e);
          }
        }
        this.sd = sd;

        mediaIndex = 0;
        setup(sd, mediaIndex++);

        // 心跳
        rtspStack
            .getChannel()
            .pipeline()
            .addFirst("ping", new IdleStateHandler(30, 15, 13, TimeUnit.SECONDS));

        //
        rtspStack.setSessionDescription(sd);
        break;
      case OPTIONS:
        if (response.getStatus().code() == HttpResponseStatus.UNAUTHORIZED.code()) {
          sendDescribe(buildAuthorizationString(response));
        } else {
          sendDescribe();
        }

        setState(RTSP.DESCRIBE);
        break;
      case PLAYING:
        break;
      default:
        logger.warn("I dont't Known What to do with {}", response);
        break;
    }
  }