1 module hunt.http.codec.http.frame.PingFrame; 2 3 import hunt.http.codec.http.frame.Frame; 4 import hunt.http.codec.http.frame.FrameType; 5 6 import hunt.Exceptions; 7 8 class PingFrame :Frame { 9 static int PING_LENGTH = 8; 10 private static byte[] EMPTY_PAYLOAD = new byte[8]; 11 12 private byte[] payload; 13 private bool reply; 14 15 /** 16 * Creates a PING frame with an empty payload. 17 * 18 * @param reply 19 * whether this PING frame is a reply 20 */ 21 this(bool reply) { 22 this(EMPTY_PAYLOAD, reply); 23 } 24 25 /** 26 * Creates a PING frame with the given {@code long} {@code value} as 27 * payload. 28 * 29 * @param value 30 * the value to use as a payload for this PING frame 31 * @param reply 32 * whether this PING frame is a reply 33 */ 34 this(long value, bool reply) { 35 this(toBytes(value), reply); 36 } 37 38 /** 39 * Creates a PING frame with the given {@code payload}. 40 * 41 * @param payload 42 * the payload for this PING frame 43 * @param reply 44 * whether this PING frame is a reply 45 */ 46 this(byte[] payload, bool reply) { 47 assert(payload !is null); 48 super(FrameType.PING); 49 this.payload = payload; 50 if (payload.length != PING_LENGTH) 51 throw new IllegalArgumentException("PING payload must be 8 bytes"); 52 this.reply = reply; 53 } 54 55 byte[] getPayload() { 56 return payload; 57 } 58 59 long getPayloadAsLong() { 60 return toLong(payload); 61 } 62 63 bool isReply() { 64 return reply; 65 } 66 67 private static byte[] toBytes(long value) { 68 byte[] result = new byte[8]; 69 for (size_t i = result.length - 1; i >= 0; --i) { 70 result[i] = cast(byte) (value & 0xFF); 71 value >>= 8; 72 } 73 return result; 74 } 75 76 private static long toLong(byte[] payload) { 77 long result = 0; 78 for (size_t i = 0; i < 8; ++i) { 79 result <<= 8; 80 result |= (payload[i] & 0xFF); 81 } 82 return result; 83 } 84 }