1 module hunt.http.codec.websocket.frame.ControlFrame; 2 3 import hunt.http.codec.websocket.frame.AbstractWebSocketFrame; 4 import hunt.http.Exceptions; 5 6 import hunt.io.BufferUtils; 7 import hunt.io.ByteBuffer; 8 9 import std.conv; 10 11 abstract class ControlFrame : AbstractWebSocketFrame { 12 /** 13 * Maximum size of Control frame, per RFC 6455 14 */ 15 enum int MAX_CONTROL_PAYLOAD = 125; 16 17 this(byte opcode) { 18 super(opcode); 19 } 20 21 override void assertValid() { 22 if (isControlFrame()) { 23 if (getPayloadLength() > ControlFrame.MAX_CONTROL_PAYLOAD) { 24 throw new ProtocolException("Desired payload length [" ~ getPayloadLength().to!string() ~ 25 "] exceeds maximum control payload length [" ~ 26 MAX_CONTROL_PAYLOAD.to!string() ~ "]"); 27 } 28 29 if ((finRsvOp & 0x80) == 0) { 30 throw new ProtocolException("Cannot have FIN==false on Control frames"); 31 } 32 33 if ((finRsvOp & 0x40) != 0) { 34 throw new ProtocolException("Cannot have RSV1==true on Control frames"); 35 } 36 37 if ((finRsvOp & 0x20) != 0) { 38 throw new ProtocolException("Cannot have RSV2==true on Control frames"); 39 } 40 41 if ((finRsvOp & 0x10) != 0) { 42 throw new ProtocolException("Cannot have RSV3==true on Control frames"); 43 } 44 } 45 } 46 47 override bool opEquals(Object obj) { 48 if (obj is null) 49 return false; 50 51 if (this is obj) 52 return true; 53 54 ControlFrame other = cast(ControlFrame) obj; 55 if(other is null) return false; 56 57 if (data is null) { 58 if (other.data !is null) { 59 return false; 60 } 61 } else if (!data.opEquals(other.data)) { 62 return false; 63 } 64 return finRsvOp == other.finRsvOp && mask == other.mask && masked == other.masked; 65 } 66 67 override bool isControlFrame() { 68 return true; 69 } 70 71 override 72 bool isDataFrame() { 73 return false; 74 } 75 76 override 77 AbstractWebSocketFrame setPayload(ByteBuffer buf) { 78 if (buf !is null && buf.remaining() > MAX_CONTROL_PAYLOAD) { 79 throw new ProtocolException("Control Payloads can not exceed " ~ MAX_CONTROL_PAYLOAD ~ " bytes in length."); 80 } 81 return super.setPayload(buf); 82 } 83 84 override 85 ByteBuffer getPayload() { 86 if (super.getPayload() is null) { 87 return BufferUtils.EMPTY_BUFFER; 88 } 89 return super.getPayload(); 90 } 91 }