mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-03 12:03:02 +00:00
1fceee8316
This patch implements "req.ungrpc" sample fetch method to decode and parse a gRPC request. It takes only one argument: a protocol buffers field number to identify the protocol buffers message number to be looked up. This argument is a sort of path in dotted notation to the terminal field number to be retrieved. ex: req.ungrpc(1.2.3.4) This sample fetch catch the data in raw mode, without interpreting them. Some protocol buffers specific converters may be used to convert the data to the correct type.
186 lines
4.3 KiB
C
186 lines
4.3 KiB
C
/*
|
|
* include/proto/protocol_buffers.h
|
|
* This file contains functions and macros declarations for protocol buffers decoding.
|
|
*
|
|
* Copyright 2012 Willy Tarreau <w@1wt.eu>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation, version 2.1
|
|
* exclusively.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#ifndef _PROTO_PROTOCOL_BUFFERS_H
|
|
#define _PROTO_PROTOCOL_BUFFERS_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
|
|
|
|
#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
|
|
|
|
/*
|
|
* Decode a protocol buffers varint located in a buffer at <pos> address with
|
|
* <len> as length. The decoded value is stored at <val>.
|
|
* Returns 1 if succeeded, 0 if not.
|
|
*/
|
|
static inline int
|
|
protobuf_varint(uint64_t *val, unsigned char *pos, size_t len)
|
|
{
|
|
unsigned int shift;
|
|
|
|
*val = 0;
|
|
shift = 0;
|
|
|
|
while (len > 0) {
|
|
int stop = !(*pos & PBUF_VARINT_DONT_STOP_BITMASK);
|
|
|
|
*val |= ((uint64_t)(*pos & PBUF_VARINT_DATA_BITMASK)) << shift;
|
|
|
|
++pos;
|
|
--len;
|
|
|
|
if (stop)
|
|
break;
|
|
else if (!len)
|
|
return 0;
|
|
|
|
shift += 7;
|
|
/* The maximum length in bytes of a 64-bit encoded value is 10. */
|
|
if (shift > 70)
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Decode a protocol buffers varint located in a buffer at <pos> offset address with
|
|
* <len> as length address. Update <pos> and <len> consequently. Decrease <*len>
|
|
* by the number of decoded bytes. The decoded value is stored at <val>.
|
|
* Returns 1 if succeeded, 0 if not.
|
|
*/
|
|
static inline int
|
|
protobuf_decode_varint(uint64_t *val, unsigned char **pos, size_t *len)
|
|
{
|
|
unsigned int shift;
|
|
|
|
*val = 0;
|
|
shift = 0;
|
|
|
|
while (*len > 0) {
|
|
int stop = !(**pos & PBUF_VARINT_DONT_STOP_BITMASK);
|
|
|
|
*val |= ((uint64_t)**pos & PBUF_VARINT_DATA_BITMASK) << shift;
|
|
|
|
++*pos;
|
|
--*len;
|
|
|
|
if (stop)
|
|
break;
|
|
else if (!*len)
|
|
return 0;
|
|
|
|
shift += 7;
|
|
/* The maximum length in bytes of a 64-bit encoded value is 10. */
|
|
if (shift > 70)
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* Skip a protocol buffer varint found at <pos> as position address with <len>
|
|
* as available length address. Update <*pos> to make it point to the next
|
|
* 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)
|
|
{
|
|
unsigned int shift;
|
|
|
|
shift = 0;
|
|
|
|
while (*len > 0) {
|
|
int stop = !(**pos & PBUF_VARINT_DONT_STOP_BITMASK);
|
|
|
|
++*pos;
|
|
--*len;
|
|
|
|
if (stop)
|
|
break;
|
|
else if (!*len)
|
|
return 0;
|
|
|
|
shift += 7;
|
|
/* The maximum length in bytes of a 64-bit encoded value is 10. */
|
|
if (shift > 70)
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* If succeeded, return the length of a prococol buffers varint found at <pos> as
|
|
* position address, with <len> as address of the available bytes at <*pos>.
|
|
* Update <*pos> to make it point to the next available byte. Decrease <*len>
|
|
* by the number of bytes used to encode this varint.
|
|
* Return -1 if failed.
|
|
*/
|
|
static inline int
|
|
protobuf_varint_getlen(unsigned char **pos, size_t *len)
|
|
{
|
|
unsigned char *spos;
|
|
unsigned int shift;
|
|
|
|
shift = 0;
|
|
spos = *pos;
|
|
|
|
while (*len > 0) {
|
|
int stop = !(**pos & PBUF_VARINT_DONT_STOP_BITMASK);
|
|
|
|
++*pos;
|
|
--*len;
|
|
|
|
if (stop)
|
|
break;
|
|
else if (!*len)
|
|
return -1;
|
|
|
|
shift += 7;
|
|
/* The maximum length in bytes of a 64-bit encoded value is 10. */
|
|
if (shift > 70)
|
|
return -1;
|
|
}
|
|
|
|
return *pos - spos;
|
|
}
|
|
|
|
#endif /* _PROTO_PROTOCOL_BUFFERS_H */
|
|
|
|
/*
|
|
* Local variables:
|
|
* c-indent-level: 8
|
|
* c-basic-offset: 8
|
|
* End:
|
|
*/
|