This prefix is followed by a name. The separator is a '.'. The name may only
contain characters 'a-z', 'A-Z', '0-9', '.' and '_'.
-svarint
- Converts a binary input sample of a protocol buffers signed "varint" ("sint32"
- and "sint64") to an integer.
- More information may be found here about the protocol buffers message field types:
- https://developers.google.com/protocol-buffers/docs/encoding
-
table_bytes_in_rate(<table>)
Uses the string representation of the input sample to perform a look up in
the specified table. If the key is not found in the table, integer value zero
Takes an url-encoded string provided as input and returns the decoded
version as output. The input and the output are of type string.
-ungrpc(<field_number>) : binary
+ungrpc(<field_number>,[<field_type>])
This extracts the protocol buffers message field in raw mode of an input binary
- sample with <field_number> as field number (dotted notation).
+ sample with <field_number> as field number (dotted notation) if <field_type>
+ is not present, or as an integer sample if this field is present.
+ The list of the authorized types is the following one: "int32", "int64", "uint32",
+ "uint64", "sint32", "sint64", "bool", "enum" for the "varint" wire type 0
+ "fixed64", "sfixed64", "double" for the 64bit wire type 1, "fixed32", "sfixed32",
+ "float" for the wire type 5. Note that "string" is considered as a length-delimited
+ type. So it does not require any <field_type> argument to be extracted.
+ More information may be found here about the protocol buffers message field types:
+ https://developers.google.com/protocol-buffers/docs/encoding
Example:
// with such a protocol buffer .proto file content adapted from
protocol buffers messages), the four protocol buffers fields could be
extracted with these "ungrpc" directives:
- req.body,ungrpc(48.59.1) # "latitude" of "lo" first PPoint
- req.body,ungrpc(48.59.2) # "longitude" of "lo" first PPoint
- req.body,ungrpc(49.59.1) # "latidude" of "hi" second PPoint
- req.body,ungrpc(49.59.2) # "longitude" of "hi" second PPoint
+ req.body,ungrpc(48.59.1,int32) # "latitude" of "lo" first PPoint
+ req.body,ungrpc(48.59.2,int32) # "longitude" of "lo" first PPoint
+ req.body,ungrpc(49.59.1,int32) # "latidude" of "hi" second PPoint
+ req.body,ungrpc(49.59.2,int32) # "longitude" of "hi" second PPoint
+
+ We could also extract the intermediary 48.59 field as a binary sample as follows:
+
+ req.body,ungrpc(48.59)
+
unset-var(<var name>)
Unsets a variable if the input content is defined. The name of the variable
# e.g. 20140710162350 127.0.0.1:57325
log-format %[date,utime(%Y%m%d%H%M%S)]\ %ci:%cp
-varint
- Converts a binary input sample of a protocol buffers "varint", excepted
- the signed ones "sint32" and "sint64", to an integer.
- More information may be found here about the protocol buffers message field types:
- https://developers.google.com/protocol-buffers/docs/encoding
-
word(<index>,<delimiters>[,<count>])
Extracts the nth word counting from the beginning (positive index) or from
the end (negative index) considering given delimiters from an input string.
/* .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,
+int protobuf_smp_store_varint(struct sample *smp, int type,
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,
+int protobuf_smp_store_64bit(struct sample *smp, int type,
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,
+int protobuf_smp_store_vlen(struct sample *smp, int type,
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,
+int protobuf_smp_store_32bit(struct sample *smp, int type,
unsigned char *pos, size_t len, size_t vlen);
struct protobuf_parser_def protobuf_parser_defs [] = {
},
};
+/*
+ * Note that the field values with protocol buffers 32bit and 64bit fixed size as type
+ * are sent in little-endian byte order to the network.
+ */
+
+/* Convert a little-endian ordered 32bit integer to the byte order of the host. */
+static inline uint32_t pbuf_le32toh(uint32_t v)
+{
+ uint8_t *p = (uint8_t *)&v;
+ return (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));
+}
+
+/* Convert a little-endian ordered 64bit integer to the byte order of the host. */
+static inline uint64_t pbuf_le64toh(uint64_t v)
+{
+ return (uint64_t)(pbuf_le32toh(v >> 32)) << 32 | pbuf_le32toh(v);
+}
+
+/*
+ * Return a protobuf type enum from <s> string if succedeed, -1 if not.
+ */
+int protobuf_type(const char *s)
+{
+ /* varint types. */
+ if (!strcmp(s, "int32"))
+ return PBUF_T_VARINT_INT32;
+ else if (!strcmp(s, "uint32"))
+ return PBUF_T_VARINT_UINT32;
+ else if (!strcmp(s, "sint32"))
+ return PBUF_T_VARINT_SINT32;
+ else if (!strcmp(s, "int64"))
+ return PBUF_T_VARINT_INT64;
+ else if (!strcmp(s, "uint64"))
+ return PBUF_T_VARINT_UINT64;
+ else if (!strcmp(s, "sint64"))
+ return PBUF_T_VARINT_SINT64;
+ else if (!strcmp(s, "bool"))
+ return PBUF_T_VARINT_BOOL;
+ else if (!strcmp(s, "enum"))
+ return PBUF_T_VARINT_ENUM;
+
+ /* 32bit fixed size types. */
+ else if (!strcmp(s, "fixed32"))
+ return PBUF_T_32BIT_FIXED32;
+ else if (!strcmp(s, "sfixed32"))
+ return PBUF_T_32BIT_SFIXED32;
+ else if (!strcmp(s, "float"))
+ return PBUF_T_32BIT_FLOAT;
+
+ /* 64bit fixed size types. */
+ else if (!strcmp(s, "fixed64"))
+ return PBUF_T_64BIT_FIXED64;
+ else if (!strcmp(s, "sfixed64"))
+ return PBUF_T_64BIT_SFIXED64;
+ else if (!strcmp(s, "double"))
+ return PBUF_T_64BIT_DOUBLE;
+ else
+ return -1;
+}
+
/*
* Decode a protocol buffers varint located in a buffer at <pos> address with
* <len> as length. The decoded value is stored at <val>.
}
/*
- * Store a raw varint field value in a sample from <pos> buffer
- * with <len> available bytes.
+ * Store a varint field value in a sample from <pos> buffer
+ * with <len> available bytes after having decoded it if needed
+ * depending on <type> the expected protocol buffer type of the field.
* Return 1 if succeeded, 0 if not.
*/
-int protobuf_smp_store_varint(struct sample *smp,
+int protobuf_smp_store_varint(struct sample *smp, int type,
unsigned char *pos, size_t len, size_t vlen)
{
- int varint_len;
+ switch (type) {
+ case PBUF_T_BINARY:
+ {
+ 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;
+ break;
+ }
+
+ case PBUF_T_VARINT_INT32 ... PBUF_T_VARINT_ENUM:
+ {
+ uint64_t varint;
+
+ if (!protobuf_varint(&varint, pos, len))
+ return 0;
+
+ smp->data.u.sint = varint;
+ smp->data.type = SMP_T_SINT;
+ break;
+ }
+
+ case PBUF_T_VARINT_SINT32 ... PBUF_T_VARINT_SINT64:
+ {
+ uint64_t varint;
+
+ if (!protobuf_varint(&varint, pos, len))
+ return 0;
+
+ /* zigzag decoding. */
+ smp->data.u.sint = (varint >> 1) ^ -(varint & 1);
+ smp->data.type = SMP_T_SINT;
+ break;
+ }
- varint_len = protobuf_varint_getlen(pos, len);
- if (varint_len == -1)
+ default:
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;
}
/*
* Store a fixed size 64bit field value in a sample from <pos> buffer
- * with <len> available bytes.
+ * with <len> available bytes after having decoded it depending on <type>
+ * the expected protocol buffer type of the field.
* Return 1 if succeeded, 0 if not.
*/
-int protobuf_smp_store_64bit(struct sample *smp,
+int protobuf_smp_store_64bit(struct sample *smp, int type,
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;
+ switch (type) {
+ case PBUF_T_BINARY:
+ 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;
+ break;
+
+ case PBUF_T_64BIT_FIXED64:
+ case PBUF_T_64BIT_SFIXED64:
+ smp->data.type = SMP_T_SINT;
+ smp->data.u.sint = pbuf_le64toh(*(uint64_t *)pos);
+ smp->flags = SMP_F_VOL_TEST;
+ break;
+
+ case PBUF_T_64BIT_DOUBLE:
+ smp->data.type = SMP_T_SINT;
+ smp->data.u.sint = pbuf_le64toh(*(double *)pos);
+ smp->flags = SMP_F_VOL_TEST;
+ break;
+
+ default:
+ return 0;
+ }
return 1;
}
* buffer with <len> available bytes.
* Return 1 if succeeded, 0 if not.
*/
-int protobuf_smp_store_vlen(struct sample *smp,
+int protobuf_smp_store_vlen(struct sample *smp, int type,
unsigned char *pos, size_t len, size_t vlen)
{
if (len < vlen)
return 0;
+ if (type != PBUF_T_BINARY)
+ return 0;
+
smp->data.type = SMP_T_BIN;
smp->data.u.str.area = (char *)pos;
smp->data.u.str.data = vlen;
/*
* Store a fixed size 32bit field value in a sample from <pos> buffer
- * with <len> available bytes.
+ * with <len> available bytes after having decoded it depending on <type>
+ * the expected protocol buffer type of the field.
* Return 1 if succeeded, 0 if not.
*/
-int protobuf_smp_store_32bit(struct sample *smp,
+int protobuf_smp_store_32bit(struct sample *smp, int type,
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;
+ switch (type) {
+ case PBUF_T_BINARY:
+ 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;
+ break;
+
+ case PBUF_T_32BIT_FIXED32:
+ smp->data.type = SMP_T_SINT;
+ smp->data.u.sint = pbuf_le32toh(*(uint32_t *)pos);
+ smp->flags = SMP_F_VOL_TEST;
+ break;
+
+ case PBUF_T_32BIT_SFIXED32:
+ smp->data.type = SMP_T_SINT;
+ smp->data.u.sint = (int32_t)pbuf_le32toh(*(uint32_t *)pos);
+ smp->flags = SMP_F_VOL_TEST;
+ break;
+
+ case PBUF_T_32BIT_FLOAT:
+ smp->data.type = SMP_T_SINT;
+ smp->data.u.sint = pbuf_le32toh(*(float *)pos);
+ smp->flags = SMP_F_VOL_TEST;
+ break;
+
+ default:
+ return 0;
+ }
return 1;
}
return 1;
}
-/* Decode an unsigned protocol buffers varint */
-static int sample_conv_varint(const struct arg *arg_p, struct sample *smp, void *private)
-{
- uint64_t varint;
-
- if (!protobuf_varint(&varint, (unsigned char *)smp->data.u.str.area, smp->data.u.str.data))
- return 0;
-
- smp->data.u.sint = varint;
- smp->data.type = SMP_T_SINT;
- return 1;
-}
-
-/* Decode a signed protocol buffers varint encoded as (zigzag + varint). */
-static int sample_conv_svarint(const struct arg *arg_p, struct sample *smp, void *private)
-{
- uint64_t varint;
-
- if (!protobuf_varint(&varint, (unsigned char *)smp->data.u.str.area, smp->data.u.str.data))
- return 0;
-
- /* zigzag decoding. */
- smp->data.u.sint = (varint >> 1) ^ -(varint & 1);
- smp->data.type = SMP_T_SINT;
- return 1;
-}
-
/* This function escape special json characters. The returned string can be
* safely set between two '"' and used as json string. The json string is
* defined like this:
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. */
return 0;
}
else if (field == fid_sz - 1) {
- return pbuf_parser->smp_store(smp, pos, left, 0);
+ return pbuf_parser->smp_store(smp, type, pos, left, 0);
}
break;
if (!pbuf_parser->skip(&pos, &left, elen))
return 0;
} else if (field == fid_sz - 1) {
- return pbuf_parser->smp_store(smp, pos, left, elen);
+ return pbuf_parser->smp_store(smp, type, pos, left, elen);
}
break;
return 0;
}
+static int sample_conv_ungrpc_check(struct arg *args, struct sample_conv *conv,
+ const char *file, int line, char **err)
+{
+ if (!args[1].type) {
+ args[1].type = ARGT_SINT;
+ args[1].data.sint = PBUF_T_BINARY;
+ }
+ else {
+ int pbuf_type;
+
+ pbuf_type = protobuf_type(args[1].data.str.area);
+ if (pbuf_type == -1) {
+ memprintf(err, "Wrong protocol buffer type '%s'", args[1].data.str.area);
+ return 0;
+ }
+
+ args[1].type = ARGT_SINT;
+ args[1].data.sint = pbuf_type;
+ }
+
+ return 1;
+}
+
/* This function checks the "strcmp" converter's arguments and extracts the
* variable name and its scope.
*/
{ "strcmp", sample_conv_strcmp, ARG1(1,STR), smp_check_strcmp, SMP_T_STR, SMP_T_SINT },
/* gRPC converters. */
- { "ungrpc", sample_conv_ungrpc, ARG1(1,PBUF_FNUM), NULL, SMP_T_BIN, SMP_T_BIN },
- { "varint", sample_conv_varint, 0, NULL, SMP_T_BIN, SMP_T_SINT },
- { "svarint", sample_conv_svarint, 0, NULL, SMP_T_BIN, SMP_T_SINT },
+ { "ungrpc", sample_conv_ungrpc, ARG2(1,PBUF_FNUM,STR), sample_conv_ungrpc_check, SMP_T_BIN, SMP_T_BIN },
{ "and", sample_conv_binary_and, ARG1(1,STR), check_operator, SMP_T_SINT, SMP_T_SINT },
{ "or", sample_conv_binary_or, ARG1(1,STR), check_operator, SMP_T_SINT, SMP_T_SINT },