@Override
  public void handleEvent(StreamConnection channel) {
    // set read and write timeouts
    try {
      Integer readTimeout = channel.getOption(Options.READ_TIMEOUT);
      Integer idleTimeout = undertowOptions.get(UndertowOptions.IDLE_TIMEOUT);
      if ((readTimeout == null || readTimeout <= 0) && idleTimeout != null) {
        readTimeout = idleTimeout;
      } else if (readTimeout != null && idleTimeout != null && idleTimeout > 0) {
        readTimeout = Math.min(readTimeout, idleTimeout);
      }
      if (readTimeout != null && readTimeout > 0) {
        channel
            .getSourceChannel()
            .setConduit(
                new ReadTimeoutStreamSourceConduit(
                    channel.getSourceChannel().getConduit(), channel, this));
      }
      Integer writeTimeout = channel.getOption(Options.WRITE_TIMEOUT);
      if ((writeTimeout == null || writeTimeout <= 0) && idleTimeout != null) {
        writeTimeout = idleTimeout;
      } else if (writeTimeout != null && idleTimeout != null && idleTimeout > 0) {
        writeTimeout = Math.min(writeTimeout, idleTimeout);
      }
      if (writeTimeout != null && writeTimeout > 0) {
        channel
            .getSinkChannel()
            .setConduit(
                new WriteTimeoutStreamSinkConduit(
                    channel.getSinkChannel().getConduit(), channel, this));
      }
    } catch (IOException e) {
      IoUtils.safeClose(channel);
      UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
    }

    final PortForwardServerConnection connection =
        new PortForwardServerConnection(channel, bufferPool, undertowOptions, bufferSize);
    connection
        .getWorker()
        .execute(
            new Runnable() {
              @Override
              public void run() {
                try {
                  connection.startForwarding(
                      masterPortForwardConnection,
                      urlPath,
                      targetPort,
                      requestId.getAndIncrement());
                } catch (IOException e) {
                } finally {
                  IoUtils.safeClose(connection);
                }
              }
            });
  }
 @Override
 public void awaitWritable() throws IOException {
   Integer timeout = connection.getOption(Options.WRITE_TIMEOUT);
   if (timeout != null && timeout > 0) {
     super.awaitWritable(timeout + FUZZ_FACTOR, TimeUnit.MILLISECONDS);
   } else {
     super.awaitWritable();
   }
 }
 @Override
 public void awaitWritable(long time, TimeUnit timeUnit) throws IOException {
   Integer timeout = connection.getOption(Options.WRITE_TIMEOUT);
   if (timeout != null && timeout > 0) {
     long millis = timeUnit.toMillis(time);
     super.awaitWritable(Math.min(millis, timeout + FUZZ_FACTOR), TimeUnit.MILLISECONDS);
   } else {
     super.awaitWritable(time, timeUnit);
   }
 }
 private void handleWriteTimeout(final long ret) throws IOException {
   Integer writeTimout = connection.getOption(Options.WRITE_TIMEOUT);
   if (writeTimout != null && writeTimout > 0) {
     if (ret == 0 && handle == null) {
       handle =
           super.getWriteThread()
               .executeAfter(timeoutCommand, writeTimout + FUZZ_FACTOR, TimeUnit.MILLISECONDS);
     } else if (ret > 0 && handle != null) {
       handle.remove();
     }
   }
 }
 /** {@inheritDoc} */
 @Override
 public <T> T getOption(final Option<T> option) throws IOException {
   if (option == Options.SSL_CLIENT_AUTH_MODE) {
     return option.cast(
         engine.getNeedClientAuth()
             ? SslClientAuthMode.REQUIRED
             : engine.getWantClientAuth()
                 ? SslClientAuthMode.REQUESTED
                 : SslClientAuthMode.NOT_REQUESTED);
   } else {
     return option == Options.SECURE ? (T) Boolean.TRUE : delegate.getOption(option);
   }
 }
 public <T> T getOption(final Option<T> option) throws IOException {
   return channel.getOption(option);
 }
 @Override
 public <T> T getOption(Option<T> option) throws IOException {
   return connection.getOption(option);
 }