16static size_t put16(uint8_t *p, uint16_t v)
18 p[0] = (uint8_t)(v >> 8);
23static size_t put32(uint8_t *p, uint32_t v)
25 p[0] = (uint8_t)(v >> 24);
26 p[1] = (uint8_t)(v >> 16);
27 p[2] = (uint8_t)(v >> 8);
32static uint16_t get16(
const uint8_t *p)
34 return (uint16_t)(((uint16_t)p[0] << 8) | p[1]);
37static uint32_t get32(
const uint8_t *p)
39 return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | p[3];
42size_t amqp_protocol_header(uint8_t *buf,
size_t cap)
44 static const uint8_t hdr[8] = {
'A',
'M',
'Q',
'P', 0, 0, 9, 1};
45 if (!buf || cap <
sizeof(hdr))
47 memcpy(buf, hdr,
sizeof(hdr));
52static size_t write_frame_header(uint8_t *buf, uint8_t type, uint16_t channel, uint32_t size)
56 p += put16(buf + p, channel);
57 p += put32(buf + p, size);
61size_t amqp_build_frame(uint8_t *buf,
size_t cap, uint8_t type, uint16_t channel,
const uint8_t *payload,
64 if (!buf || (payload_len && !payload) || payload_len > 0xFFFFFFFFu)
66 size_t total = AMQP_FRAME_OVERHEAD + payload_len;
69 size_t p = write_frame_header(buf, type, channel, (uint32_t)payload_len);
72 memcpy(buf + p, payload, payload_len);
75 buf[p++] = AMQP_FRAME_END;
79size_t amqp_build_method(uint8_t *buf,
size_t cap, uint16_t channel, uint16_t class_id, uint16_t method_id,
80 const uint8_t *args,
size_t args_len)
82 if (!buf || (args_len && !args))
84 size_t payload_len = 4 + args_len;
85 size_t total = AMQP_FRAME_OVERHEAD + payload_len;
89 size_t p = write_frame_header(buf, AMQP_FRAME_METHOD, channel, (uint32_t)payload_len);
90 p += put16(buf + p, class_id);
91 p += put16(buf + p, method_id);
94 memcpy(buf + p, args, args_len);
97 buf[p++] = AMQP_FRAME_END;
101size_t amqp_build_heartbeat(uint8_t *buf,
size_t cap)
103 return amqp_build_frame(buf, cap, AMQP_FRAME_HEARTBEAT, 0,
nullptr, 0);
106bool amqp_parse_frame(
const uint8_t *buf,
size_t len, AmqpFrame *out,
size_t *consumed)
108 if (!buf || !out || len < AMQP_FRAME_OVERHEAD)
110 uint32_t size = get32(buf + 3);
113 if (size > len - AMQP_FRAME_OVERHEAD)
115 size_t total = AMQP_FRAME_OVERHEAD + (size_t)size;
116 if (buf[7 + size] != AMQP_FRAME_END)
119 out->channel = get16(buf + 1);
120 out->payload = buf + 7;
121 out->payload_len = size;
127bool amqp_parse_method(
const uint8_t *payload,
size_t payload_len, uint16_t *class_id, uint16_t *method_id,
128 const uint8_t **args,
size_t *args_len)
130 if (!payload || payload_len < 4)
133 *class_id = get16(payload);
135 *method_id = get16(payload + 2);
139 *args_len = payload_len - 4;
AMQP 0-9-1 frame codec (DETWS_ENABLE_AMQP) - zero-heap frame builder + parser for the RabbitMQ wire p...