1 module hunt.http.codec.websocket.decode.payload; 2 3 import hunt.http.Exceptions; 4 import hunt.http.WebSocketFrame; 5 6 import hunt.io.ByteBuffer; 7 import hunt.http.WebSocketFrame; 8 9 import hunt.io.ByteBuffer; 10 11 12 /** 13 * Process the payload (for demasking, validating, etc..) 14 */ 15 interface PayloadProcessor { 16 /** 17 * Used to process payloads for in the spec. 18 * 19 * @param payload the payload to process 20 * @throws BadPayloadException the exception when the payload fails to validate properly 21 */ 22 void process(ByteBuffer payload); 23 24 void reset(WebSocketFrame frame); 25 } 26 27 class DeMaskProcessor : PayloadProcessor { 28 private byte[] maskBytes; 29 private int maskInt; 30 private int maskOffset; 31 32 void process(ByteBuffer payload) { 33 if (maskBytes is null) { 34 return; 35 } 36 37 int maskInt = this.maskInt; 38 int start = payload.position(); 39 int end = payload.limit(); 40 int offset = this.maskOffset; 41 int remaining; 42 while ((remaining = end - start) > 0) { 43 if (remaining >= 4 && (offset & 3) == 0) { 44 payload.putInt(start, payload.getInt(start) ^ maskInt); 45 start += 4; 46 offset += 4; 47 } else { 48 payload.put(start, cast(byte) (payload.get(start) ^ maskBytes[offset & 3])); 49 ++start; 50 ++offset; 51 } 52 } 53 maskOffset = offset; 54 } 55 56 void reset(byte[] mask) { 57 this.maskBytes = mask; 58 int maskInt = 0; 59 if (mask !is null) { 60 foreach (byte maskByte ; mask) 61 maskInt = (maskInt << 8) + (maskByte & 0xFF); 62 } 63 this.maskInt = maskInt; 64 this.maskOffset = 0; 65 } 66 67 override 68 void reset(WebSocketFrame frame) { 69 reset(frame.getMask()); 70 } 71 } 72 73