@Override
 public String toString() {
   return String.format(
       "%s[requested=%s,negotiated=%s]",
       getClass().getSimpleName(),
       configRequested.getParameterizedName(),
       configNegotiated.getParameterizedName());
 }
  @Override
  public void setConfig(final ExtensionConfig config) {
    configRequested = new ExtensionConfig(config);
    configNegotiated = new ExtensionConfig(config.getName());

    for (String key : config.getParameterKeys()) {
      key = key.trim();
      switch (key) {
        case "client_max_window_bits":
        case "server_max_window_bits":
          {
            // Not supported by Jetty
            // Don't negotiate these parameters
            break;
          }
        case "client_no_context_takeover":
          {
            configNegotiated.setParameter("client_no_context_takeover");
            switch (getPolicy().getBehavior()) {
              case CLIENT:
                incomingContextTakeover = false;
                break;
              case SERVER:
                outgoingContextTakeover = false;
                break;
            }
            break;
          }
        case "server_no_context_takeover":
          {
            configNegotiated.setParameter("server_no_context_takeover");
            switch (getPolicy().getBehavior()) {
              case CLIENT:
                outgoingContextTakeover = false;
                break;
              case SERVER:
                incomingContextTakeover = false;
                break;
            }
            break;
          }
        default:
          {
            throw new IllegalArgumentException();
          }
      }
    }

    super.setConfig(configNegotiated);
  }
  @Override
  public Extension newInstance(ExtensionConfig config) {
    if (config == null) {
      return null;
    }

    String name = config.getName();
    if (StringUtil.isBlank(name)) {
      return null;
    }

    Class<? extends Extension> extClass = getExtension(name);
    if (extClass == null) {
      return null;
    }

    try {
      Extension ext = extClass.newInstance();
      if (ext instanceof AbstractExtension) {
        AbstractExtension aext = (AbstractExtension) ext;
        aext.setConfig(config);
        aext.setPolicy(policy);
        aext.setBufferPool(bufferPool);
      }
      return ext;
    } catch (InstantiationException | IllegalAccessException e) {
      throw new WebSocketException("Cannot instantiate extension: " + extClass, e);
    }
  }
  /** Incoming PING (Control Frame) should pass through extension unmodified */
  @Test
  public void testIncomingPing() {
    IncomingFramesCapture capture = new IncomingFramesCapture();

    FragmentExtension ext = new FragmentExtension();
    ext.setBufferPool(new MappedByteBufferPool());
    ext.setPolicy(WebSocketPolicy.newServerPolicy());
    ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=4");
    ext.setConfig(config);

    ext.setNextIncomingFrames(capture);

    String payload = "Are you there?";
    Frame ping = WebSocketFrame.ping().setPayload(payload);
    ext.incomingFrame(ping);

    capture.assertFrameCount(1);
    capture.assertHasFrame(OpCode.PING, 1);
    WebSocketFrame actual = capture.getFrames().getFirst();

    Assert.assertThat("Frame.opcode", actual.getOpCode(), is(OpCode.PING));
    Assert.assertThat("Frame.fin", actual.isFin(), is(true));
    Assert.assertThat("Frame.rsv1", actual.isRsv1(), is(false));
    Assert.assertThat("Frame.rsv2", actual.isRsv2(), is(false));
    Assert.assertThat("Frame.rsv3", actual.isRsv3(), is(false));

    ByteBuffer expected = BufferUtil.toBuffer(payload, StringUtil.__UTF8_CHARSET);
    Assert.assertThat("Frame.payloadLength", actual.getPayloadLength(), is(expected.remaining()));
    ByteBufferAssert.assertEquals("Frame.payload", expected, actual.getPayload().slice());
  }
  @Override
  public void initializeNativeSession(Session session) {
    super.initializeNativeSession(session);

    this.id = ObjectUtils.getIdentityHexString(getNativeSession());
    this.uri = session.getUpgradeRequest().getRequestURI();

    this.headers = new HttpHeaders();
    this.headers.putAll(getNativeSession().getUpgradeRequest().getHeaders());
    this.headers = HttpHeaders.readOnlyHttpHeaders(headers);

    this.acceptedProtocol = session.getUpgradeResponse().getAcceptedSubProtocol();

    List<ExtensionConfig> source = getNativeSession().getUpgradeResponse().getExtensions();
    this.extensions = new ArrayList<WebSocketExtension>(source.size());
    for (ExtensionConfig ec : source) {
      this.extensions.add(new WebSocketExtension(ec.getName(), ec.getParameters()));
    }

    if (this.user == null) {
      this.user = session.getUpgradeRequest().getUserPrincipal();
    }
  }
  /** Verify that incoming frames are passed thru without modification */
  @Test
  public void testIncomingFrames() {
    IncomingFramesCapture capture = new IncomingFramesCapture();

    FragmentExtension ext = new FragmentExtension();
    ext.setBufferPool(new MappedByteBufferPool());
    ext.setPolicy(WebSocketPolicy.newClientPolicy());
    ExtensionConfig config = ExtensionConfig.parse("fragment;maxLength=4");
    ext.setConfig(config);

    ext.setNextIncomingFrames(capture);

    // Quote
    List<String> quote = new ArrayList<>();
    quote.add("No amount of experimentation can ever prove me right;");
    quote.add("a single experiment can prove me wrong.");
    quote.add("-- Albert Einstein");

    // Manually create frame and pass into extension
    for (String q : quote) {
      Frame frame = WebSocketFrame.text(q);
      ext.incomingFrame(frame);
    }

    int len = quote.size();
    capture.assertFrameCount(len);
    capture.assertHasFrame(OpCode.TEXT, len);

    String prefix;
    for (int i = 0; i < len; i++) {
      prefix = "Frame[" + i + "]";

      WebSocketFrame actual = capture.getFrames().get(i);

      Assert.assertThat(prefix + ".opcode", actual.getOpCode(), is(OpCode.TEXT));
      Assert.assertThat(prefix + ".fin", actual.isFin(), is(true));
      Assert.assertThat(prefix + ".rsv1", actual.isRsv1(), is(false));
      Assert.assertThat(prefix + ".rsv2", actual.isRsv2(), is(false));
      Assert.assertThat(prefix + ".rsv3", actual.isRsv3(), is(false));

      ByteBuffer expected = BufferUtil.toBuffer(quote.get(i), StringUtil.__UTF8_CHARSET);
      Assert.assertThat(
          prefix + ".payloadLength", actual.getPayloadLength(), is(expected.remaining()));
      ByteBufferAssert.assertEquals(prefix + ".payload", expected, actual.getPayload().slice());
    }
  }
  private void validateResponse(ClientUpgradeResponse response) {
    // Check the Accept hash
    String reqKey = request.getKey();
    String expectedHash = AcceptHash.hashKey(reqKey);
    response.validateWebSocketHash(expectedHash);

    // Parse extensions
    List<ExtensionConfig> extensions = new ArrayList<>();
    List<String> extValues = response.getHeaders("Sec-WebSocket-Extensions");
    if (extValues != null) {
      for (String extVal : extValues) {
        QuotedStringTokenizer tok = new QuotedStringTokenizer(extVal, ",");
        while (tok.hasMoreTokens()) {
          extensions.add(ExtensionConfig.parse(tok.nextToken()));
        }
      }
    }
    response.setExtensions(extensions);
  }
  private void assertIncoming(byte[] raw, String... expectedTextDatas) {
    WebSocketPolicy policy = WebSocketPolicy.newClientPolicy();

    DeflateFrameExtension ext = new DeflateFrameExtension();
    ext.setBufferPool(bufferPool);
    ext.setPolicy(policy);

    ExtensionConfig config = ExtensionConfig.parse("deflate-frame");
    ext.setConfig(config);

    // Setup capture of incoming frames
    IncomingFramesCapture capture = new IncomingFramesCapture();

    // Wire up stack
    ext.setNextIncomingFrames(capture);

    Parser parser = new UnitParser(policy);
    parser.configureFromExtensions(Collections.singletonList(ext));
    parser.setIncomingFramesHandler(ext);

    parser.parse(ByteBuffer.wrap(raw));

    int len = expectedTextDatas.length;
    capture.assertFrameCount(len);
    capture.assertHasFrame(OpCode.TEXT, len);

    int i = 0;
    for (WebSocketFrame actual : capture.getFrames()) {
      String prefix = "Frame[" + i + "]";
      Assert.assertThat(prefix + ".opcode", actual.getOpCode(), is(OpCode.TEXT));
      Assert.assertThat(prefix + ".fin", actual.isFin(), is(true));
      Assert.assertThat(
          prefix + ".rsv1", actual.isRsv1(), is(false)); // RSV1 should be unset at this point
      Assert.assertThat(prefix + ".rsv2", actual.isRsv2(), is(false));
      Assert.assertThat(prefix + ".rsv3", actual.isRsv3(), is(false));

      ByteBuffer expected = BufferUtil.toBuffer(expectedTextDatas[i], StandardCharsets.UTF_8);
      Assert.assertThat(
          prefix + ".payloadLength", actual.getPayloadLength(), is(expected.remaining()));
      ByteBufferAssert.assertEquals(prefix + ".payload", expected, actual.getPayload().slice());
      i++;
    }
  }
  private void assertOutgoing(String text, String expectedHex) throws IOException {
    WebSocketPolicy policy = WebSocketPolicy.newClientPolicy();

    DeflateFrameExtension ext = new DeflateFrameExtension();
    ext.setBufferPool(bufferPool);
    ext.setPolicy(policy);

    ExtensionConfig config = ExtensionConfig.parse("deflate-frame");
    ext.setConfig(config);

    boolean validating = true;
    Generator generator = new Generator(policy, bufferPool, validating);
    generator.configureFromExtensions(Collections.singletonList(ext));

    OutgoingNetworkBytesCapture capture = new OutgoingNetworkBytesCapture(generator);
    ext.setNextOutgoingFrames(capture);

    Frame frame = new TextFrame().setPayload(text);
    ext.outgoingFrame(frame, null);

    capture.assertBytes(0, expectedHex);
  }
  /** Verify that outgoing text frames are fragmented by default configuration */
  @Test
  public void testOutgoingFramesDefaultConfig() throws IOException {
    OutgoingFramesCapture capture = new OutgoingFramesCapture();

    FragmentExtension ext = new FragmentExtension();
    ext.setBufferPool(new MappedByteBufferPool());
    ext.setPolicy(WebSocketPolicy.newServerPolicy());
    ExtensionConfig config = ExtensionConfig.parse("fragment");
    ext.setConfig(config);

    ext.setNextOutgoingFrames(capture);

    // Quote
    List<String> quote = new ArrayList<>();
    quote.add("No amount of experimentation can ever prove me right;");
    quote.add("a single experiment can prove me wrong.");
    quote.add("-- Albert Einstein");

    // Write quote as separate frames
    for (String section : quote) {
      Frame frame = WebSocketFrame.text(section);
      ext.outgoingFrame(frame, null);
    }

    // Expected Frames
    List<WebSocketFrame> expectedFrames = new ArrayList<>();
    expectedFrames.add(
        new WebSocketFrame(OpCode.TEXT)
            .setPayload("No amount of experimentation can ever prove me right;"));
    expectedFrames.add(
        new WebSocketFrame(OpCode.TEXT).setPayload("a single experiment can prove me wrong."));
    expectedFrames.add(new WebSocketFrame(OpCode.TEXT).setPayload("-- Albert Einstein"));

    // capture.dump();

    int len = expectedFrames.size();
    capture.assertFrameCount(len);

    String prefix;
    LinkedList<WebSocketFrame> frames = capture.getFrames();
    for (int i = 0; i < len; i++) {
      prefix = "Frame[" + i + "]";
      WebSocketFrame actualFrame = frames.get(i);
      WebSocketFrame expectedFrame = expectedFrames.get(i);

      // Validate Frame
      Assert.assertThat(prefix + ".opcode", actualFrame.getOpCode(), is(expectedFrame.getOpCode()));
      Assert.assertThat(prefix + ".fin", actualFrame.isFin(), is(expectedFrame.isFin()));
      Assert.assertThat(prefix + ".rsv1", actualFrame.isRsv1(), is(expectedFrame.isRsv1()));
      Assert.assertThat(prefix + ".rsv2", actualFrame.isRsv2(), is(expectedFrame.isRsv2()));
      Assert.assertThat(prefix + ".rsv3", actualFrame.isRsv3(), is(expectedFrame.isRsv3()));

      // Validate Payload
      ByteBuffer expectedData = expectedFrame.getPayload().slice();
      ByteBuffer actualData = actualFrame.getPayload().slice();

      Assert.assertThat(
          prefix + ".payloadLength", actualData.remaining(), is(expectedData.remaining()));
      ByteBufferAssert.assertEquals(prefix + ".payload", expectedData, actualData);
    }
  }
 @Override
 public void setConfig(ExtensionConfig config) {
   super.setConfig(config);
   maxLength = config.getParameter("maxLength", -1);
 }