Skip to content

Commit d098fc6

Browse files
committed
Add WebSocket frame size limit & compression ratio
Add a new JSON configuration parameter "WEBSOCKET_MAX_FRAME_SIZE" to set a limit for the maximum WebSocket frame size, as especially with the new compression support, unbounded frame sizes pose a risk. The default is left at 0 (unbounded) to keep compatibility with all existing uses, but it is strongly recommended to set an appropriate limit. Add a new API MultiProtocolJSONClient#getCompressionRatio() to retrieve the current compression ratio for informational purposes. Increase the WebSocket compression threshold from 0 to 64 bytes, as it was observed that frames smaller than 64 bytes typically grow in size when compression is applied.
1 parent f6a609c commit d098fc6

4 files changed

Lines changed: 44 additions & 8 deletions

File tree

ocpp-json/src/main/java/eu/chargetime/ocpp/JSONConfiguration.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public class JSONConfiguration {
3939
public static final String CONNECT_NON_BLOCKING_PARAMETER = "CONNECT_NON_BLOCKING";
4040
public static final String CONNECT_TIMEOUT_IN_MS_PARAMETER = "CONNECT_TIMEOUT_IN_MS";
4141
public static final String WEBSOCKET_COMPRESSION_SUPPORT = "WEBSOCKET_COMPRESSION_SUPPORT";
42+
public static final String WEBSOCKET_MAX_FRAME_SIZE = "WEBSOCKET_MAX_FRAME_SIZE";
4243
public static final String WEBSOCKET_WORKER_COUNT = "WEBSOCKET_WORKER_COUNT";
4344
public static final String HTTP_HEALTH_CHECK_ENABLED = "HTTP_HEALTH_CHECK_ENABLED";
4445
public static final String OCPPJ_CP_MIN_PASSWORD_LENGTH = "OCPPJ_CP_MIN_PASSWORD_LENGTH";

ocpp-v2/src/main/java/eu/chargetime/ocpp/MultiProtocolJSONClient.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,14 @@ public MultiProtocolJSONClient(
8989
List<ProtocolVersion> protocolVersions, String identity, JSONConfiguration configuration) {
9090
this.identity = identity;
9191
featureRepository = new MultiProtocolFeatureRepository(protocolVersions);
92+
int maxFrameSize = configuration.getParameter(JSONConfiguration.WEBSOCKET_MAX_FRAME_SIZE, 0);
9293
List<IExtension> inputExtensions = new ArrayList<>();
9394
if (configuration.getParameter(JSONConfiguration.WEBSOCKET_COMPRESSION_SUPPORT, false)) {
9495
PerMessageDeflateExtension perMessageDeflateExtension =
95-
new PerMessageDeflateExtension(Deflater.BEST_COMPRESSION);
96-
perMessageDeflateExtension.setThreshold(0);
96+
maxFrameSize > 0
97+
? new PerMessageDeflateExtension(Deflater.BEST_COMPRESSION, maxFrameSize)
98+
: new PerMessageDeflateExtension(Deflater.BEST_COMPRESSION);
99+
perMessageDeflateExtension.setThreshold(64);
97100
perMessageDeflateExtension.setServerNoContextTakeover(false);
98101
perMessageDeflateExtension.setClientNoContextTakeover(false);
99102
inputExtensions.add(perMessageDeflateExtension);
@@ -102,7 +105,10 @@ public MultiProtocolJSONClient(
102105
for (ProtocolVersion protocolVersion : protocolVersions) {
103106
inputProtocols.add(new Protocol(protocolVersion.getSubProtocolName()));
104107
}
105-
Draft draft = new Draft_6455(inputExtensions, inputProtocols);
108+
Draft draft =
109+
maxFrameSize > 0
110+
? new Draft_6455(inputExtensions, inputProtocols, maxFrameSize)
111+
: new Draft_6455(inputExtensions, inputProtocols);
106112
transmitter = new MultiProtocolWebSocketTransmitter(featureRepository, configuration, draft);
107113
JSONCommunicator communicator = new JSONCommunicator(transmitter, false);
108114
ISessionFactory sessionFactory = new MultiProtocolSessionFactory(featureRepository);
@@ -216,6 +222,14 @@ public void disconnect() {
216222
client.disconnect();
217223
}
218224

225+
public double getCompressionRatio() {
226+
IExtension extension = transmitter.getExtension();
227+
if (extension instanceof PerMessageDeflateExtension) {
228+
return ((PerMessageDeflateExtension) extension).getCompressionRatio();
229+
}
230+
return 1;
231+
}
232+
219233
public Exception getLastError() {
220234
return transmitter.getLastError();
221235
}

ocpp-v2/src/main/java/eu/chargetime/ocpp/MultiProtocolJSONServer.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,14 @@ public MultiProtocolJSONServer(
6767
List<ProtocolVersion> protocolVersions, JSONConfiguration configuration) {
6868
featureRepository = new MultiProtocolFeatureRepository(protocolVersions);
6969
MultiProtocolSessionFactory sessionFactory = new MultiProtocolSessionFactory(featureRepository);
70-
70+
int maxFrameSize = configuration.getParameter(JSONConfiguration.WEBSOCKET_MAX_FRAME_SIZE, 0);
7171
List<IExtension> extensions = new ArrayList<>();
7272
if (configuration.getParameter(JSONConfiguration.WEBSOCKET_COMPRESSION_SUPPORT, true)) {
7373
PerMessageDeflateExtension perMessageDeflateExtension =
74-
new PerMessageDeflateExtension(Deflater.BEST_COMPRESSION);
75-
perMessageDeflateExtension.setThreshold(0);
74+
maxFrameSize > 0
75+
? new PerMessageDeflateExtension(Deflater.BEST_COMPRESSION, maxFrameSize)
76+
: new PerMessageDeflateExtension(Deflater.BEST_COMPRESSION);
77+
perMessageDeflateExtension.setThreshold(64);
7678
perMessageDeflateExtension.setServerNoContextTakeover(false);
7779
perMessageDeflateExtension.setClientNoContextTakeover(false);
7880
extensions.add(perMessageDeflateExtension);
@@ -81,8 +83,10 @@ public MultiProtocolJSONServer(
8183
for (ProtocolVersion protocolVersion : protocolVersions) {
8284
protocols.add(new Protocol(protocolVersion.getSubProtocolName()));
8385
}
84-
Draft draft = new Draft_6455(extensions, protocols);
85-
86+
Draft draft =
87+
maxFrameSize > 0
88+
? new Draft_6455(extensions, protocols, maxFrameSize)
89+
: new Draft_6455(extensions, protocols);
8690
if (configuration.getParameter(JSONConfiguration.HTTP_HEALTH_CHECK_ENABLED, true)) {
8791
logger.info("JSONServer with HttpHealthCheckDraft");
8892
listener =

ocpp-v2/src/main/java/eu/chargetime/ocpp/MultiProtocolWebSocketTransmitter.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,12 @@ of this software and associated documentation files (the "Software"), to deal
3535
import java.util.HashMap;
3636
import java.util.Map;
3737
import javax.net.SocketFactory;
38+
import org.java_websocket.WebSocket;
3839
import org.java_websocket.client.WebSocketClient;
3940
import org.java_websocket.drafts.Draft;
41+
import org.java_websocket.drafts.Draft_6455;
4042
import org.java_websocket.exceptions.WebsocketNotConnectedException;
43+
import org.java_websocket.extensions.IExtension;
4144
import org.java_websocket.handshake.ServerHandshake;
4245
import org.slf4j.Logger;
4346
import org.slf4j.LoggerFactory;
@@ -264,6 +267,20 @@ public void send(Object request) throws NotConnectedException {
264267
}
265268
}
266269

270+
public IExtension getExtension() {
271+
WebSocketClient webSocketClient = client;
272+
if (webSocketClient != null) {
273+
WebSocket webSocket = webSocketClient.getConnection();
274+
if (webSocket != null) {
275+
Draft draft = webSocket.getDraft();
276+
if (draft instanceof Draft_6455) {
277+
return ((Draft_6455) draft).getExtension();
278+
}
279+
}
280+
}
281+
return null;
282+
}
283+
267284
public Exception getLastError() {
268285
return lastError;
269286
}

0 commit comments

Comments
 (0)