Class WriteStallTimeoutHandler

java.lang.Object
io.netty.channel.ChannelHandlerAdapter
io.netty.channel.ChannelOutboundHandlerAdapter
org.mockserver.netty.connection.WriteStallTimeoutHandler
All Implemented Interfaces:
io.netty.channel.ChannelHandler, io.netty.channel.ChannelOutboundHandler, Runnable

public final class WriteStallTimeoutHandler extends io.netty.channel.ChannelOutboundHandlerAdapter implements Runnable
Closes an inbound connection when bytes have been waiting for its client for responseWriteStallTimeoutMillis and the client has taken none of them, so a client that stops reading cannot hold what is queued for it (and, for a streamed response, its upstream connection) indefinitely. Closing ends the response in progress incomplete.

Progress is the socket accepting more of the connection's outbound buffer. A slow reader's socket accepts bytes in bursts, as the kernel wakes a writer only once a share of its send buffer is free, so the timeout must sit well above that gap. On the native epoll transport the kernel's own record of when it last sent data to the client counts as progress too, which removes the burst gap there.

Installed first when the connection is accepted and kept for its life, so it also bounds a stalled tunnel or WebSocket client. Inspecting the outbound buffer costs nothing per write; a timer runs only while a flush has left bytes waiting.

  • Nested Class Summary

    Nested classes/interfaces inherited from interface io.netty.channel.ChannelHandler

    io.netty.channel.ChannelHandler.Sharable
  • Constructor Summary

    Constructors
    Constructor
    Description
    WriteStallTimeoutHandler(long timeoutMillis, org.mockserver.logging.MockServerLogger mockServerLogger)
     
  • Method Summary

    Modifier and Type
    Method
    Description
    static long
    checkIntervalMillis(long timeoutMillis)
    How often a timer checks for progress: often enough that a stall is noticed soon after the timeout, never more than once a second.
    static void
    exempt(io.netty.channel.Channel channel)
    Stop watching a connection whose silences are MockServer's own backpressure rather than its client's: the loopback leg of a CONNECT/SOCKS relay is read only as fast as the relay's proxy client takes what it is sent, and that client's own connection is watched.
    void
    flush(io.netty.channel.ChannelHandlerContext ctx)
     
    void
    handlerAdded(io.netty.channel.ChannelHandlerContext ctx)
     
    void
    handlerRemoved(io.netty.channel.ChannelHandlerContext ctx)
     
    static boolean
    isExempt(io.netty.channel.Channel channel)
     
    void
    run()
     

    Methods inherited from class io.netty.channel.ChannelOutboundHandlerAdapter

    bind, close, connect, deregister, disconnect, read, write

    Methods inherited from class io.netty.channel.ChannelHandlerAdapter

    ensureNotSharable, exceptionCaught, isSharable

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

    Methods inherited from interface io.netty.channel.ChannelHandler

    exceptionCaught
  • Constructor Details

    • WriteStallTimeoutHandler

      public WriteStallTimeoutHandler(long timeoutMillis, org.mockserver.logging.MockServerLogger mockServerLogger)
  • Method Details

    • checkIntervalMillis

      public static long checkIntervalMillis(long timeoutMillis)
      How often a timer checks for progress: often enough that a stall is noticed soon after the timeout, never more than once a second.
    • exempt

      public static void exempt(io.netty.channel.Channel channel)
      Stop watching a connection whose silences are MockServer's own backpressure rather than its client's: the loopback leg of a CONNECT/SOCKS relay is read only as fast as the relay's proxy client takes what it is sent, and that client's own connection is watched. Must be called on the connection's event loop.
    • isExempt

      public static boolean isExempt(io.netty.channel.Channel channel)
    • handlerAdded

      public void handlerAdded(io.netty.channel.ChannelHandlerContext ctx)
      Specified by:
      handlerAdded in interface io.netty.channel.ChannelHandler
      Overrides:
      handlerAdded in class io.netty.channel.ChannelHandlerAdapter
    • handlerRemoved

      public void handlerRemoved(io.netty.channel.ChannelHandlerContext ctx)
      Specified by:
      handlerRemoved in interface io.netty.channel.ChannelHandler
      Overrides:
      handlerRemoved in class io.netty.channel.ChannelHandlerAdapter
    • flush

      public void flush(io.netty.channel.ChannelHandlerContext ctx)
      Specified by:
      flush in interface io.netty.channel.ChannelOutboundHandler
      Overrides:
      flush in class io.netty.channel.ChannelOutboundHandlerAdapter
    • run

      public void run()
      Specified by:
      run in interface Runnable