java.lang.Object
net.i2p.i2ptunnel.I2PTunnelHTTPServer.CompressedRequestor
All Implemented Interfaces:
Runnable
Enclosing class:
I2PTunnelHTTPServer

private static class I2PTunnelHTTPServer.CompressedRequestorextends Object implements Runnable
Copies a gzipped request through to the web server.
  • Field Details

    • _tunnelId

      private final String _tunnelId
      Far-side label for transfer logs, e.g. [skank / aanoquc2]. Null when the caller did not supply one.
    • _webserver

      private final Socket _webserver
      The web server socket.
    • _browser

      private final I2PSocket _browser
      The browser's I2P socket.
    • _headers

      private final String _headers
      The request headers to forward.
    • _ctx

      private final I2PAppContext _ctx
      The app context.
    • _log

      private final Log _log
      Logger, shadows the one in the superclass.
    • _shouldCompress

      private final boolean _shouldCompress
      True when the request is gzipped.
    • _upgrade

      private final boolean _upgrade
      True for an upgrade request.
    • _tpe

      private final ThreadPoolExecutor _tpe
      The executor running this task.
    • _keepalive

      private volatile boolean _keepalive
      Whether the browser connection stays open.
    • _waiter

      private final AtomicInteger _waiter
      Waiter count for the IO pool.
    • _ioPool

      private final java.util.function.Supplier<ThreadPoolExecutor> _ioPool
      Supplier of the shared IO pool.
    • BUF_SIZE

      private static final int BUF_SIZE
      Copy buffer size.
      See Also:
  • Constructor Details

    • CompressedRequestor

      public CompressedRequestor(Socket webserver, I2PSocket browser, String headers, I2PAppContext ctx, Log log, boolean shouldCompress, boolean upgrade, ThreadPoolExecutor tpe, boolean keepalive, AtomicInteger waiter, java.util.function.Supplier<ThreadPoolExecutor> ioPool)
      Serves a gzipped response from the web server to the browser.
      Parameters:
      webserver - the web server socket to read the response from
      browser - the browser socket to send the response to
      headers - the request headers to forward to the web server
      ctx - the application context, used to schedule the stall watchdog
      log - the logger for the transfer logs
      shouldCompress - if false, don't compress, just filter server headers
      upgrade - true if the request is a protocol upgrade, which disables keepalive
      tpe - the thread pool that runs the inline server-to-browser sender
      keepalive - true if the browser connection may be reused afterwards
      waiter - to notify when done, if non-null; will set value to 1: not keepalive-able response, or 2: keepalive
      ioPool - resolves the owning tunnel's I/O transfer pool (never returns null in production)
    • CompressedRequestor

      public CompressedRequestor(Socket webserver, I2PSocket browser, String headers, I2PAppContext ctx, Log log, boolean shouldCompress, boolean upgrade, ThreadPoolExecutor tpe, boolean keepalive, AtomicInteger waiter, java.util.function.Supplier<ThreadPoolExecutor> ioPool, String tunnelId)
      Serves a gzipped response, with an optional stall watchdog.
      Parameters:
      webserver - the web server socket to read the response from
      browser - the browser socket to send the response to
      headers - the request headers to forward to the web server
      ctx - the application context, used to schedule the stall watchdog
      log - the logger for the transfer logs
      shouldCompress - if false, don't compress, just filter server headers
      upgrade - true if the request is a protocol upgrade, which disables keepalive
      tpe - the thread pool that runs the inline server-to-browser sender
      keepalive - true if the browser connection may be reused afterwards
      waiter - to notify when done, if non-null; will set value to 1: not keepalive-able response, or 2: keepalive
      ioPool - resolves the owning tunnel's I/O transfer pool (never returns null in production)
      tunnelId - far-side label for transfer logs, e.g. [skank / aanoquc2]; may be null
  • Method Details

    • urlSuffix

      private static String urlSuffix(String req)
      Returns the URL suffix of a request line.
      Parameters:
      req - the request line
      Returns:
      the path after the method, empty if malformed
    • runOnIO

      private void runOnIO(I2PTunnelHTTPServer.Sender s, String desc) throws IOException
      Run a Sender on the dedicated I/O pool with idle-based stall detection. The handler thread polls Future.get() in short slices and cancels only after I2PTunnelHTTPServer.ioStallTimeoutMs with no read progress. A total-timeout Future.get would kill any transfer longer than the stall window (a multi-minute I2P download at hundreds of KB/s), which is expected latency — not a stall. On true idle the Sender thread is interrupted (breaking any blocking read()), and an IOException propagates to the finally-block cleanup.

      Used for keepalive responses (must wait before the next request) and as a fallback when async handoff is not taken.

      Parameters:
      s - the Sender to run
      desc - descriptive name for error messages
      Throws:
      IOException - if the transfer goes idle for the stall timeout, fails, or the pool rejects the task
    • run

      public void run()
      This thread handles the response from the server back to the browser. If the request was not GET or HEAD, (typically POST or CONNECT), it spawns another thread "Sender" to push the remaining request data from the browser to the server.
      Specified by:
      run in interface Runnable
    • scheduleBodyWatchdog

      private void scheduleBodyWatchdog(I2PTunnelHTTPServer.Sender body, AtomicBoolean finished, Runnable finish, InputStream browserin, OutputStream browserout, InputStream serverin, OutputStream serverout)
      Attach a I2PTunnelHTTPServer.BodyWatchdog to a detached async body. The poll interval is fixed at I2PTunnelHTTPServer.BodyWatchdog.POLL_MS (the SimpleTimer2 5s minimum); the stall window itself is I2PTunnelHTTPServer.ioStallTimeoutMs. The watchdog cancels itself on the next tick after finishTransfer sets the finished flag, so it never outlives the connection.
      Parameters:
      body - detached Server-to-Client Sender
      finished - request-wide finish-once flag
      finish - idempotent finish shared with the handoff
      browserin - browser-side request stream; may be null
      browserout - browser-side response stream; may be null
      serverin - I2P-side response body stream; may be null
      serverout - I2P-side request stream; may be null
    • finishTransfer

      private void finishTransfer(AtomicBoolean finished, I2PTunnelHTTPServer.Sender body, I2PTunnelHTTPServer.Sender reqSender, OutputStream serverout, OutputStream browserout, I2PTunnelHTTPServer.CompressedResponseOutputStream compressedout, InputStream browserin, InputStream serverin, String req)
      Tear down a completed (or failed) request exactly once. Invoked from the handler finally when the body ran on this thread, or from the I/O pool worker after an async body handoff.
      Parameters:
      finished - CAS flag; first caller performs cleanup
      body - Server→Client Sender (may be null)
      reqSender - Client→Server Sender (may be null)
      serverout - local webserver output (may be null)
      browserout - browser-side output (may be null)
      compressedout - gzip wrapper (may be null)
      browserin - local webserver input (may be null)
      serverin - I2P-side response body (may be null)
      req - request URL for logging (may be null)
    • readAndRewriteServerResponse

      static String readAndRewriteServerResponse(InputStream serverin, int timeout, I2PAppContext ctx) throws IOException
      Read the server response headers, filter them for security, and re-format them for the client.
      Parameters:
      serverin - stream from the webserver
      timeout - timeout for the header read
      ctx - the I2P app context
      Returns:
      the formatted, filtered headers
      Throws:
      IOException - if the webserver stream fails
    • propagateFailure

      private void propagateFailure(IOException ioex, String req)
      On failure, propagate a reset to the other end of the connection, simplified from I2PTunnelRunner.
      Parameters:
      ioex - the failure that triggered the reset
      req - the request URL for logging