15size_t pc_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)
21 size_t total = GRPCWEB_PREFIX_LEN + body_len;
27 buf[1] = (uint8_t)(body_len >> 24);
28 buf[2] = (uint8_t)(body_len >> 16);
29 buf[3] = (uint8_t)(body_len >> 8);
30 buf[4] = (uint8_t)(body_len);
33 memcpy(buf + GRPCWEB_PREFIX_LEN, body, body_len);
38size_t pc_grpcweb_frame_message(uint8_t *buf,
size_t cap,
const uint8_t *msg,
size_t msg_len,
bool compressed)
40 return pc_grpcweb_frame(buf, cap, compressed ? GRPCWEB_FLAG_COMPRESSED : 0, msg, msg_len);
44static bool put_str(uint8_t *buf,
size_t cap,
size_t *pos,
const char *s)
46 size_t n = strnlen(s, cap + 1);
51 memcpy(buf + *pos, s, n);
57static bool put_int(uint8_t *buf,
size_t cap,
size_t *pos,
int v)
73 rev[r++] = (char)(
'0' + (v % 10));
84 memcpy(buf + *pos, tmp, n);
89size_t pc_grpcweb_frame_trailer(uint8_t *buf,
size_t cap,
int status,
const char *message)
91 if (!buf || cap < GRPCWEB_PREFIX_LEN)
95 size_t pos = GRPCWEB_PREFIX_LEN;
96 if (!put_str(buf, cap, &pos,
"grpc-status:") || !put_int(buf, cap, &pos, status) ||
97 !put_str(buf, cap, &pos,
"\r\n"))
101 if (message && *message)
103 if (!put_str(buf, cap, &pos,
"grpc-message:") || !put_str(buf, cap, &pos, message) ||
104 !put_str(buf, cap, &pos,
"\r\n"))
109 size_t body_len = pos - GRPCWEB_PREFIX_LEN;
110 buf[0] = GRPCWEB_FLAG_TRAILER;
111 buf[1] = (uint8_t)(body_len >> 24);
112 buf[2] = (uint8_t)(body_len >> 16);
113 buf[3] = (uint8_t)(body_len >> 8);
114 buf[4] = (uint8_t)(body_len);
118bool pc_grpcweb_parse(
const uint8_t *buf,
size_t len, GrpcWebFrame *out,
size_t *consumed)
120 if (!buf || !out || !consumed || len < GRPCWEB_PREFIX_LEN)
124 uint32_t body_len = ((uint32_t)buf[1] << 24) | ((uint32_t)buf[2] << 16) | ((uint32_t)buf[3] << 8) | buf[4];
125 if ((
size_t)GRPCWEB_PREFIX_LEN + body_len > len)
130 out->compressed = (buf[0] & GRPCWEB_FLAG_COMPRESSED) != 0;
131 out->trailer = (buf[0] & GRPCWEB_FLAG_TRAILER) != 0;
132 out->body = buf + GRPCWEB_PREFIX_LEN;
133 out->body_len = body_len;
134 *consumed = GRPCWEB_PREFIX_LEN + body_len;
138bool pc_grpcweb_trailer_status(
const uint8_t *body,
size_t len,
int *status)
144 static const char key[] =
"grpc-status:";
145 const size_t klen =
sizeof(key) - 1;
146 for (
size_t i = 0; i + klen <= len; i++)
149 if ((i == 0 || body[i - 1] ==
'\n') && memcmp(body + i, key, klen) == 0)
152 if (j >= len || body[j] <
'0' || body[j] >
'9')
157 for (; j < len && body[j] >=
'0' && body[j] <=
'9'; j++)
159 v = v * 10 + (body[j] -
'0');
171bool pc_grpcweb_trailer_message(
const uint8_t *body,
size_t len,
const char **msg,
size_t *msg_len)
177 static const char key[] =
"grpc-message:";
178 const size_t klen =
sizeof(key) - 1;
179 for (
size_t i = 0; i + klen <= len; i++)
182 if ((i == 0 || body[i - 1] ==
'\n') && memcmp(body + i, key, klen) == 0)
184 size_t start = i + klen;
186 while (j < len && body[j] !=
'\r' && body[j] !=
'\n')
192 *msg = (
const char *)(body + start);
196 *msg_len = j - start;
gRPC-Web message framing (PC_ENABLE_GRPC_WEB) - zero-heap length-prefixed frame builder + parser,...