mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-10 00:57:02 +02: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
|
#define _PROTO_PROTOCOL_BUFFERS_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <types/arg.h>
|
||||||
#include <types/protocol_buffers.h>
|
#include <types/protocol_buffers.h>
|
||||||
#include <proto/sample.h>
|
#include <proto/sample.h>
|
||||||
|
|
||||||
@ -477,6 +478,95 @@ int protobuf_smp_store_32bit(struct sample *smp, int type,
|
|||||||
return 1;
|
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 */
|
#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;
|
unsigned char *pos;
|
||||||
size_t grpc_left;
|
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;
|
pos = (unsigned char *)smp->data.u.str.area;
|
||||||
/* Remaining bytes in the body to be parsed. */
|
|
||||||
grpc_left = smp->data.u.str.data;
|
grpc_left = smp->data.u.str.data;
|
||||||
|
|
||||||
while (grpc_left > GRPC_MSG_HEADER_SZ) {
|
while (grpc_left > GRPC_MSG_HEADER_SZ) {
|
||||||
int field, found;
|
|
||||||
size_t grpc_msg_len, left;
|
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));
|
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)
|
if (grpc_left < left)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
found = 1;
|
if (protobuf_field_lookup(arg_p, smp, &pos, &left))
|
||||||
/* Length of the length-delimited messages if any. */
|
return 1;
|
||||||
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 (found) {
|
|
||||||
field++;
|
|
||||||
}
|
|
||||||
else if ((ssize_t)elen <= 0) {
|
|
||||||
field = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
grpc_left -= grpc_msg_len;
|
grpc_left -= grpc_msg_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user