From: Thierry FOURNIER Date: Wed, 19 Apr 2017 09:49:44 +0000 (+0200) Subject: REORG: spoe: move spoe_encode_varint / spoe_decode_varint from spoe to common X-Git-Tag: v1.8-dev2~56 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6ab2bae08499442ec22d2d43d5bfed0127d2db86;p=thirdparty%2Fhaproxy.git REORG: spoe: move spoe_encode_varint / spoe_decode_varint from spoe to common These encoding functions does general stuff and can be used in other context than spoe. This patch moves the function spoe_encode_varint and spoe_decode_varint from spoe to common. It also remove the prefix spoe. These functions will be used for encoding values in new binary sample fetch. --- diff --git a/contrib/spoa_example/spoa.c b/contrib/spoa_example/spoa.c index 7c6d50424c..8fb62e022f 100644 --- a/contrib/spoa_example/spoa.c +++ b/contrib/spoa_example/spoa.c @@ -267,7 +267,7 @@ check_max_frame_size(struct spoe_frame *frame, char **buf, char *end) (type & SPOE_DATA_T_MASK) != SPOE_DATA_T_UINT32 && (type & SPOE_DATA_T_MASK) != SPOE_DATA_T_UINT64) return -1; - if (spoe_decode_varint(&p, end, &sz) == -1) + if (decode_varint(&p, end, &sz) == -1) return -1; /* Keep the lower value */ @@ -453,7 +453,7 @@ check_discon_status_code(struct spoe_frame *frame, char **buf, char *end) (type & SPOE_DATA_T_MASK) != SPOE_DATA_T_UINT32 && (type & SPOE_DATA_T_MASK) != SPOE_DATA_T_UINT64) return -1; - if (spoe_decode_varint(&p, end, &sz) == -1) + if (decode_varint(&p, end, &sz) == -1) return -1; frame->client->status_code = (unsigned int)sz; @@ -709,9 +709,9 @@ handle_hanotify(struct spoe_frame *frame) } /* Read the stream-id and frame-id */ - if (spoe_decode_varint(&p, end, &stream_id) == -1) + if (decode_varint(&p, end, &stream_id) == -1) goto ignore; - if (spoe_decode_varint(&p, end, &frame_id) == -1) + if (decode_varint(&p, end, &frame_id) == -1) goto ignore; frame->stream_id = (unsigned int)stream_id; @@ -765,9 +765,9 @@ handle_hafrag(struct spoe_frame *frame) p+= 4; /* Read the stream-id and frame-id */ - if (spoe_decode_varint(&p, end, &stream_id) == -1) + if (decode_varint(&p, end, &stream_id) == -1) goto ignore; - if (spoe_decode_varint(&p, end, &frame_id) == -1) + if (decode_varint(&p, end, &frame_id) == -1) goto ignore; if (frame->fragmented == false || @@ -842,7 +842,7 @@ prepare_agenthello(struct spoe_frame *frame) /* "max-frame-size" K/V item */ spoe_encode_buffer("max-frame-size", 14, &p ,end); *p++ = SPOE_DATA_T_UINT32; - spoe_encode_varint(client->max_frame_size, &p, end); + encode_varint(client->max_frame_size, &p, end); DEBUG(frame->worker, "<%lu> Agent maximum frame size : %u", client->id, client->max_frame_size); @@ -917,7 +917,7 @@ prepare_agentdicon(struct spoe_frame *frame) /* "status-code" K/V item */ spoe_encode_buffer("status-code", 11, &p, end); *p++ = SPOE_DATA_T_UINT32; - spoe_encode_varint(client->status_code, &p, end); + encode_varint(client->status_code, &p, end); DEBUG(frame->worker, "<%lu> Disconnect status code : %u", client->id, client->status_code); @@ -956,8 +956,8 @@ prepare_agentack(struct spoe_frame *frame) p += 4; /* Set stream-id and frame-id for ACK frames */ - spoe_encode_varint(frame->stream_id, &p, end); - spoe_encode_varint(frame->frame_id, &p, end); + encode_varint(frame->stream_id, &p, end); + encode_varint(frame->frame_id, &p, end); DEBUG(frame->worker, "STREAM-ID=%u - FRAME-ID=%u", frame->stream_id, frame->frame_id); @@ -1369,7 +1369,7 @@ process_frame_cb(evutil_socket_t fd, short events, void *arg) *p++ = SPOE_SCOPE_SESS; /* Arg 1: the scope */ spoe_encode_buffer("ip_score", 8, &p, end); /* Arg 2: variable name */ *p++ = SPOE_DATA_T_UINT32; - spoe_encode_varint(frame->ip_score, &p, end); /* Arg 3: variable value */ + encode_varint(frame->ip_score, &p, end); /* Arg 3: variable value */ frame->len = (p - frame->buf); } write_frame(NULL, frame); diff --git a/include/common/standard.h b/include/common/standard.h index 682711105e..4ba6a950c1 100644 --- a/include/common/standard.h +++ b/include/common/standard.h @@ -205,6 +205,83 @@ static inline const char *LIM2A(unsigned long n, const char *alt) return ret; } +/* Encode the integer into a varint (variable-length integer). The encoded + * value is copied in <*buf>. Here is the encoding format: + * + * 0 <= X < 240 : 1 byte (7.875 bits) [ XXXX XXXX ] + * 240 <= X < 2288 : 2 bytes (11 bits) [ 1111 XXXX ] [ 0XXX XXXX ] + * 2288 <= X < 264432 : 3 bytes (18 bits) [ 1111 XXXX ] [ 1XXX XXXX ] [ 0XXX XXXX ] + * 264432 <= X < 33818864 : 4 bytes (25 bits) [ 1111 XXXX ] [ 1XXX XXXX ]*2 [ 0XXX XXXX ] + * 33818864 <= X < 4328786160 : 5 bytes (32 bits) [ 1111 XXXX ] [ 1XXX XXXX ]*3 [ 0XXX XXXX ] + * ... + * + * On success, it returns the number of written bytes and <*buf> is moved after + * the encoded value. Otherwise, it returns -1. */ +static inline int +encode_varint(uint64_t i, char **buf, char *end) +{ + unsigned char *p = (unsigned char *)*buf; + int r; + + if (p >= (unsigned char *)end) + return -1; + + if (i < 240) { + *p++ = i; + *buf = (char *)p; + return 1; + } + + *p++ = (unsigned char)i | 240; + i = (i - 240) >> 4; + while (i >= 128) { + if (p >= (unsigned char *)end) + return -1; + *p++ = (unsigned char)i | 128; + i = (i - 128) >> 7; + } + + if (p >= (unsigned char *)end) + return -1; + *p++ = (unsigned char)i; + + r = ((char *)p - *buf); + *buf = (char *)p; + return r; +} + +/* Decode a varint from <*buf> and save the decoded value in <*i>. See + * 'spoe_encode_varint' for details about varint. + * On success, it returns the number of read bytes and <*buf> is moved after the + * varint. Otherwise, it returns -1. */ +static inline int +decode_varint(char **buf, char *end, uint64_t *i) +{ + unsigned char *p = (unsigned char *)*buf; + int r; + + if (p >= (unsigned char *)end) + return -1; + + *i = *p++; + if (*i < 240) { + *buf = (char *)p; + return 1; + } + + r = 4; + do { + if (p >= (unsigned char *)end) + return -1; + *i += (uint64_t)*p << r; + r += 7; + } while (*p++ >= 128); + + r = ((char *)p - *buf); + *buf = (char *)p; + return r; +} + /* returns a locally allocated string containing the quoted encoding of the * input string. The output may be truncated to QSTR_SIZE chars, but it is * guaranteed that the string will always be properly terminated. Quotes are diff --git a/include/proto/spoe.h b/include/proto/spoe.h index da19db1d77..1372a7d457 100644 --- a/include/proto/spoe.h +++ b/include/proto/spoe.h @@ -22,88 +22,13 @@ #ifndef _PROTO_SPOE_H #define _PROTO_SPOE_H +#include + #include #include -/* Encode the integer into a varint (variable-length integer). The encoded - * value is copied in <*buf>. Here is the encoding format: - * - * 0 <= X < 240 : 1 byte (7.875 bits) [ XXXX XXXX ] - * 240 <= X < 2288 : 2 bytes (11 bits) [ 1111 XXXX ] [ 0XXX XXXX ] - * 2288 <= X < 264432 : 3 bytes (18 bits) [ 1111 XXXX ] [ 1XXX XXXX ] [ 0XXX XXXX ] - * 264432 <= X < 33818864 : 4 bytes (25 bits) [ 1111 XXXX ] [ 1XXX XXXX ]*2 [ 0XXX XXXX ] - * 33818864 <= X < 4328786160 : 5 bytes (32 bits) [ 1111 XXXX ] [ 1XXX XXXX ]*3 [ 0XXX XXXX ] - * ... - * - * On success, it returns the number of written bytes and <*buf> is moved after - * the encoded value. Otherwise, it returns -1. */ -static inline int -spoe_encode_varint(uint64_t i, char **buf, char *end) -{ - unsigned char *p = (unsigned char *)*buf; - int r; - - if (p >= (unsigned char *)end) - return -1; - - if (i < 240) { - *p++ = i; - *buf = (char *)p; - return 1; - } - - *p++ = (unsigned char)i | 240; - i = (i - 240) >> 4; - while (i >= 128) { - if (p >= (unsigned char *)end) - return -1; - *p++ = (unsigned char)i | 128; - i = (i - 128) >> 7; - } - - if (p >= (unsigned char *)end) - return -1; - *p++ = (unsigned char)i; - - r = ((char *)p - *buf); - *buf = (char *)p; - return r; -} - -/* Decode a varint from <*buf> and save the decoded value in <*i>. See - * 'spoe_encode_varint' for details about varint. - * On success, it returns the number of read bytes and <*buf> is moved after the - * varint. Otherwise, it returns -1. */ -static inline int -spoe_decode_varint(char **buf, char *end, uint64_t *i) -{ - unsigned char *p = (unsigned char *)*buf; - int r; - - if (p >= (unsigned char *)end) - return -1; - - *i = *p++; - if (*i < 240) { - *buf = (char *)p; - return 1; - } - - r = 4; - do { - if (p >= (unsigned char *)end) - return -1; - *i += (uint64_t)*p << r; - r += 7; - } while (*p++ >= 128); - - r = ((char *)p - *buf); - *buf = (char *)p; - return r; -} - /* Encode a buffer. Its length is encoded as a varint, followed by a copy * of . It must have enough space in <*buf> to encode the buffer, else an * error is triggered. @@ -124,7 +49,7 @@ spoe_encode_buffer(const char *str, size_t len, char **buf, char *end) return 0; } - ret = spoe_encode_varint(len, &p, end); + ret = encode_varint(len, &p, end); if (ret == -1 || p + len > end) return -1; @@ -152,7 +77,7 @@ spoe_encode_frag_buffer(const char *str, size_t len, char **buf, char *end) return 0; } - ret = spoe_encode_varint(len, &p, end); + ret = encode_varint(len, &p, end); if (ret == -1 || p >= end) return -1; @@ -176,7 +101,7 @@ spoe_decode_buffer(char **buf, char *end, char **str, size_t *len) *str = NULL; *len = 0; - ret = spoe_decode_varint(&p, end, &sz); + ret = decode_varint(&p, end, &sz); if (ret == -1 || p + sz > end) return -1; @@ -217,7 +142,7 @@ spoe_encode_data(struct sample *smp, unsigned int *off, char **buf, char *end) case SMP_T_SINT: *p++ = SPOE_DATA_T_INT64; - if (spoe_encode_varint(smp->data.u.sint, &p, end) == -1) + if (encode_varint(smp->data.u.sint, &p, end) == -1) return -1; break; @@ -313,7 +238,7 @@ spoe_encode_data(struct sample *smp, unsigned int *off, char **buf, char *end) * * A types data is composed of a type (1 byte) and corresponding data: * - boolean: non additional data (0 bytes) - * - integers: a variable-length integer (see spoe_decode_varint) + * - integers: a variable-length integer (see decode_varint) * - ipv4: 4 bytes * - ipv6: 16 bytes * - binary and string: a buffer prefixed by its size, a variable-length @@ -337,7 +262,7 @@ spoe_skip_data(char **buf, char *end) case SPOE_DATA_T_INT64: case SPOE_DATA_T_UINT32: case SPOE_DATA_T_UINT64: - if (spoe_decode_varint(&p, end, &v) == -1) + if (decode_varint(&p, end, &v) == -1) return -1; break; case SPOE_DATA_T_IPV4: @@ -386,7 +311,7 @@ spoe_decode_data(char **buf, char *end, struct sample *smp) case SPOE_DATA_T_INT64: case SPOE_DATA_T_UINT32: case SPOE_DATA_T_UINT64: - if (spoe_decode_varint(&p, end, (uint64_t *)&smp->data.u.sint) == -1) + if (decode_varint(&p, end, (uint64_t *)&smp->data.u.sint) == -1) return -1; smp->data.type = SMP_T_SINT; break; diff --git a/src/flt_spoe.c b/src/flt_spoe.c index 42e9c0c16b..9288de99fa 100644 --- a/src/flt_spoe.c +++ b/src/flt_spoe.c @@ -388,7 +388,7 @@ spoe_prepare_hahello_frame(struct appctx *appctx, char *frame, size_t size) goto too_big; *p++ = SPOE_DATA_T_UINT32; - if (spoe_encode_varint(SPOE_APPCTX(appctx)->max_frame_size, &p, end) == -1) + if (encode_varint(SPOE_APPCTX(appctx)->max_frame_size, &p, end) == -1) goto too_big; /* "capabilities" K/V item */ @@ -469,7 +469,7 @@ spoe_prepare_hadiscon_frame(struct appctx *appctx, char *frame, size_t size) goto too_big; *p++ = SPOE_DATA_T_UINT32; - if (spoe_encode_varint(SPOE_APPCTX(appctx)->status_code, &p, end) == -1) + if (encode_varint(SPOE_APPCTX(appctx)->status_code, &p, end) == -1) goto too_big; /* "message" K/V item */ @@ -527,9 +527,9 @@ spoe_prepare_hanotify_frame(struct appctx *appctx, struct spoe_context *ctx, p += 4; /* Set stream-id and frame-id */ - if (spoe_encode_varint(stream_id, &p, end) == -1) + if (encode_varint(stream_id, &p, end) == -1) goto too_big; - if (spoe_encode_varint(frame_id, &p, end) == -1) + if (encode_varint(frame_id, &p, end) == -1) goto too_big; /* Copy encoded messages, if possible */ @@ -583,9 +583,9 @@ spoe_prepare_hafrag_frame(struct appctx *appctx, struct spoe_context *ctx, p += 4; /* Set stream-id and frame-id */ - if (spoe_encode_varint(stream_id, &p, end) == -1) + if (encode_varint(stream_id, &p, end) == -1) goto too_big; - if (spoe_encode_varint(frame_id, &p, end) == -1) + if (encode_varint(frame_id, &p, end) == -1) goto too_big; if (ctx == NULL) @@ -706,7 +706,7 @@ spoe_handle_agenthello_frame(struct appctx *appctx, char *frame, size_t size) SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_INVALID; return 0; } - if (spoe_decode_varint(&p, end, &sz) == -1) { + if (decode_varint(&p, end, &sz) == -1) { SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_INVALID; return 0; } @@ -858,7 +858,7 @@ spoe_handle_agentdiscon_frame(struct appctx *appctx, char *frame, size_t size) SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_INVALID; return 0; } - if (spoe_decode_varint(&p, end, &sz) == -1) { + if (decode_varint(&p, end, &sz) == -1) { SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_INVALID; return 0; } @@ -935,11 +935,11 @@ spoe_handle_agentack_frame(struct appctx *appctx, struct spoe_context **ctx, } /* Get the stream-id and the frame-id */ - if (spoe_decode_varint(&p, end, &stream_id) == -1) { + if (decode_varint(&p, end, &stream_id) == -1) { SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_INVALID; return 0; } - if (spoe_decode_varint(&p, end, &frame_id) == -1) { + if (decode_varint(&p, end, &frame_id) == -1) { SPOE_APPCTX(appctx)->status_code = SPOE_FRM_ERR_INVALID; return 0; }