/**
  * This method is used to write the zero length chunk. Writing the zero length chunk tells the
  * client that the response has been fully sent, and the next sequence of bytes from the HTTP
  * pipeline is the start of the next response. This will signal to the server kernel that the next
  * request is read to read.
  */
 private void finish() throws IOException {
   try {
     sender.send(zero);
     monitor.ready(sender);
   } catch (Exception cause) {
     if (sender != null) {
       monitor.close(sender);
     }
     throw new ProducerException("Error flushing response", cause);
   }
 }
 /**
  * This method is used to flush the contents of the buffer to the client. This method will block
  * until such time as all of the data has been sent to the client. If at any point there is an
  * error sending the content an exception is thrown.
  */
 public void flush() throws IOException {
   try {
     if (!monitor.isClosed()) {
       sender.flush();
     }
   } catch (Exception cause) {
     if (sender != null) {
       monitor.close(sender);
     }
     throw new ProducerException("Error sending response", cause);
   }
 }
  /**
   * This method is used to encode the provided buffer of bytes in a HTTP/1.1 compliant format and
   * sent it to the client. Once the data has been encoded it is handed to the transport layer
   * within the server, which may choose to buffer the data if the content is too small to send
   * efficiently or if the socket is not write ready.
   *
   * @param buffer this is the buffer of bytes to send to the client
   * @param off this is the offset within the buffer to send from
   * @param len this is the number of bytes that are to be sent
   */
  public void produce(ByteBuffer buffer, int off, int len) throws IOException {
    int pos = 7;

    if (monitor.isClosed()) {
      throw new ProducerException("Stream has been closed");
    }
    if (len > 0) {
      for (int num = len; num > 0; num >>>= 4) {
        size[pos--] = index[num & 0xf];
      }
      try {
        sender.send(size, pos + 1, 9 - pos);
        sender.send(buffer, off, len);
        sender.send(size, 8, 2);
      } catch (Exception cause) {
        if (sender != null) {
          monitor.error(sender);
        }
        throw new ProducerException("Error sending response", cause);
      }
    }
  }