Skip to content

Commit 2821d91

Browse files
committed
Remove unmasking logic (only needed on server)
1 parent dd6b212 commit 2821d91

3 files changed

Lines changed: 2 additions & 68 deletions

File tree

core/src/main/java/io/questdb/client/cutlass/http/client/WebSocketClient.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -772,11 +772,6 @@ private Boolean tryParseFrame(WebSocketFrameHandler handler) {
772772
}
773773
int payloadLen = (int) payloadLength;
774774

775-
// Unmask if needed (server frames should not be masked)
776-
if (frameParser.isMasked()) {
777-
frameParser.unmaskPayload(payloadPtr, payloadLen);
778-
}
779-
780775
// Handle frame by opcode
781776
int opcode = frameParser.getOpcode();
782777
switch (opcode) {

core/src/main/java/io/questdb/client/cutlass/qwp/websocket/WebSocketFrameParser.java

Lines changed: 2 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ public class WebSocketFrameParser {
6060
// Frame header bits
6161
private static final int FIN_BIT = 0x80;
6262
private static final int LENGTH_MASK = 0x7F;
63-
private static final int MASK_BIT = 0x80;
6463
// Control frame max payload size (RFC 6455)
6564
private static final int MAX_CONTROL_FRAME_PAYLOAD = 125;
6665
private static final int OPCODE_MASK = 0x0F;
@@ -69,8 +68,6 @@ public class WebSocketFrameParser {
6968
// Parsed frame data
7069
private boolean fin;
7170
private int headerSize;
72-
private int maskKey;
73-
private boolean masked;
7471
private int opcode;
7572
private long payloadLength;
7673
// Parser state
@@ -100,10 +97,6 @@ public boolean isFin() {
10097
return fin;
10198
}
10299

103-
public boolean isMasked() {
104-
return masked;
105-
}
106-
107100
/**
108101
* Parses a WebSocket frame from the given buffer.
109102
*
@@ -147,15 +140,10 @@ public int parse(long buf, long limit) {
147140
return 0;
148141
}
149142

150-
final boolean masked = (byte1 & MASK_BIT) != 0;
151-
this.masked = masked;
152143
int lengthField = byte1 & LENGTH_MASK;
153144

154-
// Validate masking based on mode
155-
// Configuration
156-
// If true, expect masked frames from clients
157-
if (masked) {
158-
// Server frames MUST NOT be masked
145+
// Server frames MUST NOT be masked (RFC 6455 section 5.1)
146+
if ((byte1 & 0x80) != 0) {
159147
state = STATE_ERROR;
160148
errorCode = WebSocketCloseCode.PROTOCOL_ERROR;
161149
return 0;
@@ -164,7 +152,6 @@ public int parse(long buf, long limit) {
164152
// Calculate header size and payload length
165153
int offset = 2;
166154

167-
// If true, reject non-minimal length encodings
168155
if (lengthField <= 125) {
169156
payloadLength = lengthField;
170157
} else if (lengthField == 126) {
@@ -176,9 +163,6 @@ public int parse(long buf, long limit) {
176163
int high = Unsafe.getUnsafe().getByte(buf + 2) & 0xFF;
177164
int low = Unsafe.getUnsafe().getByte(buf + 3) & 0xFF;
178165
payloadLength = (high << 8) | low;
179-
180-
// Strict mode: reject non-minimal encodings
181-
182166
offset = 4;
183167
} else {
184168
// 64-bit extended length
@@ -188,8 +172,6 @@ public int parse(long buf, long limit) {
188172
}
189173
payloadLength = Long.reverseBytes(Unsafe.getUnsafe().getLong(buf + 2));
190174

191-
// Strict mode: reject non-minimal encodings
192-
193175
// MSB must be 0 (no negative lengths)
194176
if (payloadLength < 0) {
195177
state = STATE_ERROR;
@@ -214,7 +196,6 @@ public int parse(long buf, long limit) {
214196
return 0;
215197
}
216198

217-
maskKey = 0;
218199
headerSize = offset;
219200

220201
// Check if we have the complete payload
@@ -235,50 +216,9 @@ public void reset() {
235216
state = STATE_HEADER;
236217
fin = false;
237218
opcode = 0;
238-
masked = false;
239-
maskKey = 0;
240219
payloadLength = 0;
241220
headerSize = 0;
242221
errorCode = 0;
243222
}
244223

245-
/**
246-
* Unmasks the payload data in place.
247-
*
248-
* @param buf the start of the payload data
249-
* @param len the length of the payload
250-
*/
251-
public void unmaskPayload(long buf, long len) {
252-
if (!masked || maskKey == 0) {
253-
// a zero maskKey is a no-op (makes no change to the data)
254-
return;
255-
}
256-
257-
// Process 8 bytes at a time when possible for better performance
258-
long i = 0;
259-
long longMask = ((long) maskKey << 32) | (maskKey & 0xFFFFFFFFL);
260-
261-
// Process 8-byte chunks
262-
while (i + 8 <= len) {
263-
long value = Unsafe.getUnsafe().getLong(buf + i);
264-
Unsafe.getUnsafe().putLong(buf + i, value ^ longMask);
265-
i += 8;
266-
}
267-
268-
// Process 4-byte chunk if remaining
269-
if (i + 4 <= len) {
270-
int value = Unsafe.getUnsafe().getInt(buf + i);
271-
Unsafe.getUnsafe().putInt(buf + i, value ^ maskKey);
272-
i += 4;
273-
}
274-
275-
// Process remaining bytes
276-
while (i < len) {
277-
byte b = Unsafe.getUnsafe().getByte(buf + i);
278-
int shift = ((int) (i % 4)) << 3; // 0, 8, 16, or 24
279-
byte maskByte = (byte) ((maskKey >> shift) & 0xFF);
280-
Unsafe.getUnsafe().putByte(buf + i, (byte) (b ^ maskByte));
281-
i++;
282-
}
283-
}
284224
}

core/src/test/java/io/questdb/client/test/cutlass/qwp/websocket/WebSocketFrameParserTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,6 @@ public void testParseMinimalFrame() throws Exception {
466466
Assert.assertTrue(parser.isFin());
467467
Assert.assertEquals(WebSocketOpcode.BINARY, parser.getOpcode());
468468
Assert.assertEquals(1, parser.getPayloadLength());
469-
Assert.assertFalse(parser.isMasked());
470469
} finally {
471470
freeBuffer(buf, 16);
472471
}

0 commit comments

Comments
 (0)