MINOR: sample: Code factorization "ungrpc" converter.
Parsing protocol buffer fields always consists in skip the field if the field is not found or store the field value if found. So, with this patch we factorize a little bit the code for "ungrpc" converter.
This commit is contained in:
parent
9255e7e971
commit
7c93e88d0c
@ -22,19 +22,53 @@
|
||||
#ifndef _PROTO_PROTOCOL_BUFFERS_H
|
||||
#define _PROTO_PROTOCOL_BUFFERS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <types/protocol_buffers.h>
|
||||
|
||||
#define PBUF_TYPE_VARINT 0
|
||||
#define PBUF_TYPE_64BIT 1
|
||||
#define PBUF_TYPE_LENGTH_DELIMITED 2
|
||||
#define PBUF_TYPE_START_GROUP 3
|
||||
#define PBUF_TYPE_STOP_GROUP 4
|
||||
#define PBUF_TYPE_32BIT 5
|
||||
#include <proto/sample.h>
|
||||
|
||||
#define PBUF_VARINT_DONT_STOP_BIT 7
|
||||
#define PBUF_VARINT_DONT_STOP_BITMASK (1 << PBUF_VARINT_DONT_STOP_BIT)
|
||||
#define PBUF_VARINT_DATA_BITMASK ~PBUF_VARINT_DONT_STOP_BITMASK
|
||||
|
||||
/* .skip and .smp_store prototypes. */
|
||||
int protobuf_skip_varint(unsigned char **pos, size_t *len, size_t vlen);
|
||||
int protobuf_smp_store_varint(struct sample *smp,
|
||||
unsigned char *pos, size_t len, size_t vlen);
|
||||
int protobuf_skip_64bit(unsigned char **pos, size_t *len, size_t vlen);
|
||||
int protobuf_smp_store_64bit(struct sample *smp,
|
||||
unsigned char *pos, size_t len, size_t vlen);
|
||||
int protobuf_skip_vlen(unsigned char **pos, size_t *len, size_t vlen);
|
||||
int protobuf_smp_store_vlen(struct sample *smp,
|
||||
unsigned char *pos, size_t len, size_t vlen);
|
||||
int protobuf_skip_32bit(unsigned char **pos, size_t *len, size_t vlen);
|
||||
int protobuf_smp_store_32bit(struct sample *smp,
|
||||
unsigned char *pos, size_t len, size_t vlen);
|
||||
|
||||
struct protobuf_parser_def protobuf_parser_defs [] = {
|
||||
[PBUF_TYPE_VARINT ] = {
|
||||
.skip = protobuf_skip_varint,
|
||||
.smp_store = protobuf_smp_store_varint,
|
||||
},
|
||||
[PBUF_TYPE_64BIT ] = {
|
||||
.skip = protobuf_skip_64bit,
|
||||
.smp_store = protobuf_smp_store_64bit,
|
||||
},
|
||||
[PBUF_TYPE_LENGTH_DELIMITED] = {
|
||||
.skip = protobuf_skip_vlen,
|
||||
.smp_store = protobuf_smp_store_vlen,
|
||||
},
|
||||
[PBUF_TYPE_START_GROUP ] = {
|
||||
/* XXX Deprecated XXX */
|
||||
},
|
||||
[PBUF_TYPE_STOP_GROUP ] = {
|
||||
/* XXX Deprecated XXX */
|
||||
},
|
||||
[PBUF_TYPE_32BIT ] = {
|
||||
.skip = protobuf_skip_32bit,
|
||||
.smp_store = protobuf_smp_store_32bit,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Decode a protocol buffers varint located in a buffer at <pos> address with
|
||||
* <len> as length. The decoded value is stored at <val>.
|
||||
@ -112,8 +146,8 @@ protobuf_decode_varint(uint64_t *val, unsigned char **pos, size_t *len)
|
||||
* available byte. Decrease <*len> by the number of skipped bytes.
|
||||
* Returns 1 if succeeded, 0 if not.
|
||||
*/
|
||||
static inline int
|
||||
protobuf_skip_varint(unsigned char **pos, size_t *len)
|
||||
int
|
||||
protobuf_skip_varint(unsigned char **pos, size_t *len, size_t vlen)
|
||||
{
|
||||
unsigned int shift;
|
||||
|
||||
@ -147,23 +181,23 @@ protobuf_skip_varint(unsigned char **pos, size_t *len)
|
||||
* Return -1 if failed.
|
||||
*/
|
||||
static inline int
|
||||
protobuf_varint_getlen(unsigned char **pos, size_t *len)
|
||||
protobuf_varint_getlen(unsigned char *pos, size_t len)
|
||||
{
|
||||
unsigned char *spos;
|
||||
unsigned int shift;
|
||||
|
||||
shift = 0;
|
||||
spos = *pos;
|
||||
spos = pos;
|
||||
|
||||
while (*len > 0) {
|
||||
int stop = !(**pos & PBUF_VARINT_DONT_STOP_BITMASK);
|
||||
while (len > 0) {
|
||||
int stop = !(*pos & PBUF_VARINT_DONT_STOP_BITMASK);
|
||||
|
||||
++*pos;
|
||||
--*len;
|
||||
++pos;
|
||||
--len;
|
||||
|
||||
if (stop)
|
||||
break;
|
||||
else if (!*len)
|
||||
else if (!len)
|
||||
return -1;
|
||||
|
||||
shift += 7;
|
||||
@ -172,7 +206,129 @@ protobuf_varint_getlen(unsigned char **pos, size_t *len)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return *pos - spos;
|
||||
return pos - spos;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store a raw varint field value in a sample from <pos> buffer
|
||||
* with <len> available bytes.
|
||||
* Return 1 if succeeded, 0 if not.
|
||||
*/
|
||||
int protobuf_smp_store_varint(struct sample *smp,
|
||||
unsigned char *pos, size_t len, size_t vlen)
|
||||
{
|
||||
int varint_len;
|
||||
|
||||
varint_len = protobuf_varint_getlen(pos, len);
|
||||
if (varint_len == -1)
|
||||
return 0;
|
||||
|
||||
smp->data.type = SMP_T_BIN;
|
||||
smp->data.u.str.area = (char *)pos;
|
||||
smp->data.u.str.data = varint_len;
|
||||
smp->flags = SMP_F_VOL_TEST;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move forward <*pos> buffer by 8 bytes. Used to skip a 64bit field.
|
||||
*/
|
||||
int protobuf_skip_64bit(unsigned char **pos, size_t *len, size_t vlen)
|
||||
{
|
||||
if (*len < sizeof(uint64_t))
|
||||
return 0;
|
||||
|
||||
*pos += sizeof(uint64_t);
|
||||
*len -= sizeof(uint64_t);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store a fixed size 64bit field value in a sample from <pos> buffer
|
||||
* with <len> available bytes.
|
||||
* Return 1 if succeeded, 0 if not.
|
||||
*/
|
||||
int protobuf_smp_store_64bit(struct sample *smp,
|
||||
unsigned char *pos, size_t len, size_t vlen)
|
||||
{
|
||||
if (len < sizeof(uint64_t))
|
||||
return 0;
|
||||
|
||||
smp->data.type = SMP_T_BIN;
|
||||
smp->data.u.str.area = (char *)pos;
|
||||
smp->data.u.str.data = sizeof(uint64_t);
|
||||
smp->flags = SMP_F_VOL_TEST;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move forward <*pos> buffer by <vlen> bytes. Use to skip a length-delimited
|
||||
* field.
|
||||
*/
|
||||
int protobuf_skip_vlen(unsigned char **pos, size_t *len, size_t vlen)
|
||||
{
|
||||
if (*len < vlen)
|
||||
return 0;
|
||||
|
||||
*pos += vlen;
|
||||
*len -= vlen;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store a <vlen>-bytes length-delimited field value in a sample from <pos>
|
||||
* buffer with <len> available bytes.
|
||||
* Return 1 if succeeded, 0 if not.
|
||||
*/
|
||||
int protobuf_smp_store_vlen(struct sample *smp,
|
||||
unsigned char *pos, size_t len, size_t vlen)
|
||||
{
|
||||
if (len < vlen)
|
||||
return 0;
|
||||
|
||||
smp->data.type = SMP_T_BIN;
|
||||
smp->data.u.str.area = (char *)pos;
|
||||
smp->data.u.str.data = vlen;
|
||||
smp->flags = SMP_F_VOL_TEST;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Move forward <*pos> buffer by 4 bytes. Used to skip a 32bit field.
|
||||
*/
|
||||
int protobuf_skip_32bit(unsigned char **pos, size_t *len, size_t vlen)
|
||||
{
|
||||
if (*len < sizeof(uint32_t))
|
||||
return 0;
|
||||
|
||||
*pos += sizeof(uint32_t);
|
||||
*len -= sizeof(uint32_t);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store a fixed size 32bit field value in a sample from <pos> buffer
|
||||
* with <len> available bytes.
|
||||
* Return 1 if succeeded, 0 if not.
|
||||
*/
|
||||
int protobuf_smp_store_32bit(struct sample *smp,
|
||||
unsigned char *pos, size_t len, size_t vlen)
|
||||
{
|
||||
if (len < sizeof(uint32_t))
|
||||
return 0;
|
||||
|
||||
smp->data.type = SMP_T_BIN;
|
||||
smp->data.u.str.area = (char *)pos;
|
||||
smp->data.u.str.data = sizeof(uint32_t);
|
||||
smp->flags = SMP_F_VOL_TEST;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* _PROTO_PROTOCOL_BUFFERS_H */
|
||||
|
@ -22,11 +22,25 @@
|
||||
#ifndef _TYPES_PROTOCOL_BUFFERS_H
|
||||
#define _TYPES_PROTOCOL_BUFFERS_H
|
||||
|
||||
enum protobuf_wire_type {
|
||||
PBUF_TYPE_VARINT,
|
||||
PBUF_TYPE_64BIT,
|
||||
PBUF_TYPE_LENGTH_DELIMITED,
|
||||
PBUF_TYPE_START_GROUP, /* Deprecated */
|
||||
PBUF_TYPE_STOP_GROUP, /* Deprecated */
|
||||
PBUF_TYPE_32BIT,
|
||||
};
|
||||
|
||||
struct pbuf_fid {
|
||||
unsigned int *ids;
|
||||
size_t sz;
|
||||
};
|
||||
|
||||
struct protobuf_parser_def {
|
||||
int (*skip)(unsigned char **pos, size_t *left, size_t vlen);
|
||||
int (*smp_store)(struct sample *, unsigned char *pos, size_t left, size_t vlen);
|
||||
};
|
||||
|
||||
#endif /* _TYPES_PROTOCOL_BUFFERS_H */
|
||||
|
||||
/*
|
||||
|
88
src/sample.c
88
src/sample.c
@ -2803,8 +2803,8 @@ static int sample_conv_ungrpc(const struct arg *arg_p, struct sample *smp, void
|
||||
/* Remaining bytes in the body to be parsed. */
|
||||
grpc_left = smp->data.u.str.data;
|
||||
|
||||
while (grpc_left > GRPC_MSG_COMPRESS_FLAG_SZ + GRPC_MSG_LENGTH_SZ) {
|
||||
int next_field, found;
|
||||
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;
|
||||
@ -2824,8 +2824,8 @@ static int sample_conv_ungrpc(const struct arg *arg_p, struct sample *smp, void
|
||||
/* Message decoding: there may be serveral key+value protobuf pairs by
|
||||
* gRPC message.
|
||||
*/
|
||||
next_field = 0;
|
||||
while (next_field < fid_sz) {
|
||||
field = 0;
|
||||
while (field < fid_sz) {
|
||||
uint64_t sleft;
|
||||
|
||||
if ((ssize_t)left <= 0)
|
||||
@ -2840,50 +2840,32 @@ static int sample_conv_ungrpc(const struct arg *arg_p, struct sample *smp, void
|
||||
|
||||
wire_type = key & 0x7;
|
||||
field_number = key >> 3;
|
||||
found = field_number == fid[next_field];
|
||||
|
||||
if (found && field_number != fid[next_field])
|
||||
found = 0;
|
||||
found = field_number == fid[field];
|
||||
|
||||
switch (wire_type) {
|
||||
case PBUF_TYPE_VARINT:
|
||||
{
|
||||
if (!found) {
|
||||
protobuf_skip_varint(&pos, &left);
|
||||
} else if (next_field == fid_sz - 1) {
|
||||
int varint_len;
|
||||
unsigned char *spos = pos;
|
||||
|
||||
varint_len = protobuf_varint_getlen(&pos, &left);
|
||||
if (varint_len == -1)
|
||||
return 0;
|
||||
|
||||
smp->data.type = SMP_T_BIN;
|
||||
smp->data.u.str.area = (char *)spos;
|
||||
smp->data.u.str.data = varint_len;
|
||||
smp->flags = SMP_F_VOL_TEST;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PBUF_TYPE_32BIT:
|
||||
case PBUF_TYPE_64BIT:
|
||||
{
|
||||
struct protobuf_parser_def *pbuf_parser;
|
||||
|
||||
pbuf_parser = &protobuf_parser_defs[wire_type];
|
||||
if (!found) {
|
||||
pos += sizeof(uint64_t);
|
||||
left -= sizeof(uint64_t);
|
||||
} else if (next_field == fid_sz - 1) {
|
||||
smp->data.type = SMP_T_BIN;
|
||||
smp->data.u.str.area = (char *)pos;
|
||||
smp->data.u.str.data = sizeof(uint64_t);
|
||||
smp->flags = SMP_F_VOL_TEST;
|
||||
return 1;
|
||||
/* Skip the data. */
|
||||
if (!pbuf_parser->skip(&pos, &left, 0))
|
||||
return 0;
|
||||
}
|
||||
else if (field == fid_sz - 1) {
|
||||
return pbuf_parser->smp_store(smp, 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;
|
||||
@ -2895,33 +2877,15 @@ static int sample_conv_ungrpc(const struct arg *arg_p, struct sample *smp, void
|
||||
* the bytes to encode the previous lenght.*
|
||||
*/
|
||||
sleft = left;
|
||||
pbuf_parser = &protobuf_parser_defs[wire_type];
|
||||
if (!found) {
|
||||
/* Skip the current length-delimited field. */
|
||||
pos += elen;
|
||||
left -= elen;
|
||||
break;
|
||||
} else if (next_field == fid_sz - 1) {
|
||||
smp->data.type = SMP_T_BIN;
|
||||
smp->data.u.str.area = (char *)pos;
|
||||
smp->data.u.str.data = elen;
|
||||
smp->flags = SMP_F_VOL_TEST;
|
||||
return 1;
|
||||
/* Skip the data. */
|
||||
if (!pbuf_parser->skip(&pos, &left, elen))
|
||||
return 0;
|
||||
} else if (field == fid_sz - 1) {
|
||||
return pbuf_parser->smp_store(smp, pos, left, elen);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PBUF_TYPE_32BIT:
|
||||
{
|
||||
if (!found) {
|
||||
pos += sizeof(uint32_t);
|
||||
left -= sizeof(uint32_t);
|
||||
} else if (next_field == fid_sz - 1) {
|
||||
smp->data.type = SMP_T_BIN;
|
||||
smp->data.u.str.area = (char *)pos;
|
||||
smp->data.u.str.data = sizeof(uint32_t);
|
||||
smp->flags = SMP_F_VOL_TEST;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2933,10 +2897,10 @@ static int sample_conv_ungrpc(const struct arg *arg_p, struct sample *smp, void
|
||||
elen -= sleft - left;
|
||||
|
||||
if (found) {
|
||||
next_field++;
|
||||
field++;
|
||||
}
|
||||
else if ((ssize_t)elen <= 0) {
|
||||
next_field = 0;
|
||||
field = 0;
|
||||
}
|
||||
}
|
||||
grpc_left -= grpc_msg_len;
|
||||
|
Loading…
x
Reference in New Issue
Block a user