Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
Expand Down Expand Up @@ -47,15 +46,14 @@ public class PerMessageDeflateExtension extends CompressionExtension {
private boolean serverNoContextTakeover = true;
private boolean clientNoContextTakeover = false;

// For WebSocketServers, this variable holds the extension parameters that the peer client has requested.
// For WebSocketClients, this variable holds the extension parameters that client himself has requested.
private Map<String, String> requestedParameters = new LinkedHashMap<>();

private final int compressionLevel;

private final Inflater inflater;
private final Deflater deflater;

private boolean resetDeflater = false;
private boolean resetInflater = false;

/**
* Constructor for the PerMessage Deflate Extension (<a href="https://tools.ietf.org/html/rfc7692#section-7">7&#46; Thepermessage-deflate" Extension</a>)
*
Expand Down Expand Up @@ -184,8 +182,8 @@ We can check the getRemaining() method to see whether the data we supplied has b

if (inputFrame.isFin()) {
decompress(TAIL_BYTES, output);
// If context takeover is disabled, inflater can be reset.
if (clientNoContextTakeover) {
// If context takeover is disabled on the other end, inflater can be reset.
if (resetInflater) {
inflater.reset();
}
}
Expand Down Expand Up @@ -254,8 +252,8 @@ public void encodeFrame(Framedata inputFrame) {
if (endsWithTail(outputBytes)) {
outputLength -= TAIL_BYTES.length;
}

if (serverNoContextTakeover) {
// If context takeover is disabled on this end, deflater can be reset.
if (resetDeflater) {
deflater.reset();
}
}
Expand Down Expand Up @@ -294,11 +292,19 @@ public boolean acceptProvidedExtensionAsServer(String inputExtension) {

// Holds parameters that peer client has sent.
Map<String, String> headers = extensionData.getExtensionParameters();
requestedParameters.putAll(headers);
if (requestedParameters.containsKey(CLIENT_NO_CONTEXT_TAKEOVER)) {
if (headers.containsKey(SERVER_NO_CONTEXT_TAKEOVER)) {
serverNoContextTakeover = true;
}
if (headers.containsKey(CLIENT_NO_CONTEXT_TAKEOVER)) {
clientNoContextTakeover = true;
}

// RFC 7692:
// server_ prefix parameters configure the server compressor (deflater)
// client_ prefix parameters configure the server decompressor (inflater)
resetDeflater = serverNoContextTakeover;
resetInflater = clientNoContextTakeover;

return true;
}

Expand All @@ -316,7 +322,25 @@ public boolean acceptProvidedExtensionAsClient(String inputExtension) {

// Holds parameters that are sent by the server, as a response to our initial extension request.
Map<String, String> headers = extensionData.getExtensionParameters();
// After this point, parameters that the server sent back can be configured, but we don't use them for now.
if (headers.containsKey(SERVER_NO_CONTEXT_TAKEOVER)) {
serverNoContextTakeover = true;
} else {
// If the server does not return server_no_context_takeover, the client must not reset the
// decompressor (inflater) because that would break communication. Note that in contrast,
// the client can reset the compressor (deflater) even if the server does not reset the
// decompressor (inflater), so this is not required for client_no_context_takeover below.
serverNoContextTakeover = false;
}
if (headers.containsKey(CLIENT_NO_CONTEXT_TAKEOVER)) {
clientNoContextTakeover = true;
}

// RFC 7692:
// client_ prefix parameters configure the client compressor (deflater)
// server_ prefix parameters configure the client decompressor (inflater)
resetDeflater = clientNoContextTakeover;
resetInflater = serverNoContextTakeover;

return true;
}

Expand All @@ -325,17 +349,15 @@ public boolean acceptProvidedExtensionAsClient(String inputExtension) {

@Override
public String getProvidedExtensionAsClient() {
requestedParameters.put(CLIENT_NO_CONTEXT_TAKEOVER, ExtensionRequestData.EMPTY_VALUE);
requestedParameters.put(SERVER_NO_CONTEXT_TAKEOVER, ExtensionRequestData.EMPTY_VALUE);

return EXTENSION_REGISTERED_NAME + "; " + SERVER_NO_CONTEXT_TAKEOVER + "; "
+ CLIENT_NO_CONTEXT_TAKEOVER;
return EXTENSION_REGISTERED_NAME
+ (serverNoContextTakeover ? "; " + SERVER_NO_CONTEXT_TAKEOVER : "")
+ (clientNoContextTakeover ? "; " + CLIENT_NO_CONTEXT_TAKEOVER : "");
}

@Override
public String getProvidedExtensionAsServer() {
return EXTENSION_REGISTERED_NAME
+ "; " + SERVER_NO_CONTEXT_TAKEOVER
+ (serverNoContextTakeover ? "; " + SERVER_NO_CONTEXT_TAKEOVER : "")
+ (clientNoContextTakeover ? "; " + CLIENT_NO_CONTEXT_TAKEOVER : "");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ public void testIsFrameValid() {
@Test
public void testGetProvidedExtensionAsClient() {
PerMessageDeflateExtension deflateExtension = new PerMessageDeflateExtension();
assertEquals("permessage-deflate; server_no_context_takeover; client_no_context_takeover",
assertEquals("permessage-deflate; server_no_context_takeover",
deflateExtension.getProvidedExtensionAsClient());
}

Expand Down Expand Up @@ -242,6 +242,8 @@ public void testSetServerNoContextTakeover() {
PerMessageDeflateExtension deflateExtension = new PerMessageDeflateExtension();
deflateExtension.setServerNoContextTakeover(false);
assertFalse(deflateExtension.isServerNoContextTakeover());
assertEquals("permessage-deflate",
deflateExtension.getProvidedExtensionAsServer());
}

@Test
Expand All @@ -255,6 +257,8 @@ public void testSetClientNoContextTakeover() {
PerMessageDeflateExtension deflateExtension = new PerMessageDeflateExtension();
deflateExtension.setClientNoContextTakeover(true);
assertTrue(deflateExtension.isClientNoContextTakeover());
assertEquals("permessage-deflate; server_no_context_takeover; client_no_context_takeover",
deflateExtension.getProvidedExtensionAsClient());
}

@Test
Expand Down
Loading