Class StatusCapturingDraft

java.lang.Object
org.java_websocket.drafts.Draft
org.java_websocket.drafts.Draft_6455
com.ultikits.ultitools.utils.StatusCapturingDraft

final class StatusCapturingDraft extends org.java_websocket.drafts.Draft_6455
A Draft_6455 that records the HTTP status of the upgrade response, so the agent socket can tell a refused upgrade (401, 402, 426, 429, ...) from a lost connection (as of 6.3.1).

Why an override of translateHandshake. Measured with javap -c on Java-WebSocket 1.6.0: for a client, WebSocketImpl.decodeHandshake calls the public, non-final Draft.translateHandshake(ByteBuffer); its private translateHandshakeHttpClient throws InvalidHandshakeException("Invalid status code received: ...") as soon as the status line is complete and the status is not 101, and WebSocketImpl turns that into flushAndClose(1002, message, false) -- no accept hook (acceptHandshakeAsClient) runs for a refused upgrade, so the status is visible only here. The client's WebSocketImpl copies its draft with copyInstance(), which is why that is overridden too: the copy shares this instance's sink.

The response is read from a duplicate of the buffer, so the parent sees it untouched. Nothing is recorded until the status line's CRLF has arrived; the parent then throws its incomplete-handshake exception and the library calls again with more bytes.

Refusal bodies in later segments. The parent rejects a non-101 status as soon as the status line is complete, so on its own the library never reads past the bytes of the first read. A server, proxy or TLS layer may send the head and the body in separate segments, and the body (a 402's reason, grace end and manage link) would then be lost. So for a non-101 status this draft throws IncompleteHandshakeException itself, before the parent sees the response, while the response is still incomplete: until the head's terminating blank line has arrived (within 16 KiB), and then until the bytes after the head hold the whole body per Content-Length (at most 8 KiB). WebSocketImpl.decodeHandshake answers that exception by buffering the bytes and calling again when more arrive -- the same path the library uses for a head that is not yet complete. The sink holds the status (and the headers once the head is complete) while the body is awaited, so a connection that ends first is still reported as that refusal, status-only. The wait is bounded three ways: by the byte caps, by the end of the stream, and by the caller's handshake deadline, which closes an attempt that has not opened (AgentConnection.HANDSHAKE_DEADLINE_MS). A body over the cap, a refusal without Content-Length and a head over 16 KiB are not waited for: the status alone decides.

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    private static final String
     
    private static final int
     
    private static final int
     
     
    (package private) static final int
    Status recorded for an accepted upgrade.

    Fields inherited from class org.java_websocket.drafts.Draft

    continuousFrameType, role
  • Constructor Summary

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    private int
    Records what the response says so far.
    private static long
     
    org.java_websocket.drafts.Draft
     
    private static int
    indexOf(byte[] data, int from, int to, byte[] pattern)
     
    private static Map<String,String>
     
    private static int
    parseStatus(String statusLine)
     
     
    org.java_websocket.handshake.Handshakedata
     

    Methods inherited from class org.java_websocket.drafts.Draft_6455

    acceptHandshakeAsClient, acceptHandshakeAsServer, createBinaryFrame, createFrames, createFrames, equals, getCloseHandshakeType, getExtension, getKnownExtensions, getKnownProtocols, getMaxFrameSize, getProtocol, hashCode, postProcessHandshakeRequestAsClient, postProcessHandshakeResponseAsServer, processFrame, reset, toString, translateFrame

    Methods inherited from class org.java_websocket.drafts.Draft

    basicAccept, checkAlloc, continuousFrame, createHandshake, createHandshake, createHandshake, createHandshake, getRole, readLine, readStringLine, setParseMode, translateHandshakeHttp

    Methods inherited from class java.lang.Object

    clone, finalize, getClass, notify, notifyAll, wait, wait, wait
  • Field Details

  • Constructor Details

    • StatusCapturingDraft

      StatusCapturingDraft(AtomicReference<UpgradeRejection> sink)
      Parameters:
      sink - where the parsed response is stored; shared with every copy of this draft
  • Method Details

    • sink

      Returns:
      the sink this draft writes to
    • translateHandshake

      public org.java_websocket.handshake.Handshakedata translateHandshake(ByteBuffer buf) throws org.java_websocket.exceptions.InvalidHandshakeException
      Overrides:
      translateHandshake in class org.java_websocket.drafts.Draft
      Throws:
      org.java_websocket.exceptions.InvalidHandshakeException
    • copyInstance

      public org.java_websocket.drafts.Draft copyInstance()
      Overrides:
      copyInstance in class org.java_websocket.drafts.Draft_6455
    • capture

      private int capture(ByteBuffer view)
      Records what the response says so far.
      Parameters:
      view - a duplicate of the handshake bytes received so far
      Returns:
      0 when the parent should decide now; otherwise the refusal is still arriving: a positive value is the total byte count the complete refusal needs, -1 means the head is not yet complete
    • parseStatus

      private static int parseStatus(String statusLine)
    • parseHeaders

      private static Map<String,String> parseHeaders(String block)
    • contentLength

      private static long contentLength(String raw)
    • indexOf

      private static int indexOf(byte[] data, int from, int to, byte[] pattern)