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