mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-01 11:01:46 +00:00
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.
This commit is contained in:
parent
1aabc93978
commit
5f33f85ce8
@ -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 @@ int protobuf_smp_store_32bit(struct sample *smp, int type,
|
||||
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 */
|
||||
|
||||
/*
|
||||
|
101
src/sample.c
101
src/sample.c
@ -2763,26 +2763,12 @@ static int sample_conv_ungrpc(const struct arg *arg_p, struct sample *smp, void
|
||||
{
|
||||
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 @@ static int sample_conv_ungrpc(const struct arg *arg_p, struct sample *smp, void
|
||||
if (grpc_left < left)
|
||||
return 0;
|
||||
|
||||
found = 1;
|
||||
/* Length of the length-delimited messages if any. */
|
||||
elen = 0;
|
||||
if (protobuf_field_lookup(arg_p, smp, &pos, &left))
|
||||
return 1;
|
||||
|
||||
/* 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 (found) {
|
||||
field++;
|
||||
}
|
||||
else if ((ssize_t)elen <= 0) {
|
||||
field = 0;
|
||||
}
|
||||
}
|
||||
grpc_left -= grpc_msg_len;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user