MINOR: sample: Extract some protocol buffers specific code.
We move the code responsible of parsing protocol buffers messages
inside gRPC messages from sample.c to include/proto/protocol_buffers.h
so that to reuse it to cascade "ungrpc" converter.
diff --git a/include/proto/protocol_buffers.h b/include/proto/protocol_buffers.h
index 97f9bf5..a9deab1 100644
--- a/include/proto/protocol_buffers.h
+++ b/include/proto/protocol_buffers.h
@@ -23,6 +23,7 @@
#define _PROTO_PROTOCOL_BUFFERS_H
#include <stdint.h>
+#include <types/arg.h>
#include <types/protocol_buffers.h>
#include <proto/sample.h>
@@ -477,6 +478,95 @@
return 1;
}
+/*
+ * Lookup for a protocol buffers field whose parameters are provided by <arg_p>
+ * first argument in the buffer with <pos> as address and <len> as length address.
+ * If found, store its value depending on the type of storage to use provided by <arg_p>
+ * second argument and return 1, 0 if not.
+ */
+static inline int protobuf_field_lookup(const struct arg *arg_p, struct sample *smp,
+ unsigned char **pos, size_t *len)
+{
+ unsigned int *fid;
+ size_t fid_sz;
+ int type;
+ uint64_t elen;
+ int field;
+
+ fid = arg_p[0].data.fid.ids;
+ fid_sz = arg_p[0].data.fid.sz;
+ type = arg_p[1].data.sint;
+
+ /* Length of the length-delimited messages if any. */
+ elen = 0;
+ field = 0;
+
+ while (field < fid_sz) {
+ int found;
+ uint64_t key, sleft;
+ struct protobuf_parser_def *pbuf_parser = NULL;
+ unsigned int wire_type, field_number;
+
+ if ((ssize_t)*len <= 0)
+ return 0;
+
+ /* Remaining bytes saving. */
+ sleft = *len;
+
+ /* Key decoding */
+ if (!protobuf_decode_varint(&key, pos, len))
+ return 0;
+
+ wire_type = key & 0x7;
+ field_number = key >> 3;
+ found = field_number == fid[field];
+
+ /* Skip the data if the current field does not match. */
+ switch (wire_type) {
+ case PBUF_TYPE_VARINT:
+ case PBUF_TYPE_32BIT:
+ case PBUF_TYPE_64BIT:
+ pbuf_parser = &protobuf_parser_defs[wire_type];
+ if (!found && !pbuf_parser->skip(pos, len, 0))
+ return 0;
+ break;
+
+ case PBUF_TYPE_LENGTH_DELIMITED:
+ /* Decode the length of this length-delimited field. */
+ if (!protobuf_decode_varint(&elen, pos, len) || elen > *len)
+ return 0;
+
+ /* The size of the current field is computed from here to skip
+ * the bytes used to encode the previous length.*
+ */
+ sleft = *len;
+ pbuf_parser = &protobuf_parser_defs[wire_type];
+ if (!found && !pbuf_parser->skip(pos, len, elen))
+ return 0;
+ break;
+
+ default:
+ return 0;
+ }
+
+ /* Store the data if found. Note that <pbuf_parser> is not NULL */
+ if (found && field == fid_sz - 1)
+ return pbuf_parser->smp_store(smp, type, *pos, *len, elen);
+
+ if ((ssize_t)(elen) > 0)
+ elen -= sleft - *len;
+
+ if (found) {
+ field++;
+ }
+ else if ((ssize_t)elen <= 0) {
+ field = 0;
+ }
+ }
+
+ return 0;
+}
+
#endif /* _PROTO_PROTOCOL_BUFFERS_H */
/*
diff --git a/src/sample.c b/src/sample.c
index 5b0ccc9..e95c57c 100644
--- a/src/sample.c
+++ b/src/sample.c
@@ -2763,26 +2763,12 @@
{
unsigned char *pos;
size_t grpc_left;
- unsigned int *fid;
- size_t fid_sz;
- int type;
-
- if (!smp->strm)
- return 0;
-
- fid = arg_p[0].data.fid.ids;
- fid_sz = arg_p[0].data.fid.sz;
- type = arg_p[1].data.sint;
pos = (unsigned char *)smp->data.u.str.area;
- /* Remaining bytes in the body to be parsed. */
grpc_left = smp->data.u.str.data;
while (grpc_left > GRPC_MSG_HEADER_SZ) {
- int field, found;
size_t grpc_msg_len, left;
- unsigned int wire_type, field_number;
- uint64_t key, elen;
grpc_msg_len = left = ntohl(*(uint32_t *)(pos + GRPC_MSG_COMPRESS_FLAG_SZ));
@@ -2792,92 +2778,9 @@
if (grpc_left < left)
return 0;
- found = 1;
- /* Length of the length-delimited messages if any. */
- elen = 0;
-
- /* Message decoding: there may be serveral key+value protobuf pairs by
- * gRPC message.
- */
- field = 0;
- while (field < fid_sz) {
- uint64_t sleft;
-
- if ((ssize_t)left <= 0)
- return 0;
-
- /* Remaining bytes saving. */
- sleft = left;
-
- /* Key decoding */
- if (!protobuf_decode_varint(&key, &pos, &left))
- return 0;
-
- wire_type = key & 0x7;
- field_number = key >> 3;
- found = field_number == fid[field];
-
- switch (wire_type) {
- case PBUF_TYPE_VARINT:
- case PBUF_TYPE_32BIT:
- case PBUF_TYPE_64BIT:
- {
- struct protobuf_parser_def *pbuf_parser;
-
- pbuf_parser = &protobuf_parser_defs[wire_type];
- if (!found) {
- /* Skip the data. */
- if (!pbuf_parser->skip(&pos, &left, 0))
- return 0;
- }
- else if (field == fid_sz - 1) {
- return pbuf_parser->smp_store(smp, type, pos, left, 0);
- }
-
- break;
- }
-
- case PBUF_TYPE_LENGTH_DELIMITED:
- {
- struct protobuf_parser_def *pbuf_parser;
-
- /* Decode the length of this length-delimited field. */
- if (!protobuf_decode_varint(&elen, &pos, &left))
- return 0;
-
- if (elen > left)
- return 0;
-
- /* The size of the current field is computed from here do skip
- * the bytes to encode the previous lenght.*
- */
- sleft = left;
- pbuf_parser = &protobuf_parser_defs[wire_type];
- if (!found) {
- /* Skip the data. */
- if (!pbuf_parser->skip(&pos, &left, elen))
- return 0;
- } else if (field == fid_sz - 1) {
- return pbuf_parser->smp_store(smp, type, pos, left, elen);
- }
-
- break;
- }
-
- default:
- return 0;
- }
-
- if ((ssize_t)(elen) > 0)
- elen -= sleft - left;
+ if (protobuf_field_lookup(arg_p, smp, &pos, &left))
+ return 1;
- if (found) {
- field++;
- }
- else if ((ssize_t)elen <= 0) {
- field = 0;
- }
- }
grpc_left -= grpc_msg_len;
}