11#if DETWS_ENABLE_GRPC_WEB
15size_t grpcweb_frame(uint8_t *buf,
size_t cap, uint8_t flags,
const uint8_t *body,
size_t body_len)
17 if (!buf || (body_len && !body) || body_len > 0xFFFFFFFFu)
19 size_t total = GRPCWEB_PREFIX_LEN + body_len;
23 buf[1] = (uint8_t)(body_len >> 24);
24 buf[2] = (uint8_t)(body_len >> 16);
25 buf[3] = (uint8_t)(body_len >> 8);
26 buf[4] = (uint8_t)(body_len);
28 memcpy(buf + GRPCWEB_PREFIX_LEN, body, body_len);
32size_t grpcweb_frame_message(uint8_t *buf,
size_t cap,
const uint8_t *msg,
size_t msg_len,
bool compressed)
34 return grpcweb_frame(buf, cap, compressed ? GRPCWEB_FLAG_COMPRESSED : 0, msg, msg_len);
38static bool put_str(uint8_t *buf,
size_t cap,
size_t *pos,
const char *s)
40 size_t n = strnlen(s, cap + 1);
43 memcpy(buf + *pos, s, n);
49static bool put_int(uint8_t *buf,
size_t cap,
size_t *pos,
int v)
61 rev[r++] = (char)(
'0' + (v % 10));
68 memcpy(buf + *pos, tmp, n);
73size_t grpcweb_frame_trailer(uint8_t *buf,
size_t cap,
int status,
const char *message)
75 if (!buf || cap < GRPCWEB_PREFIX_LEN)
77 size_t pos = GRPCWEB_PREFIX_LEN;
78 if (!put_str(buf, cap, &pos,
"grpc-status:") || !put_int(buf, cap, &pos, status) ||
79 !put_str(buf, cap, &pos,
"\r\n"))
81 if (message && *message)
83 if (!put_str(buf, cap, &pos,
"grpc-message:") || !put_str(buf, cap, &pos, message) ||
84 !put_str(buf, cap, &pos,
"\r\n"))
87 size_t body_len = pos - GRPCWEB_PREFIX_LEN;
88 buf[0] = GRPCWEB_FLAG_TRAILER;
89 buf[1] = (uint8_t)(body_len >> 24);
90 buf[2] = (uint8_t)(body_len >> 16);
91 buf[3] = (uint8_t)(body_len >> 8);
92 buf[4] = (uint8_t)(body_len);
96bool grpcweb_parse(
const uint8_t *buf,
size_t len, GrpcWebFrame *out,
size_t *consumed)
98 if (!buf || !out || !consumed || len < GRPCWEB_PREFIX_LEN)
100 uint32_t body_len = ((uint32_t)buf[1] << 24) | ((uint32_t)buf[2] << 16) | ((uint32_t)buf[3] << 8) | buf[4];
101 if ((
size_t)GRPCWEB_PREFIX_LEN + body_len > len)
104 out->compressed = (buf[0] & GRPCWEB_FLAG_COMPRESSED) != 0;
105 out->trailer = (buf[0] & GRPCWEB_FLAG_TRAILER) != 0;
106 out->body = buf + GRPCWEB_PREFIX_LEN;
107 out->body_len = body_len;
108 *consumed = GRPCWEB_PREFIX_LEN + body_len;
112bool grpcweb_trailer_status(
const uint8_t *body,
size_t len,
int *status)
116 static const char key[] =
"grpc-status:";
117 const size_t klen =
sizeof(key) - 1;
118 for (
size_t i = 0; i + klen <= len; i++)
121 if ((i == 0 || body[i - 1] ==
'\n') && memcmp(body + i, key, klen) == 0)
124 if (j >= len || body[j] <
'0' || body[j] >
'9')
127 for (; j < len && body[j] >=
'0' && body[j] <=
'9'; j++)
128 v = v * 10 + (body[j] -
'0');
gRPC-Web message framing (DETWS_ENABLE_GRPC_WEB) - zero-heap length-prefixed frame builder + parser,...